EmulateInstructionARM.cpp revision 24bc5d9bfad2a1c562c27e7cf37e1c56d85c45e7
164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton//
364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton//                     The LLVM Compiler Infrastructure
464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton//
564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton// This file is distributed under the University of Illinois Open Source
664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton// License. See LICENSE.TXT for details.
764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton//
864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton//===----------------------------------------------------------------------===//
964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
10fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice#include <stdlib.h>
11fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
1264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#include "EmulateInstructionARM.h"
13395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton#include "lldb/Core/ArchSpec.h"
148482dedc1d0fb4669d1ec63ec259d1cb8eaeb20fGreg Clayton#include "lldb/Core/ConstString.h"
158482dedc1d0fb4669d1ec63ec259d1cb8eaeb20fGreg Clayton
16f29a08f9176c1a443942c08a999763e79b911f62Greg Clayton#include "Plugins/Process/Utility/ARMDefines.h"
17f29a08f9176c1a443942c08a999763e79b911f62Greg Clayton#include "Plugins/Process/Utility/ARMUtils.h"
18f29a08f9176c1a443942c08a999763e79b911f62Greg Clayton#include "Utility/ARM_DWARF_Registers.h"
19f29a08f9176c1a443942c08a999763e79b911f62Greg Clayton
209b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
21930704795c783e5bf1768a43da6f957108b40873Johnny Chen                                     // and CountTrailingZeros_32 function
2264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
2364c8443d255f44267490c8c839f4a9365cf55ea7Greg Claytonusing namespace lldb;
2464c8443d255f44267490c8c839f4a9365cf55ea7Greg Claytonusing namespace lldb_private;
2564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
26e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen// Convenient macro definitions.
27b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
28b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
29e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
30f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
320e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//----------------------------------------------------------------------
330e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//
340e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen// ITSession implementation
350e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//
360e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//----------------------------------------------------------------------
370e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen
38930704795c783e5bf1768a43da6f957108b40873Johnny Chen// A8.6.50
39930704795c783e5bf1768a43da6f957108b40873Johnny Chen// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40930704795c783e5bf1768a43da6f957108b40873Johnny Chenstatic unsigned short CountITSize(unsigned ITMask) {
41930704795c783e5bf1768a43da6f957108b40873Johnny Chen    // First count the trailing zeros of the IT mask.
42930704795c783e5bf1768a43da6f957108b40873Johnny Chen    unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43930704795c783e5bf1768a43da6f957108b40873Johnny Chen    if (TZ > 3)
44930704795c783e5bf1768a43da6f957108b40873Johnny Chen    {
45930704795c783e5bf1768a43da6f957108b40873Johnny Chen        printf("Encoding error: IT Mask '0000'\n");
46930704795c783e5bf1768a43da6f957108b40873Johnny Chen        return 0;
47930704795c783e5bf1768a43da6f957108b40873Johnny Chen    }
48930704795c783e5bf1768a43da6f957108b40873Johnny Chen    return (4 - TZ);
49930704795c783e5bf1768a43da6f957108b40873Johnny Chen}
50930704795c783e5bf1768a43da6f957108b40873Johnny Chen
51930704795c783e5bf1768a43da6f957108b40873Johnny Chen// Init ITState.  Note that at least one bit is always 1 in mask.
52930704795c783e5bf1768a43da6f957108b40873Johnny Chenbool ITSession::InitIT(unsigned short bits7_0)
53930704795c783e5bf1768a43da6f957108b40873Johnny Chen{
54930704795c783e5bf1768a43da6f957108b40873Johnny Chen    ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55930704795c783e5bf1768a43da6f957108b40873Johnny Chen    if (ITCounter == 0)
56930704795c783e5bf1768a43da6f957108b40873Johnny Chen        return false;
57930704795c783e5bf1768a43da6f957108b40873Johnny Chen
58930704795c783e5bf1768a43da6f957108b40873Johnny Chen    // A8.6.50 IT
59930704795c783e5bf1768a43da6f957108b40873Johnny Chen    unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60930704795c783e5bf1768a43da6f957108b40873Johnny Chen    if (FirstCond == 0xF)
61930704795c783e5bf1768a43da6f957108b40873Johnny Chen    {
62930704795c783e5bf1768a43da6f957108b40873Johnny Chen        printf("Encoding error: IT FirstCond '1111'\n");
63930704795c783e5bf1768a43da6f957108b40873Johnny Chen        return false;
64930704795c783e5bf1768a43da6f957108b40873Johnny Chen    }
65930704795c783e5bf1768a43da6f957108b40873Johnny Chen    if (FirstCond == 0xE && ITCounter != 1)
66930704795c783e5bf1768a43da6f957108b40873Johnny Chen    {
67930704795c783e5bf1768a43da6f957108b40873Johnny Chen        printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68930704795c783e5bf1768a43da6f957108b40873Johnny Chen        return false;
69930704795c783e5bf1768a43da6f957108b40873Johnny Chen    }
70930704795c783e5bf1768a43da6f957108b40873Johnny Chen
71930704795c783e5bf1768a43da6f957108b40873Johnny Chen    ITState = bits7_0;
72930704795c783e5bf1768a43da6f957108b40873Johnny Chen    return true;
73930704795c783e5bf1768a43da6f957108b40873Johnny Chen}
74930704795c783e5bf1768a43da6f957108b40873Johnny Chen
75930704795c783e5bf1768a43da6f957108b40873Johnny Chen// Update ITState if necessary.
76930704795c783e5bf1768a43da6f957108b40873Johnny Chenvoid ITSession::ITAdvance()
77930704795c783e5bf1768a43da6f957108b40873Johnny Chen{
78930704795c783e5bf1768a43da6f957108b40873Johnny Chen    assert(ITCounter);
79930704795c783e5bf1768a43da6f957108b40873Johnny Chen    --ITCounter;
80930704795c783e5bf1768a43da6f957108b40873Johnny Chen    if (ITCounter == 0)
81930704795c783e5bf1768a43da6f957108b40873Johnny Chen        ITState = 0;
82930704795c783e5bf1768a43da6f957108b40873Johnny Chen    else
83930704795c783e5bf1768a43da6f957108b40873Johnny Chen    {
84930704795c783e5bf1768a43da6f957108b40873Johnny Chen        unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85930704795c783e5bf1768a43da6f957108b40873Johnny Chen        SetBits32(ITState, 4, 0, NewITState4_0);
86930704795c783e5bf1768a43da6f957108b40873Johnny Chen    }
87930704795c783e5bf1768a43da6f957108b40873Johnny Chen}
88930704795c783e5bf1768a43da6f957108b40873Johnny Chen
89930704795c783e5bf1768a43da6f957108b40873Johnny Chen// Return true if we're inside an IT Block.
90930704795c783e5bf1768a43da6f957108b40873Johnny Chenbool ITSession::InITBlock()
91930704795c783e5bf1768a43da6f957108b40873Johnny Chen{
92930704795c783e5bf1768a43da6f957108b40873Johnny Chen    return ITCounter != 0;
93930704795c783e5bf1768a43da6f957108b40873Johnny Chen}
94930704795c783e5bf1768a43da6f957108b40873Johnny Chen
95c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen// Return true if we're the last instruction inside an IT Block.
96c315f860b343cf4a143f43c7d570d151989abb46Johnny Chenbool ITSession::LastInITBlock()
97c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen{
98c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    return ITCounter == 1;
99c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen}
100c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen
101930704795c783e5bf1768a43da6f957108b40873Johnny Chen// Get condition bits for the current thumb instruction.
102930704795c783e5bf1768a43da6f957108b40873Johnny Chenuint32_t ITSession::GetCond()
103930704795c783e5bf1768a43da6f957108b40873Johnny Chen{
104c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    if (InITBlock())
105c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen        return Bits32(ITState, 7, 4);
106c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    else
107c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen        return COND_AL;
108930704795c783e5bf1768a43da6f957108b40873Johnny Chen}
109930704795c783e5bf1768a43da6f957108b40873Johnny Chen
11064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton// ARM constants used during decoding
11164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define REG_RD          0
11264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define LDM_REGLIST     1
113e39f22d1a369866808b8739c3cec15063d806833Johnny Chen#define SP_REG          13
114e39f22d1a369866808b8739c3cec15063d806833Johnny Chen#define LR_REG          14
11564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define PC_REG          15
11664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define PC_REGLIST_BIT  0x8000
11764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
118251af6aedbd3a5b6f1a105ab9303f13b53e332ffJohnny Chen#define ARMv4     (1u << 0)
11964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define ARMv4T    (1u << 1)
12064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define ARMv5T    (1u << 2)
12164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define ARMv5TE   (1u << 3)
12264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define ARMv5TEJ  (1u << 4)
123251af6aedbd3a5b6f1a105ab9303f13b53e332ffJohnny Chen#define ARMv6     (1u << 5)
12464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define ARMv6K    (1u << 6)
12564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define ARMv6T2   (1u << 7)
126251af6aedbd3a5b6f1a105ab9303f13b53e332ffJohnny Chen#define ARMv7     (1u << 8)
12760c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen#define ARMv8     (1u << 9)
12864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#define ARMvAll   (0xffffffffu)
12964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
1309b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#define ARMV4T_ABOVE  (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
1319b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#define ARMV5_ABOVE   (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
1321697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
13359e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen#define ARMV5J_ABOVE  (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
1346bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice#define ARMV6_ABOVE   (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
1359b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
1362b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
1370e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//----------------------------------------------------------------------
1380e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//
1390e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen// EmulateInstructionARM implementation
1400e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//
1410e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen//----------------------------------------------------------------------
1420e00af21580d7ee85e14abd518d4aa54157dcbf5Johnny Chen
1432b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonvoid
1442b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg ClaytonEmulateInstructionARM::Initialize ()
1457dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen{
1462b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton}
1477dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen
1482b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonvoid
1492b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg ClaytonEmulateInstructionARM::Terminate ()
15064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton{
1512b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton}
1522b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
153fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice// Write "bits (32) UNKNOWN" to memory address "address".  Helper function for many ARM instructions.
154fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Ticebool
155fa17220ce8b3db56b05317fd5e69c450127f8538Caroline TiceEmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
156fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice{
1579bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    EmulateInstruction::Context context;
1589bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
1599bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.SetNoArgs ();
160fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
161fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    uint32_t random_data = rand ();
162fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    const uint32_t addr_byte_size = GetAddressByteSize();
163fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
164cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice    if (!MemAWrite (context, address, random_data, addr_byte_size))
165fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        return false;
166fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
167fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    return true;
168fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice}
169fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
170713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// Write "bits (32) UNKNOWN" to register n.  Helper function for many ARM instructions.
171713c2665a27096b68f3f8956222375354f1292f8Caroline Ticebool
172713c2665a27096b68f3f8956222375354f1292f8Caroline TiceEmulateInstructionARM::WriteBits32Unknown (int n)
173713c2665a27096b68f3f8956222375354f1292f8Caroline Tice{
1749bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    EmulateInstruction::Context context;
1759bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
1769bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.SetNoArgs ();
177713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
17862ff6f5a8c243ea8fb08039c71830a8138990945Johnny Chen    bool success;
179713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
180713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
181713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    if (!success)
182713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        return false;
183713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
184713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
185713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        return false;
186713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
187713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    return true;
188713c2665a27096b68f3f8956222375354f1292f8Caroline Tice}
189713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
19008c25e855749d94d89ff162a30ff46c9a2911aceJohnny Chen// Push Multiple Registers stores multiple registers to the stack, storing to
19108c25e855749d94d89ff162a30ff46c9a2911aceJohnny Chen// consecutive memory locations ending just below the address in SP, and updates
19208c25e855749d94d89ff162a30ff46c9a2911aceJohnny Chen// SP to point to the start of the stored data.
1932b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
1947bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
19564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton{
19664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#if 0
19764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    // ARM pseudo code...
19864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    if (ConditionPassed())
19964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    {
20064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        EncodingSpecificOperations();
20164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        NullCheckIfThumbEE(13);
20264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        address = SP - 4*BitCount(registers);
20364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
20464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        for (i = 0 to 14)
20564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        {
206bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if (registers<i> == '1')
20764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            {
20864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
20964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    MemA[address,4] = bits(32) UNKNOWN;
21064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                else
21164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    MemA[address,4] = R[i];
21264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                address = address + 4;
21364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            }
21464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        }
21564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
216bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if (registers<15> == '1') // Only possible for encoding A1 or A2
21764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            MemA[address,4] = PCStoreValue();
21864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
21964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        SP = SP - 4*BitCount(registers);
22064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    }
22164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton#endif
22264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
22364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    bool success = false;
2247bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
22564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    {
2262b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        const uint32_t addr_byte_size = GetAddressByteSize();
227e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
22864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        if (!success)
22964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            return false;
2303c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen        uint32_t registers = 0;
23191d998659e5d38aeebb3b8ebe2fb596907bd0548Johnny Chen        uint32_t Rt; // the source register
2323c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen        switch (encoding) {
233aedde1c6a33b123031499800f56954adc86058f5Johnny Chen        case eEncodingT1:
234108d5aaa1379f154e459d82aa482b4f2ddf134c7Johnny Chen            registers = Bits32(opcode, 7, 0);
235aedde1c6a33b123031499800f56954adc86058f5Johnny Chen            // The M bit represents LR.
236bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            if (Bit32(opcode, 8))
237ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                registers |= (1u << 14);
238aedde1c6a33b123031499800f56954adc86058f5Johnny Chen            // if BitCount(registers) < 1 then UNPREDICTABLE;
239aedde1c6a33b123031499800f56954adc86058f5Johnny Chen            if (BitCount(registers) < 1)
240aedde1c6a33b123031499800f56954adc86058f5Johnny Chen                return false;
241aedde1c6a33b123031499800f56954adc86058f5Johnny Chen            break;
2427dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen        case eEncodingT2:
2437dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen            // Ignore bits 15 & 13.
244108d5aaa1379f154e459d82aa482b4f2ddf134c7Johnny Chen            registers = Bits32(opcode, 15, 0) & ~0xa000;
2457dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen            // if BitCount(registers) < 2 then UNPREDICTABLE;
2467dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen            if (BitCount(registers) < 2)
2477dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen                return false;
2487dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen            break;
2497dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen        case eEncodingT3:
250108d5aaa1379f154e459d82aa482b4f2ddf134c7Johnny Chen            Rt = Bits32(opcode, 15, 12);
2517dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen            // if BadReg(t) then UNPREDICTABLE;
25291d998659e5d38aeebb3b8ebe2fb596907bd0548Johnny Chen            if (BadReg(Rt))
2537dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen                return false;
25491d998659e5d38aeebb3b8ebe2fb596907bd0548Johnny Chen            registers = (1u << Rt);
2557dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen            break;
2563c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen        case eEncodingA1:
257108d5aaa1379f154e459d82aa482b4f2ddf134c7Johnny Chen            registers = Bits32(opcode, 15, 0);
258a33d4846702ea5ee033c4e3d133548ab57ff17f3Johnny Chen            // Instead of return false, let's handle the following case as well,
259a33d4846702ea5ee033c4e3d133548ab57ff17f3Johnny Chen            // which amounts to pushing one reg onto the full descending stacks.
260a33d4846702ea5ee033c4e3d133548ab57ff17f3Johnny Chen            // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
2613c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen            break;
2623c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen        case eEncodingA2:
263108d5aaa1379f154e459d82aa482b4f2ddf134c7Johnny Chen            Rt = Bits32(opcode, 15, 12);
2647dc60e15db4643826ed68f41b5122c6075454a24Johnny Chen            // if t == 13 then UNPREDICTABLE;
26591d998659e5d38aeebb3b8ebe2fb596907bd0548Johnny Chen            if (Rt == dwarf_sp)
2663c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen                return false;
26791d998659e5d38aeebb3b8ebe2fb596907bd0548Johnny Chen            registers = (1u << Rt);
2683c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen            break;
269ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        default:
270ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen            return false;
2713c75c76090e770bb5e47154ba4ebe3244027daa4Johnny Chen        }
272ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        addr_t sp_offset = addr_byte_size * BitCount (registers);
27364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        addr_t addr = sp - sp_offset;
27464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        uint32_t i;
27564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
2769bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
2779bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextPushRegisterOnStack;
2789bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
2799bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
2802b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice        Register sp_reg;
2812b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice        sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
28264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        for (i=0; i<15; ++i)
28364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        {
2847c1bf922ae84a214225869dbe6a1847e891815d0Johnny Chen            if (BitIsSet (registers, i))
28564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            {
2869bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice                dwarf_reg.num = dwarf_r0 + i;
2872b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice                context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
288e39f22d1a369866808b8739c3cec15063d806833Johnny Chen                uint32_t reg_value = ReadCoreReg(i, &success);
28964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                if (!success)
29064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    return false;
291cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                if (!MemAWrite (context, addr, reg_value, addr_byte_size))
29264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    return false;
29364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                addr += addr_byte_size;
29464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            }
29564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        }
29664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
2977c1bf922ae84a214225869dbe6a1847e891815d0Johnny Chen        if (BitIsSet (registers, 15))
29864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        {
2999bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            dwarf_reg.num = dwarf_pc;
3009bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
301e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            const uint32_t pc = ReadCoreReg(PC_REG, &success);
30264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            if (!success)
30364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                return false;
304e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            if (!MemAWrite (context, addr, pc, addr_byte_size))
30564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                return false;
30664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        }
30764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
30864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        context.type = EmulateInstruction::eContextAdjustStackPointer;
3099bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetImmediateSigned (-sp_offset);
31064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
3112b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
31264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            return false;
31364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    }
31464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    return true;
31564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton}
31664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
317ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen// Pop Multiple Registers loads multiple registers from the stack, loading from
318ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen// consecutive memory locations staring at the address in SP, and updates
319ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen// SP to point just above the loaded data.
3202b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
3217bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
322ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen{
323ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen#if 0
324ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    // ARM pseudo code...
325ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    if (ConditionPassed())
326ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    {
327ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        EncodingSpecificOperations(); NullCheckIfThumbEE(13);
328ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        address = SP;
329ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        for i = 0 to 14
330bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
331ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
332bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then
333ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            if UnalignedAllowed then
334ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                LoadWritePC(MemU[address,4]);
335ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            else
336ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                LoadWritePC(MemA[address,4]);
337bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<13> == '0' then SP = SP + 4*BitCount(registers);
338bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<13> == '1' then SP = bits(32) UNKNOWN;
339ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    }
340ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen#endif
341ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
342ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    bool success = false;
343ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
3447bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
345ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    {
3462b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        const uint32_t addr_byte_size = GetAddressByteSize();
347e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
348ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        if (!success)
349ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            return false;
350ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        uint32_t registers = 0;
351ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        uint32_t Rt; // the destination register
352ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        switch (encoding) {
353ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        case eEncodingT1:
354ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            registers = Bits32(opcode, 7, 0);
355ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // The P bit represents PC.
356bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            if (Bit32(opcode, 8))
357ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                registers |= (1u << 15);
358ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // if BitCount(registers) < 1 then UNPREDICTABLE;
359ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            if (BitCount(registers) < 1)
360ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                return false;
361ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            break;
362ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        case eEncodingT2:
363ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // Ignore bit 13.
364ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            registers = Bits32(opcode, 15, 0) & ~0x2000;
365ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
366bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
367ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                return false;
368098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
369098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
370098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen                return false;
371ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            break;
372ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        case eEncodingT3:
373ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            Rt = Bits32(opcode, 15, 12);
374ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
375098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (Rt == 13)
376098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen                return false;
377098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (Rt == 15 && InITBlock() && !LastInITBlock())
378ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                return false;
379ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            registers = (1u << Rt);
380ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            break;
381ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        case eEncodingA1:
382ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            registers = Bits32(opcode, 15, 0);
383ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // Instead of return false, let's handle the following case as well,
384ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // which amounts to popping one reg from the full descending stacks.
385ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
386ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
387bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
388098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
389ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                return false;
390ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            break;
391ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        case eEncodingA2:
392ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            Rt = Bits32(opcode, 15, 12);
393ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            // if t == 13 then UNPREDICTABLE;
394ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            if (Rt == dwarf_sp)
395ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                return false;
396ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            registers = (1u << Rt);
397ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            break;
398ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        default:
399ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            return false;
400ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        }
401ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        addr_t sp_offset = addr_byte_size * BitCount (registers);
402ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        addr_t addr = sp;
403ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        uint32_t i, data;
404ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
4059bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
4069bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextPopRegisterOffStack;
4079bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
4089bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
4098ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        Register sp_reg;
4108ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
411ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        for (i=0; i<15; ++i)
412ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        {
4137c1bf922ae84a214225869dbe6a1847e891815d0Johnny Chen            if (BitIsSet (registers, i))
414ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            {
4159bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice                dwarf_reg.num = dwarf_r0 + i;
4168ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                context.SetRegisterPlusOffset (sp_reg, addr - sp);
417cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                data = MemARead(context, addr, 4, 0, &success);
418ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                if (!success)
419ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                    return false;
4209bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice                if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
421ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                    return false;
422ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                addr += addr_byte_size;
423ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            }
424ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        }
425ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
4267c1bf922ae84a214225869dbe6a1847e891815d0Johnny Chen        if (BitIsSet (registers, 15))
427ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        {
4289bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            dwarf_reg.num = dwarf_pc;
4298ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            context.SetRegisterPlusOffset (sp_reg, addr - sp);
430cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            data = MemARead(context, addr, 4, 0, &success);
431ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            if (!success)
432ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                return false;
433f3eaacfc02d0a98d3bac1eaef74ad5c1c66ccfdcJohnny Chen            // In ARMv5T and above, this is an interworking branch.
434668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen            if (!LoadWritePC(context, data))
435ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen                return false;
436ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            addr += addr_byte_size;
437ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        }
438ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
439ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen        context.type = EmulateInstruction::eContextAdjustStackPointer;
4409bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetImmediateSigned (sp_offset);
441ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
4422b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
443ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen            return false;
444ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    }
445ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen    return true;
446ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen}
447ef85e9162b61fa40ff9d3c9e32476e53cc94aac1Johnny Chen
4485b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen// Set r7 or ip to point to saved value residing within the stack.
449bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen// ADD (SP plus immediate)
4502b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
4517bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
452bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen{
453bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen#if 0
454bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    // ARM pseudo code...
455bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    if (ConditionPassed())
456bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    {
457bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        EncodingSpecificOperations();
458bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
459bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        if d == 15 then
460bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen           ALUWritePC(result); // setflags is always FALSE here
461bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        else
462bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            R[d] = result;
463bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            if setflags then
464bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen                APSR.N = result<31>;
465bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen                APSR.Z = IsZeroBit(result);
466bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen                APSR.C = carry;
467bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen                APSR.V = overflow;
468bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    }
469bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen#endif
470bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen
471bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    bool success = false;
472bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen
4737bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
474bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    {
475e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
476bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        if (!success)
477bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            return false;
478bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        uint32_t Rd; // the destination register
479bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        uint32_t imm32;
480bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        switch (encoding) {
481bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        case eEncodingT1:
482bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            Rd = 7;
483bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
484bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            break;
485bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        case eEncodingA1:
486bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            Rd = Bits32(opcode, 15, 12);
487bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
488bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            break;
489bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        default:
490bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            return false;
491bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        }
492bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        addr_t sp_offset = imm32;
493bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen        addr_t addr = sp + sp_offset; // a pointer to the stack area
494bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen
4959bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
4969bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
4979bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register sp_reg;
4989bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
4999bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (sp_reg, sp_offset);
500bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen
5012b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
502bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen            return false;
503bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    }
504bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen    return true;
505bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen}
506bcec3afc23f922f87f60f4d216b0dfb5c209c67dJohnny Chen
5072ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen// Set r7 or ip to the current stack pointer.
5082ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen// MOV (register)
5092b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
5107bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
5112ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen{
5122ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen#if 0
5132ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    // ARM pseudo code...
5142ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    if (ConditionPassed())
5152ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    {
5162ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        EncodingSpecificOperations();
5172ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        result = R[m];
5182ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        if d == 15 then
5192ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
5202ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        else
5212ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            R[d] = result;
5222ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            if setflags then
5232ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen                APSR.N = result<31>;
5242ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen                APSR.Z = IsZeroBit(result);
5252ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen                // APSR.C unchanged
5262ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen                // APSR.V unchanged
5272ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    }
5282ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen#endif
5292ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen
5302ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    bool success = false;
5312ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen
5327bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5332ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    {
534e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
5352ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        if (!success)
5362ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            return false;
5372ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        uint32_t Rd; // the destination register
5382ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        switch (encoding) {
5392ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        case eEncodingT1:
5402ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            Rd = 7;
5412ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            break;
5422ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        case eEncodingA1:
5432ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            Rd = 12;
5442ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            break;
5452ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        default:
5462ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            return false;
5472ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen        }
5489bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice
5499bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
5509bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
5519bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register sp_reg;
5529bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
5539bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (sp_reg, 0);
5542ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen
5552b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
5562ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen            return false;
5572ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    }
5582ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen    return true;
5592ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen}
5602ccad833be6e4122ee94efd0f5918a34afb02f9eJohnny Chen
5611c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen// Move from high register (r8-r15) to low register (r0-r7).
5621c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen// MOV (register)
5632b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
5647bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
5651c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen{
5667bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateMOVRdRm (opcode, encoding);
567338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen}
568338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen
569338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen// Move from register to register.
570338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen// MOV (register)
571338bf54a49633d90f3c5e808847470901f25dee9Johnny Chenbool
5727bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
573338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen{
5741c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen#if 0
5751c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    // ARM pseudo code...
5761c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    if (ConditionPassed())
5771c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    {
5781c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        EncodingSpecificOperations();
5791c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        result = R[m];
5801c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        if d == 15 then
5811c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
5821c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        else
5831c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen            R[d] = result;
5841c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen            if setflags then
5851c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen                APSR.N = result<31>;
5861c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen                APSR.Z = IsZeroBit(result);
5871c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen                // APSR.C unchanged
5881c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen                // APSR.V unchanged
5891c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    }
5901c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen#endif
5911c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen
5921c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    bool success = false;
5931c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen
5947bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5951c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    {
5961c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        uint32_t Rm; // the source register
5971c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        uint32_t Rd; // the destination register
598338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen        bool setflags;
5991c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        switch (encoding) {
6001c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        case eEncodingT1:
6017c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
6021c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen            Rm = Bits32(opcode, 6, 3);
603338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen            setflags = false;
6047c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (Rd == 15 && InITBlock() && !LastInITBlock())
6057c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
606338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen            break;
607338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen        case eEncodingT2:
6087c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Bits32(opcode, 2, 0);
609338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen            Rm = Bits32(opcode, 5, 3);
610338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen            setflags = true;
6117c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (InITBlock())
6127c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
6131c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen            break;
6147c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        case eEncodingT3:
6157c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Bits32(opcode, 11, 8);
6167c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rm = Bits32(opcode, 3, 0);
6177c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            setflags = BitIsSet(opcode, 20);
6187c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
6197c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (setflags && (BadReg(Rd) || BadReg(Rm)))
6207c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
6217c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
6227c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
6237c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
624ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
62501d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen        case eEncodingA1:
62601d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen            Rd = Bits32(opcode, 15, 12);
62701d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen            Rm = Bits32(opcode, 3, 0);
62801d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen            setflags = BitIsSet(opcode, 20);
62901d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
63001d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
63101d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen            if (Rd == 15 && setflags)
63201d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen                return false;
63301d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen            break;
6341c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        default:
6351c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen            return false;
6361c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        }
6377c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t result = ReadCoreReg(Rm, &success);
6381c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        if (!success)
6391c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen            return false;
6401c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen
6411c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen        // The context specifies that Rm is to be moved into Rd.
6429bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
6432b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice        context.type = EmulateInstruction::eContextRegisterLoad;
6449bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
6459bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
6462b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice        context.SetRegister (dwarf_reg);
647ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen
64810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
649ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            return false;
6501c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    }
6511c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen    return true;
6521c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen}
6531c13b62188b2ae5d1f2acce539f1034d71189516Johnny Chen
654357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen// Move (immediate) writes an immediate value to the destination register.  It
655357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen// can optionally update the condition flags based on the value.
656357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen// MOV (immediate)
657357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chenbool
6587bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
659357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen{
660357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen#if 0
661357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen    // ARM pseudo code...
662357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen    if (ConditionPassed())
663357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen    {
664357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        EncodingSpecificOperations();
665357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        result = imm32;
666357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
667357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
668357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        else
669357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen            R[d] = result;
670357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen            if setflags then
671357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen                APSR.N = result<31>;
672357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen                APSR.Z = IsZeroBit(result);
673357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen                APSR.C = carry;
674357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen                // APSR.V unchanged
675357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen    }
676357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen#endif
677357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen
6787bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
679357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen    {
680357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        uint32_t Rd; // the destination register
681357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        uint32_t imm32; // the immediate value to be written to Rd
682357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
683357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        bool setflags;
684357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        switch (encoding) {
68589c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            case eEncodingT1:
68689c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                Rd = Bits32(opcode, 10, 8);
68789c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                setflags = !InITBlock();
68889c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
68989c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                carry = APSR_C;
69089c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
69189c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                break;
69289c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
69389c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            case eEncodingT2:
69489c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                Rd = Bits32(opcode, 11, 8);
69589c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                setflags = BitIsSet(opcode, 20);
69689c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
69789c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                if (BadReg(Rd))
69889c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                  return false;
69989c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
70089c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                break;
70189c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
70289c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            case eEncodingT3:
70389c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            {
70489c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
70589c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                Rd = Bits32 (opcode, 11, 8);
70689c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                setflags = false;
70789c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                uint32_t imm4 = Bits32 (opcode, 19, 16);
70889c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                uint32_t imm3 = Bits32 (opcode, 14, 12);
70989c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                uint32_t i = Bit32 (opcode, 26);
71089c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                uint32_t imm8 = Bits32 (opcode, 7, 0);
71189c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
71289c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
71389c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                // if BadReg(d) then UNPREDICTABLE;
71489c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                if (BadReg (Rd))
71589c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                    return false;
71689c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            }
71789c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                break;
71889c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
71989c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            case eEncodingA1:
72089c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
72189c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
72289c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                Rd = Bits32 (opcode, 15, 12);
72389c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                setflags = BitIsSet (opcode, 20);
72489c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
72589c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
72689c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                break;
72789c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
72889c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            case eEncodingA2:
72989c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            {
73089c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
73189c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                Rd = Bits32 (opcode, 15, 12);
73289c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                setflags = false;
73389c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                uint32_t imm4 = Bits32 (opcode, 19, 16);
73489c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                uint32_t imm12 = Bits32 (opcode, 11, 0);
73589c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                imm32 = (imm4 << 12) | imm12;
73689c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
73789c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                // if d == 15 then UNPREDICTABLE;
73889c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                if (Rd == 15)
73989c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                    return false;
74089c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            }
74189c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice                break;
74289c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice
74389c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice            default:
7449798cfcb34cd66965fb3ff58e60a14309534b29eJohnny Chen                return false;
745357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        }
746357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        uint32_t result = imm32;
747357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen
748357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        // The context specifies that an immediate is to be moved into Rd.
7499bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
7509bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextImmediate;
7519bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetNoArgs ();
752ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen
75310530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
754ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            return false;
755357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen    }
756357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen    return true;
757357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen}
758357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen
7595c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice// MUL multiplies two register values.  The least significant 32 bits of the result are written to the destination
7605c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice// register.  These 32 bits do not depend on whether the source register values are considered to be signed values or
7615c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice// unsigned values.
7625c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice//
7635c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice// Optionally, it can update the condition flags based on the result.  In the Thumb instruction set, this option is
7645c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice// limited to only a few forms of the instruction.
7655c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Ticebool
7667bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
7675c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice{
7685c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice#if 0
7695c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice    if ConditionPassed() then
7705c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        EncodingSpecificOperations();
7715c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
7725c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
7735c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        result = operand1 * operand2;
7745c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        R[d] = result<31:0>;
7755c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        if setflags then
7765c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            APSR.N = result<31>;
7775c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            APSR.Z = IsZeroBit(result);
7785c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            if ArchVersion() == 4 then
7795c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                APSR.C = bit UNKNOWN;
7805c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            // else APSR.C unchanged
7815c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            // APSR.V always unchanged
7825c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice#endif
7835c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
7847bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
7855c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice    {
7865c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        uint32_t d;
7875c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        uint32_t n;
7885c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        uint32_t m;
7895c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        bool setflags;
7905c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
7915c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // EncodingSpecificOperations();
7925c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        switch (encoding)
7935c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        {
7945c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            case eEncodingT1:
7955c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
7965c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                d = Bits32 (opcode, 2, 0);
7975c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                n = Bits32 (opcode, 5, 3);
7985c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                m = Bits32 (opcode, 2, 0);
7995c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                setflags = !InITBlock();
8005c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8015c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
8025c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                if ((ArchVersion() < ARMv6) && (d == n))
8035c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                    return false;
8045c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8055c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                break;
8065c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8075c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            case eEncodingT2:
8085c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
8095c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                d = Bits32 (opcode, 11, 8);
8105c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                n = Bits32 (opcode, 19, 16);
8115c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                m = Bits32 (opcode, 3, 0);
8125c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                setflags = false;
8135c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8145c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
8155c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                if (BadReg (d) || BadReg (n) || BadReg (m))
8165c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                    return false;
8175c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8185c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                break;
8195c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8205c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            case eEncodingA1:
821bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
8225c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                d = Bits32 (opcode, 19, 16);
8235c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                n = Bits32 (opcode, 3, 0);
8245c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                m = Bits32 (opcode, 11, 8);
8255c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                setflags = BitIsSet (opcode, 20);
8265c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8275c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
8285c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                if ((d == 15) ||  (n == 15) || (m == 15))
8295c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                    return false;
8305c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8315c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
8325c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                if ((ArchVersion() < ARMv6) && (d == n))
8335c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                    return false;
8345c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8355c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                break;
8365c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8375c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            default:
8385c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                return false;
8395c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        }
8407bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton
8417bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        bool success = false;
8427bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton
8435c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
8445c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8455c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        if (!success)
8465c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            return false;
8475c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8485c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
8495c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8505c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        if (!success)
8515c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            return false;
8525c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8535c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // result = operand1 * operand2;
8545c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        uint64_t result = operand1 * operand2;
8555c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8565c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // R[d] = result<31:0>;
8575c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        Register op1_reg;
8585c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        Register op2_reg;
8595c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8605c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
8615c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8625c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        EmulateInstruction::Context context;
8635c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        context.type = eContextMultiplication;
8645c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        context.SetRegisterRegisterOperands (op1_reg, op2_reg);
8655c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8665c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
8675c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            return false;
8685c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8695c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // if setflags then
8705c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        if (setflags)
8715c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        {
8725c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            // APSR.N = result<31>;
8735c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            // APSR.Z = IsZeroBit(result);
874b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            m_new_inst_cpsr = m_opcode_cpsr;
8755c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
8765c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
877b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            if (m_new_inst_cpsr != m_opcode_cpsr)
8785c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            {
8795c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
8805c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                    return false;
8815c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            }
8825c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
8835c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice            // if ArchVersion() == 4 then
8845c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice                // APSR.C = bit UNKNOWN;
8855c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        }
8865c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice    }
8875c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice    return true;
8885c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice}
8895c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice
890d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
891d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen// It can optionally update the condition flags based on the value.
89228070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chenbool
8937bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
89428070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen{
89528070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen#if 0
89628070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen    // ARM pseudo code...
89728070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen    if (ConditionPassed())
89828070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen    {
89928070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen        EncodingSpecificOperations();
90028070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen        result = NOT(imm32);
90128070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
90228070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
90328070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen        else
90428070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen            R[d] = result;
90528070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen            if setflags then
90628070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen                APSR.N = result<31>;
90728070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen                APSR.Z = IsZeroBit(result);
90828070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen                APSR.C = carry;
90928070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen                // APSR.V unchanged
91028070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen    }
91128070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen#endif
91233bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen
9137bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
91433bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen    {
91533bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        uint32_t Rd; // the destination register
916357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
917357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
91833bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        bool setflags;
91933bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        switch (encoding) {
92033bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        case eEncodingT1:
92133bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen            Rd = Bits32(opcode, 11, 8);
92233bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen            setflags = BitIsSet(opcode, 20);
923d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
92433bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen            break;
92533bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        case eEncodingA1:
92633bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen            Rd = Bits32(opcode, 15, 12);
92733bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen            setflags = BitIsSet(opcode, 20);
928d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
929d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
930d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
931d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            if (Rd == 15 && setflags)
932d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen                return false;
93333bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen            break;
93433bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        default:
93533bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen            return false;
93633bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        }
93733bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        uint32_t result = ~imm32;
93833bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen
93933bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen        // The context specifies that an immediate is to be moved into Rd.
9409bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
9419bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextImmediate;
9429bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetNoArgs ();
943ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen
94410530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
945ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            return false;
94633bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen    }
94733bf6ab6b5771f1bae225edcc2115772d9d041acJohnny Chen    return true;
94828070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen}
94928070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen
950d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
951d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen// It can optionally update the condition flags based on the result.
952d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chenbool
9537bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
954d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen{
955d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen#if 0
956d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen    // ARM pseudo code...
957d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen    if (ConditionPassed())
958d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen    {
959d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        EncodingSpecificOperations();
960d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
961d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        result = NOT(shifted);
962d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
963d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
964d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        else
965d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            R[d] = result;
966d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            if setflags then
967d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen                APSR.N = result<31>;
968d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen                APSR.Z = IsZeroBit(result);
969d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen                APSR.C = carry;
970d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen                // APSR.V unchanged
971d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen    }
972d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen#endif
973d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen
9747bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
975d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen    {
976d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        uint32_t Rm; // the source register
977d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        uint32_t Rd; // the destination register
978d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        ARM_ShifterType shift_t;
979d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
980d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        bool setflags;
981d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        uint32_t carry; // the carry bit after the shift operation
982d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        switch (encoding) {
983d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        case eEncodingT1:
984d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            Rd = Bits32(opcode, 2, 0);
985d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            Rm = Bits32(opcode, 5, 3);
986d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            setflags = !InITBlock();
987d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            shift_t = SRType_LSL;
988d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            shift_n = 0;
989d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            if (InITBlock())
990d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen                return false;
991d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            break;
992d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        case eEncodingT2:
993d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            Rd = Bits32(opcode, 11, 8);
994d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            Rm = Bits32(opcode, 3, 0);
995d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            setflags = BitIsSet(opcode, 20);
9963dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
997d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
998ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            if (BadReg(Rd) || BadReg(Rm))
999d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen                return false;
1000ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
1001d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        case eEncodingA1:
1002d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            Rd = Bits32(opcode, 15, 12);
1003d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            Rm = Bits32(opcode, 3, 0);
1004d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            setflags = BitIsSet(opcode, 20);
10053dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
1006d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            break;
1007d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        default:
1008d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            return false;
1009d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        }
10107bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        bool success = false;
1011d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        uint32_t value = ReadCoreReg(Rm, &success);
1012d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        if (!success)
1013d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            return false;
1014d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen
1015d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1016d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        uint32_t result = ~shifted;
1017d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen
1018d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        // The context specifies that an immediate is to be moved into Rd.
1019d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        EmulateInstruction::Context context;
1020d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
1021d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        context.SetNoArgs ();
1022d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen
1023d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1024d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen            return false;
1025d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen    }
1026d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen    return true;
1027d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen}
1028d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen
1029788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1030788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen// LDR (literal)
10312b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
10327bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
1033788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen{
1034788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen#if 0
1035788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen    // ARM pseudo code...
1036788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen    if (ConditionPassed())
1037788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen    {
1038788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1039788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        base = Align(PC,4);
1040788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        address = if add then (base + imm32) else (base - imm32);
1041788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        data = MemU[address,4];
1042788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        if t == 15 then
1043bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1044bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        elsif UnalignedSupport() || address<1:0> = '00' then
1045788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen            R[t] = data;
1046788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        else // Can only apply before ARMv7
1047788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen            if CurrentInstrSet() == InstrSet_ARM then
1048788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen                R[t] = ROR(data, 8*UInt(address<1:0>));
1049788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen            else
1050788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen                R[t] = bits(32) UNKNOWN;
1051788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen    }
1052788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen#endif
1053788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen
10547bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
1055788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen    {
10567bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        bool success = false;
1057e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const uint32_t pc = ReadCoreReg(PC_REG, &success);
1058788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        if (!success)
1059788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen            return false;
1060809742eb9fcff84b07b72f06838f927d4fccfa49Johnny Chen
1061809742eb9fcff84b07b72f06838f927d4fccfa49Johnny Chen        // PC relative immediate load context
10629bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
10639bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
10649bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register pc_reg;
10659bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
10669bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (pc_reg, 0);
10679bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice
1068c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        uint32_t Rt;    // the destination register
1069788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        uint32_t imm32; // immediate offset from the PC
1070c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        bool add;       // +imm32 or -imm32?
1071c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        addr_t base;    // the base address
1072c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        addr_t address; // the PC relative address
1073788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        uint32_t data;  // the literal data value from the PC relative load
1074788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        switch (encoding) {
1075788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        case eEncodingT1:
1076c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            Rt = Bits32(opcode, 10, 8);
1077788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen            imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1078c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            add = true;
1079c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            break;
1080c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        case eEncodingT2:
1081c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            Rt = Bits32(opcode, 15, 12);
1082c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1083c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            add = BitIsSet(opcode, 23);
1084098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (Rt == 15 && InITBlock() && !LastInITBlock())
1085c9de910d61f0471d18fced716fc10681ef432010Johnny Chen                return false;
1086788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen            break;
1087788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        default:
1088788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen            return false;
1089788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        }
1090c9de910d61f0471d18fced716fc10681ef432010Johnny Chen
1091e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        base = Align(pc, 4);
1092c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        if (add)
1093c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            address = base + imm32;
1094c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        else
1095c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            address = base - imm32;
1096e39f22d1a369866808b8739c3cec15063d806833Johnny Chen
1097e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        context.SetRegisterPlusOffset(pc_reg, address - base);
1098cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice        data = MemURead(context, address, 4, 0, &success);
1099788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen        if (!success)
1100809742eb9fcff84b07b72f06838f927d4fccfa49Johnny Chen            return false;
1101c9de910d61f0471d18fced716fc10681ef432010Johnny Chen
1102c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        if (Rt == 15)
1103c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        {
1104c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            if (Bits32(address, 1, 0) == 0)
1105c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            {
1106c9de910d61f0471d18fced716fc10681ef432010Johnny Chen                // In ARMv5T and above, this is an interworking branch.
1107668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen                if (!LoadWritePC(context, data))
1108c9de910d61f0471d18fced716fc10681ef432010Johnny Chen                    return false;
1109c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            }
1110c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            else
1111c9de910d61f0471d18fced716fc10681ef432010Johnny Chen                return false;
1112c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        }
1113c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1114c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        {
1115c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1116c9de910d61f0471d18fced716fc10681ef432010Johnny Chen                return false;
1117c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        }
1118c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        else // We don't handle ARM for now.
1119c9de910d61f0471d18fced716fc10681ef432010Johnny Chen            return false;
1120c9de910d61f0471d18fced716fc10681ef432010Johnny Chen
1121788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen    }
1122788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen    return true;
1123788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen}
1124788e05550dfd52699d427bb44c9716f320d2adacJohnny Chen
11255b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen// An add operation to adjust the SP.
1126fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen// ADD (SP plus immediate)
11272b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
11287bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
1129fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen{
1130fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen#if 0
1131fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    // ARM pseudo code...
1132fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    if (ConditionPassed())
1133fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    {
1134fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        EncodingSpecificOperations();
1135bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1136fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        if d == 15 then // Can only occur for ARM encoding
1137fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
1138fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        else
1139fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen            R[d] = result;
1140fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen            if setflags then
1141fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen                APSR.N = result<31>;
1142fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen                APSR.Z = IsZeroBit(result);
1143fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen                APSR.C = carry;
1144fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen                APSR.V = overflow;
1145fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    }
1146fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen#endif
1147fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen
1148fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    bool success = false;
1149fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen
11507bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
1151fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    {
1152e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
1153fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        if (!success)
1154fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen            return false;
1155fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        uint32_t imm32; // the immediate operand
1156e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        uint32_t d;
1157e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        bool setflags;
1158e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        switch (encoding)
1159e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        {
1160e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice            case eEncodingT1:
1161bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1162e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                d = Bits32 (opcode, 10, 8);
1163e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                setflags = false;
1164e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                imm32 = (Bits32 (opcode, 7, 0) << 2);
1165e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice
1166e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                break;
1167e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice
1168e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice            case eEncodingT2:
1169bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1170e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                d = 13;
1171e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                setflags = false;
1172e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1173e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice
1174e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                break;
1175e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice
1176e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice            default:
1177e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                return false;
1178fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        }
1179fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        addr_t sp_offset = imm32;
1180fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen        addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1181fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen
11829bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
11839bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextAdjustStackPointer;
11849bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetImmediateSigned (sp_offset);
1185fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen
1186e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        if (d == 15)
1187e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        {
1188e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice            if (!ALUWritePC (context, addr))
1189e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                return false;
1190e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        }
1191e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        else
1192e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        {
1193e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1194e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice                return false;
1195e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        }
1196fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    }
1197fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen    return true;
1198fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen}
1199fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen
1200fdd179e6f94128924473c3cce1123ad1c749015dJohnny Chen// An add operation to adjust the SP.
12015b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen// ADD (SP plus register)
12022b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
12037bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
12045b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen{
12055b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen#if 0
12065b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    // ARM pseudo code...
12075b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    if (ConditionPassed())
12085b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    {
12095b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        EncodingSpecificOperations();
12105b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1211bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
12125b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        if d == 15 then
12135b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
12145b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        else
12155b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            R[d] = result;
12165b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            if setflags then
12175b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen                APSR.N = result<31>;
12185b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen                APSR.Z = IsZeroBit(result);
12195b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen                APSR.C = carry;
12205b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen                APSR.V = overflow;
12215b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    }
12225b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen#endif
12235b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen
12245b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    bool success = false;
12255b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen
12267bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
12275b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    {
1228e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
12295b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        if (!success)
12305b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            return false;
12315b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        uint32_t Rm; // the second operand
12325b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        switch (encoding) {
12335b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        case eEncodingT2:
12345b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            Rm = Bits32(opcode, 6, 3);
12355b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            break;
12365b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        default:
12375b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            return false;
12385b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        }
1239e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        int32_t reg_value = ReadCoreReg(Rm, &success);
12405b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        if (!success)
12415b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            return false;
12425b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen
12435b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen        addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
12445b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen
12459bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
12469bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextAdjustStackPointer;
12479bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetImmediateSigned (reg_value);
12485b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen
12492b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
12505b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen            return false;
12515b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    }
12525b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen    return true;
12535b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen}
12545b442b7326d1c96eaf93290bb8285635579eb38fJohnny Chen
12559b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
12569b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen// at a PC-relative address, and changes instruction set from ARM to Thumb, or
12579b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen// from Thumb to ARM.
12589b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen// BLX (immediate)
12599b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chenbool
12607bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
12619b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen{
12629b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#if 0
12639b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    // ARM pseudo code...
12649b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    if (ConditionPassed())
12659b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    {
12669b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        EncodingSpecificOperations();
12679b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        if CurrentInstrSet() == InstrSet_ARM then
12689b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            LR = PC - 4;
12699b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        else
12709b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            LR = PC<31:1> : '1';
12719b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        if targetInstrSet == InstrSet_ARM then
12729b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            targetAddress = Align(PC,4) + imm32;
12739b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        else
12749b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            targetAddress = PC + imm32;
12759b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        SelectInstrSet(targetInstrSet);
12769b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        BranchWritePC(targetAddress);
12779b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    }
12789b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#endif
12799b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen
12807bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    bool success = true;
12819b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen
12827bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
12839b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    {
12849bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
12859bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRelativeBranchImmediate;
1286e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const uint32_t pc = ReadCoreReg(PC_REG, &success);
12879b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        if (!success)
12889b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
128953ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        addr_t lr; // next instruction address
129053ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        addr_t target; // target address
12919b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        int32_t imm32; // PC-relative offset
12929b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        switch (encoding) {
1293d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen        case eEncodingT1:
1294d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            {
1295e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            lr = pc | 1u; // return address
1296bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t S = Bit32(opcode, 26);
1297d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            uint32_t imm10 = Bits32(opcode, 25, 16);
1298bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J1 = Bit32(opcode, 13);
1299bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J2 = Bit32(opcode, 11);
1300d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            uint32_t imm11 = Bits32(opcode, 10, 0);
1301d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            uint32_t I1 = !(J1 ^ S);
1302d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            uint32_t I2 = !(J2 ^ S);
130353ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen            uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
1304d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            imm32 = llvm::SignExtend32<25>(imm25);
1305e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = pc + imm32;
13069bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
1307098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (InITBlock() && !LastInITBlock())
1308ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen                return false;
1309d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            break;
1310d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen            }
13119b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        case eEncodingT2:
13129b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            {
1313e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            lr = pc | 1u; // return address
1314bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t S = Bit32(opcode, 26);
13159b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            uint32_t imm10H = Bits32(opcode, 25, 16);
1316bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J1 = Bit32(opcode, 13);
1317bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J2 = Bit32(opcode, 11);
13189b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            uint32_t imm10L = Bits32(opcode, 10, 1);
13199b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            uint32_t I1 = !(J1 ^ S);
13209b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            uint32_t I2 = !(J2 ^ S);
132153ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen            uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
13229b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            imm32 = llvm::SignExtend32<25>(imm25);
1323e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = Align(pc, 4) + imm32;
13249bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
1325098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (InITBlock() && !LastInITBlock())
1326ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen                return false;
13279b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            break;
13289b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            }
1329c47d0caf319bef8b7263b60366ad62606a2ccb20Johnny Chen        case eEncodingA1:
13302b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice            lr = pc - 4; // return address
1331c47d0caf319bef8b7263b60366ad62606a2ccb20Johnny Chen            imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
1332e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = Align(pc, 4) + imm32;
13339bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
1334c47d0caf319bef8b7263b60366ad62606a2ccb20Johnny Chen            break;
13359b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        case eEncodingA2:
13362b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice            lr = pc - 4; // return address
13379b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
1338e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = pc + imm32;
13399bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
13409b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            break;
13419b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        default:
13429b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
13439b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        }
13449b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
13459b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
13469ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        if (!BranchWritePC(context, target))
13479b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
13489b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    }
13499b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    return true;
13509b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen}
13519b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen
13529b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen// Branch with Link and Exchange (register) calls a subroutine at an address and
13539b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen// instruction set specified by a register.
13549b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen// BLX (register)
13559b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chenbool
13567bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
13579b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen{
13589b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#if 0
13599b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    // ARM pseudo code...
13609b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    if (ConditionPassed())
13619b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    {
13629b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        EncodingSpecificOperations();
13639b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        target = R[m];
13649b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        if CurrentInstrSet() == InstrSet_ARM then
13659b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            next_instr_addr = PC - 4;
13669b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            LR = next_instr_addr;
13679b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        else
13689b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            next_instr_addr = PC - 2;
1369bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            LR = next_instr_addr<31:1> : '1';
13709b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        BXWritePC(target);
13719b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    }
13729b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen#endif
13739b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen
13749b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    bool success = false;
13759b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen
13767bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
13779b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    {
13789bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
13799bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1380e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const uint32_t pc = ReadCoreReg(PC_REG, &success);
13819b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        addr_t lr; // next instruction address
13829b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        if (!success)
13839b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
13849b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        uint32_t Rm; // the register with the target address
13859b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        switch (encoding) {
13869b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        case eEncodingT1:
1387e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            lr = (pc - 2) | 1u; // return address
13889b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            Rm = Bits32(opcode, 6, 3);
13899b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            // if m == 15 then UNPREDICTABLE;
13909b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            if (Rm == 15)
13919b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen                return false;
1392098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (InITBlock() && !LastInITBlock())
1393ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen                return false;
13949b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            break;
13959b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        case eEncodingA1:
1396e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            lr = pc - 4; // return address
13979b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            Rm = Bits32(opcode, 3, 0);
13989b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            // if m == 15 then UNPREDICTABLE;
13999b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            if (Rm == 15)
14009b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen                return false;
1401b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            break;
14029b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        default:
14039b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
14049b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        }
1405e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        addr_t target = ReadCoreReg (Rm, &success);
1406ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        if (!success)
1407ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            return false;
14089bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
14099bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
14109bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegister (dwarf_reg);
14119b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
14129b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
1413668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen        if (!BXWritePC(context, target))
14149b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen            return false;
14159b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    }
14169b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen    return true;
14179b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen}
14189b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen
1419ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen// Branch and Exchange causes a branch to an address and instruction set specified by a register.
1420ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chenbool
14217bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
1422ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen{
1423ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen#if 0
1424ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen    // ARM pseudo code...
1425ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen    if (ConditionPassed())
1426ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen    {
1427ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        EncodingSpecificOperations();
1428ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        BXWritePC(R[m]);
1429ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen    }
1430ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen#endif
1431ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen
14327bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
1433ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen    {
14349bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
14359bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1436ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        uint32_t Rm; // the register with the target address
1437ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        switch (encoding) {
1438ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        case eEncodingT1:
1439ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            Rm = Bits32(opcode, 6, 3);
1440098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen            if (InITBlock() && !LastInITBlock())
1441ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen                return false;
1442ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            break;
1443ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        case eEncodingA1:
1444ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            Rm = Bits32(opcode, 3, 0);
1445ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            break;
1446ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        default:
1447ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            return false;
1448ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        }
14497bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        bool success = false;
1450e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        addr_t target = ReadCoreReg (Rm, &success);
1451ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        if (!success)
1452ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            return false;
14539bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice
14549bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
14559bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1456668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen        context.SetRegister (dwarf_reg);
1457668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen        if (!BXWritePC(context, target))
1458ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen            return false;
1459ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen    }
1460ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen    return true;
1461ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen}
1462ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen
146359e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
146459e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen// address and instruction set specified by a register as though it were a BX instruction.
146559e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen//
146659e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen// TODO: Emulate Jazelle architecture?
146759e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen//       We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
146859e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chenbool
14697bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
147059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen{
147159e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen#if 0
147259e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen    // ARM pseudo code...
147359e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen    if (ConditionPassed())
147459e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen    {
147559e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        EncodingSpecificOperations();
1476bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
147759e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            BXWritePC(R[m]);
147859e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        else
147959e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            if JazelleAcceptsExecution() then
148059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen                SwitchToJazelleExecution();
148159e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            else
148259e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen                SUBARCHITECTURE_DEFINED handler call;
148359e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen    }
148459e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen#endif
148559e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen
14867bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
148759e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen    {
148859e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        EmulateInstruction::Context context;
148959e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
149059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        uint32_t Rm; // the register with the target address
149159e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        switch (encoding) {
149259e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        case eEncodingT1:
149359e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            Rm = Bits32(opcode, 19, 16);
149459e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            if (BadReg(Rm))
149559e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen                return false;
149659e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            if (InITBlock() && !LastInITBlock())
149759e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen                return false;
149859e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            break;
149959e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        case eEncodingA1:
150059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            Rm = Bits32(opcode, 3, 0);
150159e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            if (Rm == 15)
150259e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen                return false;
150359e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            break;
150459e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        default:
150559e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            return false;
150659e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        }
15077bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        bool success = false;
150859e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        addr_t target = ReadCoreReg (Rm, &success);
150959e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        if (!success)
151059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            return false;
151159e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen
151259e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        Register dwarf_reg;
151359e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
151459e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        context.SetRegister (dwarf_reg);
151559e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        if (!BXWritePC(context, target))
151659e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen            return false;
151759e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen    }
151859e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen    return true;
151959e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen}
152059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen
15210d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen// Set r7 to point to some ip offset.
15220d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen// SUB (immediate)
15232b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
15247bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
15250d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen{
15260d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen#if 0
15270d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    // ARM pseudo code...
15280d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    if (ConditionPassed())
15290d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    {
15300d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        EncodingSpecificOperations();
1531bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
15320d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        if d == 15 then // Can only occur for ARM encoding
15330d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen           ALUWritePC(result); // setflags is always FALSE here
15340d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        else
15350d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            R[d] = result;
15360d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            if setflags then
15370d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.N = result<31>;
15380d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.Z = IsZeroBit(result);
15390d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.C = carry;
15400d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.V = overflow;
15410d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    }
15420d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen#endif
15430d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
15447bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
15450d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    {
15467bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        bool success = false;
1547e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t ip = ReadCoreReg (12, &success);
15480d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        if (!success)
15490d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            return false;
15500d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        uint32_t imm32;
15510d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        switch (encoding) {
15520d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        case eEncodingA1:
15530d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
15540d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            break;
15550d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        default:
15560d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            return false;
15570d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        }
15580d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        addr_t ip_offset = imm32;
15590d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        addr_t addr = ip - ip_offset; // the adjusted ip value
15600d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
15619bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
15629bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
15639bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
15649bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
15659bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
15660d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
15672b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
15680d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            return false;
15690d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    }
15700d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    return true;
15710d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen}
15720d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
15730d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen// Set ip to point to some stack offset.
15740d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen// SUB (SP minus immediate)
15752b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
15767bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
15770d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen{
15780d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen#if 0
15790d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    // ARM pseudo code...
15800d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    if (ConditionPassed())
15810d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    {
15820d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        EncodingSpecificOperations();
1583bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
15840d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        if d == 15 then // Can only occur for ARM encoding
15850d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen           ALUWritePC(result); // setflags is always FALSE here
15860d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        else
15870d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            R[d] = result;
15880d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            if setflags then
15890d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.N = result<31>;
15900d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.Z = IsZeroBit(result);
15910d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.C = carry;
15920d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen                APSR.V = overflow;
15930d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    }
15940d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen#endif
15950d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
15967bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
15970d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    {
15987bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        bool success = false;
1599e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
16000d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        if (!success)
16010d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            return false;
16020d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        uint32_t imm32;
16030d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        switch (encoding) {
16040d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        case eEncodingA1:
16050d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
16060d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            break;
16070d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        default:
16080d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            return false;
16090d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        }
16100d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        addr_t sp_offset = imm32;
16110d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen        addr_t addr = sp - sp_offset; // the adjusted stack pointer value
16120d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
16139bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
16149bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
16159bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
16169bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
16179bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
16180d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
16192b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
16200d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen            return false;
16210d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    }
16220d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen    return true;
16230d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen}
16240d0148e3b359e7be24ae00cb484503241f71f47cJohnny Chen
1625c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen// This instruction subtracts an immediate value from the SP value, and writes
1626c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen// the result to the destination register.
1627c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen//
1628c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
16292b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
16307bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
16314c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen{
16324c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen#if 0
16334c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    // ARM pseudo code...
16344c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    if (ConditionPassed())
16354c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    {
16364c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        EncodingSpecificOperations();
1637bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
163815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if d == 15 then        // Can only occur for ARM encoding
1639799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen           ALUWritePC(result); // setflags is always FALSE here
16404c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        else
16414c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen            R[d] = result;
16424c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen            if setflags then
16434c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen                APSR.N = result<31>;
16444c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen                APSR.Z = IsZeroBit(result);
16454c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen                APSR.C = carry;
16464c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen                APSR.V = overflow;
16474c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    }
16484c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen#endif
16494c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen
16504c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    bool success = false;
16517bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
16524c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    {
1653e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
16544c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        if (!success)
16554c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen            return false;
1656c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen
1657c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        uint32_t Rd;
1658c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        bool setflags;
16594c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        uint32_t imm32;
16604c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        switch (encoding) {
1661e44550232e767c692c25eb933fd88d7b857a6d55Johnny Chen        case eEncodingT1:
1662c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            Rd = 13;
1663c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            setflags = false;
1664a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1665ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
166660c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen        case eEncodingT2:
1667c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            Rd = Bits32(opcode, 11, 8);
1668c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            setflags = BitIsSet(opcode, 20);
166960c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen            imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
1670c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            if (Rd == 15 && setflags)
16717bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                return EmulateCMPImm(opcode, eEncodingT2);
1672c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            if (Rd == 15 && !setflags)
1673c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen                return false;
167460c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen            break;
167560c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen        case eEncodingT3:
1676c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            Rd = Bits32(opcode, 11, 8);
1677c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            setflags = false;
167860c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen            imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
167915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            if (Rd == 15)
168015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen                return false;
168160c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen            break;
16824c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        case eEncodingA1:
1683c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            Rd = Bits32(opcode, 15, 12);
1684c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            setflags = BitIsSet(opcode, 20);
168560c0d627a506752b3b9ef5c0b11f1640b739b9ffJohnny Chen            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
168615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
168715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
168815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            if (Rd == 15 && setflags)
168915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen                return false;
16904c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen            break;
16914c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        default:
16924c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen            return false;
16934c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen        }
1694c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1695c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen
16969bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
1697c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        if (Rd == 13)
1698c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        {
16992b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice            uint64_t imm64 = imm32;  // Need to expand it to 64 bits before attempting to negate it, or the wrong
17002b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice                                     // value gets passed down to context.SetImmediateSigned.
1701c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            context.type = EmulateInstruction::eContextAdjustStackPointer;
17022b03ed8c697040c107d9c0c7d810fcb2e5c7fb8dCaroline Tice            context.SetImmediateSigned (-imm64); // the stack pointer offset
1703c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        }
1704c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        else
1705c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        {
1706c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            context.type = EmulateInstruction::eContextImmediate;
1707c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen            context.SetNoArgs ();
1708c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        }
1709c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen
1710c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
17114c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen            return false;
17124c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    }
17134c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen    return true;
17144c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen}
17154c0e0bc24aa6a4dc2c18a6f6d01b9217dee5c4bfJohnny Chen
171608c25e855749d94d89ff162a30ff46c9a2911aceJohnny Chen// A store operation to the stack that also updates the SP.
17172b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
17187bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
1719ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen{
1720ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen#if 0
1721ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    // ARM pseudo code...
1722ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    if (ConditionPassed())
1723ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    {
1724ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        EncodingSpecificOperations();
1725ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1726ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        address = if index then offset_addr else R[n];
1727ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1728ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        if wback then R[n] = offset_addr;
1729ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    }
1730ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen#endif
1731ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen
1732ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    bool success = false;
1733ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen
17347bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
1735ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    {
17362b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        const uint32_t addr_byte_size = GetAddressByteSize();
1737e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
1738ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        if (!success)
1739ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen            return false;
174091d998659e5d38aeebb3b8ebe2fb596907bd0548Johnny Chen        uint32_t Rt; // the source register
1741ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        uint32_t imm12;
17423e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        uint32_t Rn;  // This function assumes Rn is the SP, but we should verify that.
17433e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice
17443e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        bool index;
17453e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        bool add;
17463e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        bool wback;
1747ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        switch (encoding) {
1748ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        case eEncodingA1:
1749108d5aaa1379f154e459d82aa482b4f2ddf134c7Johnny Chen            Rt = Bits32(opcode, 15, 12);
1750108d5aaa1379f154e459d82aa482b4f2ddf134c7Johnny Chen            imm12 = Bits32(opcode, 11, 0);
17513e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            Rn = Bits32 (opcode, 19, 16);
17523e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice
17533e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            if (Rn != 13) // 13 is the SP reg on ARM.  Verify that Rn == SP.
17543e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice                return false;
17553e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice
17563e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            index = BitIsSet (opcode, 24);
17573e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            add = BitIsSet (opcode, 23);
17583e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
17593e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice
17603e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            if (wback && ((Rn == 15) || (Rn == Rt)))
17613e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice                return false;
1762ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen            break;
1763ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        default:
1764ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen            return false;
1765ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        }
17663e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        addr_t offset_addr;
17673e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        if (add)
17683e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            offset_addr = sp + imm12;
17693e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        else
17703e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            offset_addr = sp - imm12;
17713e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice
17723e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        addr_t addr;
17733e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        if (index)
17743e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            addr = offset_addr;
17753e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        else
17763e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            addr = sp;
1777ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen
17789bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
17799bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextPushRegisterOnStack;
17803e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        Register sp_reg;
17813e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
17823e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        context.SetRegisterPlusOffset (sp_reg, addr - sp);
178391d998659e5d38aeebb3b8ebe2fb596907bd0548Johnny Chen        if (Rt != 15)
1784ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        {
1785e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            uint32_t reg_value = ReadCoreReg(Rt, &success);
1786ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen            if (!success)
1787ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen                return false;
1788cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            if (!MemUWrite (context, addr, reg_value, addr_byte_size))
1789ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen                return false;
1790ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        }
1791ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        else
1792ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        {
1793e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            const uint32_t pc = ReadCoreReg(PC_REG, &success);
1794ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen            if (!success)
1795ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen                return false;
17968d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            if (!MemUWrite (context, addr, pc, addr_byte_size))
1797ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen                return false;
1798ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen        }
1799ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen
18003e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice
18013e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        if (wback)
18023e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        {
18033e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            context.type = EmulateInstruction::eContextAdjustStackPointer;
18043e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            context.SetImmediateSigned (addr - sp);
18053e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
18063e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice                return false;
18073e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        }
1808ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    }
1809ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen    return true;
1810ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen}
1811ce1ca773286c85b4c2a81b99aaa42f46b47e64c2Johnny Chen
181208c25e855749d94d89ff162a30ff46c9a2911aceJohnny Chen// Vector Push stores multiple extension registers to the stack.
181308c25e855749d94d89ff162a30ff46c9a2911aceJohnny Chen// It also updates SP to point to the start of the stored data.
18142b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Claytonbool
18157bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
1816799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen{
1817799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen#if 0
1818799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    // ARM pseudo code...
1819799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    if (ConditionPassed())
1820799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    {
1821799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1822799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        address = SP - imm32;
1823799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        SP = SP - imm32;
1824799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        if single_regs then
1825799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            for r = 0 to regs-1
1826799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                MemA[address,4] = S[d+r]; address = address+4;
1827799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        else
1828799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            for r = 0 to regs-1
1829799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                // Store as two word-aligned words in the correct order for current endianness.
1830799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1831799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1832799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                address = address+8;
1833799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    }
1834799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen#endif
1835799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen
1836799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    bool success = false;
1837799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen
18387bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
1839799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    {
18402b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        const uint32_t addr_byte_size = GetAddressByteSize();
1841e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
1842799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        if (!success)
1843799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            return false;
1844799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        bool single_regs;
1845587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint32_t d;     // UInt(D:Vd) or UInt(Vd:D) starting register
1846799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        uint32_t imm32; // stack offset
1847799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        uint32_t regs;  // number of registers
1848799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        switch (encoding) {
1849799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        case eEncodingT1:
1850799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        case eEncodingA1:
1851799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            single_regs = false;
1852bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
1853799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1854799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            // If UInt(imm8) is odd, see "FSTMX".
1855799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            regs = Bits32(opcode, 7, 0) / 2;
1856799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1857799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            if (regs == 0 || regs > 16 || (d + regs) > 32)
1858799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                return false;
1859799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            break;
1860799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        case eEncodingT2:
1861799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        case eEncodingA2:
1862799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            single_regs = true;
1863bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
1864799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1865799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            regs = Bits32(opcode, 7, 0);
1866799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1867799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            if (regs == 0 || regs > 16 || (d + regs) > 32)
1868799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                return false;
1869799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            break;
1870799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        default:
1871799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            return false;
1872799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        }
1873799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1874799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1875799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        addr_t sp_offset = imm32;
1876799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        addr_t addr = sp - sp_offset;
1877799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        uint32_t i;
1878799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen
18799bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
18809bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextPushRegisterOnStack;
18819bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
18829bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
1883bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        Register sp_reg;
1884bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1885bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        for (i=0; i<regs; ++i)
1886799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        {
1887bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            dwarf_reg.num = start_reg + d + i;
1888bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
1889799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            // uint64_t to accommodate 64-bit registers.
18909bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
1891799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            if (!success)
1892799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                return false;
1893cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            if (!MemAWrite (context, addr, reg_value, reg_byte_size))
1894799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen                return false;
1895799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            addr += reg_byte_size;
1896799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        }
1897799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen
1898799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen        context.type = EmulateInstruction::eContextAdjustStackPointer;
18999bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetImmediateSigned (-sp_offset);
1900799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen
19012b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1902799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen            return false;
1903799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    }
1904799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen    return true;
1905799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen}
1906799dfd0f6946879ef5035f131c0f3f04145a68ceJohnny Chen
1907587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen// Vector Pop loads multiple extension registers from the stack.
1908587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen// It also updates SP to point just above the loaded data.
1909587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chenbool
19107bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
1911587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen{
1912587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen#if 0
1913587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    // ARM pseudo code...
1914587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    if (ConditionPassed())
1915587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    {
1916587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1917587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        address = SP;
1918587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        SP = SP + imm32;
1919587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        if single_regs then
1920587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            for r = 0 to regs-1
1921587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                S[d+r] = MemA[address,4]; address = address+4;
1922587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        else
1923587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            for r = 0 to regs-1
1924587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1925587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                // Combine the word-aligned words in the correct order for current endianness.
1926587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1927587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    }
1928587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen#endif
1929587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen
1930587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    bool success = false;
1931587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen
19327bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
1933587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    {
1934587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        const uint32_t addr_byte_size = GetAddressByteSize();
1935e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const addr_t sp = ReadCoreReg (SP_REG, &success);
1936587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        if (!success)
1937587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            return false;
1938587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        bool single_regs;
1939587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint32_t d;     // UInt(D:Vd) or UInt(Vd:D) starting register
1940587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint32_t imm32; // stack offset
1941587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint32_t regs;  // number of registers
1942587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        switch (encoding) {
1943587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        case eEncodingT1:
1944587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        case eEncodingA1:
1945587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            single_regs = false;
1946bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
1947587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1948587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            // If UInt(imm8) is odd, see "FLDMX".
1949587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            regs = Bits32(opcode, 7, 0) / 2;
1950587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1951587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            if (regs == 0 || regs > 16 || (d + regs) > 32)
1952587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                return false;
1953587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            break;
1954587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        case eEncodingT2:
1955587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        case eEncodingA2:
1956587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            single_regs = true;
1957bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
1958587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1959587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            regs = Bits32(opcode, 7, 0);
1960587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1961587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            if (regs == 0 || regs > 16 || (d + regs) > 32)
1962587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                return false;
1963587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            break;
1964587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        default:
1965587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            return false;
1966587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        }
1967587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1968587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1969587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        addr_t sp_offset = imm32;
1970587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        addr_t addr = sp;
1971587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint32_t i;
1972587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        uint64_t data; // uint64_t to accomodate 64-bit registers.
1973587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen
19749bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
19759bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextPopRegisterOffStack;
19769bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
19779bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
1978bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        Register sp_reg;
1979bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1980bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        for (i=0; i<regs; ++i)
1981587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        {
1982bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            dwarf_reg.num = start_reg + d + i;
1983bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            context.SetRegisterPlusOffset (sp_reg, addr - sp);
1984cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            data = MemARead(context, addr, reg_byte_size, 0, &success);
1985587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            if (!success)
1986587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                return false;
19879bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
1988587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen                return false;
1989587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            addr += reg_byte_size;
1990587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        }
1991587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen
1992587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        context.type = EmulateInstruction::eContextAdjustStackPointer;
19939bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetImmediateSigned (sp_offset);
1994587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen
1995587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1996587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen            return false;
1997587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    }
1998587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen    return true;
1999587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen}
2000587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen
2001b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen// SVC (previously SWI)
2002b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chenbool
20037bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
2004b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen{
2005b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen#if 0
2006b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    // ARM pseudo code...
2007b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    if (ConditionPassed())
2008b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    {
2009b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        EncodingSpecificOperations();
2010b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        CallSupervisor();
2011b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    }
2012b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen#endif
2013b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen
2014b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    bool success = false;
2015b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen
20167bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
2017b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    {
2018e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const uint32_t pc = ReadCoreReg(PC_REG, &success);
2019b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        addr_t lr; // next instruction address
2020b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        if (!success)
2021b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            return false;
2022b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        uint32_t imm32; // the immediate constant
2023b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        uint32_t mode;  // ARM or Thumb mode
2024b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        switch (encoding) {
2025b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        case eEncodingT1:
2026b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            lr = (pc + 2) | 1u; // return address
2027b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            imm32 = Bits32(opcode, 7, 0);
2028b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            mode = eModeThumb;
2029b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            break;
2030b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        case eEncodingA1:
2031b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            lr = pc + 4; // return address
2032b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            imm32 = Bits32(opcode, 23, 0);
2033b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            mode = eModeARM;
2034b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            break;
2035b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        default:
2036b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            return false;
2037b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        }
20389bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice
20399bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
20409bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextSupervisorCall;
20419bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetModeAndImmediate (mode, imm32);
2042b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2043b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen            return false;
2044b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    }
2045b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen    return true;
2046b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen}
2047b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen
2048c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen// If Then makes up to four following instructions (the IT block) conditional.
2049c315f860b343cf4a143f43c7d570d151989abb46Johnny Chenbool
20507bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
2051c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen{
2052c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen#if 0
2053c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    // ARM pseudo code...
2054c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    EncodingSpecificOperations();
2055c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    ITSTATE.IT<7:0> = firstcond:mask;
2056c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen#endif
2057c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen
2058c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    m_it_session.InitIT(Bits32(opcode, 7, 0));
2059c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    return true;
2060c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen}
2061c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen
20623b620b38cd170c20ea607585021ab2ab50286943Johnny Chen// Branch causes a branch to a target address.
20633b620b38cd170c20ea607585021ab2ab50286943Johnny Chenbool
20647bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
20653b620b38cd170c20ea607585021ab2ab50286943Johnny Chen{
20663b620b38cd170c20ea607585021ab2ab50286943Johnny Chen#if 0
20673b620b38cd170c20ea607585021ab2ab50286943Johnny Chen    // ARM pseudo code...
20683b620b38cd170c20ea607585021ab2ab50286943Johnny Chen    if (ConditionPassed())
20693b620b38cd170c20ea607585021ab2ab50286943Johnny Chen    {
20703b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        EncodingSpecificOperations();
20713b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        BranchWritePC(PC + imm32);
20723b620b38cd170c20ea607585021ab2ab50286943Johnny Chen    }
20733b620b38cd170c20ea607585021ab2ab50286943Johnny Chen#endif
20743b620b38cd170c20ea607585021ab2ab50286943Johnny Chen
20753b620b38cd170c20ea607585021ab2ab50286943Johnny Chen    bool success = false;
20763b620b38cd170c20ea607585021ab2ab50286943Johnny Chen
20777bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
20789ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    {
20799bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
20809bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2081e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        const uint32_t pc = ReadCoreReg(PC_REG, &success);
20829ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        if (!success)
20839ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            return false;
208453ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        addr_t target; // target address
20859ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        int32_t imm32; // PC-relative offset
20869ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        switch (encoding) {
20879ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        case eEncodingT1:
20889ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
20899ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
2090e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = pc + imm32;
20919bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
20929ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            break;
20939ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        case eEncodingT2:
20949ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
2095e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = pc + imm32;
20969bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
20979ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            break;
20989ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        case eEncodingT3:
20999ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
21009ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            {
2101bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t S = Bit32(opcode, 26);
21029ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            uint32_t imm6 = Bits32(opcode, 21, 16);
2103bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J1 = Bit32(opcode, 13);
2104bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J2 = Bit32(opcode, 11);
21059ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            uint32_t imm11 = Bits32(opcode, 10, 0);
210653ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen            uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
21079ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            imm32 = llvm::SignExtend32<21>(imm21);
2108e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = pc + imm32;
21099bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
21109ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            break;
21119ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            }
21129ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        case eEncodingT4:
21139ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            {
2114bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t S = Bit32(opcode, 26);
21159ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            uint32_t imm10 = Bits32(opcode, 25, 16);
2116bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J1 = Bit32(opcode, 13);
2117bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            uint32_t J2 = Bit32(opcode, 11);
21189ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            uint32_t imm11 = Bits32(opcode, 10, 0);
21199ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            uint32_t I1 = !(J1 ^ S);
21209ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            uint32_t I2 = !(J2 ^ S);
212153ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen            uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
21229ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            imm32 = llvm::SignExtend32<25>(imm25);
2123e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = pc + imm32;
21249bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
21259ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            break;
21269ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            }
21279ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        case eEncodingA1:
21289ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2129e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            target = pc + imm32;
21309bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
21319ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            break;
21329ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        default:
21339ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            return false;
21349ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        }
21359ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        if (!BranchWritePC(context, target))
21369ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen            return false;
21379ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    }
21389ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    return true;
21393b620b38cd170c20ea607585021ab2ab50286943Johnny Chen}
21403b620b38cd170c20ea607585021ab2ab50286943Johnny Chen
214153ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
214253ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen// zero and conditionally branch forward a constant value.  They do not affect the condition flags.
214353ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen// CBNZ, CBZ
214453ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chenbool
21457bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
214653ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen{
214753ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen#if 0
214853ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    // ARM pseudo code...
214953ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    EncodingSpecificOperations();
215053ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    if nonzero ^ IsZero(R[n]) then
215153ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        BranchWritePC(PC + imm32);
215253ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen#endif
215353ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
215453ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    bool success = false;
215553ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
215653ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    // Read the register value from the operand register Rn.
2157e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
215853ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    if (!success)
215953ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        return false;
216053ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
21619bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    EmulateInstruction::Context context;
21629bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2163e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    const uint32_t pc = ReadCoreReg(PC_REG, &success);
216453ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    if (!success)
216553ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        return false;
216653ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
216753ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    addr_t target;  // target address
216853ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    uint32_t imm32; // PC-relative offset to branch forward
216953ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    bool nonzero;
217053ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    switch (encoding) {
217153ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    case eEncodingT1:
2172bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen        imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
217353ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        nonzero = BitIsSet(opcode, 11);
2174e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        target = pc + imm32;
21759bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
217653ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        break;
217753ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    default:
217853ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        return false;
217953ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    }
218053ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    if (nonzero ^ (reg_val == 0))
218153ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        if (!BranchWritePC(context, target))
218253ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen            return false;
218353ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
218453ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    return true;
218553ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen}
218653ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
218760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
218860299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen// A base register provides a pointer to the table, and a second register supplies an index into the table.
218960299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen// The branch length is twice the value of the byte returned from the table.
219060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen//
219160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
219260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen// A base register provides a pointer to the table, and a second register supplies an index into the table.
219360299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen// The branch length is twice the value of the halfword returned from the table.
219460299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen// TBB, TBH
219560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chenbool
21967bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
219760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen{
219860299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen#if 0
219960299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    // ARM pseudo code...
220060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    EncodingSpecificOperations(); NullCheckIfThumbEE(n);
220160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    if is_tbh then
220260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
220360299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    else
220460299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        halfwords = UInt(MemU[R[n]+R[m], 1]);
220560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    BranchWritePC(PC + 2*halfwords);
220660299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen#endif
220760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
220860299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    bool success = false;
220960299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
221060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    uint32_t Rn;     // the base register which contains the address of the table of branch lengths
221160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    uint32_t Rm;     // the index register which contains an integer pointing to a byte/halfword in the table
221260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    bool is_tbh;     // true if table branch halfword
221360299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    switch (encoding) {
221460299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    case eEncodingT1:
221560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        Rn = Bits32(opcode, 19, 16);
221660299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        Rm = Bits32(opcode, 3, 0);
221760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        is_tbh = BitIsSet(opcode, 4);
221860299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        if (Rn == 13 || BadReg(Rm))
221960299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen            return false;
222060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        if (InITBlock() && !LastInITBlock())
222160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen            return false;
222260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        break;
222360299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    default:
222460299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        return false;
222560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    }
222660299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
222760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    // Read the address of the table from the operand register Rn.
222860299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    // The PC can be used, in which case the table immediately follows this instruction.
2229e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    uint32_t base = ReadCoreReg(Rm, &success);
223060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    if (!success)
223160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        return false;
223260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
223360299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    // the table index
2234e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    uint32_t index = ReadCoreReg(Rm, &success);
223560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    if (!success)
223660299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        return false;
223760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
223860299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    // the offsetted table address
223960299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    addr_t addr = base + (is_tbh ? index*2 : index);
224060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
224160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    // PC-relative offset to branch forward
224260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    EmulateInstruction::Context context;
224360299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    context.type = EmulateInstruction::eContextTableBranchReadMemory;
2244104c8b69863f229033d616245f56243ca51f1de9Johnny Chen    uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
224560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    if (!success)
224660299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        return false;
224760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
2248e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    const uint32_t pc = ReadCoreReg(PC_REG, &success);
224960299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    if (!success)
225060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        return false;
225160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
225260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    // target address
2253e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    addr_t target = pc + offset;
225460299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
225560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
225660299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
225760299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    if (!BranchWritePC(context, target))
225860299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        return false;
225960299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
226060299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen    return true;
226160299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen}
226260299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen
2263dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2264dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice// It can optionally update the condition flags based on the result.
2265dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Ticebool
22667bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
2267dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice{
2268dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice#if 0
2269dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice    if ConditionPassed() then
2270dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        EncodingSpecificOperations();
2271bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2272dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        R[d] = result;
2273dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        if setflags then
2274dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            APSR.N = result<31>;
2275dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            APSR.Z = IsZeroBit(result);
2276dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            APSR.C = carry;
2277dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            APSR.V = overflow;
2278dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice#endif
2279dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2280dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice    bool success = false;
2281dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
22827bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
2283dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice    {
2284dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        uint32_t d;
2285dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        uint32_t n;
2286dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        bool setflags;
2287dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        uint32_t imm32;
2288dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        uint32_t carry_out;
2289dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2290dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        //EncodingSpecificOperations();
2291dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        switch (encoding)
2292dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        {
2293dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            case eEncodingT1:
2294dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2295dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                d = Bits32 (opcode, 2, 0);
2296dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                n = Bits32 (opcode, 5, 3);
2297dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                setflags = !InITBlock();
2298dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                imm32 = Bits32 (opcode, 8,6);
2299dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2300dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                break;
2301dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2302dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            case eEncodingT2:
2303dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2304dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                d = Bits32 (opcode, 10, 8);
2305dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                n = Bits32 (opcode, 10, 8);
2306dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                setflags = !InITBlock();
2307dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                imm32 = Bits32 (opcode, 7, 0);
2308dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2309dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                break;
2310dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2311dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            case eEncodingT3:
2312bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2313bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1101' then SEE ADD (SP plus immediate);
2314bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
2315dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                d = Bits32 (opcode, 11, 8);
2316dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                n = Bits32 (opcode, 19, 16);
2317dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                setflags = BitIsSet (opcode, 20);
2318dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2319dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2320dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                // if BadReg(d) || n == 15 then UNPREDICTABLE;
2321dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                if (BadReg (d) || (n == 15))
2322dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                    return false;
2323dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2324dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                break;
2325dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2326dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            case eEncodingT4:
2327dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            {
2328bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE ADR;
2329bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1101' then SEE ADD (SP plus immediate);
2330dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2331dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                d = Bits32 (opcode, 11, 8);
2332dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                n = Bits32 (opcode, 19, 16);
2333dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                setflags = false;
2334dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                uint32_t i = Bit32 (opcode, 26);
2335dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                uint32_t imm3 = Bits32 (opcode, 14, 12);
2336dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                uint32_t imm8 = Bits32 (opcode, 7, 0);
2337dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                imm32 = (i << 11) | (imm3 << 8) | imm8;
2338dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2339dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                // if BadReg(d) then UNPREDICTABLE;
2340dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                if (BadReg (d))
2341dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                    return false;
2342dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2343dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                break;
2344dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            }
2345dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            default:
2346dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice                return false;
2347dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        }
2348dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2349dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2350dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        if (!success)
2351dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            return false;
2352dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2353bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2354dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2355dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2356dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        Register reg_n;
2357dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2358dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2359dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        EmulateInstruction::Context context;
2360dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        context.type = eContextAddition;
2361dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        context.SetRegisterPlusOffset (reg_n, imm32);
2362dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2363dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        //R[d] = result;
2364dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        //if setflags then
2365dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            //APSR.N = result<31>;
2366dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            //APSR.Z = IsZeroBit(result);
2367dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            //APSR.C = carry;
2368dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            //APSR.V = overflow;
2369dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2370dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice            return false;
2371dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
2372dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice    }
2373dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice    return true;
2374dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice}
2375dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice
23768fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen// This instruction adds an immediate value to a register value, and writes the result to the destination
23778fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen// register.  It can optionally update the condition flags based on the result.
23788fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chenbool
23797bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
23808fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen{
23818fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen#if 0
23828fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen    // ARM pseudo code...
23838fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen    if ConditionPassed() then
23848fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        EncodingSpecificOperations();
23858fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
23868fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        if d == 15 then
23878fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
23888fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        else
23898fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            R[d] = result;
23908fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            if setflags then
23918fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen                APSR.N = result<31>;
23928fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen                APSR.Z = IsZeroBit(result);
23938fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen                APSR.C = carry;
23948fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen                APSR.V = overflow;
23958fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen#endif
23968fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen
23978fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen    bool success = false;
23988fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen
23997bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
24008fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen    {
24018fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        uint32_t Rd, Rn;
24028fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        uint32_t imm32; // the immediate value to be added to the value obtained from Rn
24038fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        bool setflags;
24048fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        switch (encoding)
24058fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        {
24068fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        case eEncodingA1:
24078fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            Rd = Bits32(opcode, 15, 12);
24088fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            Rn = Bits32(opcode, 19, 16);
24098fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            setflags = BitIsSet(opcode, 20);
24108fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
24118fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            break;
24128fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        default:
24138fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            return false;
24148fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        }
24158fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen
24168fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        // Read the first operand.
2417157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
24188fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        if (!success)
24198fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            return false;
24208fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen
24218fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
24228fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen
24238fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        EmulateInstruction::Context context;
24248fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
24258fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        context.SetNoArgs ();
24268fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen
24278fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
24288fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            return false;
24298fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen    }
24308fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen    return true;
24318fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen}
24328fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen
2433d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen// This instruction adds a register value and an optionally-shifted register value, and writes the result
2434d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen// to the destination register. It can optionally update the condition flags based on the result.
243526863dc1d68712415ed56c9953f6fed79b38e131Johnny Chenbool
24367bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
243726863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen{
243826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen#if 0
243926863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    // ARM pseudo code...
244026863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    if ConditionPassed() then
244126863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        EncodingSpecificOperations();
244226863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
244326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
244426863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        if d == 15 then
244526863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
244626863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        else
244726863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            R[d] = result;
244826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            if setflags then
244926863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen                APSR.N = result<31>;
245026863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen                APSR.Z = IsZeroBit(result);
245126863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen                APSR.C = carry;
245226863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen                APSR.V = overflow;
245326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen#endif
245426863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen
245526863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    bool success = false;
245626863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen
24577bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
245826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    {
245926863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        uint32_t Rd, Rn, Rm;
2460d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen        ARM_ShifterType shift_t;
2461d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
2462ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen        bool setflags;
246326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        switch (encoding)
246426863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        {
2465d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen        case eEncodingT1:
2466d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            Rd = Bits32(opcode, 2, 0);
2467d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            Rn = Bits32(opcode, 5, 3);
2468d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            Rm = Bits32(opcode, 8, 6);
2469d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            setflags = !InITBlock();
2470d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            shift_t = SRType_LSL;
2471d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            shift_n = 0;
2472ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
247326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        case eEncodingT2:
2474bd599907c7c6203e02123d825d1df017ce58f653Johnny Chen            Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
247526863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            Rm = Bits32(opcode, 6, 3);
2476ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            setflags = false;
2477d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            shift_t = SRType_LSL;
2478d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            shift_n = 0;
247926863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            if (Rn == 15 && Rm == 15)
248026863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen                return false;
2481d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen            if (Rd == 15 && InITBlock() && !LastInITBlock())
2482d761dcf991d66ab1d686f874270ba3c8cc9ff28cJohnny Chen                return false;
248326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            break;
24848fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        case eEncodingA1:
24858fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            Rd = Bits32(opcode, 15, 12);
24868fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            Rn = Bits32(opcode, 19, 16);
24878fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            Rm = Bits32(opcode, 3, 0);
24888fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            setflags = BitIsSet(opcode, 20);
24893dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
24908fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen            break;
249126863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        default:
249226863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            return false;
249326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        }
249426863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen
249526863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        // Read the first operand.
2496157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
249726863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        if (!success)
249826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            return false;
249926863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen
250026863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        // Read the second operand.
2501157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t val2 = ReadCoreReg(Rm, &success);
250226863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        if (!success)
250326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen            return false;
250426863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen
2505e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
25068fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
25079bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice
25089bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
25098ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        context.type = EmulateInstruction::eContextAddition;
25108ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        Register op1_reg;
25118ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        Register op2_reg;
25128ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
25138ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
25148ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        context.SetRegisterRegisterOperands (op1_reg, op2_reg);
2515ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen
251610530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2517ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            return false;
251826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    }
251926863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    return true;
252026863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen}
252126863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen
252234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// Compare Negative (immediate) adds a register value and an immediate value.
252334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// It updates the condition flags based on the result, and discards the result.
252434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chenbool
25257bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
252634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen{
252734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen#if 0
252834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    // ARM pseudo code...
252934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    if ConditionPassed() then
253034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        EncodingSpecificOperations();
253134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
253234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.N = result<31>;
253334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.Z = IsZeroBit(result);
253434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.C = carry;
253534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.V = overflow;
253634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen#endif
253734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
253834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    bool success = false;
253934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
254034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t Rn; // the first operand
254134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t imm32; // the immediate value to be compared with
254234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    switch (encoding) {
254334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    case eEncodingT1:
2544078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        Rn = Bits32(opcode, 19, 16);
2545078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2546078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        if (Rn == 15)
2547078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen            return false;
2548ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
254934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    case eEncodingA1:
255034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rn = Bits32(opcode, 19, 16);
255134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
255234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        break;
255334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    default:
255434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        return false;
255534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    }
255634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    // Read the register value from the operand register Rn.
255734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t reg_val = ReadCoreReg(Rn, &success);
255834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    if (!success)
255934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        return false;
256034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
2561078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen    AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
256234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
256334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    EmulateInstruction::Context context;
256434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
256534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    context.SetNoArgs ();
256634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
256734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        return false;
256834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
256934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    return true;
257034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen}
257134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
257234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// Compare Negative (register) adds a register value and an optionally-shifted register value.
257334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// It updates the condition flags based on the result, and discards the result.
257434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chenbool
25757bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
257634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen{
257734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen#if 0
257834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    // ARM pseudo code...
257934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    if ConditionPassed() then
258034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        EncodingSpecificOperations();
258134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
258234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
258334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.N = result<31>;
258434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.Z = IsZeroBit(result);
258534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.C = carry;
258634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        APSR.V = overflow;
258734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen#endif
258834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
258934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    bool success = false;
259034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
259134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t Rn; // the first operand
259234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t Rm; // the second operand
259334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    ARM_ShifterType shift_t;
259434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t shift_n; // the shift applied to the value read from Rm
259534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    switch (encoding) {
259634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    case eEncodingT1:
259734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rn = Bits32(opcode, 2, 0);
259834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rm = Bits32(opcode, 5, 3);
259934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        shift_t = SRType_LSL;
260034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        shift_n = 0;
260134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        break;
260234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    case eEncodingT2:
2603078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        Rn = Bits32(opcode, 19, 16);
2604078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        Rm = Bits32(opcode, 3, 0);
26053dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen        shift_n = DecodeImmShiftThumb(opcode, shift_t);
2606078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        // if n == 15 || BadReg(m) then UNPREDICTABLE;
2607078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        if (Rn == 15 || BadReg(Rm))
260834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen            return false;
260934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        break;
261034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    case eEncodingA1:
261134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rn = Bits32(opcode, 19, 16);
261234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rm = Bits32(opcode, 3, 0);
26133dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen        shift_n = DecodeImmShiftARM(opcode, shift_t);
2614ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
261534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    default:
261634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        return false;
261734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    }
261834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    // Read the register value from register Rn.
261934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t val1 = ReadCoreReg(Rn, &success);
262034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    if (!success)
262134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        return false;
262234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
262334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    // Read the register value from register Rm.
262434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t val2 = ReadCoreReg(Rm, &success);
262534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    if (!success)
262634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        return false;
262734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
262834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2629078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen    AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
263034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
263134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    EmulateInstruction::Context context;
263234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
263334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    context.SetNoArgs();
263434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
263534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        return false;
263634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
263734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    return true;
263834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen}
263934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
264034075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// Compare (immediate) subtracts an immediate value from a register value.
264134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// It updates the condition flags based on the result, and discards the result.
2642d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chenbool
26437bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
2644d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen{
2645d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen#if 0
2646d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    // ARM pseudo code...
2647d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    if ConditionPassed() then
2648d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        EncodingSpecificOperations();
2649d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2650d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        APSR.N = result<31>;
2651d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        APSR.Z = IsZeroBit(result);
2652d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        APSR.C = carry;
2653d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        APSR.V = overflow;
2654d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen#endif
2655d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen
2656d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    bool success = false;
2657d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen
2658d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    uint32_t Rn; // the first operand
2659d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    uint32_t imm32; // the immediate value to be compared with
2660d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    switch (encoding) {
2661d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    case eEncodingT1:
2662d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        Rn = Bits32(opcode, 10, 8);
2663d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        imm32 = Bits32(opcode, 7, 0);
2664ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
2665078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen    case eEncodingT2:
2666078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        Rn = Bits32(opcode, 19, 16);
2667078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2668078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        if (Rn == 15)
2669078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen            return false;
2670ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
267134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    case eEncodingA1:
267234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rn = Bits32(opcode, 19, 16);
267334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2674d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        break;
2675d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    default:
2676d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        return false;
2677d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    }
2678d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    // Read the register value from the operand register Rn.
2679e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    uint32_t reg_val = ReadCoreReg(Rn, &success);
2680d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    if (!success)
2681d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen        return false;
2682d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen
268310530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
268410530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen
26859bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    EmulateInstruction::Context context;
26869bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.type = EmulateInstruction::eContextImmediate;
26879bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.SetNoArgs ();
268810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
268910530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        return false;
269010530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen
2691d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen    return true;
2692d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen}
2693d4dc4444e124b290cbe30cdaade7e97161fa47c8Johnny Chen
269434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// Compare (register) subtracts an optionally-shifted register value from a register value.
269534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen// It updates the condition flags based on the result, and discards the result.
2696e4a4d301f3a06539098608749c55afaec063fca9Johnny Chenbool
26977bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
2698e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen{
2699e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen#if 0
2700e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    // ARM pseudo code...
2701e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    if ConditionPassed() then
2702e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        EncodingSpecificOperations();
2703e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2704e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2705e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        APSR.N = result<31>;
2706e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        APSR.Z = IsZeroBit(result);
2707e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        APSR.C = carry;
2708e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        APSR.V = overflow;
2709e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen#endif
2710e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen
2711e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    bool success = false;
2712e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen
2713e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    uint32_t Rn; // the first operand
2714e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    uint32_t Rm; // the second operand
271534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    ARM_ShifterType shift_t;
271634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t shift_n; // the shift applied to the value read from Rm
2717e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    switch (encoding) {
2718e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    case eEncodingT1:
2719e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        Rn = Bits32(opcode, 2, 0);
2720e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        Rm = Bits32(opcode, 5, 3);
272134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        shift_t = SRType_LSL;
272234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        shift_n = 0;
2723e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        break;
2724e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    case eEncodingT2:
2725e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2726e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        Rm = Bits32(opcode, 6, 3);
272734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        shift_t = SRType_LSL;
272834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        shift_n = 0;
2729e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        if (Rn < 8 && Rm < 8)
2730e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen            return false;
2731e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        if (Rn == 15 || Rm == 15)
2732e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen            return false;
2733e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        break;
273434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    case eEncodingA1:
273534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rn = Bits32(opcode, 19, 16);
273634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        Rm = Bits32(opcode, 3, 0);
27373dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen        shift_n = DecodeImmShiftARM(opcode, shift_t);
2738ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
2739e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    default:
2740e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        return false;
2741e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    }
2742e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    // Read the register value from register Rn.
274334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t val1 = ReadCoreReg(Rn, &success);
2744e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    if (!success)
2745e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        return false;
274634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen
2747e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    // Read the register value from register Rm.
274834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t val2 = ReadCoreReg(Rm, &success);
2749e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    if (!success)
2750e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen        return false;
2751e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen
275234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
275334075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen    AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
275410530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen
27559bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    EmulateInstruction::Context context;
27569bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.type = EmulateInstruction::eContextImmediate;
27579bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice    context.SetNoArgs();
275810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
275910530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        return false;
276010530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen
2761e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen    return true;
2762e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen}
2763e4a4d301f3a06539098608749c55afaec063fca9Johnny Chen
276482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
276582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen// shifting in copies of its sign bit, and writes the result to the destination register.  It can
276682f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen// optionally update the condition flags based on the result.
276782f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chenbool
27687bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
276982f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen{
277082f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen#if 0
277182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen    // ARM pseudo code...
277282f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen    if ConditionPassed() then
277382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        EncodingSpecificOperations();
277482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
277582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
277682f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
277782f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        else
277882f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            R[d] = result;
277982f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            if setflags then
278082f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen                APSR.N = result<31>;
278182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen                APSR.Z = IsZeroBit(result);
278282f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen                APSR.C = carry;
278382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen                // APSR.V unchanged
278482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen#endif
278582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
27867bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftImm (opcode, encoding, SRType_ASR);
278741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen}
278841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
278941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
279041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// shifting in copies of its sign bit, and writes the result to the destination register.
279141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// The variable number of bits is read from the bottom byte of a register. It can optionally update
279241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// the condition flags based on the result.
279341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chenbool
27947bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
279541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen{
279641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#if 0
279741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    // ARM pseudo code...
279841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    if ConditionPassed() then
279941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        EncodingSpecificOperations();
280041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        shift_n = UInt(R[m]<7:0>);
280141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
280241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        R[d] = result;
280341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        if setflags then
280441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.N = result<31>;
280541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.Z = IsZeroBit(result);
280641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.C = carry;
280741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            // APSR.V unchanged
280841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#endif
280941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
28107bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftReg (opcode, encoding, SRType_ASR);
281141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen}
281241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
281341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
281441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// shifting in zeros, and writes the result to the destination register.  It can optionally
281541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// update the condition flags based on the result.
281641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chenbool
28177bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
281841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen{
281941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#if 0
282041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    // ARM pseudo code...
282141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    if ConditionPassed() then
282241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        EncodingSpecificOperations();
282341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
282441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
282541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
282641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        else
282741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            R[d] = result;
282841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            if setflags then
282941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                APSR.N = result<31>;
283041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                APSR.Z = IsZeroBit(result);
283141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                APSR.C = carry;
283241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                // APSR.V unchanged
283341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#endif
283441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
28357bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftImm (opcode, encoding, SRType_LSL);
283641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen}
283741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
283841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// Logical Shift Left (register) shifts a register value left by a variable number of bits,
283941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// shifting in zeros, and writes the result to the destination register.  The variable number
284041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// of bits is read from the bottom byte of a register. It can optionally update the condition
284141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// flags based on the result.
284241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chenbool
28437bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
284441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen{
284541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#if 0
284641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    // ARM pseudo code...
284741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    if ConditionPassed() then
284841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        EncodingSpecificOperations();
284941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        shift_n = UInt(R[m]<7:0>);
285041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
285141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        R[d] = result;
285241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        if setflags then
285341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.N = result<31>;
285441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.Z = IsZeroBit(result);
285541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.C = carry;
285641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            // APSR.V unchanged
285741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#endif
285841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
28597bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftReg (opcode, encoding, SRType_LSL);
286041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen}
286141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
286241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
286341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// shifting in zeros, and writes the result to the destination register.  It can optionally
286441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// update the condition flags based on the result.
286541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chenbool
28667bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
286741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen{
286841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#if 0
286941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    // ARM pseudo code...
287041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    if ConditionPassed() then
287141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        EncodingSpecificOperations();
287241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
287341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
287441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
287541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        else
287641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            R[d] = result;
287741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            if setflags then
287841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                APSR.N = result<31>;
287941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                APSR.Z = IsZeroBit(result);
288041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                APSR.C = carry;
288141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen                // APSR.V unchanged
288241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#endif
288341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
28847bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftImm (opcode, encoding, SRType_LSR);
288541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen}
288641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
288741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// Logical Shift Right (register) shifts a register value right by a variable number of bits,
288841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// shifting in zeros, and writes the result to the destination register.  The variable number
288941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// of bits is read from the bottom byte of a register. It can optionally update the condition
289041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen// flags based on the result.
289141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chenbool
28927bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
289341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen{
289441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#if 0
289541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    // ARM pseudo code...
289641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    if ConditionPassed() then
289741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        EncodingSpecificOperations();
289841a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        shift_n = UInt(R[m]<7:0>);
289941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
290041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        R[d] = result;
290141a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen        if setflags then
290241a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.N = result<31>;
290341a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.Z = IsZeroBit(result);
290441a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            APSR.C = carry;
290541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen            // APSR.V unchanged
290641a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen#endif
290741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
29087bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftReg (opcode, encoding, SRType_LSR);
290941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen}
291041a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
2911eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2912eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2913eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// It can optionally update the condition flags based on the result.
2914eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chenbool
29157bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
2916eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen{
2917eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen#if 0
2918eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen    // ARM pseudo code...
2919eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen    if ConditionPassed() then
2920eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        EncodingSpecificOperations();
2921eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2922eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
2923eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
2924eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        else
2925eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            R[d] = result;
2926eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            if setflags then
2927eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                APSR.N = result<31>;
2928eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                APSR.Z = IsZeroBit(result);
2929eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                APSR.C = carry;
2930eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                // APSR.V unchanged
2931eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen#endif
2932eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
29337bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftImm (opcode, encoding, SRType_ROR);
2934eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen}
2935eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
2936eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2937eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2938eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2939eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// flags based on the result.
2940eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chenbool
29417bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
2942eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen{
2943eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen#if 0
2944eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen    // ARM pseudo code...
2945eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen    if ConditionPassed() then
2946eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        EncodingSpecificOperations();
2947eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        shift_n = UInt(R[m]<7:0>);
2948eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2949eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        R[d] = result;
2950eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        if setflags then
2951eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            APSR.N = result<31>;
2952eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            APSR.Z = IsZeroBit(result);
2953eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            APSR.C = carry;
2954eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            // APSR.V unchanged
2955eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen#endif
2956eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
29577bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftReg (opcode, encoding, SRType_ROR);
2958eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen}
2959eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
2960eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2961eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// with the carry flag shifted into bit [31].
2962eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen//
2963eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// RRX can optionally update the condition flags based on the result.
2964eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen// In that case, bit [0] is shifted into the carry flag.
2965eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chenbool
29667bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
2967eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen{
2968eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen#if 0
2969eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen    // ARM pseudo code...
2970eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen    if ConditionPassed() then
2971eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        EncodingSpecificOperations();
2972eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2973eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
2974eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
2975eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        else
2976eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            R[d] = result;
2977eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            if setflags then
2978eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                APSR.N = result<31>;
2979eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                APSR.Z = IsZeroBit(result);
2980eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                APSR.C = carry;
2981eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen                // APSR.V unchanged
2982eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen#endif
2983eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
29847bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    return EmulateShiftImm (opcode, encoding, SRType_RRX);
2985eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen}
2986eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
298741a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chenbool
29887bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
298941a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen{
2990bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice    assert(shift_type == SRType_ASR
2991bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice           || shift_type == SRType_LSL
2992bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice           || shift_type == SRType_LSR
2993bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice           || shift_type == SRType_ROR
2994bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice           || shift_type == SRType_RRX);
299541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen
299682f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen    bool success = false;
299782f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
29987bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
299982f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen    {
3000e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t Rd;    // the destination register
3001e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t Rm;    // the first operand register
3002e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t imm5;  // encoding for the shift amount
300382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        uint32_t carry; // the carry bit after the shift operation
300482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        bool setflags;
3005eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
3006eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // Special case handling!
3007eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // A8.6.139 ROR (immediate) -- Encoding T1
30087bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        ARMEncoding use_encoding = encoding;
30097bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
3010eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        {
3011eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3012eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            // have the same decoding of bit fields as the other Thumb2 shift operations.
30137bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            use_encoding = eEncodingT2;
3014eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        }
3015eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
30167bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        switch (use_encoding) {
301782f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        case eEncodingT1:
3018eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            // Due to the above special case handling!
3019eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            assert(shift_type != SRType_ROR);
3020eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
302182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            Rd = Bits32(opcode, 2, 0);
302282f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            Rm = Bits32(opcode, 5, 3);
302382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            setflags = !InITBlock();
302482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            imm5 = Bits32(opcode, 10, 6);
302582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            break;
302682f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        case eEncodingT2:
3027eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            // A8.6.141 RRX
3028eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            assert(shift_type != SRType_RRX);
3029eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
303082f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            Rd = Bits32(opcode, 11, 8);
303182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            Rm = Bits32(opcode, 3, 0);
303282f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            setflags = BitIsSet(opcode, 20);
303382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
303482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            if (BadReg(Rd) || BadReg(Rm))
303582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen                return false;
303682f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            break;
303782f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        case eEncodingA1:
303882f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            Rd = Bits32(opcode, 15, 12);
303982f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            Rm = Bits32(opcode, 3, 0);
304082f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            setflags = BitIsSet(opcode, 20);
304182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            imm5 = Bits32(opcode, 11, 7);
304282f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            break;
304382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        default:
304482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            return false;
304582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        }
304682f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
3047eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // A8.6.139 ROR (immediate)
3048eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        if (shift_type == SRType_ROR && imm5 == 0)
3049eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen            shift_type = SRType_RRX;
3050eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen
305182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        // Get the first operand.
3052e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        uint32_t value = ReadCoreReg (Rm, &success);
305382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        if (!success)
305482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen            return false;
305582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
3056eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // Decode the shift amount if not RRX.
3057eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
305882f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
3059e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
306082f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
306182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        // The context specifies that an immediate is to be moved into Rd.
306282f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        EmulateInstruction::Context context;
306382f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
306482f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        context.SetNoArgs ();
306582f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
306610530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3067ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            return false;
306882f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen    }
306982f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen    return true;
307082f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen}
307182f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen
3072e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chenbool
30737bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
3074e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen{
307541a0a15df85a0d4b428c13dff8606a064f5d8dfeJohnny Chen    assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
3076e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
3077e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen    bool success = false;
3078e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
30797bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
3080e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen    {
3081e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t Rd;    // the destination register
3082e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t Rn;    // the first operand register
3083e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t Rm;    // the register whose bottom byte contains the amount to shift by
3084e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t carry; // the carry bit after the shift operation
3085e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        bool setflags;
3086e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        switch (encoding) {
3087e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        case eEncodingT1:
3088e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rd = Bits32(opcode, 2, 0);
3089e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rn = Rd;
3090e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rm = Bits32(opcode, 5, 3);
3091e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            setflags = !InITBlock();
3092e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            break;
3093e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        case eEncodingT2:
3094e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rd = Bits32(opcode, 11, 8);
3095e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rn = Bits32(opcode, 19, 16);
3096e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rm = Bits32(opcode, 3, 0);
3097e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            setflags = BitIsSet(opcode, 20);
3098e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3099e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen                return false;
3100e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            break;
3101e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        case eEncodingA1:
3102e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rd = Bits32(opcode, 15, 12);
3103e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rn = Bits32(opcode, 3, 0);
3104e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            Rm = Bits32(opcode, 11, 8);
3105e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            setflags = BitIsSet(opcode, 20);
3106e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            if (Rd == 15 || Rn == 15 || Rm == 15)
3107e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen                return false;
3108e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            break;
3109e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        default:
3110e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            return false;
3111e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        }
3112e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
3113e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        // Get the first operand.
3114e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        uint32_t value = ReadCoreReg (Rn, &success);
3115e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        if (!success)
3116e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            return false;
3117e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        // Get the Rm register content.
3118e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        uint32_t val = ReadCoreReg (Rm, &success);
3119e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        if (!success)
3120e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            return false;
3121e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
3122e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        // Get the shift amount.
3123e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        uint32_t amt = Bits32(val, 7, 0);
3124e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
3125e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
3126e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
3127e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        // The context specifies that an immediate is to be moved into Rd.
3128e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        EmulateInstruction::Context context;
3129e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
3130e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        context.SetNoArgs ();
3131e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
313210530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3133e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen            return false;
3134e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen    }
3135e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen    return true;
3136e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen}
3137e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen
3138b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice// LDM loads multiple registers from consecutive memory locations, using an
3139713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// address from a base register.  Optionally the address just above the highest of those locations
3140b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice// can be written back to the base register.
3141b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Ticebool
31427bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
3143b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice{
3144b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice#if 0
3145b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice    // ARM pseudo code...
3146b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice    if ConditionPassed()
3147b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3148b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        address = R[n];
3149b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3150b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        for i = 0 to 14
3151b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            if registers<i> == '1' then
3152b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                R[i] = MemA[address, 4]; address = address + 4;
3153b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        if registers<15> == '1' then
3154b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            LoadWritePC (MemA[address, 4]);
3155b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3156b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3157b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3158b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3159b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice#endif
3160b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3161b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice    bool success = false;
3162b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
31637bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
3164b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice    {
3165b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        uint32_t n;
3166b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        uint32_t registers = 0;
3167b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        bool wback;
3168b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
3169b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        switch (encoding)
3170b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        {
3171b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            case eEncodingT1:
3172bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
3173b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                n = Bits32 (opcode, 10, 8);
3174b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                registers = Bits32 (opcode, 7, 0);
3175b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = registers & 0x00ff;  // Make sure the top 8 bits are zeros.
3176b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                wback = BitIsClear (registers, n);
3177b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                // if BitCount(registers) < 1 then UNPREDICTABLE;
3178b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                if (BitCount(registers) < 1)
3179b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    return false;
3180b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                break;
3181b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            case eEncodingT2:
3182bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if W == '1' && Rn == '1101' then SEE POP;
3183bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3184b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                n = Bits32 (opcode, 19, 16);
3185b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                registers = Bits32 (opcode, 15, 0);
3186b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = registers & 0xdfff; // Make sure bit 13 is zero.
3187b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                wback = BitIsSet (opcode, 21);
3188b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
3189bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
3190b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                if ((n == 15)
3191b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    || (BitCount (registers) < 2)
3192b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3193b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    return false;
3194b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
3195bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3196098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen                if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
3197b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    return false;
3198b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
3199bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if wback && registers<n> == '1' then UNPREDICTABLE;
3200b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                if (wback
3201b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    && BitIsSet (registers, n))
3202b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    return false;
3203b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                break;
3204b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
3205b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            case eEncodingA1:
3206b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                n = Bits32 (opcode, 19, 16);
3207b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                registers = Bits32 (opcode, 15, 0);
3208b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                wback = BitIsSet (opcode, 21);
3209b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                if ((n == 15)
3210b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    || (BitCount (registers) < 1))
3211b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    return false;
3212b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                break;
3213b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            default:
3214b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                return false;
3215b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        }
3216b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3217b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        int32_t offset = 0;
3218b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3219b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        if (!success)
3220b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            return false;
322185aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
32229bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
32239bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
32249bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
32259bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
32269bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (dwarf_reg, offset);
3227b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3228b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        for (int i = 0; i < 14; ++i)
3229b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        {
3230b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            if (BitIsSet (registers, i))
3231b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            {
323285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                context.type = EmulateInstruction::eContextRegisterPlusOffset;
32339bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice                context.SetRegisterPlusOffset (dwarf_reg, offset);
3234b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                if (wback && (n == 13)) // Pop Instruction
3235b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    context.type = EmulateInstruction::eContextPopRegisterOffStack;
3236b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3237b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                // R[i] = MemA [address, 4]; address = address + 4;
3238cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
3239b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                if (!success)
3240b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    return false;
3241b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3242b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3243b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                    return false;
3244b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3245b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                offset += addr_byte_size;
3246b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            }
3247b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        }
3248b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3249b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        if (BitIsSet (registers, 15))
3250b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        {
3251b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            //LoadWritePC (MemA [address, 4]);
325285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            context.type = EmulateInstruction::eContextRegisterPlusOffset;
32539bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetRegisterPlusOffset (dwarf_reg, offset);
3254cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
3255b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            if (!success)
3256b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                return false;
3257e62b50d64e9cdf806a36cefd4cbf96250679669dJohnny Chen            // In ARMv5T and above, this is an interworking branch.
3258668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen            if (!LoadWritePC(context, data))
3259b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                return false;
3260b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        }
3261b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3262b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        if (wback && BitIsClear (registers, n))
3263b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        {
3264fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            // R[n] = R[n] + 4 * BitCount (registers)
3265fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            int32_t offset = addr_byte_size * BitCount (registers);
3266fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
32679bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetRegisterPlusOffset (dwarf_reg, offset);
3268b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3269b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3270b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice                return false;
3271b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        }
3272b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        if (wback && BitIsSet (registers, n))
3273b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice            // R[n] bits(32) UNKNOWN;
3274713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            return WriteBits32Unknown (n);
3275b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice    }
3276b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice    return true;
3277b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice}
3278713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3279bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3280bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice// The consecutive memory locations end at this address and the address just below the lowest of those locations
3281bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice// can optionally be written back to the base register.
3282713c2665a27096b68f3f8956222375354f1292f8Caroline Ticebool
32837bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
3284713c2665a27096b68f3f8956222375354f1292f8Caroline Tice{
3285713c2665a27096b68f3f8956222375354f1292f8Caroline Tice#if 0
3286713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    // ARM pseudo code...
3287713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    if ConditionPassed() then
3288713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        EncodingSpecificOperations();
3289713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        address = R[n] - 4*BitCount(registers) + 4;
3290713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3291713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        for i = 0 to 14
3292bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
3293713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                  R[i] = MemA[address,4]; address = address + 4;
3294713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3295bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then
3296713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            LoadWritePC(MemA[address,4]);
3297713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3298bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3299bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3300713c2665a27096b68f3f8956222375354f1292f8Caroline Tice#endif
3301713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3302713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    bool success = false;
3303713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
33047bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
3305713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    {
3306713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        uint32_t n;
3307713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        uint32_t registers = 0;
3308713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        bool wback;
3309713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
3310713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3311713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        // EncodingSpecificOperations();
3312713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        switch (encoding)
3313713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        {
3314713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            case eEncodingA1:
3315bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = register_list; wback = (W == '1');
3316713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                n = Bits32 (opcode, 19, 16);
3317713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                registers = Bits32 (opcode, 15, 0);
3318713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                wback = BitIsSet (opcode, 21);
3319b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice
3320713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3321713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                if ((n == 15) || (BitCount (registers) < 1))
3322713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                    return false;
3323713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3324713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                break;
3325713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3326713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            default:
3327713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                return false;
3328713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        }
3329713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        // address = R[n] - 4*BitCount(registers) + 4;
3330713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3331713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        int32_t offset = 0;
3332bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t Rn = ReadCoreReg (n, &success);
3333713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3334713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        if (!success)
3335713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            return false;
3336713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3337bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3338713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
33399bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
33409bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
33419bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
33429bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
33439bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (dwarf_reg, offset);
3344713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3345713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        // for i = 0 to 14
3346713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        for (int i = 0; i < 14; ++i)
3347713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        {
3348bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if registers<i> == '1' then
3349713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            if (BitIsSet (registers, i))
3350713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            {
3351713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                  // R[i] = MemA[address,4]; address = address + 4;
3352bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                  context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
3353cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                  uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3354713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                  if (!success)
3355713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                      return false;
3356713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                  if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3357713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                      return false;
3358713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                  offset += addr_byte_size;
3359713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            }
3360713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        }
3361713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3362bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if registers<15> == '1' then
3363713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        //     LoadWritePC(MemA[address,4]);
3364713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        if (BitIsSet (registers, 15))
3365713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        {
33669bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetRegisterPlusOffset (dwarf_reg, offset);
3367cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
3368713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            if (!success)
3369713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                return false;
337044c10f05a667cd279c6baea7b80b40b49c02f20cJohnny Chen            // In ARMv5T and above, this is an interworking branch.
3371668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen            if (!LoadWritePC(context, data))
3372713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                return false;
3373713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        }
3374713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3375bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3376713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        if (wback && BitIsClear (registers, n))
3377713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        {
3378713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            if (!success)
3379713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                return false;
3380fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3381fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            offset = (addr_byte_size * BitCount (registers)) * -1;
3382fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
33839bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetImmediateSigned (offset);
3384bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            addr_t addr = Rn + offset;
3385713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3386713c2665a27096b68f3f8956222375354f1292f8Caroline Tice                return false;
3387713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        }
3388713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3389bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
3390713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        if (wback && BitIsSet (registers, n))
3391713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            return WriteBits32Unknown (n);
3392713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    }
3393713c2665a27096b68f3f8956222375354f1292f8Caroline Tice    return true;
3394713c2665a27096b68f3f8956222375354f1292f8Caroline Tice}
3395713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3396713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// LDMDB loads multiple registers from consecutive memory locations using an address from a base register.  The
3397713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3398713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// be optionally written back to the base register.
33990b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Ticebool
34007bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
34010b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice{
34020b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice#if 0
34030b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice    // ARM pseudo code...
34040b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice    if ConditionPassed() then
34050b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
34060b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        address = R[n] - 4*BitCount(registers);
34070b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34080b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        for i = 0 to 14
3409bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
34100b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                  R[i] = MemA[address,4]; address = address + 4;
3411bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then
34120b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                  LoadWritePC(MemA[address,4]);
34130b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3414bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3415bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
34160b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice#endif
34170b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34180b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice    bool success = false;
34190b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34207bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
34210b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice    {
34220b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        uint32_t n;
34230b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        uint32_t registers = 0;
34240b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        bool wback;
34250b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
34260b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        switch (encoding)
34270b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        {
34280b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            case eEncodingT1:
3429bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
34300b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                n = Bits32 (opcode, 19, 16);
34310b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                registers = Bits32 (opcode, 15, 0);
3432b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = registers & 0xdfff;  // Make sure bit 13 is a zero.
34330b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                wback = BitIsSet (opcode, 21);
34340b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3435bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
34360b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                if ((n == 15)
34370b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    || (BitCount (registers) < 2)
34380b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
34390b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    return false;
34400b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3441bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3442098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen                if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
34430b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    return false;
34440b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3445bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if wback && registers<n> == '1' then UNPREDICTABLE;
34460b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                if (wback && BitIsSet (registers, n))
34470b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    return false;
34480b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34490b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                break;
34500b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34510b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            case eEncodingA1:
3452bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = register_list; wback = (W == '1');
34530b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                n = Bits32 (opcode, 19, 16);
34540b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                registers = Bits32 (opcode, 15, 0);
34550b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                wback = BitIsSet (opcode, 21);
34560b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34570b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
34580b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                if ((n == 15) || (BitCount (registers) < 1))
34590b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    return false;
34600b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34610b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                break;
34620b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34630b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            default:
34640b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                return false;
34650b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        }
34660b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3467713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        // address = R[n] - 4*BitCount(registers);
3468713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
34690b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        int32_t offset = 0;
3470bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3471713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3472713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        if (!success)
3473713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            return false;
3474713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3475bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t address = Rn - (addr_byte_size * BitCount (registers));
34769bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
34779bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
34789bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
34799bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3480bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
34810b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34820b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        for (int i = 0; i < 14; ++i)
34830b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        {
34840b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            if (BitIsSet (registers, i))
34850b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            {
34860b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                // R[i] = MemA[address,4]; address = address + 4;
3487bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
3488cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
34890b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                if (!success)
34900b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    return false;
34910b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34920b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
34930b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                    return false;
34940b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
34950b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                offset += addr_byte_size;
34960b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            }
34970b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        }
34980b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3499bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if registers<15> == '1' then
35000b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        //     LoadWritePC(MemA[address,4]);
35010b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        if (BitIsSet (registers, 15))
35020b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        {
35039bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetRegisterPlusOffset (dwarf_reg, offset);
3504cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
35050b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            if (!success)
35060b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                return false;
3507e62b50d64e9cdf806a36cefd4cbf96250679669dJohnny Chen            // In ARMv5T and above, this is an interworking branch.
3508668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen            if (!LoadWritePC(context, data))
35090b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                return false;
35100b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        }
35110b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3512bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
35130b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        if (wback && BitIsClear (registers, n))
35140b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        {
35150b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            if (!success)
35160b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                return false;
3517fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3518fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            offset = (addr_byte_size * BitCount (registers)) * -1;
3519fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
35209bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetImmediateSigned (offset);
3521bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            addr_t addr = Rn + offset;
35220b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
35230b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice                return false;
35240b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        }
35250b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3526bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
35270b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        if (wback && BitIsSet (registers, n))
3528713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            return WriteBits32Unknown (n);
35290b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice    }
35300b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice    return true;
35310b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice}
353285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
3533713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// LDMIB loads multiple registers from consecutive memory locations using an address from a base register.  The
3534713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3535713c2665a27096b68f3f8956222375354f1292f8Caroline Tice// optinoally be written back to the base register.
353685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Ticebool
35377bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
353885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice{
353985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice#if 0
354085aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice    if ConditionPassed() then
354185aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        EncodingSpecificOperations();
354285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        address = R[n] + 4;
354385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
354485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        for i = 0 to 14
3545bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
354685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                  R[i] = MemA[address,4]; address = address + 4;
3547bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then
354885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            LoadWritePC(MemA[address,4]);
354985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
3550bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3551bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
355285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice#endif
355385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
355485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice    bool success = false;
355585aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
35567bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
355785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice    {
355885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        uint32_t n;
355985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        uint32_t registers = 0;
356085aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        bool wback;
356185aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
356285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        switch (encoding)
356385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        {
356485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            case eEncodingA1:
3565bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = register_list; wback = (W == '1');
356685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                n = Bits32 (opcode, 19, 16);
356785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                registers = Bits32 (opcode, 15, 0);
356885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                wback = BitIsSet (opcode, 21);
356985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
357085aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
357185aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                if ((n == 15) || (BitCount (registers) < 1))
357285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                    return false;
357385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
357485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                break;
357585aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            default:
357685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                return false;
357785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        }
357885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        // address = R[n] + 4;
357985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
358085aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        int32_t offset = 0;
3581bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3582713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3583713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        if (!success)
3584713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            return false;
3585713c2665a27096b68f3f8956222375354f1292f8Caroline Tice
3586bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t address = Rn + addr_byte_size;
358785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
35889bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
35899bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterPlusOffset;
35909bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register dwarf_reg;
35919bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
35929bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.SetRegisterPlusOffset (dwarf_reg, offset);
359385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
359485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        for (int i = 0; i < 14; ++i)
359585aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        {
359685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            if (BitIsSet (registers, i))
359785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            {
359885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                // R[i] = MemA[address,4]; address = address + 4;
359985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
3600bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
3601cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
360285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                if (!success)
360385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                    return false;
360485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
360585aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
360685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                    return false;
360785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
360885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                offset += addr_byte_size;
360985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            }
361085aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        }
361185aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
3612bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if registers<15> == '1' then
361385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        //     LoadWritePC(MemA[address,4]);
361485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        if (BitIsSet (registers, 15))
361585aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        {
36169bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetRegisterPlusOffset (dwarf_reg, offset);
3617cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
361885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            if (!success)
361985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                return false;
3620e62b50d64e9cdf806a36cefd4cbf96250679669dJohnny Chen            // In ARMv5T and above, this is an interworking branch.
3621668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen            if (!LoadWritePC(context, data))
362285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                return false;
362385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        }
362485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
3625bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
362685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        if (wback && BitIsClear (registers, n))
362785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        {
362885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            if (!success)
362985aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                return false;
3630fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3631fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            offset = addr_byte_size * BitCount (registers);
3632fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
36339bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetImmediateSigned (offset);
3634bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            addr_t addr = Rn + offset;
363585aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
363685aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice                return false;
363785aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        }
363885aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice
3639bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
364085aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        if (wback && BitIsSet (registers, n))
3641713c2665a27096b68f3f8956222375354f1292f8Caroline Tice            return WriteBits32Unknown (n);
364285aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice    }
364385aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice    return true;
364485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice}
36450b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice
3646ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen// Load Register (immediate) calculates an address from a base register value and
3647ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen// an immediate offset, loads a word from memory, and writes to a register.
3648ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen// LDR (immediate, Thumb)
3649ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chenbool
36507bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
3651ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen{
3652ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen#if 0
3653ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    // ARM pseudo code...
3654ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    if (ConditionPassed())
3655ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    {
3656ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3657ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3658ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        address = if index then offset_addr else R[n];
3659ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        data = MemU[address,4];
3660ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        if wback then R[n] = offset_addr;
3661ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        if t == 15 then
3662ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3663ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        elsif UnalignedSupport() || address<1:0> = '00' then
3664ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            R[t] = data;
3665ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3666ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    }
3667ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen#endif
3668ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
3669ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    bool success = false;
3670ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
36717bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
3672ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    {
3673ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        uint32_t Rt; // the destination register
3674ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        uint32_t Rn; // the base register
3675ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        uint32_t imm32; // the immediate offset used to form the address
3676ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        addr_t offset_addr; // the offset address
3677ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        addr_t address; // the calculated address
3678ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        uint32_t data; // the literal data value from memory load
3679ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        bool add, index, wback;
3680ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        switch (encoding) {
3681baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            case eEncodingT1:
3682baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rt = Bits32(opcode, 5, 3);
3683baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rn = Bits32(opcode, 2, 0);
3684baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3685baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE
3686baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                add = true;
3687baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                index = true;
3688baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                wback = false;
3689baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3690baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                break;
3691baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3692baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            case eEncodingT2:
3693bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
3694baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rt = Bits32 (opcode, 10, 8);
3695baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rn = 13;
3696baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                imm32 = Bits32 (opcode, 7, 0) << 2;
3697baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3698baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
3699baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                index = true;
3700baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                add = true;
3701baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                wback = false;
3702baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3703baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                break;
3704baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3705baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            case eEncodingT3:
3706bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDR (literal);
3707baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3708baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rt = Bits32 (opcode, 15, 12);
3709baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rn = Bits32 (opcode, 19, 16);
3710baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
3711baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3712baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
3713baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                index = true;
3714baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                add = true;
3715baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                wback = false;
3716baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3717baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3718baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                if ((Rt == 15) && InITBlock() && !LastInITBlock())
3719baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                    return false;
3720baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3721baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                break;
3722baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3723baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            case eEncodingT4:
3724bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDR (literal);
3725bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3726bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3727bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '0' then UNDEFINED;
3728baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3729baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                    return false;
3730baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3731baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3732baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rt = Bits32 (opcode, 15, 12);
3733baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                Rn = Bits32 (opcode, 19, 16);
3734baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                imm32 = Bits32 (opcode, 7, 0);
3735baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3736bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
3737baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                index = BitIsSet (opcode, 10);
3738baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                add = BitIsSet (opcode, 9);
3739baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                wback = BitIsSet (opcode, 8);
3740baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3741baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3742baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3743baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                    return false;
3744baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3745baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                break;
3746baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice
3747baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            default:
3748baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                return false;
3749ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        }
3750baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        uint32_t base = ReadCoreReg (Rn, &success);
3751ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        if (!success)
3752ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            return false;
3753ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        if (add)
3754ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            offset_addr = base + imm32;
3755ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        else
3756ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            offset_addr = base - imm32;
3757ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
3758ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        address = (index ? offset_addr : base);
3759ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
3760baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        Register base_reg;
3761baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3762ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        if (wback)
3763ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        {
37649bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            EmulateInstruction::Context ctx;
3765baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3766baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
37679bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice
3768ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3769ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen                return false;
3770ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        }
3771ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
3772ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        // Prepare to write to the Rt register.
37739bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
3774baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        context.type = EmulateInstruction::eContextRegisterLoad;
3775baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
3776ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
3777ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        // Read memory from the address.
3778cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice        data = MemURead(context, address, 4, 0, &success);
3779ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        if (!success)
3780ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            return false;
3781ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
3782ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        if (Rt == 15)
3783ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        {
3784ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            if (Bits32(address, 1, 0) == 0)
3785ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            {
3786668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen                if (!LoadWritePC(context, data))
3787ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen                    return false;
3788ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            }
3789ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            else
3790ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen                return false;
3791ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        }
3792ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3793ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        {
3794ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3795ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen                return false;
3796ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        }
3797ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        else
3798baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice            WriteBits32Unknown (Rt);
3799ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    }
3800ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    return true;
3801ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen}
3802ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
3803af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3804af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// from a base register.  The consecutive memory locations start at this address, and teh address just above the last
3805af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// of those locations can optionally be written back to the base register.
3806fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Ticebool
38077bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
3808fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice{
3809fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice#if 0
3810fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    if ConditionPassed() then
3811fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3812fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        address = R[n];
3813fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3814fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        for i = 0 to 14
3815bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
3816fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                if i == n && wback && i != LowestSetBit(registers) then
3817fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                    MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3818fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                else
3819fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                    MemA[address,4] = R[i];
3820fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                address = address + 4;
3821fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3822bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then // Only possible for encoding A1
3823fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            MemA[address,4] = PCStoreValue();
3824fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        if wback then R[n] = R[n] + 4*BitCount(registers);
3825fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice#endif
3826fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3827fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    bool success = false;
3828fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
38297bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
3830fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    {
3831fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        uint32_t n;
3832fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        uint32_t registers = 0;
3833fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        bool wback;
3834fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
3835fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3836fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3837fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        switch (encoding)
3838fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        {
3839fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            case eEncodingT1:
3840bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
3841fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                n = Bits32 (opcode, 10, 8);
3842fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                registers = Bits32 (opcode, 7, 0);
3843b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = registers & 0x00ff;  // Make sure the top 8 bits are zeros.
3844fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                wback = true;
3845fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3846fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                // if BitCount(registers) < 1 then UNPREDICTABLE;
3847fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                if (BitCount (registers) < 1)
3848fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                    return false;
3849fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3850fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                break;
3851fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3852fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            case eEncodingT2:
3853bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
3854fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                n = Bits32 (opcode, 19, 16);
3855fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                registers = Bits32 (opcode, 15, 0);
3856b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3857fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                wback = BitIsSet (opcode, 21);
3858fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3859fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3860fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                if ((n == 15) || (BitCount (registers) < 2))
3861fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                    return false;
3862fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3863bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if wback && registers<n> == '1' then UNPREDICTABLE;
3864fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                if (wback && BitIsSet (registers, n))
3865fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                    return false;
3866fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3867fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                break;
3868fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3869fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            case eEncodingA1:
3870bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = register_list; wback = (W == '1');
3871fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                n = Bits32 (opcode, 19, 16);
3872fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                registers = Bits32 (opcode, 15, 0);
3873fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                wback = BitIsSet (opcode, 21);
3874fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3875fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3876fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                if ((n == 15) || (BitCount (registers) < 1))
3877fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                    return false;
3878fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3879fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                break;
3880fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3881fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            default:
3882fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                return false;
3883fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        }
3884fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3885fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        // address = R[n];
3886fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        int32_t offset = 0;
3887fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3888fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        if (!success)
3889fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            return false;
3890fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
38919bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        EmulateInstruction::Context context;
38929bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        context.type = EmulateInstruction::eContextRegisterStore;
38939bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        Register base_reg;
38949bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3895fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3896fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        // for i = 0 to 14
3897bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        int lowest_set_bit = 14;
3898fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        for (int i = 0; i < 14; ++i)
3899fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        {
3900bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if registers<i> == '1' then
3901fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            if (BitIsSet (registers, i))
3902fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            {
3903fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  if (i < lowest_set_bit)
3904fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                      lowest_set_bit = i;
3905fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  // if i == n && wback && i != LowestSetBit(registers) then
3906fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  if ((i == n) && wback && (i != lowest_set_bit))
3907fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                      // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3908fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                      WriteBits32UnknownToMemory (address + offset);
3909fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  else
3910fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  {
3911fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                     // MemA[address,4] = R[i];
3912fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                      uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3913fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                      if (!success)
3914fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                          return false;
3915fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
39169bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice                      Register data_reg;
39179bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice                      data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
39189bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice                      context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
3919cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                      if (!MemAWrite (context, address + offset, data, addr_byte_size))
3920fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                          return false;
3921fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  }
3922fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3923fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  // address = address + 4;
3924fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                  offset += addr_byte_size;
3925fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            }
3926fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        }
3927fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3928bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if registers<15> == '1' then // Only possible for encoding A1
3929fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        //     MemA[address,4] = PCStoreValue();
3930fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        if (BitIsSet (registers, 15))
3931fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        {
39329bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            Register pc_reg;
39339bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
39349bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetRegisterPlusOffset (pc_reg, 8);
39358d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            const uint32_t pc = ReadCoreReg (PC_REG, &success);
3936fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            if (!success)
3937fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                return false;
3938fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
39398d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
3940fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                return false;
3941fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        }
3942fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3943fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        // if wback then R[n] = R[n] + 4*BitCount(registers);
3944fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        if (wback)
3945fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        {
3946fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            offset = addr_byte_size * BitCount (registers);
3947fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
39489bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            context.SetImmediateSigned (offset);
3949fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            addr_t data = address + offset;
3950fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3951fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice                return false;
3952fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        }
3953fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    }
3954fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice    return true;
3955fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice}
3956fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
3957af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3958af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// from a base register.  The consecutive memory locations end at this address, and the address just below the lowest
3959af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// of those locations can optionally be written back to the base register.
39601511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Ticebool
39617bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
39621511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice{
39631511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice#if 0
39641511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice    if ConditionPassed() then
39651511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        EncodingSpecificOperations();
39661511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        address = R[n] - 4*BitCount(registers) + 4;
39671511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
39681511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        for i = 0 to 14
3969bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
39701511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                if i == n && wback && i != LowestSetBit(registers) then
39711511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    MemA[address,4] = bits(32) UNKNOWN;
39721511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                else
39731511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    MemA[address,4] = R[i];
39741511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                address = address + 4;
39751511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
3976bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then
39771511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            MemA[address,4] = PCStoreValue();
39781511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
39791511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        if wback then R[n] = R[n] - 4*BitCount(registers);
39801511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice#endif
39811511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
39821511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice    bool success = false;
39831511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
39847bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
39851511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice    {
39861511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        uint32_t n;
39871511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        uint32_t registers = 0;
39881511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        bool wback;
39891511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
39901511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
39911511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        // EncodingSpecificOperations();
39921511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        switch (encoding)
39931511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        {
39941511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            case eEncodingA1:
3995bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = register_list; wback = (W == '1');
39961511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                n = Bits32 (opcode, 19, 16);
39971511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                registers = Bits32 (opcode, 15, 0);
39981511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                wback = BitIsSet (opcode, 21);
39991511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40001511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
40011511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                if ((n == 15) || (BitCount (registers) < 1))
40021511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    return false;
40031511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                break;
40041511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            default:
40051511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                return false;
40061511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        }
40071511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40081511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        // address = R[n] - 4*BitCount(registers) + 4;
40091511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        int32_t offset = 0;
4010bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t Rn = ReadCoreReg (n, &success);
40111511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        if (!success)
40121511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            return false;
40131511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
4014bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
40151511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40161511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        EmulateInstruction::Context context;
40171511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        context.type = EmulateInstruction::eContextRegisterStore;
40181511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        Register base_reg;
40191511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
40201511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40211511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        // for i = 0 to 14
4022bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        int lowest_bit_set = 14;
40231511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        for (int i = 0; i < 14; ++i)
40241511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        {
4025bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if registers<i> == '1' then
40261511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            if (BitIsSet (registers, i))
40271511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            {
40281511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                if (i < lowest_bit_set)
40291511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    lowest_bit_set = i;
40301511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                //if i == n && wback && i != LowestSetBit(registers) then
40311511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                if ((i == n) && wback && (i != lowest_bit_set))
40321511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    // MemA[address,4] = bits(32) UNKNOWN;
40331511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    WriteBits32UnknownToMemory (address + offset);
40341511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                else
40351511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                {
40361511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    // MemA[address,4] = R[i];
40371511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
40381511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    if (!success)
40391511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                        return false;
40401511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40411511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    Register data_reg;
40421511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                    data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4043bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
4044cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                    if (!MemAWrite (context, address + offset, data, addr_byte_size))
40451511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                        return false;
40461511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                }
40471511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40481511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                // address = address + 4;
40491511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                offset += addr_byte_size;
40501511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            }
40511511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        }
40521511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
4053bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if registers<15> == '1' then
40541511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        //    MemA[address,4] = PCStoreValue();
40551511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        if (BitIsSet (registers, 15))
40561511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        {
40571511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            Register pc_reg;
40581511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
40591511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            context.SetRegisterPlusOffset (pc_reg, 8);
40608d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            const uint32_t pc = ReadCoreReg (PC_REG, &success);
40611511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            if (!success)
40621511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                return false;
40631511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40648d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
40651511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                return false;
40661511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        }
40671511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
40681511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        // if wback then R[n] = R[n] - 4*BitCount(registers);
40691511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        if (wback)
40701511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        {
4071af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            offset = (addr_byte_size * BitCount (registers)) * -1;
40721511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
40731511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            context.SetImmediateSigned (offset);
4074bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            addr_t data = Rn + offset;
40751511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
40761511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice                return false;
40771511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        }
40781511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice    }
40791511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice    return true;
40801511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice}
40811511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
4082af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4083af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// from a base register.  The consecutive memory locations end just below this address, and the address of the first of
4084af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// those locations can optionally be written back to the base register.
4085b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Ticebool
40867bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
4087b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice{
4088b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice#if 0
4089b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice    if ConditionPassed() then
4090b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4091b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        address = R[n] - 4*BitCount(registers);
4092b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4093b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        for i = 0 to 14
4094bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
4095b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if i == n && wback && i != LowestSetBit(registers) then
4096b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4097b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                else
4098b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    MemA[address,4] = R[i];
4099b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                address = address + 4;
4100b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4101bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then // Only possible for encoding A1
4102b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            MemA[address,4] = PCStoreValue();
4103b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4104b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        if wback then R[n] = R[n] - 4*BitCount(registers);
4105b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice#endif
4106b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4107b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4108b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice    bool success = false;
4109b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
41107bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
4111b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice    {
4112b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        uint32_t n;
4113b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        uint32_t registers = 0;
4114b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        bool wback;
4115b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
4116b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4117b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4118b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        switch (encoding)
4119b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        {
4120b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            case eEncodingT1:
4121bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if W == '1' && Rn == '1101' then SEE PUSH;
4122b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4123b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                {
4124b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    // See PUSH
4125b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                }
4126bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4127b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                n = Bits32 (opcode, 19, 16);
4128b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = Bits32 (opcode, 15, 0);
4129b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = registers & 0x5fff;  // Make sure bits 15 & 13 are zeros.
4130b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                wback = BitIsSet (opcode, 21);
4131b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4132b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if ((n == 15) || BitCount (registers) < 2)
4133b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    return false;
4134bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if wback && registers<n> == '1' then UNPREDICTABLE;
4135b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if (wback && BitIsSet (registers, n))
4136b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    return false;
4137b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                break;
4138b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4139b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            case eEncodingA1:
4140bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4141b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4142b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                {
4143b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    // See Push
4144b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                }
4145bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = register_list; wback = (W == '1');
4146b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                n = Bits32 (opcode, 19, 16);
4147b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                registers = Bits32 (opcode, 15, 0);
4148b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                wback = BitIsSet (opcode, 21);
4149b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4150b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if ((n == 15) || BitCount (registers) < 1)
4151b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    return false;
4152b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                break;
4153b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4154b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            default:
4155b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                return false;
4156b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        }
4157b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4158b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        // address = R[n] - 4*BitCount(registers);
4159b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4160b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        int32_t offset = 0;
4161bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4162b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        if (!success)
4163b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        return false;
4164b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4165bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t address = Rn - (addr_byte_size * BitCount (registers));
4166b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4167b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        EmulateInstruction::Context context;
4168b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        context.type = EmulateInstruction::eContextRegisterStore;
4169b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        Register base_reg;
4170b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4171b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4172b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        // for i = 0 to 14
4173bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        uint32_t lowest_set_bit = 14;
4174b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        for (int i = 0; i < 14; ++i)
4175b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        {
4176bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if registers<i> == '1' then
4177b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            if (BitIsSet (registers, i))
4178b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            {
4179b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if (i < lowest_set_bit)
4180b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    lowest_set_bit = i;
4181b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                // if i == n && wback && i != LowestSetBit(registers) then
4182b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                if ((i == n) && wback && (i != lowest_set_bit))
4183b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4184b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    WriteBits32UnknownToMemory (address + offset);
4185b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                else
4186b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                {
4187b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    // MemA[address,4] = R[i];
4188b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4189b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    if (!success)
4190b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                        return false;
4191b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4192b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    Register data_reg;
4193b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                    data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4194bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
4195cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                    if (!MemAWrite (context, address + offset, data, addr_byte_size))
4196b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                        return false;
4197b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                }
4198b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4199b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                // address = address + 4;
4200b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                offset += addr_byte_size;
4201b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            }
4202b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        }
4203b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4204bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if registers<15> == '1' then // Only possible for encoding A1
4205b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        //     MemA[address,4] = PCStoreValue();
4206b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        if (BitIsSet (registers, 15))
4207b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        {
4208b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            Register pc_reg;
4209b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4210b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            context.SetRegisterPlusOffset (pc_reg, 8);
42118d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            const uint32_t pc = ReadCoreReg (PC_REG, &success);
4212b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            if (!success)
4213b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                return false;
4214b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
42158d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4216b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                return false;
4217b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        }
4218b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
4219b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        // if wback then R[n] = R[n] - 4*BitCount(registers);
4220b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        if (wback)
4221b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        {
4222af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            offset = (addr_byte_size * BitCount (registers)) * -1;
4223af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
4224af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            context.SetImmediateSigned (offset);
4225bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            addr_t data = Rn + offset;
4226af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4227af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                return false;
4228af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        }
4229af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice    }
4230af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice    return true;
4231af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice}
4232af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4233af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4234af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// from a base register.  The consecutive memory locations start just above this address, and the address of the last
4235af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice// of those locations can optionally be written back to the base register.
4236af556564f80fd417a9158754f5e2ee692e183f6dCaroline Ticebool
42377bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
4238af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice{
4239af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice#if 0
4240af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice    if ConditionPassed() then
4241af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        EncodingSpecificOperations();
4242af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        address = R[n] + 4;
4243af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4244af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        for i = 0 to 14
4245bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if registers<i> == '1' then
4246af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                if i == n && wback && i != LowestSetBit(registers) then
4247af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    MemA[address,4] = bits(32) UNKNOWN;
4248af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                else
4249af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    MemA[address,4] = R[i];
4250af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                address = address + 4;
4251af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4252bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if registers<15> == '1' then
4253af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            MemA[address,4] = PCStoreValue();
4254af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4255af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        if wback then R[n] = R[n] + 4*BitCount(registers);
4256af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice#endif
4257af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4258af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice    bool success = false;
4259af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
42607bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
4261af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice    {
4262af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        uint32_t n;
4263af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        uint32_t registers = 0;
4264af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        bool wback;
4265af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
4266af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4267af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        // EncodingSpecificOperations();
4268af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        switch (encoding)
4269af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        {
4270af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            case eEncodingA1:
4271bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); registers = register_list; wback = (W == '1');
4272af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                n = Bits32 (opcode, 19, 16);
4273af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                registers = Bits32 (opcode, 15, 0);
4274af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                wback = BitIsSet (opcode, 21);
4275af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4276af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4277af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                if ((n == 15) && (BitCount (registers) < 1))
4278af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    return false;
4279af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                break;
4280af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            default:
4281af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                return false;
4282af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        }
4283af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        // address = R[n] + 4;
4284af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4285af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        int32_t offset = 0;
4286bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t Rn = ReadCoreReg (n, &success);
4287af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        if (!success)
4288af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            return false;
4289af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4290bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        addr_t address = Rn + addr_byte_size;
4291af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4292af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        EmulateInstruction::Context context;
4293af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        context.type = EmulateInstruction::eContextRegisterStore;
4294af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        Register base_reg;
4295af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4296af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4297af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        uint32_t lowest_set_bit = 14;
4298af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        // for i = 0 to 14
4299af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        for (int i = 0; i < 14; ++i)
4300af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        {
4301bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if registers<i> == '1' then
4302af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            if (BitIsSet (registers, i))
4303af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            {
4304af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                if (i < lowest_set_bit)
4305af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    lowest_set_bit = i;
4306af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                // if i == n && wback && i != LowestSetBit(registers) then
4307af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                if ((i == n) && wback && (i != lowest_set_bit))
4308af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    // MemA[address,4] = bits(32) UNKNOWN;
4309af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    WriteBits32UnknownToMemory (address + offset);
4310af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                // else
4311af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                else
4312af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                {
4313af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    // MemA[address,4] = R[i];
4314af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4315af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    if (!success)
4316af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                        return false;
4317af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4318af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    Register data_reg;
4319af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                    data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4320bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
4321cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                    if (!MemAWrite (context, address + offset, data, addr_byte_size))
4322af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                        return false;
4323af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                }
4324af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4325af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                // address = address + 4;
4326af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                offset += addr_byte_size;
4327af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            }
4328af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        }
4329af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4330bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if registers<15> == '1' then
4331af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            // MemA[address,4] = PCStoreValue();
4332af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        if (BitIsSet (registers, 15))
4333af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        {
4334af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            Register pc_reg;
4335af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4336af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            context.SetRegisterPlusOffset (pc_reg, 8);
43378d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            const uint32_t pc = ReadCoreReg (PC_REG, &success);
4338af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            if (!success)
4339af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice            return false;
4340af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
43418d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
4342af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice                return false;
4343af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        }
4344af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
4345af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        // if wback then R[n] = R[n] + 4*BitCount(registers);
4346af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        if (wback)
4347af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        {
4348b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            offset = addr_byte_size * BitCount (registers);
4349b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            context.type = EmulateInstruction::eContextAdjustBaseRegister;
4350b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            context.SetImmediateSigned (offset);
4351bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            addr_t data = Rn + offset;
4352b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4353b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice                return false;
4354b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        }
4355b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice    }
4356b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice    return true;
4357b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice}
43587fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
43597fac857ec72051dc0a91b027719c275ea672a470Caroline Tice// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
43607fac857ec72051dc0a91b027719c275ea672a470Caroline Tice// from a register to memory.  It can use offset, post-indexed, or pre-indexed addressing.
43617fac857ec72051dc0a91b027719c275ea672a470Caroline Ticebool
43627bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
43637fac857ec72051dc0a91b027719c275ea672a470Caroline Tice{
43647fac857ec72051dc0a91b027719c275ea672a470Caroline Tice#if 0
43657fac857ec72051dc0a91b027719c275ea672a470Caroline Tice    if ConditionPassed() then
43667fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
43677fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
43687fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        address = if index then offset_addr else R[n];
4369bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<1:0> == '00' then
43707fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            MemU[address,4] = R[t];
43717fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        else // Can only occur before ARMv7
43727fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            MemU[address,4] = bits(32) UNKNOWN;
43737fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        if wback then R[n] = offset_addr;
43747fac857ec72051dc0a91b027719c275ea672a470Caroline Tice#endif
43757fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
43767fac857ec72051dc0a91b027719c275ea672a470Caroline Tice    bool success = false;
43777fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
43787bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
43797fac857ec72051dc0a91b027719c275ea672a470Caroline Tice    {
43807fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
43817fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
43827fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        uint32_t t;
43837fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        uint32_t n;
43847fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        uint32_t imm32;
43857fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        bool index;
43867fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        bool add;
43877fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        bool wback;
43887fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
43897fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        switch (encoding)
43907fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        {
43917fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            case eEncodingT1:
4392bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
43937fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                t = Bits32 (opcode, 2, 0);
43947fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                n = Bits32 (opcode, 5, 3);
43957fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                imm32 = Bits32 (opcode, 10, 6) << 2;
43967fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
43977fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
43987fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                index = true;
43997fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                add = false;
44007fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                wback = false;
44017fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                break;
44027fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44037fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            case eEncodingT2:
4404bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
44057fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                t = Bits32 (opcode, 10, 8);
44067fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                n = 13;
44077fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                imm32 = Bits32 (opcode, 7, 0) << 2;
44087fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44097fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
44107fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                index = true;
44117fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                add = true;
44127fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                wback = false;
44137fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                break;
44147fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44157fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            case eEncodingT3:
4416bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then UNDEFINED;
44177fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                if (Bits32 (opcode, 19, 16) == 15)
44187fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                    return false;
44197fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44207fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
44217fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                t = Bits32 (opcode, 15, 12);
44227fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                n = Bits32 (opcode, 19, 16);
44237fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
44247fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44257fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
44267fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                index = true;
44277fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                add = true;
44287fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                wback = false;
44297fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44307fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                // if t == 15 then UNPREDICTABLE;
44317fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                if (t == 15)
44327fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                    return false;
44337fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                break;
44347fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44357fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            case eEncodingT4:
4436bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '1' && U == '1' && W == '0' then SEE STRT;
4437bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4438bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
44397fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                if ((Bits32 (opcode, 19, 16) == 15)
44407fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                      || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
44417fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                    return false;
44427fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44437fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
44447fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                t = Bits32 (opcode, 15, 12);
44457fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                n = Bits32 (opcode, 19, 16);
44467fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                imm32 = Bits32 (opcode, 7, 0);
44477fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
4448bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
44497fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                index = BitIsSet (opcode, 10);
44507fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                add = BitIsSet (opcode, 9);
44517fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                wback = BitIsSet (opcode, 8);
44527fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44537fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                // if t == 15 || (wback && n == t) then UNPREDICTABLE;
44547fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                if ((t == 15) || (wback && (n == t)))
44557fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                    return false;
44567fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                break;
44577fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44587fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            default:
44597fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                return false;
44607fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        }
44617fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44627fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        addr_t offset_addr;
44637fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        addr_t address;
4464b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice
44657fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4466baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        uint32_t base_address = ReadCoreReg (n, &success);
44677fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        if (!success)
44687fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            return false;
44697fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44707fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        if (add)
44717fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            offset_addr = base_address + imm32;
44727fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        else
44737fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            offset_addr = base_address - imm32;
44747fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44757fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        // address = if index then offset_addr else R[n];
44767fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        if (index)
44777fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            address = offset_addr;
44787fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        else
44797fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            address = base_address;
44807fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44817fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        EmulateInstruction::Context context;
44827fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        context.type = eContextRegisterStore;
44837fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        Register base_reg;
44847fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +  n);
44857fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
4486bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<1:0> == '00' then
44877fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
44887fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        {
44897fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            // MemU[address,4] = R[t];
44907fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
44917fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            if (!success)
44927fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                return false;
44937fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
44947fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            Register data_reg;
44957fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
44967fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            int32_t offset = address - base_address;
44977fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
4498cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            if (!MemUWrite (context, address, data, addr_byte_size))
44997fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                return false;
45007fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        }
45017fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        else
45027fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        {
45037fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            // MemU[address,4] = bits(32) UNKNOWN;
45047fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            WriteBits32UnknownToMemory (address);
45057fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        }
45067fac857ec72051dc0a91b027719c275ea672a470Caroline Tice
45077fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        // if wback then R[n] = offset_addr;
45087fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        if (wback)
45097fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        {
45107fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            context.type = eContextRegisterLoad;
45117fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            context.SetAddress (offset_addr);
45127fac857ec72051dc0a91b027719c275ea672a470Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
45137fac857ec72051dc0a91b027719c275ea672a470Caroline Tice                return false;
45147fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        }
45157fac857ec72051dc0a91b027719c275ea672a470Caroline Tice    }
45167fac857ec72051dc0a91b027719c275ea672a470Caroline Tice    return true;
45177fac857ec72051dc0a91b027719c275ea672a470Caroline Tice}
4518af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice
45193fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
45203fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice// word from a register to memory.   The offset register value can optionally be shifted.
45213fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Ticebool
45227bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
45233fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice{
45243fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice#if 0
45253fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice    if ConditionPassed() then
45263fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
45273fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        offset = Shift(R[m], shift_t, shift_n, APSR.C);
45283fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        offset_addr = if add then (R[n] + offset) else (R[n] - offset);
45293fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        address = if index then offset_addr else R[n];
45303fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if t == 15 then // Only possible for encoding A1
45313fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            data = PCStoreValue();
45323fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        else
45333fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            data = R[t];
4534bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
45353fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            MemU[address,4] = data;
45363fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        else // Can only occur before ARMv7
45373fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            MemU[address,4] = bits(32) UNKNOWN;
45383fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if wback then R[n] = offset_addr;
45393fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice#endif
45403fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45413fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice    bool success = false;
45423fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45437bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
45443fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice    {
45453fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
45463fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45473fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        uint32_t t;
45483fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        uint32_t n;
45493fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        uint32_t m;
45503fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        ARM_ShifterType shift_t;
45513fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        uint32_t shift_n;
45523fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        bool index;
45533fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        bool add;
45543fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        bool wback;
45553fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45563fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
45573fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        switch (encoding)
45583fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        {
45593fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            case eEncodingT1:
45603fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
45613fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
45623fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                t = Bits32 (opcode, 2, 0);
45633fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                n = Bits32 (opcode, 5, 3);
45643fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                m = Bits32 (opcode, 8, 6);
45653fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45663fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
45673fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                index = true;
45683fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                add = true;
45693fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                wback = false;
45703fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45713fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
45723fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                shift_t = SRType_LSL;
45733fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                shift_n = 0;
45743fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                break;
45753fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45763fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            case eEncodingT2:
4577bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then UNDEFINED;
45783fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                if (Bits32 (opcode, 19, 16) == 15)
45793fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                    return false;
45803fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45813fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
45823fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                t = Bits32 (opcode, 15, 12);
45833fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                n = Bits32 (opcode, 19, 16);
45843fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                m = Bits32 (opcode, 3, 0);
45853fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45863fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
45873fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                index = true;
45883fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                add = true;
45893fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                wback = false;
45903fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45913fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
45923fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                shift_t = SRType_LSL;
45933fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                shift_n = Bits32 (opcode, 5, 4);
45943fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
45953fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // if t == 15 || BadReg(m) then UNPREDICTABLE;
45963fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                if ((t == 15) || (BadReg (m)))
45973fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                    return false;
45983fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                break;
45993fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46003fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            case eEncodingA1:
46013fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            {
4602bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE STRT;
46033fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
46043fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                t = Bits32 (opcode, 15, 12);
46053fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                n = Bits32 (opcode, 19, 16);
46063fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                m = Bits32 (opcode, 3, 0);
46073fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
4608bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
46093fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                index = BitIsSet (opcode, 24);
46103fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                add = BitIsSet (opcode, 23);
46113fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
46123fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46133fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
46143fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                uint32_t typ = Bits32 (opcode, 6, 5);
46153fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                uint32_t imm5 = Bits32 (opcode, 11, 7);
46163fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                shift_n = DecodeImmShift(typ, imm5, shift_t);
46173fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46183fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // if m == 15 then UNPREDICTABLE;
46193fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                if (m == 15)
46203fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                    return false;
46213fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46223fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
46233fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                if (wback && ((n == 15) || (n == t)))
46243fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                    return false;
46253fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46263fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                break;
46273fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            }
46283fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            default:
46293fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                return false;
46303fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        }
46313fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46323fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        addr_t offset_addr;
46333fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        addr_t address;
46343fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        int32_t offset = 0;
46353fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46363fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
46373fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (!success)
46383fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            return false;
46393fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46403fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
46413fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (!success)
46423fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            return false;
46433fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46443fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4645e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
46463fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46473fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
46483fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (add)
46493fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            offset_addr = base_address + offset;
46503fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        else
46513fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            offset_addr = base_address - offset;
46523fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46533fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        // address = if index then offset_addr else R[n];
46543fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (index)
46553fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            address = offset_addr;
46563fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        else
46573fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            address = base_address;
46583fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46593fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        uint32_t data;
46603fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        // if t == 15 then // Only possible for encoding A1
46613fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (t == 15)
46623fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            // data = PCStoreValue();
46638d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            data = ReadCoreReg (PC_REG, &success);
46643fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        else
46653fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            // data = R[t];
46663fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
46673fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46683fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (!success)
46693fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            return false;
46703fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46713fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        EmulateInstruction::Context context;
46723fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        context.type = eContextRegisterStore;
46733fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
4674bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
46753fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (UnalignedSupport ()
46763fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            || (BitIsClear (address, 1) && BitIsClear (address, 0))
46773fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            || CurrentInstrSet() == eModeARM)
46783fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        {
46793fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            // MemU[address,4] = data;
46803fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46813fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            Register base_reg;
46823fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +  n);
46833fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46843fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            Register data_reg;
46853fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
46863fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46873fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4688cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice            if (!MemUWrite (context, address, data, addr_byte_size))
46893fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                return false;
46903fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46913fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        }
46923fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        else
46933fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            // MemU[address,4] = bits(32) UNKNOWN;
46943fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            WriteBits32UnknownToMemory (address);
46953fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
46963fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        // if wback then R[n] = offset_addr;
46973fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        if (wback)
46983fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        {
46993fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            context.type = eContextRegisterLoad;
47003fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            context.SetAddress (offset_addr);
47013fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
47023fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice                return false;
47033fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        }
47043fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
47053fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice    }
47063fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice    return true;
47073fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice}
470873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
470973a29de4b8f59594fd7a559c05fa795afe754551Caroline Ticebool
47107bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
471173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice{
471273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice#if 0
471373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice    if ConditionPassed() then
471473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
471573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
471673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        address = if index then offset_addr else R[n];
471773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        MemU[address,1] = R[t]<7:0>;
471873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        if wback then R[n] = offset_addr;
471973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice#endif
472073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
472173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
472273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice    bool success = false;
472373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
47247bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
472573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice    {
472673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        uint32_t t;
472773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        uint32_t n;
472873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        uint32_t imm32;
472973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        bool index;
473073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        bool add;
473173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        bool wback;
473273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
473373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        switch (encoding)
473473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        {
473573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            case eEncodingT1:
473673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
473773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                t = Bits32 (opcode, 2, 0);
473873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                n = Bits32 (opcode, 5, 3);
473973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                imm32 = Bits32 (opcode, 10, 6);
474073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
474173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
474273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                index = true;
474373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                add = true;
474473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                wback = false;
474573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                break;
474673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
474773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            case eEncodingT2:
4748bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then UNDEFINED;
474973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                if (Bits32 (opcode, 19, 16) == 15)
475073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                    return false;
475173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
475273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
475373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                t = Bits32 (opcode, 15, 12);
475473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                n = Bits32 (opcode, 19, 16);
475573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
475673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
475773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
475873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                index = true;
475973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                add = true;
476073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                wback = false;
476173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
476273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                // if BadReg(t) then UNPREDICTABLE;
476373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                if (BadReg (t))
476473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                    return false;
476573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                break;
476673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
476773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            case eEncodingT3:
4768bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4769bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
477073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                if (Bits32 (opcode, 19, 16) == 15)
477173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                    return false;
477273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
477373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
477473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                t = Bits32 (opcode, 15, 12);
477573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                n = Bits32 (opcode, 19, 16);
477673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                imm32 = Bits32 (opcode, 7, 0);
477773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
4778bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
477973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                index = BitIsSet (opcode, 10);
478073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                add = BitIsSet (opcode, 9);
478173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                wback = BitIsSet (opcode, 8);
478273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
478373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
478473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                if ((BadReg (t)) || (wback && (n == t)))
478573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                    return false;
478673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                break;
478773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
478873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            default:
478973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                return false;
479073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        }
479173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
479273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        addr_t offset_addr;
479373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        addr_t address;
479473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
479573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        if (!success)
479673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            return false;
479773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
479873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
479973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        if (add)
480073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            offset_addr = base_address + imm32;
480173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        else
480273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            offset_addr = base_address - imm32;
480373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
480473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        // address = if index then offset_addr else R[n];
480573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        if (index)
480673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            address = offset_addr;
480773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        else
480873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            address = base_address;
480973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
4810cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice        // MemU[address,1] = R[t]<7:0>
481173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        Register base_reg;
481273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
481373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
481473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        Register data_reg;
481573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
481673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
481773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        EmulateInstruction::Context context;
481873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        context.type = eContextRegisterStore;
481973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
482073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
482173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
482273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        if (!success)
482373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            return false;
482473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
482573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        data = Bits32 (data, 7, 0);
482673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
4827cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice        if (!MemUWrite (context, address, data, 1))
482873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            return false;
482973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
483073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        // if wback then R[n] = offset_addr;
483173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        if (wback)
483273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        {
483373a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            context.type = eContextRegisterLoad;
483473a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            context.SetAddress (offset_addr);
483573a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
483673a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice                return false;
483773a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice        }
483873a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
483973a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice    }
484073a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice
484173a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice    return true;
484273a29de4b8f59594fd7a559c05fa795afe754551Caroline Tice}
48438ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48448ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice// STRH (register) calculates an address from a base register value and an offset register value, and stores a
48458ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice// halfword from a register to memory.  The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
48468ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Ticebool
48477bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
48488ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice{
48498ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice#if 0
48508ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice    if ConditionPassed() then
48518ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
48528ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        offset = Shift(R[m], shift_t, shift_n, APSR.C);
48538ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        offset_addr = if add then (R[n] + offset) else (R[n] - offset);
48548ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        address = if index then offset_addr else R[n];
4855bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<0> == '0' then
48568ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            MemU[address,2] = R[t]<15:0>;
48578ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        else // Can only occur before ARMv7
48588ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            MemU[address,2] = bits(16) UNKNOWN;
48598ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        if wback then R[n] = offset_addr;
48608ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice#endif
48618ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48628ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice    bool success = false;
48638ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48647bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
48658ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice    {
48668ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        uint32_t t;
48678ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        uint32_t n;
48688ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        uint32_t m;
48698ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        bool index;
48708ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        bool add;
48718ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        bool wback;
48728ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        ARM_ShifterType shift_t;
48738ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        uint32_t shift_n;
48748ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48758ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
48768ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        switch (encoding)
48778ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        {
48788ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            case eEncodingT1:
48798ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
48808ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
48818ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                t = Bits32 (opcode, 2, 0);
48828ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                n = Bits32 (opcode, 5, 3);
48838ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                m = Bits32 (opcode, 8, 6);
48848ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48858ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
48868ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                index = true;
48878ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                add = true;
48888ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                wback = false;
48898ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48908ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
48918ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                shift_t = SRType_LSL;
48928ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                shift_n = 0;
48938ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48948ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                break;
48958ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
48968ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            case eEncodingT2:
4897bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then UNDEFINED;
48988ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
48998ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                t = Bits32 (opcode, 15, 12);
49008ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                n = Bits32 (opcode, 19, 16);
49018ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                m = Bits32 (opcode, 3, 0);
49028ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                if (n == 15)
49038ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                    return false;
49048ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49058ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
49068ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                index = true;
49078ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                add = true;
49088ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                wback = false;
49098ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49108ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
49118ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                shift_t = SRType_LSL;
49128ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                shift_n = Bits32 (opcode, 5, 4);
49138ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49148ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
49158ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                if (BadReg (t) || BadReg (m))
49168ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                    return false;
49178ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49188ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                break;
49198ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49208ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            case eEncodingA1:
4921bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE STRHT;
49228ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
49238ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                t = Bits32 (opcode, 15, 12);
49248ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                n = Bits32 (opcode, 19, 16);
49258ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                m = Bits32 (opcode, 3, 0);
49268ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
4927bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
49288ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                index = BitIsSet (opcode, 24);
49298ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                add = BitIsSet (opcode, 23);
49308ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
49318ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49328ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
49338ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                shift_t = SRType_LSL;
49348ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                shift_n = 0;
49358ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49368ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // if t == 15 || m == 15 then UNPREDICTABLE;
49378ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                if ((t == 15) || (m == 15))
49388ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                    return false;
49398ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49408ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
49418ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                if (wback && ((n == 15) || (n == t)))
49428ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                    return false;
49438ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49448ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                break;
49458ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49468ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            default:
49478ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                return false;
49488ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        }
49498ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49508ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        uint32_t Rm = ReadCoreReg (m, &success);
49518ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        if (!success)
49528ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            return false;
49538ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49548ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
49558ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        if (!success)
49568ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            return false;
49578ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49588ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        // offset = Shift(R[m], shift_t, shift_n, APSR.C);
49598ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
49608ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49618ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
49628ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        addr_t offset_addr;
49638ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        if (add)
49648ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            offset_addr = Rn + offset;
49658ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        else
49668ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            offset_addr = Rn - offset;
49678ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49688ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        // address = if index then offset_addr else R[n];
49698ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        addr_t address;
49708ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        if (index)
49718ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            address = offset_addr;
49728ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        else
49738ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            address = Rn;
49748ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49758ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        EmulateInstruction::Context context;
49768ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        context.type = eContextRegisterStore;
49778ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        Register base_reg;
49788ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
49798ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        Register offset_reg;
49808ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
49818ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
4982bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<0> == '0' then
49838ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        if (UnalignedSupport() || BitIsClear (address, 0))
49848ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        {
49858ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            // MemU[address,2] = R[t]<15:0>;
49868ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            uint32_t Rt = ReadCoreReg (t, &success);
49878ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            if (!success)
49888ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                return false;
49898ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
49908ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            EmulateInstruction::Context context;
49918ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            context.type = eContextRegisterStore;
49928ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            Register base_reg;
49938ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
49948ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            Register offset_reg;
49958ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
49968ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            Register data_reg;
49978ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
49988ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
49998ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
50008ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
50018ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                return false;
50028ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        }
50038ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        else // Can only occur before ARMv7
50048ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        {
50058ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            // MemU[address,2] = bits(16) UNKNOWN;
50068ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        }
50078ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
50088ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        // if wback then R[n] = offset_addr;
50098ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        if (wback)
50108ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        {
50118ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            context.type = eContextAdjustBaseRegister;
50128ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            context.SetAddress (offset_addr);
50138ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
50148ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice                return false;
50158ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        }
50168ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice    }
50178ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice
50188ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice    return true;
50198ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice}
50203fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice
5021157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5022157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen// and writes the result to the destination register.  It can optionally update the condition flags
5023157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen// based on the result.
5024157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chenbool
50257bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
5026157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen{
5027157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen#if 0
5028157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    // ARM pseudo code...
5029157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    if ConditionPassed() then
5030157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        EncodingSpecificOperations();
5031157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5032157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
5033157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
5034157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        else
5035157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            R[d] = result;
5036157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            if setflags then
5037157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.N = result<31>;
5038157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.Z = IsZeroBit(result);
5039157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.C = carry;
5040157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.V = overflow;
5041157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen#endif
5042157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5043157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    bool success = false;
5044157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
50457bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5046157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    {
5047157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t Rd, Rn;
5048157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5049157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        bool setflags;
5050157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        switch (encoding)
5051157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        {
5052157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        case eEncodingT1:
5053157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rd = Bits32(opcode, 11, 8);
5054157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rn = Bits32(opcode, 19, 16);
5055157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            setflags = BitIsSet(opcode, 20);
5056157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5057157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            if (BadReg(Rd) || BadReg(Rn))
5058157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                return false;
5059157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            break;
5060157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        case eEncodingA1:
5061157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rd = Bits32(opcode, 15, 12);
5062157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rn = Bits32(opcode, 19, 16);
5063157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            setflags = BitIsSet(opcode, 20);
5064157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5065157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
5066157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            if (Rd == 15 && setflags)
5067157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                return false;
5068157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            break;
5069157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        default:
5070157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            return false;
5071157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        }
5072157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5073157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // Read the first operand.
5074157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        int32_t val1 = ReadCoreReg(Rn, &success);
5075157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        if (!success)
5076157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            return false;
5077157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5078157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5079157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5080157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        EmulateInstruction::Context context;
5081157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
5082157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        context.SetNoArgs ();
5083157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5084157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5085157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            return false;
5086157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    }
5087157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    return true;
5088157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen}
5089157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5090157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5091157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen// register value, and writes the result to the destination register.  It can optionally update the
5092157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen// condition flags based on the result.
5093157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chenbool
50947bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
5095157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen{
5096157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen#if 0
5097157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    // ARM pseudo code...
5098157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    if ConditionPassed() then
5099157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        EncodingSpecificOperations();
5100157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5101157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5102157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
5103157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
5104157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        else
5105157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            R[d] = result;
5106157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            if setflags then
5107157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.N = result<31>;
5108157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.Z = IsZeroBit(result);
5109157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.C = carry;
5110157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                APSR.V = overflow;
5111157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen#endif
5112157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5113157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    bool success = false;
5114157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
51157bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5116157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    {
5117157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t Rd, Rn, Rm;
5118157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        ARM_ShifterType shift_t;
5119157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
5120157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        bool setflags;
5121157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        switch (encoding)
5122157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        {
5123157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        case eEncodingT1:
5124157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rd = Rn = Bits32(opcode, 2, 0);
5125157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rm = Bits32(opcode, 5, 3);
5126157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            setflags = !InITBlock();
5127157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            shift_t = SRType_LSL;
5128157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            shift_n = 0;
5129ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
5130157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        case eEncodingT2:
5131157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rd = Bits32(opcode, 11, 8);
5132157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rn = Bits32(opcode, 19, 16);
5133157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rm = Bits32(opcode, 3, 0);
5134157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            setflags = BitIsSet(opcode, 20);
51353dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
5136157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5137157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                return false;
5138157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            break;
5139157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        case eEncodingA1:
5140157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rd = Bits32(opcode, 15, 12);
5141157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rn = Bits32(opcode, 19, 16);
5142157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            Rm = Bits32(opcode, 3, 0);
5143157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            setflags = BitIsSet(opcode, 20);
51443dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
5145157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
5146157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            if (Rd == 15 && setflags)
5147157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen                return false;
5148157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            break;
5149157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        default:
5150157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            return false;
5151157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        }
5152157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5153157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // Read the first operand.
5154157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        int32_t val1 = ReadCoreReg(Rn, &success);
5155157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        if (!success)
5156157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            return false;
5157157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5158157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // Read the second operand.
5159157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        int32_t val2 = ReadCoreReg(Rm, &success);
5160157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        if (!success)
5161157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            return false;
5162157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5163157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5164157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5165157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5166157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        EmulateInstruction::Context context;
5167157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
5168157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        context.SetNoArgs ();
5169157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5170157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5171157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            return false;
5172157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    }
5173157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    return true;
5174157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen}
5175157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
5176a695f958db37c102d480a9c0780abec262ba8332Johnny Chen// This instruction adds an immediate value to the PC value to form a PC-relative address,
5177a695f958db37c102d480a9c0780abec262ba8332Johnny Chen// and writes the result to the destination register.
5178a695f958db37c102d480a9c0780abec262ba8332Johnny Chenbool
51797bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
5180a695f958db37c102d480a9c0780abec262ba8332Johnny Chen{
5181a695f958db37c102d480a9c0780abec262ba8332Johnny Chen#if 0
5182a695f958db37c102d480a9c0780abec262ba8332Johnny Chen    // ARM pseudo code...
5183a695f958db37c102d480a9c0780abec262ba8332Johnny Chen    if ConditionPassed() then
5184a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        EncodingSpecificOperations();
5185a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5186a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        if d == 15 then         // Can only occur for ARM encodings
5187a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            ALUWritePC(result);
5188a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        else
5189a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            R[d] = result;
5190a695f958db37c102d480a9c0780abec262ba8332Johnny Chen#endif
5191a695f958db37c102d480a9c0780abec262ba8332Johnny Chen
5192a695f958db37c102d480a9c0780abec262ba8332Johnny Chen    bool success = false;
5193a695f958db37c102d480a9c0780abec262ba8332Johnny Chen
51947bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5195a695f958db37c102d480a9c0780abec262ba8332Johnny Chen    {
5196a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        uint32_t Rd;
5197a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5198a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        bool add;
5199a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        switch (encoding)
5200a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        {
5201a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        case eEncodingT1:
5202a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            Rd = Bits32(opcode, 10, 8);
5203a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5204a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            break;
5205a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        case eEncodingT2:
5206a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        case eEncodingT3:
5207a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            Rd = Bits32(opcode, 11, 8);
5208a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5209a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5210a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            if (BadReg(Rd))
5211a695f958db37c102d480a9c0780abec262ba8332Johnny Chen                return false;
5212a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            break;
5213a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        case eEncodingA1:
5214a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        case eEncodingA2:
5215a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            Rd = Bits32(opcode, 15, 12);
5216a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5217a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5218a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            break;
5219a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        default:
5220a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            return false;
5221a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        }
5222a695f958db37c102d480a9c0780abec262ba8332Johnny Chen
5223a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        // Read the PC value.
5224a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        uint32_t pc = ReadCoreReg(PC_REG, &success);
5225a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        if (!success)
5226a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            return false;
5227a695f958db37c102d480a9c0780abec262ba8332Johnny Chen
5228a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5229a695f958db37c102d480a9c0780abec262ba8332Johnny Chen
5230a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        EmulateInstruction::Context context;
5231a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
5232a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        context.SetNoArgs ();
5233a695f958db37c102d480a9c0780abec262ba8332Johnny Chen
5234a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        if (!WriteCoreReg(context, result, Rd))
5235a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            return false;
5236a695f958db37c102d480a9c0780abec262ba8332Johnny Chen    }
5237a695f958db37c102d480a9c0780abec262ba8332Johnny Chen    return true;
5238a695f958db37c102d480a9c0780abec262ba8332Johnny Chen}
5239a695f958db37c102d480a9c0780abec262ba8332Johnny Chen
5240e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5241e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen// to the destination register.  It can optionally update the condition flags based on the result.
5242e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chenbool
52437bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
5244e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen{
5245e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen#if 0
5246e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    // ARM pseudo code...
5247e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    if ConditionPassed() then
5248e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        EncodingSpecificOperations();
5249e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        result = R[n] AND imm32;
5250e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
5251e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
5252e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        else
5253e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            R[d] = result;
5254e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if setflags then
5255e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                APSR.N = result<31>;
5256e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                APSR.Z = IsZeroBit(result);
5257e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                APSR.C = carry;
5258e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                // APSR.V unchanged
5259e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen#endif
5260e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5261e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    bool success = false;
5262e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
52637bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5264e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    {
5265e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t Rd, Rn;
5266e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5267e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        bool setflags;
5268e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5269e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        switch (encoding)
5270e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        {
5271e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        case eEncodingT1:
5272e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rd = Bits32(opcode, 11, 8);
5273e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rn = Bits32(opcode, 19, 16);
5274e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            setflags = BitIsSet(opcode, 20);
5275e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5276de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            // if Rd == '1111' && S == '1' then SEE TST (immediate);
5277e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if (Rd == 15 && setflags)
52787bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                return EmulateTSTImm(opcode, eEncodingT1);
5279e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5280e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                return false;
5281e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            break;
5282e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        case eEncodingA1:
5283e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rd = Bits32(opcode, 15, 12);
5284e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rn = Bits32(opcode, 19, 16);
5285e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            setflags = BitIsSet(opcode, 20);
5286e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5287e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
5288e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if (Rd == 15 && setflags)
5289e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                return false;
5290e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            break;
5291e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        default:
5292e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            return false;
5293e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        }
5294e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5295e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        // Read the first operand.
5296157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
5297e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        if (!success)
5298e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            return false;
5299e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5300e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t result = val1 & imm32;
5301e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5302e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        EmulateInstruction::Context context;
5303e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
5304e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        context.SetNoArgs ();
5305e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5306e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5307e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            return false;
5308e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    }
5309e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    return true;
5310e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen}
5311e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5312e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5313e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen// and writes the result to the destination register.  It can optionally update the condition flags
5314e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen// based on the result.
5315e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chenbool
53167bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
5317e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen{
5318e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen#if 0
5319e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    // ARM pseudo code...
5320e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    if ConditionPassed() then
5321e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        EncodingSpecificOperations();
5322e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5323e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        result = R[n] AND shifted;
5324e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
5325e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
5326e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        else
5327e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            R[d] = result;
5328e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if setflags then
5329e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                APSR.N = result<31>;
5330e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                APSR.Z = IsZeroBit(result);
5331e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                APSR.C = carry;
5332e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                // APSR.V unchanged
5333e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen#endif
5334e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5335e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    bool success = false;
5336e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
53377bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5338e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    {
5339e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t Rd, Rn, Rm;
5340e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        ARM_ShifterType shift_t;
5341e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
5342e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        bool setflags;
5343e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t carry;
5344e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        switch (encoding)
5345e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        {
5346e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        case eEncodingT1:
5347e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rd = Rn = Bits32(opcode, 2, 0);
5348e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rm = Bits32(opcode, 5, 3);
5349e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            setflags = !InITBlock();
5350e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            shift_t = SRType_LSL;
5351e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            shift_n = 0;
5352ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
5353e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        case eEncodingT2:
5354e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rd = Bits32(opcode, 11, 8);
5355e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rn = Bits32(opcode, 19, 16);
5356e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rm = Bits32(opcode, 3, 0);
5357e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            setflags = BitIsSet(opcode, 20);
53583dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
5359de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            // if Rd == '1111' && S == '1' then SEE TST (register);
5360e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if (Rd == 15 && setflags)
53617bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                return EmulateTSTReg(opcode, eEncodingT2);
5362e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5363e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                return false;
5364e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            break;
5365e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        case eEncodingA1:
5366e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rd = Bits32(opcode, 15, 12);
5367e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rn = Bits32(opcode, 19, 16);
5368e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            Rm = Bits32(opcode, 3, 0);
5369e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            setflags = BitIsSet(opcode, 20);
53703dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
5371e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
5372e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            if (Rd == 15 && setflags)
5373e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen                return false;
5374e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            break;
5375e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        default:
5376e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            return false;
5377e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        }
5378e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5379e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        // Read the first operand.
5380157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
5381e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        if (!success)
5382e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            return false;
5383e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5384e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        // Read the second operand.
5385157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        uint32_t val2 = ReadCoreReg(Rm, &success);
5386e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        if (!success)
5387e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            return false;
5388e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5389e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5390e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        uint32_t result = val1 & shifted;
5391e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5392e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        EmulateInstruction::Context context;
5393e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
5394e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        context.SetNoArgs ();
5395e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5396e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5397e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen            return false;
5398e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    }
5399e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen    return true;
5400e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen}
5401e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen
5402b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5403b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen// immediate value, and writes the result to the destination register.  It can optionally update the
5404b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen// condition flags based on the result.
5405b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chenbool
54067bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
5407b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen{
5408b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen#if 0
5409b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    // ARM pseudo code...
5410b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    if ConditionPassed() then
5411b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        EncodingSpecificOperations();
5412b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        result = R[n] AND NOT(imm32);
5413b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
5414b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
5415b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        else
5416b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            R[d] = result;
5417b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            if setflags then
5418b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                APSR.N = result<31>;
5419b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                APSR.Z = IsZeroBit(result);
5420b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                APSR.C = carry;
5421b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                // APSR.V unchanged
5422b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen#endif
5423b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5424b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    bool success = false;
5425b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
54267bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5427b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    {
5428b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t Rd, Rn;
5429b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5430b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        bool setflags;
5431b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5432b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        switch (encoding)
5433b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        {
5434b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        case eEncodingT1:
5435b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rd = Bits32(opcode, 11, 8);
5436b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rn = Bits32(opcode, 19, 16);
5437b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            setflags = BitIsSet(opcode, 20);
5438b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5439b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            if (BadReg(Rd) || BadReg(Rn))
5440b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                return false;
5441b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            break;
5442b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        case eEncodingA1:
5443b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rd = Bits32(opcode, 15, 12);
5444b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rn = Bits32(opcode, 19, 16);
5445b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            setflags = BitIsSet(opcode, 20);
5446b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5447bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5448b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
5449b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            if (Rd == 15 && setflags)
5450b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                return false;
5451b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            break;
5452b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        default:
5453b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            return false;
5454b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        }
5455b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5456b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        // Read the first operand.
5457b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
5458b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        if (!success)
5459b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            return false;
5460b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5461b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t result = val1 & ~imm32;
5462b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5463b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        EmulateInstruction::Context context;
5464b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
5465b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        context.SetNoArgs ();
5466b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5467b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5468b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            return false;
5469b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    }
5470b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    return true;
5471b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen}
5472b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5473b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5474b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen// optionally-shifted register value, and writes the result to the destination register.
5475b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen// It can optionally update the condition flags based on the result.
5476b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chenbool
54777bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
5478b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen{
5479b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen#if 0
5480b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    // ARM pseudo code...
5481b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    if ConditionPassed() then
5482b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        EncodingSpecificOperations();
5483b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5484b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        result = R[n] AND NOT(shifted);
5485b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
5486b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
5487b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        else
5488b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            R[d] = result;
5489b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            if setflags then
5490b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                APSR.N = result<31>;
5491b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                APSR.Z = IsZeroBit(result);
5492b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                APSR.C = carry;
5493b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                // APSR.V unchanged
5494b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen#endif
5495b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5496b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    bool success = false;
5497b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
54987bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5499b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    {
5500b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t Rd, Rn, Rm;
5501b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        ARM_ShifterType shift_t;
5502b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
5503b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        bool setflags;
5504b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t carry;
5505b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        switch (encoding)
5506b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        {
5507b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        case eEncodingT1:
5508b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rd = Rn = Bits32(opcode, 2, 0);
5509b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rm = Bits32(opcode, 5, 3);
5510b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            setflags = !InITBlock();
5511b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            shift_t = SRType_LSL;
5512b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            shift_n = 0;
5513b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            break;
5514b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        case eEncodingT2:
5515b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rd = Bits32(opcode, 11, 8);
5516b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rn = Bits32(opcode, 19, 16);
5517b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rm = Bits32(opcode, 3, 0);
5518b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            setflags = BitIsSet(opcode, 20);
5519b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
5520b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5521b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                return false;
5522b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            break;
5523b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        case eEncodingA1:
5524b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rd = Bits32(opcode, 15, 12);
5525b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rn = Bits32(opcode, 19, 16);
5526b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            Rm = Bits32(opcode, 3, 0);
5527b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            setflags = BitIsSet(opcode, 20);
5528b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
5529bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
5530b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
5531b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            if (Rd == 15 && setflags)
5532b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen                return false;
5533b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            break;
5534b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        default:
5535b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            return false;
5536b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        }
5537b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5538b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        // Read the first operand.
5539b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
5540b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        if (!success)
5541b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            return false;
5542b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5543b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        // Read the second operand.
5544b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t val2 = ReadCoreReg(Rm, &success);
5545b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        if (!success)
5546b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            return false;
5547b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5548b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5549b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        uint32_t result = val1 & ~shifted;
5550b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5551b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        EmulateInstruction::Context context;
5552b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
5553b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        context.SetNoArgs ();
5554b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
5555b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5556b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen            return false;
5557b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    }
5558b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen    return true;
5559b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen}
5560b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen
55614d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word
5562e92b27c9262fd185359e6e2184b20d08953485f4Johnny Chen// from memory, and writes it to a register.  It can use offset, post-indexed, or pre-indexed addressing.
55634d729c559d039181f250e0e3cd444fa73638f26fCaroline Ticebool
55647bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
55654d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice{
55664d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice#if 0
55674d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice    if ConditionPassed() then
55684d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        EncodingSpecificOperations();
55694d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
55704d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        address = if index then offset_addr else R[n];
55714d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        data = MemU[address,4];
55724d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if wback then R[n] = offset_addr;
55734d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if t == 15 then
5574bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5575bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        elsif UnalignedSupport() || address<1:0> = '00' then
55764d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            R[t] = data;
55774d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        else // Can only apply before ARMv7
55784d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            R[t] = ROR(data, 8*UInt(address<1:0>));
55794d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice#endif
55804d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
55814d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice    bool success = false;
55824d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
55837bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
55844d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice    {
55854d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
55864d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
55874d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        uint32_t t;
55884d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        uint32_t n;
55894d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        uint32_t imm32;
55904d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        bool index;
55914d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        bool add;
55924d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        bool wback;
55934d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
55944d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        switch (encoding)
55954d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        {
55964d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            case eEncodingA1:
5597bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDR (literal);
5598bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRT;
5599bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
56004d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
56014d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                t = Bits32 (opcode, 15, 12);
56024d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                n = Bits32 (opcode, 19, 16);
56034d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                imm32 = Bits32 (opcode, 11, 0);
56044d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
5605bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
5606bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                index = BitIsSet (opcode, 24);
5607bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                add = BitIsSet (opcode, 23);
5608bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
56094d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56104d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                // if wback && n == t then UNPREDICTABLE;
56114d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                if (wback && (n == t))
56124d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                    return false;
56134d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56144d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                break;
56154d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56164d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            default:
56174d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                return false;
56184d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        }
56194d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56204d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        addr_t address;
56214d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        addr_t offset_addr;
56228d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice        addr_t base_address = ReadCoreReg (n, &success);
56234d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if (!success)
56244d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            return false;
56254d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56264d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
56274d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if (add)
56288d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice            offset_addr = base_address + imm32;
56294d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        else
56304d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            offset_addr = base_address - imm32;
56314d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56324d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        // address = if index then offset_addr else R[n];
56334d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if (index)
56344d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            address = offset_addr;
56354d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        else
56364d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            address = base_address;
56374d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56384d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        // data = MemU[address,4];
56394d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56404d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        Register base_reg;
56414d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
56424d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56434d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        EmulateInstruction::Context context;
56444d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        context.type = eContextRegisterLoad;
56454d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        context.SetRegisterPlusOffset (base_reg, address - base_address);
56464d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56474d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
56484d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if (!success)
56494d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            return false;
56504d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56514d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        // if wback then R[n] = offset_addr;
56524d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if (wback)
56534d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        {
56544d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            context.type = eContextAdjustBaseRegister;
56554d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            context.SetAddress (offset_addr);
56564d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
56574d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                return false;
56584d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        }
56594d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56604d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        // if t == 15 then
56614d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        if (t == 15)
56624d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        {
5663bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
56644d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            if (BitIsClear (address, 1) && BitIsClear (address, 0))
56654d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            {
56664d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                // LoadWritePC (data);
56674d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                context.type = eContextRegisterLoad;
56684d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                context.SetRegisterPlusOffset (base_reg, address - base_address);
56694d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                LoadWritePC (context, data);
56704d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            }
56714d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            else
56724d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                  return false;
56734d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        }
5674bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // elsif UnalignedSupport() || address<1:0> = '00' then
56754d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
56764d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        {
56774d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            // R[t] = data;
56784d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            context.type = eContextRegisterLoad;
56794d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            context.SetRegisterPlusOffset (base_reg, address - base_address);
56804d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
56814d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                return false;
56824d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        }
56834d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        // else // Can only apply before ARMv7
56844d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        else
56854d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        {
56864d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            // R[t] = ROR(data, 8*UInt(address<1:0>));
56874d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            data = ROR (data, Bits32 (address, 1, 0));
56884d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            context.type = eContextRegisterLoad;
56894d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            context.SetImmediate (data);
56904d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
56914d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice                return false;
56924d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        }
56934d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
56944d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice    }
56954d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice    return true;
56964d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice}
56974d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice
5698fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5699fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice// from memory, and writes it to a resgister.  The offset register value can optionally be shifted.
5700fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Ticebool
57017bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
5702fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice{
5703fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice#if 0
5704fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice    if ConditionPassed() then
5705fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5706fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        offset = Shift(R[m], shift_t, shift_n, APSR.C);
5707fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5708fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        address = if index then offset_addr else R[n];
5709fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        data = MemU[address,4];
5710fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if wback then R[n] = offset_addr;
5711fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if t == 15 then
5712bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5713bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        elsif UnalignedSupport() || address<1:0> = '00' then
5714fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            R[t] = data;
5715fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        else // Can only apply before ARMv7
5716fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            if CurrentInstrSet() == InstrSet_ARM then
5717fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                R[t] = ROR(data, 8*UInt(address<1:0>));
5718fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            else
5719fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                R[t] = bits(32) UNKNOWN;
5720fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice#endif
5721fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5722fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice    bool success = false;
5723fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
57247bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
5725fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice    {
5726fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
5727fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5728fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        uint32_t t;
5729fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        uint32_t n;
5730fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        uint32_t m;
5731fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        bool index;
5732fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        bool add;
5733fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        bool wback;
5734fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        ARM_ShifterType shift_t;
5735fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        uint32_t shift_n;
5736fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5737fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        switch (encoding)
5738fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        {
5739fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            case eEncodingT1:
5740fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5741fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5742fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                t = Bits32 (opcode, 2, 0);
5743fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                n = Bits32 (opcode, 5, 3);
5744fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                m = Bits32 (opcode, 8, 6);
5745fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5746fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
5747fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                index = true;
5748fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                add = true;
5749fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                wback = false;
5750fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5751fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
5752fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                shift_t = SRType_LSL;
5753fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                shift_n = 0;
5754fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5755fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                break;
5756fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5757fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            case eEncodingT2:
5758bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDR (literal);
5759fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5760fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                t = Bits32 (opcode, 15, 12);
5761fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                n = Bits32 (opcode, 19, 16);
5762fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                m = Bits32 (opcode, 3, 0);
5763fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5764fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
5765fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                index = true;
5766fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                add = true;
5767fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                wback = false;
5768fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5769fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5770fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                shift_t = SRType_LSL;
5771fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                shift_n = Bits32 (opcode, 5, 4);
5772fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5773fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // if BadReg(m) then UNPREDICTABLE;
5774fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                if (BadReg (m))
5775fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                    return false;
5776fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5777fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5778fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                if ((t == 15) && InITBlock() && !LastInITBlock())
5779fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                    return false;
5780fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5781fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                break;
5782fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5783fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            case eEncodingA1:
5784fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            {
5785bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRT;
5786fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5787fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                t = Bits32 (opcode, 15, 12);
5788fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                n = Bits32 (opcode, 19, 16);
5789fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                m = Bits32 (opcode, 3, 0);
5790fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5791bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
5792fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                index = BitIsSet (opcode, 24);
5793fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                add = BitIsSet (opcode, 23);
5794fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5795fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5796fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5797fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                uint32_t type = Bits32 (opcode, 6, 5);
5798fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                uint32_t imm5 = Bits32 (opcode, 11, 7);
5799fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                shift_n = DecodeImmShift (type, imm5, shift_t);
5800fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5801fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // if m == 15 then UNPREDICTABLE;
5802fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                if (m == 15)
5803fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                    return false;
5804fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5805fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5806fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                if (wback && ((n == 15) || (n == t)))
5807fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                    return false;
5808fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            }
5809fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                break;
5810fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5811fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5812fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            default:
5813fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                return false;
5814fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        }
5815fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5816fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5817fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if (!success)
5818fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            return false;
5819fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5820fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5821fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if (!success)
5822fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            return false;
5823fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5824fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        addr_t offset_addr;
5825fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        addr_t address;
5826fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5827fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        // offset = Shift(R[m], shift_t, shift_n, APSR.C);   -- Note "The APSR is an application level alias for the CPSR".
5828b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton        addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
5829fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5830fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5831fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if (add)
5832fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            offset_addr = Rn + offset;
5833fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        else
5834fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            offset_addr = Rn - offset;
5835fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5836fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        // address = if index then offset_addr else R[n];
5837fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            if (index)
5838fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                address = offset_addr;
5839fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            else
5840fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                address = Rn;
5841fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5842fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        // data = MemU[address,4];
5843fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        Register base_reg;
5844fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5845fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5846fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        EmulateInstruction::Context context;
5847fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        context.type = eContextRegisterLoad;
5848fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        context.SetRegisterPlusOffset (base_reg, address - Rn);
5849fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5850fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5851fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if (!success)
5852fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            return false;
5853fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5854fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        // if wback then R[n] = offset_addr;
5855fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if (wback)
5856fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        {
5857fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            context.type = eContextAdjustBaseRegister;
5858fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            context.SetAddress (offset_addr);
5859fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5860fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                return false;
5861fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        }
5862fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
5863fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        // if t == 15 then
5864fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        if (t == 15)
5865fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        {
5866bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5867fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            if (BitIsClear (address, 1) && BitIsClear (address, 0))
5868fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            {
5869fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                context.type = eContextRegisterLoad;
5870fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                context.SetRegisterPlusOffset (base_reg, address - Rn);
5871fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                LoadWritePC (context, data);
5872fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            }
5873fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            else
5874fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                return false;
5875fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        }
5876bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // elsif UnalignedSupport() || address<1:0> = '00' then
5877fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5878fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        {
5879fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            // R[t] = data;
5880fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            context.type = eContextRegisterLoad;
5881fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            context.SetRegisterPlusOffset (base_reg, address - Rn);
5882fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5883fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                return false;
5884fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        }
5885fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        else // Can only apply before ARMv7
5886fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        {
5887fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            // if CurrentInstrSet() == InstrSet_ARM then
5888fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            if (CurrentInstrSet () == eModeARM)
5889fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            {
5890fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // R[t] = ROR(data, 8*UInt(address<1:0>));
5891fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                data = ROR (data, Bits32 (address, 1, 0));
5892fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                context.type = eContextRegisterLoad;
5893fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                context.SetImmediate (data);
5894fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5895fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                    return false;
5896fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            }
5897fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            else
5898fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            {
5899fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                // R[t] = bits(32) UNKNOWN;
5900fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice                WriteBits32Unknown (t);
5901fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice            }
5902fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        }
5903fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice    }
5904fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice    return true;
5905fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice}
590621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
590721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice// LDRB (immediate, Thumb)
590821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Ticebool
59097bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
591021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice{
591121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice#if 0
591221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice    if ConditionPassed() then
591321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
591421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
591521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        address = if index then offset_addr else R[n];
591621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        R[t] = ZeroExtend(MemU[address,1], 32);
591721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        if wback then R[n] = offset_addr;
591821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice#endif
591921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
592021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice    bool success = false;
592121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
59227bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
592321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice    {
592421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        uint32_t t;
592521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        uint32_t n;
592621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        uint32_t imm32;
592721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        bool index;
592821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        bool add;
592921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        bool wback;
593021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
593121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
593221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        switch (encoding)
593321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        {
593421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            case eEncodingT1:
593521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
593621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                t = Bits32 (opcode, 2, 0);
593721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                n = Bits32 (opcode, 5, 3);
593821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                imm32 = Bits32 (opcode, 10, 6);
593921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
594021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
594121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                index = true;
594221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                add = true;
594321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                wback= false;
594421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
594521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                break;
594621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
594721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            case eEncodingT2:
5948bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE PLD;
5949bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRB (literal);
595021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
595121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                t = Bits32 (opcode, 15, 12);
595221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                n = Bits32 (opcode, 19, 16);
595321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                imm32 = Bits32 (opcode, 11, 0);
595421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
595521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
595621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                index = true;
595721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                add = true;
595821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                wback = false;
595921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
596021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                // if t == 13 then UNPREDICTABLE;
596121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                if (t == 13)
596221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                    return false;
596321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
596421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                break;
596521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
596621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            case eEncodingT3:
5967bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
5968bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRB (literal);
5969bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
5970bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '0' then UNDEFINED;
597121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
597221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                    return false;
597321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
597421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                  // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
597521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                t = Bits32 (opcode, 15, 12);
597621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                n = Bits32 (opcode, 19, 16);
597721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                imm32 = Bits32 (opcode, 7, 0);
597821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
5979bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
598021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                index = BitIsSet (opcode, 10);
598121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                add = BitIsSet (opcode, 9);
598221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                wback = BitIsSet (opcode, 8);
598321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
598421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
598521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                if (BadReg (t) || (wback && (n == t)))
598621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                    return false;
598721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
598821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                break;
598921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
599021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            default:
599121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                return false;
599221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        }
599321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
599421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
599521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        if (!success)
599621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            return false;
599721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
599821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        addr_t address;
599921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        addr_t offset_addr;
600021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
600121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
600221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        if (add)
600321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            offset_addr = Rn + imm32;
600421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        else
600521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            offset_addr = Rn - imm32;
600621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
600721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        // address = if index then offset_addr else R[n];
600821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        if (index)
600921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            address = offset_addr;
601021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        else
601121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            address = Rn;
601221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
601321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        // R[t] = ZeroExtend(MemU[address,1], 32);
601421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        Register base_reg;
601521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        Register data_reg;
601621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
601721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
601821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
601921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        EmulateInstruction::Context context;
602021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        context.type = eContextRegisterLoad;
602121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
602221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
602321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        uint64_t data = MemURead (context, address, 1, 0, &success);
602421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        if (!success)
602521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            return false;
602621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
602721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
602821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            return false;
602921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice
603021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        // if wback then R[n] = offset_addr;
603121b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        if (wback)
603221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        {
603321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            context.type = eContextAdjustBaseRegister;
603421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            context.SetAddress (offset_addr);
603521b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
603621b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice                return false;
603721b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        }
603821b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice    }
603921b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice    return true;
604021b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice}
6041f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6042f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6043f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice// zero-extends it to form a 32-bit word and writes it to a register.
6044f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Ticebool
60457bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
6046f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice{
6047f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice#if 0
6048f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice    if ConditionPassed() then
6049f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6050f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        base = Align(PC,4);
6051f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        address = if add then (base + imm32) else (base - imm32);
6052f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        R[t] = ZeroExtend(MemU[address,1], 32);
6053f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice#endif
6054f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6055f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice    bool success = false;
6056f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
60577bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
6058f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice    {
6059f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        uint32_t t;
6060f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        uint32_t imm32;
6061f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        bool add;
6062f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        switch (encoding)
6063f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        {
6064f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            case eEncodingT1:
6065bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE PLD;
6066bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6067f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                t = Bits32 (opcode, 15, 12);
6068f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
6069f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                add = BitIsSet (opcode, 23);
6070f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6071f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                // if t == 13 then UNPREDICTABLE;
6072f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                if (t == 13)
6073f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                    return false;
6074f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6075f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                break;
6076f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6077f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            case eEncodingA1:
6078bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6079f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                t = Bits32 (opcode, 15, 12);
6080f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
6081f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                add = BitIsSet (opcode, 23);
6082f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6083f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                // if t == 15 then UNPREDICTABLE;
6084f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                if (t == 15)
6085f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                    return false;
6086f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                break;
6087f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6088f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            default:
6089f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice                return false;
6090f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        }
6091f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6092f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        // base = Align(PC,4);
60938d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice        uint32_t pc_val = ReadCoreReg (PC_REG, &success);
6094f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        if (!success)
6095f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            return false;
6096f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6097f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        uint32_t base = AlignPC (pc_val);
6098f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6099f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        addr_t address;
6100f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        // address = if add then (base + imm32) else (base - imm32);
6101f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        if (add)
6102f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            address = base + imm32;
6103f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        else
6104f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            address = base - imm32;
6105f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6106f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        // R[t] = ZeroExtend(MemU[address,1], 32);
6107f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        EmulateInstruction::Context context;
6108f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        context.type = eContextRelativeBranchImmediate;
6109f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        context.SetImmediate (address - base);
6110f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6111f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        uint64_t data = MemURead (context, address, 1, 0, &success);
6112f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        if (!success)
6113f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            return false;
6114f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice
6115f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6116f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice            return false;
6117f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice    }
6118f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice    return true;
6119f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice}
612030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
612130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
612230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice// memory, zero-extends it to form a 32-bit word, and writes it to a register.  The offset register value can
612330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice// optionally be shifted.
612430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Ticebool
61257bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
612630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice{
612730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice#if 0
612830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice    if ConditionPassed() then
612930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
613030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        offset = Shift(R[m], shift_t, shift_n, APSR.C);
613130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        offset_addr = if add then (R[n] + offset) else (R[n] - offset);
613230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        address = if index then offset_addr else R[n];
613330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        R[t] = ZeroExtend(MemU[address,1],32);
613430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if wback then R[n] = offset_addr;
613530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice#endif
613630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
613730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice    bool success = false;
613830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
61397bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
614030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice    {
614130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        uint32_t t;
614230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        uint32_t n;
614330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        uint32_t m;
614430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        bool index;
614530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        bool add;
614630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        bool wback;
614730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        ARM_ShifterType shift_t;
614830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        uint32_t shift_n;
614930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
615030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
615130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        switch (encoding)
615230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        {
615330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            case eEncodingT1:
615430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
615530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                t = Bits32 (opcode, 2, 0);
615630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                n = Bits32 (opcode, 5, 3);
615730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                m = Bits32 (opcode, 8, 6);
615830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
615930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
616030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                index = true;
616130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                add = true;
616230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                wback = false;
616330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
616430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
616530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                shift_t = SRType_LSL;
616630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                shift_n = 0;
616730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                break;
616830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
616930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            case eEncodingT2:
6170bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE PLD;
6171bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRB (literal);
617230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
617330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                t = Bits32 (opcode, 15, 12);
617430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                n = Bits32 (opcode, 19, 16);
617530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                m = Bits32 (opcode, 3, 0);
617630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
617730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
617830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                index = true;
617930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                add = true;
618030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                wback = false;
618130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
618230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
618330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                shift_t = SRType_LSL;
618430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                shift_n = Bits32 (opcode, 5, 4);
618530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
618630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // if t == 13 || BadReg(m) then UNPREDICTABLE;
618730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                if ((t == 13) || BadReg (m))
618830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                    return false;
618930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                break;
619030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
619130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            case eEncodingA1:
619230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            {
6193bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRBT;
619430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
619530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                t = Bits32 (opcode, 15, 12);
619630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                n = Bits32 (opcode, 19, 16);
619730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                m = Bits32 (opcode, 3, 0);
619830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
6199bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
620030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                index = BitIsSet (opcode, 24);
620130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                add = BitIsSet (opcode, 23);
620230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
620330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
620430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
620530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                uint32_t type = Bits32 (opcode, 6, 5);
620630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                uint32_t imm5 = Bits32 (opcode, 11, 7);
620730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                shift_n = DecodeImmShift (type, imm5, shift_t);
620830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
620930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // if t == 15 || m == 15 then UNPREDICTABLE;
621030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                if ((t == 15) || (m == 15))
621130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                    return false;
621230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
621330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
621430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                if (wback && ((n == 15) || (n == t)))
621530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                    return false;
621630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            }
621730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                break;
621830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
621930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            default:
622030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                return false;
622130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        }
622230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
622330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        addr_t offset_addr;
622430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        addr_t address;
622530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
622630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        // offset = Shift(R[m], shift_t, shift_n, APSR.C);
622730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
622830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if (!success)
622930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            return false;
623030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
623130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
623230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
623330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
623430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
623530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if (!success)
623630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            return false;
623730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
623830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if (add)
623930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            offset_addr = Rn + offset;
624030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        else
624130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            offset_addr = Rn - offset;
624230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
624330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        // address = if index then offset_addr else R[n];
624430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if (index)
624530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            address = offset_addr;
624630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        else
624730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            address = Rn;
624830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
624930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        // R[t] = ZeroExtend(MemU[address,1],32);
625030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        Register base_reg;
625130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
625230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
625330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        EmulateInstruction::Context context;
625430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        context.type = eContextRegisterLoad;
625530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        context.SetRegisterPlusOffset (base_reg, address - Rn);
625630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
625730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        uint64_t data = MemURead (context, address, 1, 0, &success);
625830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if (!success)
625930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            return false;
626030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
626130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
626230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            return false;
626330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice
626430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        // if wback then R[n] = offset_addr;
626530fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        if (wback)
626630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        {
626730fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            context.type = eContextAdjustBaseRegister;
626830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            context.SetAddress (offset_addr);
626930fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
627030fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice                return false;
627130fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        }
627230fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice    }
627330fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice    return true;
627430fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice}
62750491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
62760491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
62770491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register.  It can use offset,
62780491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice// post-indexed, or pre-indexed addressing.
62790491b3b75e1b045ab548f77fd1f76035522debdeCaroline Ticebool
62807bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
62810491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice{
62820491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice#if 0
62830491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice    if ConditionPassed() then
62840491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
62850491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
62860491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        address = if index then offset_addr else R[n];
62870491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        data = MemU[address,2];
62880491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        if wback then R[n] = offset_addr;
6289bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<0> = '0' then
62900491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            R[t] = ZeroExtend(data, 32);
62910491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        else // Can only apply before ARMv7
62920491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            R[t] = bits(32) UNKNOWN;
62930491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice#endif
62940491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
62950491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
62960491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice    bool success = false;
62970491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
62987bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
62990491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice    {
63000491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        uint32_t t;
63010491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        uint32_t n;
63020491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        uint32_t imm32;
63030491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        bool index;
63040491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        bool add;
63050491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        bool wback;
63060491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63070491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
63080491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        switch (encoding)
63090491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        {
63100491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            case eEncodingT1:
6311bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
63120491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                t = Bits32 (opcode, 2, 0);
63130491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                n = Bits32 (opcode, 5, 3);
63140491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                imm32 = Bits32 (opcode, 10, 6) << 1;
63150491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63160491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
63170491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                index = true;
63180491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                add = true;
63190491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                wback = false;
63200491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63210491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                break;
63220491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63230491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            case eEncodingT2:
6324bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE "Unallocated memory hints";
6325bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRH (literal);
63260491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
63270491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                t = Bits32 (opcode, 15, 12);
63280491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                n = Bits32 (opcode, 19, 16);
63290491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                imm32 = Bits32 (opcode, 11, 0);
63300491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63310491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
63320491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                index = true;
63330491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                add = true;
63340491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                wback = false;
63350491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63360491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                // if t == 13 then UNPREDICTABLE;
63370491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                if (t == 13)
63380491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                    return false;
63390491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                break;
63400491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63410491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            case eEncodingT3:
6342bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRH (literal);
6343bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6344bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6345bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '0' then UNDEFINED;
63460491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
63470491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                    return false;
63480491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63490491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
63500491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                t = Bits32 (opcode, 15, 12);
63510491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                n = Bits32 (opcode, 19, 16);
63520491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                imm32 = Bits32 (opcode, 7, 0);
63530491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
6354bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
63550491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                index = BitIsSet (opcode, 10);
63560491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                add = BitIsSet (opcode, 9);
63570491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                wback = BitIsSet (opcode, 8);
63580491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63590491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
63600491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                if (BadReg (t) || (wback && (n == t)))
63610491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                    return false;
63620491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                break;
63630491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63640491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            default:
63650491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                return false;
63660491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        }
63670491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63680491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
63690491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
63700491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        if (!success)
63710491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            return false;
63720491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63730491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        addr_t offset_addr;
63740491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        addr_t address;
63750491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63760491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        if (add)
63770491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            offset_addr = Rn + imm32;
63780491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        else
63790491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            offset_addr = Rn - imm32;
63800491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63810491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        // address = if index then offset_addr else R[n];
63820491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        if (index)
63830491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            address = offset_addr;
63840491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        else
63850491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            address = Rn;
63860491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63870491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        // data = MemU[address,2];
63880491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        Register base_reg;
63890491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
63900491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63910491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        EmulateInstruction::Context context;
63920491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        context.type = eContextRegisterLoad;
63930491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        context.SetRegisterPlusOffset (base_reg, address - Rn);
63940491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63950491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        uint64_t data = MemURead (context, address, 2, 0, &success);
63960491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        if (!success)
63970491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            return false;
63980491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
63990491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        // if wback then R[n] = offset_addr;
64000491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        if (wback)
64010491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        {
64020491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            context.type = eContextAdjustBaseRegister;
64030491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            context.SetAddress (offset_addr);
64040491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
64050491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                return false;
64060491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        }
64070491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice
6408bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<0> = '0' then
64090491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        if (UnalignedSupport () || BitIsClear (address, 0))
64100491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        {
64110491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            // R[t] = ZeroExtend(data, 32);
64120491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            context.type = eContextRegisterLoad;
64130491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            context.SetRegisterPlusOffset (base_reg, address - Rn);
64140491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
64150491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice                return false;
64160491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        }
64170491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        else // Can only apply before ARMv7
64180491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        {
64190491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            // R[t] = bits(32) UNKNOWN;
64200491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice            WriteBits32Unknown (t);
64210491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        }
64220491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice    }
64230491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice    return true;
64240491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice}
6425fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice
6426952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6427952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice// zero-extends it to form a 32-bit word, and writes it to a register.
6428952b53892191222c56003cd60d8a4a71c4384aa7Caroline Ticebool
64297bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
6430952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice{
6431952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice#if 0
6432952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice    if ConditionPassed() then
6433952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6434952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        base = Align(PC,4);
6435952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        address = if add then (base + imm32) else (base - imm32);
6436952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        data = MemU[address,2];
6437bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<0> = '0' then
6438952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            R[t] = ZeroExtend(data, 32);
6439952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        else // Can only apply before ARMv7
6440952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            R[t] = bits(32) UNKNOWN;
6441952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice#endif
64420e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
6443952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice    bool success = false;
6444952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
64457bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
6446952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice    {
6447952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        uint32_t t;
6448952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        uint32_t imm32;
6449952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        bool add;
6450952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6451952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6452952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        switch (encoding)
6453952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        {
6454952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            case eEncodingT1:
6455bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE "Unallocated memory hints";
6456bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6457952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                t = Bits32 (opcode, 15, 12);
6458952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
6459952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                add = BitIsSet (opcode, 23);
6460952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6461952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                // if t == 13 then UNPREDICTABLE;
6462952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                if (t == 13)
6463952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                    return false;
6464952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6465952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                break;
6466952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6467952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            case eEncodingA1:
6468952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            {
6469952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                uint32_t imm4H = Bits32 (opcode, 11, 8);
6470952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                uint32_t imm4L = Bits32 (opcode, 3, 0);
6471952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6472bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
6473952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                t = Bits32 (opcode, 15, 12);
647440b1a6cd1190d820b630395f08c06d47e0bf6c7dCaroline Tice                imm32 = (imm4H << 4) | imm4L;
6475952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                add = BitIsSet (opcode, 23);
6476952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6477952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                // if t == 15 then UNPREDICTABLE;
6478952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                if (t == 15)
6479952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                    return false;
6480952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                break;
6481952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            }
6482952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6483952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            default:
6484952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                return false;
6485952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        }
6486952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6487952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        // base = Align(PC,4);
64888d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice        uint64_t pc_value = ReadCoreReg (PC_REG, &success);
6489952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        if (!success)
6490952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            return false;
6491952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6492952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        addr_t base = AlignPC (pc_value);
6493952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        addr_t address;
6494952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6495952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        // address = if add then (base + imm32) else (base - imm32);
6496952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        if (add)
6497952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            address = base + imm32;
6498952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        else
6499952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            address = base - imm32;
6500952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6501952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        // data = MemU[address,2];
6502952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        Register base_reg;
6503952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6504952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6505952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        EmulateInstruction::Context context;
6506952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        context.type = eContextRegisterLoad;
6507952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        context.SetRegisterPlusOffset (base_reg, address - base);
6508952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6509952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        uint64_t data = MemURead (context, address, 2, 0, &success);
6510952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        if (!success)
6511952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            return false;
6512952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6513952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6514bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<0> = '0' then
6515952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        if (UnalignedSupport () || BitIsClear (address, 0))
6516952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        {
6517952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            // R[t] = ZeroExtend(data, 32);
6518952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            context.type = eContextRegisterLoad;
6519952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            context.SetRegisterPlusOffset (base_reg, address - base);
6520952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6521952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice                return false;
6522952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
6523952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        }
6524952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        else // Can only apply before ARMv7
6525952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        {
6526952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            // R[t] = bits(32) UNKNOWN;
6527952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice            WriteBits32Unknown (t);
6528952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        }
6529952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice    }
6530952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice    return true;
6531952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice}
6532952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice
65330e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
65340e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice// from memory, zero-extends it to form a 32-bit word, and writes it to a register.  The offset register value can
65350e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice// be shifted left by 0, 1, 2, or 3 bits.
65360e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Ticebool
65377bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
65380e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice{
65390e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice#if 0
65400e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice    if ConditionPassed() then
65410e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
65420e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        offset = Shift(R[m], shift_t, shift_n, APSR.C);
65430e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        offset_addr = if add then (R[n] + offset) else (R[n] - offset);
65440e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        address = if index then offset_addr else R[n];
65450e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        data = MemU[address,2];
65460e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if wback then R[n] = offset_addr;
6547bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<0> = '0' then
65480e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            R[t] = ZeroExtend(data, 32);
65490e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        else // Can only apply before ARMv7
65500e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            R[t] = bits(32) UNKNOWN;
65510e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice#endif
65520e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65530e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice    bool success = false;
65540e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65557bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
65560e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice    {
65570e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        uint32_t t;
65580e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        uint32_t n;
65590e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        uint32_t m;
65600e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        bool index;
65610e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        bool add;
65620e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        bool wback;
65630e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        ARM_ShifterType shift_t;
65640e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        uint32_t shift_n;
65650e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65660e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
65670e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        switch (encoding)
65680e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        {
65690e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            case eEncodingT1:
65700e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
65710e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
65720e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                t = Bits32 (opcode, 2, 0);
65730e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                n = Bits32 (opcode, 5, 3);
65740e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                m = Bits32 (opcode, 8, 6);
65750e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65760e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
65770e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                index = true;
65780e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                add = true;
65790e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                wback = false;
65800e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65810e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
65820e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                shift_t = SRType_LSL;
65830e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                shift_n = 0;
65840e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65850e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                break;
65860e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65870e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            case eEncodingT2:
6588bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRH (literal);
6589bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE "Unallocated memory hints";
65900e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
65910e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                t = Bits32 (opcode, 15, 12);
65920e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                n = Bits32 (opcode, 19, 16);
65930e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                m = Bits32 (opcode, 3, 0);
65940e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
65950e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
65960e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                index = true;
65970e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                add = true;
65980e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                wback = false;
65990e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66000e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
66010e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                shift_t = SRType_LSL;
66020e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                shift_n = Bits32 (opcode, 5, 4);
66030e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66040e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // if t == 13 || BadReg(m) then UNPREDICTABLE;
66050e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                if ((t == 13) || BadReg (m))
66060e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                    return false;
66070e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                break;
66080e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66090e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            case eEncodingA1:
6610bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRHT;
66110e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
66120e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                t = Bits32 (opcode, 15, 12);
66130e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                n = Bits32 (opcode, 19, 16);
66140e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                m = Bits32 (opcode, 3, 0);
66150e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
6616bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
66170e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                index = BitIsSet (opcode, 24);
66180e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                add = BitIsSet (opcode, 23);
66190e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
66200e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66210e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
66220e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                shift_t = SRType_LSL;
66230e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                shift_n = 0;
66240e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66250e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // if t == 15 || m == 15 then UNPREDICTABLE;
66260e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                if ((t == 15) || (m == 15))
66270e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                    return false;
66280e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66290e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
66300e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                if (wback && ((n == 15) || (n == t)))
66310e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                    return false;
66320e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66330e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                break;
66340e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66350e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            default:
66360e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                return false;
66370e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        }
66380e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66390e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        // offset = Shift(R[m], shift_t, shift_n, APSR.C);
66400e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66410e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        uint64_t Rm  = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
66420e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if (!success)
66430e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            return false;
66440e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66450e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
66460e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66470e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        addr_t offset_addr;
66480e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        addr_t address;
66490e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66500e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
66510e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
66520e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if (!success)
66530e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            return false;
66540e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66550e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if (add)
66560e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            offset_addr = Rn + offset;
66570e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        else
66580e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            offset_addr = Rn - offset;
66590e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66600e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        // address = if index then offset_addr else R[n];
66610e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if (index)
66620e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            address = offset_addr;
66630e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        else
66640e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            address = Rn;
66650e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66660e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        // data = MemU[address,2];
66670e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        Register base_reg;
66680e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        Register offset_reg;
66690e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
66700e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
66710e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66720e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        EmulateInstruction::Context context;
66730e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        context.type = eContextRegisterLoad;
66740e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
66750e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        uint64_t data = MemURead (context, address, 2, 0, &success);
66760e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if (!success)
66770e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            return false;
66780e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
66790e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        // if wback then R[n] = offset_addr;
66800e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if (wback)
66810e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        {
66820e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            context.type = eContextAdjustBaseRegister;
66830e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            context.SetAddress (offset_addr);
66840e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
66850e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                return false;
66860e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        }
66870e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
6688bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<0> = '0' then
66890e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        if (UnalignedSupport() || BitIsClear (address, 0))
66900e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        {
66910e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            // R[t] = ZeroExtend(data, 32);
66920e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            context.type = eContextRegisterLoad;
66930e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
66940e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
66950e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice                return false;
66960e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        }
66970e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        else // Can only apply before ARMv7
66980e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        {
66990e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            // R[t] = bits(32) UNKNOWN;
67000e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice            WriteBits32Unknown (t);
67010e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        }
67020e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice    }
67030e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice    return true;
67040e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice}
67050e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
6706a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6707a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice// memory, sign-extends it to form a 32-bit word, and writes it to a register.  It can use offset, post-indexed,
6708a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice// or pre-indexed addressing.
6709a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Ticebool
67107bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
6711a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice{
6712a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice#if 0
6713a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice    if ConditionPassed() then
6714a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6715a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6716a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        address = if index then offset_addr else R[n];
6717a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        R[t] = SignExtend(MemU[address,1], 32);
6718a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        if wback then R[n] = offset_addr;
6719a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice#endif
6720a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6721a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice    bool success = false;
6722a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
67237bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
6724a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice    {
6725a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        uint32_t t;
6726a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        uint32_t n;
6727a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        uint32_t imm32;
6728a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        bool index;
6729a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        bool add;
6730a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        bool wback;
6731a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6732a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6733a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        switch (encoding)
6734a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        {
6735a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            case eEncodingT1:
6736bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE PLI;
6737bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSB (literal);
6738a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6739a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                t = Bits32 (opcode, 15, 12);
6740a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                n = Bits32 (opcode, 19, 16);
6741a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
6742a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6743a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
6744a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                index = true;
6745a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                add = true;
6746a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                wback = false;
6747a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6748a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                // if t == 13 then UNPREDICTABLE;
6749a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                if (t == 13)
6750a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                    return false;
6751a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6752a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                break;
6753a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6754a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            case eEncodingT2:
6755bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6756bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSB (literal);
6757bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6758bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '0' then UNDEFINED;
6759a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6760a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                    return false;
6761a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6762a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6763a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                t = Bits32 (opcode, 15, 12);
6764a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                n = Bits32 (opcode, 19, 16);
6765a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                imm32 = Bits32 (opcode, 7, 0);
6766a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6767bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6768a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                index = BitIsSet (opcode, 10);
6769a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                add = BitIsSet (opcode, 9);
6770a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                wback = BitIsSet (opcode, 8);
6771a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6772a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6773bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                  if (((t == 13) || ((t == 15)
6774bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                                     && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6775bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                      || (wback && (n == t)))
6776a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                    return false;
6777a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6778a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                break;
6779a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6780a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            case eEncodingA1:
6781a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            {
6782bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSB (literal);
6783bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRSBT;
6784a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6785a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                t = Bits32 (opcode, 15, 12);
6786a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                n = Bits32 (opcode, 19, 16);
6787a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6788a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                uint32_t imm4H = Bits32 (opcode, 11, 8);
6789a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                uint32_t imm4L = Bits32 (opcode, 3, 0);
679040b1a6cd1190d820b630395f08c06d47e0bf6c7dCaroline Tice                imm32 = (imm4H << 4) | imm4L;
6791a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6792bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
6793a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                index = BitIsSet (opcode, 24);
6794a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                add = BitIsSet (opcode, 23);
6795a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6796a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6797a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6798a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                if ((t == 15) || (wback && (n == t)))
6799a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                    return false;
6800a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6801a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                break;
6802a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            }
6803a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6804a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            default:
6805a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                return false;
6806a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        }
6807a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6808bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        uint64_t Rn = ReadCoreReg (n, &success);
6809a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        if (!success)
6810a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            return false;
6811a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6812a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        addr_t offset_addr;
6813a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        addr_t address;
6814a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6815a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6816a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        if (add)
6817a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            offset_addr = Rn + imm32;
6818a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        else
6819a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            offset_addr = Rn - imm32;
6820a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6821a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        // address = if index then offset_addr else R[n];
6822a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        if (index)
6823a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            address = offset_addr;
6824a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        else
6825a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            address = Rn;
6826a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6827a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        // R[t] = SignExtend(MemU[address,1], 32);
6828a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        Register base_reg;
6829a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6830a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6831a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        EmulateInstruction::Context context;
6832a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        context.type = eContextRegisterLoad;
6833a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        context.SetRegisterPlusOffset (base_reg, address - Rn);
6834a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6835a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6836a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        if (!success)
6837a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            return false;
6838a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6839a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6840a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6841a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            return false;
6842a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6843a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        // if wback then R[n] = offset_addr;
6844a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        if (wback)
6845a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        {
6846a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            context.type = eContextAdjustBaseRegister;
6847a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            context.SetAddress (offset_addr);
6848a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6849a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice                return false;
6850a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        }
6851a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice    }
6852a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice
6853a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice    return true;
6854a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice}
68550e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice
68565f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
68575f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice// sign-extends it to form a 32-bit word, and writes tit to a register.
68585f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Ticebool
68597bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
68605f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice{
68615f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice#if 0
68625f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice    if ConditionPassed() then
68635f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
68645f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        base = Align(PC,4);
68655f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        address = if add then (base + imm32) else (base - imm32);
68665f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        R[t] = SignExtend(MemU[address,1], 32);
68675f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice#endif
68685f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
68695f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice    bool success = false;
68705f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
68717bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
68725f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice    {
68735f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        uint32_t t;
68745f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        uint32_t imm32;
68755f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        bool add;
68765f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
68775f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
68785f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        switch (encoding)
68795f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        {
68805f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            case eEncodingT1:
6881bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE PLI;
6882bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
68835f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                t = Bits32 (opcode, 15, 12);
68845f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
68855f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                add = BitIsSet (opcode, 23);
68865f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
68875f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                // if t == 13 then UNPREDICTABLE;
68885f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                if (t == 13)
68895f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                    return false;
68905f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
68915f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                break;
68925f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
68935f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            case eEncodingA1:
68945f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            {
6895bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
68965f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                t = Bits32 (opcode, 15, 12);
68975f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                uint32_t imm4H = Bits32 (opcode, 11, 8);
68985f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                uint32_t imm4L = Bits32 (opcode, 3, 0);
689940b1a6cd1190d820b630395f08c06d47e0bf6c7dCaroline Tice                imm32 = (imm4H << 4) | imm4L;
69005f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                add = BitIsSet (opcode, 23);
69015f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69025f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                // if t == 15 then UNPREDICTABLE;
69035f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                if (t == 15)
69045f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                    return false;
69055f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69065f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                break;
69075f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            }
69085f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69095f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            default:
69105f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice                return false;
69115f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        }
69125f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69135f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        // base = Align(PC,4);
69148d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice        uint64_t pc_value = ReadCoreReg (PC_REG, &success);
69155f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        if (!success)
69165f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            return false;
69175f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        uint64_t base = AlignPC (pc_value);
69185f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69195f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        // address = if add then (base + imm32) else (base - imm32);
69205f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        addr_t address;
69215f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        if (add)
69225f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            address = base + imm32;
69235f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        else
69245f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            address = base - imm32;
69255f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69265f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        // R[t] = SignExtend(MemU[address,1], 32);
69275f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        Register base_reg;
69285f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
69295f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69305f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        EmulateInstruction::Context context;
69315f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        context.type = eContextRegisterLoad;
69325f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        context.SetRegisterPlusOffset (base_reg, address - base);
69335f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69345f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
69355f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        if (!success)
69365f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            return false;
69375f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
69385f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
69395f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
69405f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice            return false;
69415f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice    }
69425f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice    return true;
69435f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice}
69445f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice
6945672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6946672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice// memory, sign-extends it to form a 32-bit word, and writes it to a register.  The offset register value can be
6947672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice// shifted left by 0, 1, 2, or 3 bits.
6948672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Ticebool
69497bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
6950672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice{
6951672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice#if 0
6952672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice    if ConditionPassed() then
6953672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6954672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        offset = Shift(R[m], shift_t, shift_n, APSR.C);
6955672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6956672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        address = if index then offset_addr else R[n];
6957672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        R[t] = SignExtend(MemU[address,1], 32);
6958672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if wback then R[n] = offset_addr;
6959672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice#endif
6960672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
6961672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice    bool success = false;
6962672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
69637bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
6964672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice    {
6965672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        uint32_t t;
6966672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        uint32_t n;
6967672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        uint32_t m;
6968672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        bool index;
6969672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        bool add;
6970672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        bool wback;
6971672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        ARM_ShifterType shift_t;
6972672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        uint32_t shift_n;
6973672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
6974672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6975672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        switch (encoding)
6976672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        {
6977672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            case eEncodingT1:
6978672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6979672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                t = Bits32 (opcode, 2, 0);
6980672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                n = Bits32 (opcode, 5, 3);
6981672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                m = Bits32 (opcode, 8, 6);
6982672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
6983672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
6984672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                index = true;
6985672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                add = true;
6986672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                wback = false;
6987672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
6988672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
6989672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                shift_t = SRType_LSL;
6990672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                shift_n = 0;
6991672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
6992672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                break;
6993672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
6994672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            case eEncodingT2:
6995bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE PLI;
6996bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSB (literal);
6997672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6998672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                t = Bits32 (opcode, 15, 12);
6999672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                n = Bits32 (opcode, 19, 16);
7000672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                m = Bits32 (opcode, 3, 0);
7001672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7002672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
7003672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                index = true;
7004672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                add = true;
7005672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                wback = false;
7006672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7007672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7008672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                shift_t = SRType_LSL;
7009672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                shift_n = Bits32 (opcode, 5, 4);
7010672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7011672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // if t == 13 || BadReg(m) then UNPREDICTABLE;
7012672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                if ((t == 13) || BadReg (m))
7013672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                    return false;
7014672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                break;
7015672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7016672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            case eEncodingA1:
7017bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRSBT;
7018672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7019672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                t = Bits32 (opcode, 15, 12);
7020672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                n = Bits32 (opcode, 19, 16);
7021672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                m = Bits32 (opcode, 3, 0);
7022672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7023bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
7024672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                index = BitIsSet (opcode, 24);
7025672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                add = BitIsSet (opcode, 23);
7026672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7027672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7028672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
7029672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                shift_t = SRType_LSL;
7030672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                shift_n = 0;
7031672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7032672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // if t == 15 || m == 15 then UNPREDICTABLE;
7033672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                if ((t == 15) || (m == 15))
7034672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                    return false;
7035672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7036672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7037672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                if (wback && ((n == 15) || (n == t)))
7038672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                    return false;
7039672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                break;
7040672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7041672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            default:
7042672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                return false;
7043672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        }
7044672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7045672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        uint64_t Rm =  ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7046672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if (!success)
7047672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            return false;
7048672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7049672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7050672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7051672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7052672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        addr_t offset_addr;
7053672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        addr_t address;
7054672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7055672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7056672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7057672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if (!success)
7058672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            return false;
7059672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7060672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if (add)
7061672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            offset_addr = Rn + offset;
7062672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        else
7063672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            offset_addr = Rn - offset;
7064672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7065672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        // address = if index then offset_addr else R[n];
7066672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if (index)
7067672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            address = offset_addr;
7068672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        else
7069672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            address = Rn;
7070672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7071672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        // R[t] = SignExtend(MemU[address,1], 32);
7072672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        Register base_reg;
7073672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7074672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        Register offset_reg;
7075672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7076672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7077672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        EmulateInstruction::Context context;
7078672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        context.type = eContextRegisterLoad;
7079672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7080672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7081672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7082672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if (!success)
7083672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            return false;
7084672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7085672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7086672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7087672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            return false;
7088672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
7089672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        // if wback then R[n] = offset_addr;
7090672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        if (wback)
7091672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        {
7092672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            context.type = eContextAdjustBaseRegister;
7093672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            context.SetAddress (offset_addr);
7094672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7095672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice                return false;
7096672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        }
7097672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice    }
7098672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice    return true;
7099672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice}
7100672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice
710178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
710278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice// memory, sign-extends it to form a 32-bit word, and writes it to a register.  It can use offset, post-indexed, or
710378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice// pre-indexed addressing.
710478fb5638da9c01a39443f3339ede2f02056822cfCaroline Ticebool
71057bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
710678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice{
710778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice#if 0
710878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice    if ConditionPassed() then
710978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
711078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
711178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        address = if index then offset_addr else R[n];
711278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        data = MemU[address,2];
711378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        if wback then R[n] = offset_addr;
7114bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<0> = '0' then
711578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            R[t] = SignExtend(data, 32);
711678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        else // Can only apply before ARMv7
711778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            R[t] = bits(32) UNKNOWN;
711878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice#endif
711978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
712078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice    bool success = false;
712178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
71227bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
712378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice    {
712478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        uint32_t t;
712578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        uint32_t n;
712678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        uint32_t imm32;
712778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        bool index;
712878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        bool add;
712978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        bool wback;
713078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
713178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
713278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        switch (encoding)
713378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        {
713478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            case eEncodingT1:
7135bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSH (literal);
7136bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE "Unallocated memory hints";
713778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
713878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                t = Bits32 (opcode, 15, 12);
713978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                n = Bits32 (opcode, 19, 16);
714078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                imm32 = Bits32 (opcode, 11, 0);
714178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
714278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
714378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                index = true;
714478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                add = true;
714578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                wback = false;
714678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
714778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                // if t == 13 then UNPREDICTABLE;
714878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                if (t == 13)
714978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                    return false;
715078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
715178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                break;
715278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
715378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            case eEncodingT2:
7154bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSH (literal);
7155bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7156bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7157bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '0' then UNDEFINED;
715878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                  if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
715978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                  return false;
716078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
716178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
716278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                t = Bits32 (opcode, 15, 12);
716378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                n = Bits32 (opcode, 19, 16);
716478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                imm32 = Bits32 (opcode, 7, 0);
716578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
7166bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
716778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                index = BitIsSet (opcode, 10);
716878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                add = BitIsSet (opcode, 9);
716978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                wback = BitIsSet (opcode, 8);
717078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
717178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
717278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                if (BadReg (t) || (wback && (n == t)))
717378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                    return false;
717478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
717578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                break;
717678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
717778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            case eEncodingA1:
717878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            {
7179bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSH (literal);
7180bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRSHT;
718178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
718278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                t = Bits32 (opcode, 15, 12);
718378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                n = Bits32 (opcode, 19, 16);
718478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                uint32_t imm4H = Bits32 (opcode, 11,8);
718578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                uint32_t imm4L = Bits32 (opcode, 3, 0);
718640b1a6cd1190d820b630395f08c06d47e0bf6c7dCaroline Tice                imm32 = (imm4H << 4) | imm4L;
718778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
7188bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
718978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                index = BitIsSet (opcode, 24);
719078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                add = BitIsSet (opcode, 23);
719178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
719278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
719378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                // if t == 15 || (wback && n == t) then UNPREDICTABLE;
719478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                if ((t == 15) || (wback && (n == t)))
719578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                    return false;
719678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
719778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                break;
719878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            }
719978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
720078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            default:
720178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                return false;
720278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        }
720378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
720478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
720578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
720678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        if (!success)
720778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            return false;
720878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
720978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        addr_t offset_addr;
721078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        if (add)
721178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            offset_addr = Rn + imm32;
721278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        else
721378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            offset_addr = Rn - imm32;
721478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
721578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        // address = if index then offset_addr else R[n];
721678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        addr_t address;
721778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        if (index)
721878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            address = offset_addr;
721978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        else
722078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            address = Rn;
722178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
722278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        // data = MemU[address,2];
722378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        Register base_reg;
722478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
722578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
722678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        EmulateInstruction::Context context;
722778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        context.type = eContextRegisterLoad;
722878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        context.SetRegisterPlusOffset (base_reg, address - Rn);
722978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
723078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        uint64_t data = MemURead (context, address, 2, 0, &success);
723178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        if (!success)
723278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            return false;
723378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
723478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        // if wback then R[n] = offset_addr;
723578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        if (wback)
723678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        {
723778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            context.type = eContextAdjustBaseRegister;
723878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            context.SetAddress (offset_addr);
723978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
724078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                return false;
724178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        }
724278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
7243bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<0> = '0' then
724478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        if (UnalignedSupport() || BitIsClear (address, 0))
724578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        {
724678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            // R[t] = SignExtend(data, 32);
724778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            int64_t signed_data = llvm::SignExtend64<16>(data);
724878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            context.type = eContextRegisterLoad;
724978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            context.SetRegisterPlusOffset (base_reg, address - Rn);
725078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
725178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice                return false;
725278fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        }
725378fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        else // Can only apply before ARMv7
725478fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        {
725578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            // R[t] = bits(32) UNKNOWN;
725678fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice            WriteBits32Unknown (t);
725778fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        }
725878fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice    }
725978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice    return true;
726078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice}
726178fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice
7262d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7263d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice// sign-extends it to from a 32-bit word, and writes it to a register.
7264d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Ticebool
72657bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
7266d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice{
7267d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice#if 0
7268d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice    if ConditionPassed() then
7269d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7270d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        base = Align(PC,4);
7271d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        address = if add then (base + imm32) else (base - imm32);
7272d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        data = MemU[address,2];
7273bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<0> = '0' then
7274d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            R[t] = SignExtend(data, 32);
7275d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        else // Can only apply before ARMv7
7276d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            R[t] = bits(32) UNKNOWN;
7277d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice#endif
7278d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7279d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice    bool success = false;
7280d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
72817bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
7282d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice    {
7283d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        uint32_t t;
7284d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        uint32_t imm32;
7285d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        bool add;
7286d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7287d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7288d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        switch (encoding)
7289d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        {
7290d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            case eEncodingT1:
7291bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE "Unallocated memory hints";
7292bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7293d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                t = Bits32  (opcode, 15, 12);
7294d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                imm32 = Bits32 (opcode, 11, 0);
7295d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                add = BitIsSet (opcode, 23);
7296d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7297d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                // if t == 13 then UNPREDICTABLE;
7298d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                if (t == 13)
7299d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                    return false;
7300d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7301d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                break;
7302d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7303d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            case eEncodingA1:
7304d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            {
7305bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7306d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                t = Bits32 (opcode, 15, 12);
7307d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                uint32_t imm4H = Bits32 (opcode, 11, 8);
7308d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                uint32_t imm4L = Bits32 (opcode, 3, 0);
730940b1a6cd1190d820b630395f08c06d47e0bf6c7dCaroline Tice                imm32 = (imm4H << 4) | imm4L;
7310d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                add = BitIsSet (opcode, 23);
7311d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7312d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                // if t == 15 then UNPREDICTABLE;
7313d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                if (t == 15)
7314d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                    return false;
7315d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7316d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                break;
7317d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            }
7318d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            default:
7319d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                return false;
7320d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        }
7321d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7322d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        // base = Align(PC,4);
73238d681f52cd597b0148c9ae1439d5d5877aa39e4dCaroline Tice        uint64_t pc_value = ReadCoreReg (PC_REG, &success);
7324d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        if (!success)
7325d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            return false;
7326d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7327d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        uint64_t base = AlignPC (pc_value);
7328d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7329d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        addr_t address;
7330d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        // address = if add then (base + imm32) else (base - imm32);
7331d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        if (add)
7332d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            address = base + imm32;
7333d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        else
7334d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            address = base - imm32;
7335d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7336d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        // data = MemU[address,2];
7337d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        Register base_reg;
7338d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7339d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7340d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        EmulateInstruction::Context context;
7341d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        context.type = eContextRegisterLoad;
7342d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        context.SetRegisterPlusOffset (base_reg, imm32);
7343d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7344d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        uint64_t data = MemURead (context, address, 2, 0, &success);
7345d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        if (!success)
7346d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            return false;
7347d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7348bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<0> = '0' then
7349d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        if (UnalignedSupport() || BitIsClear (address, 0))
7350d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        {
7351d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            // R[t] = SignExtend(data, 32);
7352d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            int64_t signed_data = llvm::SignExtend64<16>(data);
7353d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7354d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice                return false;
7355d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        }
7356d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        else // Can only apply before ARMv7
7357d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        {
7358d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            // R[t] = bits(32) UNKNOWN;
7359d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice            WriteBits32Unknown (t);
7360d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        }
7361d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice    }
7362d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice    return true;
7363d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice}
7364d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice
7365291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7366291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice// from memory, sign-extends it to form a 32-bit word, and writes it to a register.  The offset register value can be
7367291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice// shifted left by 0, 1, 2, or 3 bits.
7368291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Ticebool
73697bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
7370291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice{
7371291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice#if 0
7372291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice    if ConditionPassed() then
7373291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7374291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        offset = Shift(R[m], shift_t, shift_n, APSR.C);
7375291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7376291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        address = if index then offset_addr else R[n];
7377291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        data = MemU[address,2];
7378291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if wback then R[n] = offset_addr;
7379bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        if UnalignedSupport() || address<0> = '0' then
7380291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            R[t] = SignExtend(data, 32);
7381291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        else // Can only apply before ARMv7
7382291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            R[t] = bits(32) UNKNOWN;
7383291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice#endif
7384291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7385291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice    bool success = false;
7386291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
73877bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
7388291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice    {
7389291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        uint32_t t;
7390291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        uint32_t n;
7391291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        uint32_t m;
7392291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        bool index;
7393291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        bool add;
7394291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        bool wback;
7395291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        ARM_ShifterType shift_t;
7396291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        uint32_t shift_n;
7397291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7398291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7399291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        switch (encoding)
7400291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        {
7401291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            case eEncodingT1:
7402291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7403291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7404291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                t = Bits32 (opcode, 2, 0);
7405291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                n = Bits32 (opcode, 5, 3);
7406291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                m = Bits32 (opcode, 8, 6);
7407291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7408291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
7409291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                index = true;
7410291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                add = true;
7411291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                wback = false;
7412291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7413291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
7414291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                shift_t = SRType_LSL;
7415291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                shift_n = 0;
7416291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7417291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                break;
7418291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7419291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            case eEncodingT2:
7420bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rn == '1111' then SEE LDRSH (literal);
7421bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if Rt == '1111' then SEE "Unallocated memory hints";
7422291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7423291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                t = Bits32 (opcode, 15, 12);
7424291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                n = Bits32 (opcode, 19, 16);
7425291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                m = Bits32 (opcode, 3, 0);
7426291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7427291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // index = TRUE; add = TRUE; wback = FALSE;
7428291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                index = true;
7429291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                add = true;
7430291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                wback = false;
7431291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7432291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7433291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                shift_t = SRType_LSL;
7434291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                shift_n = Bits32 (opcode, 5, 4);
7435291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7436291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // if t == 13 || BadReg(m) then UNPREDICTABLE;
7437291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                if ((t == 13) || BadReg (m))
7438291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                    return false;
7439291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7440291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                break;
7441291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7442291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            case eEncodingA1:
7443bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // if P == '0' && W == '1' then SEE LDRSHT;
7444291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7445291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                t = Bits32 (opcode, 15, 12);
7446291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                n = Bits32 (opcode, 19, 16);
7447291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                m = Bits32 (opcode, 3, 0);
7448291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7449bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
7450291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                index = BitIsSet (opcode, 24);
7451291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                add = BitIsSet (opcode, 23);
7452291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7453291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7454291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
7455291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                shift_t = SRType_LSL;
7456291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                shift_n = 0;
7457291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7458291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // if t == 15 || m == 15 then UNPREDICTABLE;
7459291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                if ((t == 15) || (m == 15))
7460291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                    return false;
7461291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7462291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7463291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                if (wback && ((n == 15) || (n == t)))
7464291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                    return false;
7465291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7466291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                break;
7467291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7468291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            default:
7469291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                break;
7470291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        }
7471291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7472291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7473291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if (!success)
7474291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            return false;
7475291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7476291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7477291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if (!success)
7478291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            return false;
7479291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7480291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7481291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7482291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7483291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        addr_t offset_addr;
7484291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        addr_t address;
7485291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7486291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7487291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if (add)
7488291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            offset_addr = Rn + offset;
7489291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        else
7490291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            offset_addr = Rn - offset;
7491291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7492291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        // address = if index then offset_addr else R[n];
7493291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if (index)
7494291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            address = offset_addr;
7495291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        else
7496291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            address = Rn;
7497291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7498291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        // data = MemU[address,2];
7499291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        Register base_reg;
7500291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7501291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7502291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        Register offset_reg;
7503291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7504291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7505291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        EmulateInstruction::Context context;
7506291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        context.type = eContextRegisterLoad;
7507291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7508291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7509291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        uint64_t data = MemURead (context, address, 2, 0, &success);
7510291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if (!success)
7511291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            return false;
7512291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7513291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        // if wback then R[n] = offset_addr;
7514291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if (wback)
7515291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        {
7516291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            context.type = eContextAdjustBaseRegister;
7517291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            context.SetAddress (offset_addr);
7518291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7519291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                return false;
7520291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        }
7521291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7522bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if UnalignedSupport() || address<0> = '0' then
7523291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        if (UnalignedSupport() || BitIsClear (address, 0))
7524291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        {
7525291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            // R[t] = SignExtend(data, 32);
7526291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            context.type = eContextRegisterLoad;
7527291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7528291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7529291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            int64_t signed_data = llvm::SignExtend64<16>(data);
7530291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7531291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice                return false;
7532291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        }
7533291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        else // Can only apply before ARMv7
7534291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        {
7535291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            // R[t] = bits(32) UNKNOWN;
7536291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice            WriteBits32Unknown (t);
7537291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        }
7538291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice    }
7539291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice    return true;
7540291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice}
75416bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75426bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
75436bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice// register.  You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
75446bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Ticebool
75457bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
75466bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice{
75476bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice#if 0
75486bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice    if ConditionPassed() then
75496bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        EncodingSpecificOperations();
75506bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        rotated = ROR(R[m], rotation);
75516bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        R[d] = SignExtend(rotated<7:0>, 32);
75526bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice#endif
75536bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75546bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice    bool success = false;
75556bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75567bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
75576bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice    {
75586bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        uint32_t d;
75596bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        uint32_t m;
75606bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        uint32_t rotation;
75616bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75626bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        // EncodingSpecificOperations();
75636bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        switch (encoding)
75646bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        {
75656bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice            case eEncodingT1:
75666bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
75676bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                d = Bits32 (opcode, 2, 0);
75686bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                m = Bits32 (opcode, 5, 3);
75696bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                rotation = 0;
75706bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75716bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                break;
75726bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75736bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice            case eEncodingT2:
7574bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
75756bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                d = Bits32 (opcode, 11, 8);
75766bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                m = Bits32 (opcode, 3, 0);
75776bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                rotation = Bits32 (opcode, 5, 4) << 3;
75786bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75796bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
75806bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                if (BadReg (d) || BadReg (m))
75816bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                    return false;
75826bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75836bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                break;
75846bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75856bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice            case eEncodingA1:
7586bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
75876bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                d = Bits32 (opcode, 15, 12);
75886bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                m = Bits32 (opcode, 3, 0);
75896bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                rotation = Bits32 (opcode, 11, 10) << 3;
75906bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75916bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                // if d == 15 || m == 15 then UNPREDICTABLE;
75926bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                if ((d == 15) || (m == 15))
75936bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                    return false;
75946bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75956bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                break;
75966bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
75976bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice            default:
75986bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice                return false;
75996bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        }
76006bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
7601868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7602868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        if (!success)
7603868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice            return false;
76046bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
76056bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        // rotated = ROR(R[m], rotation);
76066bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        uint64_t rotated = ROR (Rm, rotation);
76076bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
76086bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        // R[d] = SignExtend(rotated<7:0>, 32);
76098ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        int64_t data = llvm::SignExtend64<8>(rotated);
76106bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
76116bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        Register source_reg;
76126bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
76136bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
76146bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        EmulateInstruction::Context context;
76156bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        context.type = eContextRegisterLoad;
76166bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        context.SetRegister (source_reg);
76176bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
76188ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
76196bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice            return false;
76206bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice    }
76216bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice    return true;
76226bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice}
7623291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice
7624868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7625868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice// register.  You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7626868198b229fcffbda2b24518007179ef1a45ad1dCaroline Ticebool
76277bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
7628868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice{
7629868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice#if 0
7630868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice    if ConditionPassed() then
7631868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        EncodingSpecificOperations();
7632868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        rotated = ROR(R[m], rotation);
7633868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        R[d] = SignExtend(rotated<15:0>, 32);
7634868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice#endif
7635868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7636868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice    bool success = false;
7637868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
76387bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
7639868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice    {
7640868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        uint32_t d;
7641868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        uint32_t m;
7642868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        uint32_t rotation;
7643868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7644868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        // EncodingSpecificOperations();
7645868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        switch (encoding)
7646868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        {
7647868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice            case eEncodingT1:
7648868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7649868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                d = Bits32 (opcode, 2, 0);
7650868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                m = Bits32 (opcode, 5, 3);
7651868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                rotation = 0;
7652868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7653868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                break;
7654868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7655868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice            case eEncodingT2:
7656bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7657868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                d = Bits32 (opcode, 11, 8);
7658868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                m = Bits32 (opcode, 3, 0);
7659868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                rotation = Bits32 (opcode, 5, 4) << 3;
7660868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7661868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7662868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                if (BadReg (d) || BadReg (m))
7663868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                    return false;
7664868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7665868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                break;
7666868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7667868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice            case eEncodingA1:
7668bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
7669868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                d = Bits32 (opcode, 15, 12);
7670868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                m = Bits32 (opcode, 3, 0);
7671868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                rotation = Bits32 (opcode, 11, 10) << 3;
7672868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7673868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                // if d == 15 || m == 15 then UNPREDICTABLE;
7674868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                if ((d == 15) || (m == 15))
7675868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                    return false;
7676868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7677868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                break;
7678868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7679868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice            default:
7680868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice                return false;
7681868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        }
7682868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7683868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7684868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        if (!success)
7685868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice            return false;
7686868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7687868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        // rotated = ROR(R[m], rotation);
7688868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        uint64_t rotated = ROR (Rm, rotation);
7689868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7690868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        // R[d] = SignExtend(rotated<15:0>, 32);
7691868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        Register source_reg;
7692868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7693868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7694868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        EmulateInstruction::Context context;
7695868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        context.type = eContextRegisterLoad;
7696868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        context.SetRegister (source_reg);
7697868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
76988ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        int64_t data = llvm::SignExtend64<16> (rotated);
76998ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
7700868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice            return false;
7701868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice    }
7702868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
7703868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice    return true;
7704868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice}
7705868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice
77068ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
77078ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice// register.  You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
77088ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Ticebool
77097bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
77108ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice{
77118ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice#if 0
77128ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice    if ConditionPassed() then
77138ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        EncodingSpecificOperations();
77148ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        rotated = ROR(R[m], rotation);
77158ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        R[d] = ZeroExtend(rotated<7:0>, 32);
77168ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice#endif
77178ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77188ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice    bool success = false;
77198ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77207bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
77218ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice    {
77228ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        uint32_t d;
77238ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        uint32_t m;
77248ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        uint32_t rotation;
77258ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77268ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        // EncodingSpecificOperations();
77278ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        switch (encoding)
77288ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        {
77298ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice            case eEncodingT1:
77308ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
77318ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                d = Bits32 (opcode, 2, 0);
77328ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                m = Bits32 (opcode, 5, 3);
77338ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                rotation = 0;
77348ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77358ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                break;
77368ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77378ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice            case eEncodingT2:
7738bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
77398ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                d = Bits32 (opcode, 11, 8);
77408ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                m = Bits32 (opcode, 3, 0);
77418ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                  rotation = Bits32 (opcode, 5, 4) << 3;
77428ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77438ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
77448ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                if (BadReg (d) || BadReg (m))
77458ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                  return false;
77468ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77478ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                break;
77488ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77498ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice            case eEncodingA1:
7750bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
77518ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                d = Bits32 (opcode, 15, 12);
77528ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                m = Bits32 (opcode, 3, 0);
77538ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                rotation = Bits32 (opcode, 11, 10) << 3;
77548ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77558ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                // if d == 15 || m == 15 then UNPREDICTABLE;
77568ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                if ((d == 15) || (m == 15))
77578ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                    return false;
77588ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77598ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                break;
77608ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77618ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice            default:
77628ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice                return false;
77638ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        }
77648ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77658ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
77668ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        if (!success)
77678ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice            return false;
77688ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77698ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        // rotated = ROR(R[m], rotation);
77708ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        uint64_t rotated = ROR (Rm, rotation);
77718ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77728ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        // R[d] = ZeroExtend(rotated<7:0>, 32);
77738ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        Register source_reg;
77748ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
77758ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77768ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        EmulateInstruction::Context context;
77778ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        context.type = eContextRegisterLoad;
77788ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        context.SetRegister (source_reg);
77798ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
77808ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
77818ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice            return false;
77828ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice    }
77838ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice    return true;
77848ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice}
77858ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice
778611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
778711555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice// register.  You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
778811555f2f0f21beb0312f8ebe40849487d437f493Caroline Ticebool
77897bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
779011555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice{
779111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice#if 0
779211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice    if ConditionPassed() then
779311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        EncodingSpecificOperations();
779411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        rotated = ROR(R[m], rotation);
779511555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        R[d] = ZeroExtend(rotated<15:0>, 32);
779611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice#endif
779711555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
779811555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice    bool success = false;
779911555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
78007bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
780111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice    {
780211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        uint32_t d;
780311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        uint32_t m;
780411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        uint32_t rotation;
780511555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
780611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        switch (encoding)
780711555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        {
780811555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice            case eEncodingT1:
780911555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
781011555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                d = Bits32 (opcode, 2, 0);
781111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                m = Bits32 (opcode, 5, 3);
781211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                rotation = 0;
781311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
781411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                break;
781511555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
781611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice            case eEncodingT2:
7817bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
781811555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                d = Bits32 (opcode, 11, 8);
781911555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                m = Bits32 (opcode, 3, 0);
782011555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                rotation = Bits32 (opcode, 5, 4) << 3;
782111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
782211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
782311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                if (BadReg (d) || BadReg (m))
782411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                  return false;
782511555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
782611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                break;
782711555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
782811555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice            case eEncodingA1:
7829bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
783011555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                d = Bits32 (opcode, 15, 12);
783111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                m = Bits32 (opcode, 3, 0);
783211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                rotation = Bits32 (opcode, 11, 10) << 3;
783311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
783411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                // if d == 15 || m == 15 then UNPREDICTABLE;
783511555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                if ((d == 15) || (m == 15))
783611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                    return false;
783711555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
783811555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                break;
783911555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
784011555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice            default:
784111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice                return false;
784211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        }
784311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
784411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
784511555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        if (!success)
784611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice            return false;
784711555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
784811555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        // rotated = ROR(R[m], rotation);
784911555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        uint64_t rotated = ROR (Rm, rotation);
785011555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
785111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        // R[d] = ZeroExtend(rotated<15:0>, 32);
785211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        Register source_reg;
785311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
785411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
785511555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        EmulateInstruction::Context context;
785611555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        context.type = eContextRegisterLoad;
785711555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        context.SetRegister (source_reg);
785811555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
785911555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
786011555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice            return false;
786111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice    }
786211555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice    return true;
786311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice}
7864b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7865b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7866b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice// word respectively.
7867b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Ticebool
78687bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
7869b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice{
7870b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice#if 0
7871b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    if ConditionPassed() then
7872b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        EncodingSpecificOperations();
7873b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7874b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            UNPREDICTABLE;
7875b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        else
7876b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            address = if increment then R[n] else R[n]-8;
7877b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if wordhigher then address = address+4;
7878bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
7879b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            BranchWritePC(MemA[address,4]);
7880b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7881b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice#endif
7882b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7883b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    bool success = false;
7884b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
78857bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
7886b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    {
7887b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        uint32_t n;
7888b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        bool wback;
7889b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        bool increment;
7890b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        bool wordhigher;
7891b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7892b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        // EncodingSpecificOperations();
7893b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        switch (encoding)
7894b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        {
7895b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            case eEncodingT1:
7896bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
7897b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                n = Bits32 (opcode, 19, 16);
7898b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                wback = BitIsSet (opcode, 21);
7899b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                increment = false;
7900b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                wordhigher = false;
7901b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7902b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                // if n == 15 then UNPREDICTABLE;
7903b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                if (n == 15)
7904b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    return false;
7905b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7906b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7907b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                if (InITBlock() && !LastInITBlock())
7908b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    return false;
7909b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7910b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                break;
7911b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7912b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            case eEncodingT2:
7913bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
7914b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                n = Bits32 (opcode, 19, 16);
7915b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                wback = BitIsSet (opcode, 21);
7916b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                increment = true;
7917b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                wordhigher = false;
7918b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7919b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                // if n == 15 then UNPREDICTABLE;
7920b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                if (n == 15)
7921b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    return false;
7922b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7923b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7924b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                if (InITBlock() && !LastInITBlock())
7925b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    return false;
7926b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7927b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                break;
7928b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7929b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            case eEncodingA1:
7930b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                // n = UInt(Rn);
7931b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                n = Bits32 (opcode, 19, 16);
7932b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7933bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice                // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
7934b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                wback = BitIsSet (opcode, 21);
7935b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                increment = BitIsSet (opcode, 23);
7936b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7937b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7938b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                // if n == 15 then UNPREDICTABLE;
7939b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                if (n == 15)
7940b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    return false;
7941b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7942b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                break;
7943b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7944b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            default:
7945b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                return false;
7946b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        }
7947b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7948b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7949b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if (!CurrentModeIsPrivileged ())
7950b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            // UNPREDICTABLE;
7951b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            return false;
7952b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        else
7953b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        {
7954b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7955b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if (!success)
7956b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                return false;
7957b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7958b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            addr_t address;
7959b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            // address = if increment then R[n] else R[n]-8;
7960b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if (increment)
7961b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                address = Rn;
7962b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            else
7963b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                address = Rn - 8;
7964b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7965b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            // if wordhigher then address = address+4;
7966b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if (wordhigher)
7967b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                address = address + 4;
7968b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7969bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
7970b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            Register base_reg;
7971b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7972b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7973b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            EmulateInstruction::Context context;
7974b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            context.type = eContextReturnFromException;
7975b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            context.SetRegisterPlusOffset (base_reg, address - Rn);
7976b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7977b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7978b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if (!success)
7979b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                return false;
7980b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7981b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            CPSRWriteByInstr (data, 15, true);
7982b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7983b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            // BranchWritePC(MemA[address,4]);
7984b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            uint64_t data2 = MemARead (context, address, 4, 0, &success);
7985b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if (!success)
7986b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                return false;
7987b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7988b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            BranchWritePC (context, data2);
7989b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
7990b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7991b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            if (wback)
7992b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            {
7993b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                context.type = eContextAdjustBaseRegister;
7994b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                if (increment)
7995b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                {
7996b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    context.SetOffset (8);
7997b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
7998b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                        return false;
7999b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                }
8000b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                else
8001b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                {
8002b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    context.SetOffset (-8);
8003b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8004b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                        return false;
8005b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                }
8006b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            } // if wback
8007b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        }
8008b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    } // if ConditionPassed()
8009b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    return true;
8010b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice}
801111555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice
80122115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
80132115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// and writes the result to the destination register.  It can optionally update the condition flags based on
80142115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// the result.
80152115b4131b0e427341959fb4007e0173bf71778dJohnny Chenbool
80167bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
80172115b4131b0e427341959fb4007e0173bf71778dJohnny Chen{
80182115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#if 0
80192115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    // ARM pseudo code...
80202115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    if ConditionPassed() then
80212115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EncodingSpecificOperations();
80222115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        result = R[n] EOR imm32;
80232115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
80242115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
80252115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        else
80262115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            R[d] = result;
80272115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if setflags then
80282115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                APSR.N = result<31>;
80292115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                APSR.Z = IsZeroBit(result);
80302115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                APSR.C = carry;
80312115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                // APSR.V unchanged
80322115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#endif
80332115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
80342115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    bool success = false;
80352115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
80367bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
80372115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    {
80382115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t Rd, Rn;
80392115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
80402115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        bool setflags;
80412115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
80422115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        switch (encoding)
80432115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        {
80442115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingT1:
80452115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rd = Bits32(opcode, 11, 8);
80462115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
80472115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            setflags = BitIsSet(opcode, 20);
80482115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
80492115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
80502115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (Rd == 15 && setflags)
80517bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                return EmulateTEQImm (opcode, eEncodingT1);
80522115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
80532115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                return false;
80542115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
80552115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingA1:
80562115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rd = Bits32(opcode, 15, 12);
80572115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
80582115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            setflags = BitIsSet(opcode, 20);
80592115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
80602115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
80612115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
80622115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (Rd == 15 && setflags)
80632115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                return false;
80642115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
80652115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        default:
80662115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
80672115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        }
80682115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
80692115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // Read the first operand.
80702115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
80712115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!success)
80722115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
80732115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
80742115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t result = val1 ^ imm32;
80752115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
80762115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EmulateInstruction::Context context;
80772115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
80782115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.SetNoArgs ();
80792115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
80802115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
80812115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
80822115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    }
80832115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    return true;
80842115b4131b0e427341959fb4007e0173bf71778dJohnny Chen}
80852115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
80862115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
80872115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// optionally-shifted register value, and writes the result to the destination register.
80882115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// It can optionally update the condition flags based on the result.
80892115b4131b0e427341959fb4007e0173bf71778dJohnny Chenbool
80907bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
80912115b4131b0e427341959fb4007e0173bf71778dJohnny Chen{
80922115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#if 0
80932115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    // ARM pseudo code...
80942115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    if ConditionPassed() then
80952115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EncodingSpecificOperations();
80962115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
80972115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        result = R[n] EOR shifted;
80982115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if d == 15 then         // Can only occur for ARM encoding
80992115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            ALUWritePC(result); // setflags is always FALSE here
81002115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        else
81012115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            R[d] = result;
81022115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if setflags then
81032115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                APSR.N = result<31>;
81042115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                APSR.Z = IsZeroBit(result);
81052115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                APSR.C = carry;
81062115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                // APSR.V unchanged
81072115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#endif
81082115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81092115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    bool success = false;
81102115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81117bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
81122115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    {
81132115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t Rd, Rn, Rm;
81142115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        ARM_ShifterType shift_t;
81152115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
81162115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        bool setflags;
81172115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t carry;
81182115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        switch (encoding)
81192115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        {
81202115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingT1:
81212115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rd = Rn = Bits32(opcode, 2, 0);
81222115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rm = Bits32(opcode, 5, 3);
81232115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            setflags = !InITBlock();
81242115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            shift_t = SRType_LSL;
81252115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            shift_n = 0;
8126ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
81272115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingT2:
81282115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rd = Bits32(opcode, 11, 8);
81292115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
81302115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rm = Bits32(opcode, 3, 0);
81312115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            setflags = BitIsSet(opcode, 20);
81323dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
81333dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            // if Rd == '1111' && S == '1' then SEE TEQ (register);
81342115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (Rd == 15 && setflags)
81357bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                return EmulateTEQReg (opcode, eEncodingT1);
81362115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
81372115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                return false;
81382115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
81392115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingA1:
81402115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rd = Bits32(opcode, 15, 12);
81412115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
81422115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rm = Bits32(opcode, 3, 0);
81432115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            setflags = BitIsSet(opcode, 20);
81443dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
81452115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
81462115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
81472115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (Rd == 15 && setflags)
81482115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                return false;
81492115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
81502115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        default:
81512115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
81522115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        }
81532115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81542115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // Read the first operand.
81552115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
81562115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!success)
81572115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
81582115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81592115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // Read the second operand.
81602115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t val2 = ReadCoreReg(Rm, &success);
81612115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!success)
81622115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
81632115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81642115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
81652115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t result = val1 ^ shifted;
81662115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81672115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EmulateInstruction::Context context;
81682115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
81692115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.SetNoArgs ();
81702115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81712115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
81722115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
81732115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    }
81742115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    return true;
81752115b4131b0e427341959fb4007e0173bf71778dJohnny Chen}
81762115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
81777c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
81787c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen// writes the result to the destination register.  It can optionally update the condition flags based
81797c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen// on the result.
81807c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chenbool
81817bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
81827c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen{
81837c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen#if 0
81847c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    // ARM pseudo code...
81857c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    if ConditionPassed() then
81867c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        EncodingSpecificOperations();
81877c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        result = R[n] OR imm32;
81887c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
81897c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
81907c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        else
81917c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            R[d] = result;
81927c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if setflags then
81937c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                APSR.N = result<31>;
81947c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                APSR.Z = IsZeroBit(result);
81957c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                APSR.C = carry;
81967c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                // APSR.V unchanged
81977c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen#endif
81987c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
81997c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    bool success = false;
82007c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82017bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
82027c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    {
82037c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t Rd, Rn;
82047c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
82057c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        bool setflags;
82067c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
82077c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        switch (encoding)
82087c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        {
82097c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        case eEncodingT1:
82107c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Bits32(opcode, 11, 8);
82117c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rn = Bits32(opcode, 19, 16);
82127c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            setflags = BitIsSet(opcode, 20);
82137c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8214bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice            // if Rn == '1111' then SEE MOV (immediate);
82157c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (Rn == 15)
82167bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                return EmulateMOVRdImm (opcode, eEncodingT2);
82177c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (BadReg(Rd) || Rn == 13)
82187c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
82197c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            break;
82207c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        case eEncodingA1:
82217c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Bits32(opcode, 15, 12);
82227c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rn = Bits32(opcode, 19, 16);
82237c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            setflags = BitIsSet(opcode, 20);
82247c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
82257c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
82267c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (Rd == 15 && setflags)
82277c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
82287c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            break;
82297c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        default:
82307c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            return false;
82317c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        }
82327c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82337c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // Read the first operand.
82347c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
82357c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        if (!success)
82367c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            return false;
82377c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82387c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t result = val1 | imm32;
82397c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82407c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        EmulateInstruction::Context context;
82417c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
82427c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        context.SetNoArgs ();
82437c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82447c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
82457c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            return false;
82467c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    }
82477c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    return true;
82487c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen}
82497c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82507c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
82517c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen// value, and writes the result to the destination register.  It can optionally update the condition flags based
82527c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen// on the result.
82537c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chenbool
82547bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
82557c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen{
82567c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen#if 0
82577c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    // ARM pseudo code...
82587c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    if ConditionPassed() then
82597c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        EncodingSpecificOperations();
82607c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
82617c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        result = R[n] OR shifted;
82627c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
82637c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
82647c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        else
82657c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            R[d] = result;
82667c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if setflags then
82677c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                APSR.N = result<31>;
82687c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                APSR.Z = IsZeroBit(result);
82697c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                APSR.C = carry;
82707c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                // APSR.V unchanged
82717c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen#endif
82727c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82737c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    bool success = false;
82747c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
82757bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
82767c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    {
82777c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t Rd, Rn, Rm;
82787c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        ARM_ShifterType shift_t;
82797c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
82807c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        bool setflags;
82817c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t carry;
82827c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        switch (encoding)
82837c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        {
82847c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        case eEncodingT1:
82857c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Rn = Bits32(opcode, 2, 0);
82867c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rm = Bits32(opcode, 5, 3);
82877c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            setflags = !InITBlock();
82887c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            shift_t = SRType_LSL;
82897c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            shift_n = 0;
8290ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
82917c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        case eEncodingT2:
82927c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Bits32(opcode, 11, 8);
82937c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rn = Bits32(opcode, 19, 16);
82947c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rm = Bits32(opcode, 3, 0);
82957c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            setflags = BitIsSet(opcode, 20);
82963dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
82973dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            // if Rn == '1111' then SEE MOV (register);
82987c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (Rn == 15)
82997bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                return EmulateMOVRdRm (opcode, eEncodingT3);
83007c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
83017c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
83027c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            break;
83037c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        case eEncodingA1:
83047c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rd = Bits32(opcode, 15, 12);
83057c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rn = Bits32(opcode, 19, 16);
83067c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            Rm = Bits32(opcode, 3, 0);
83077c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            setflags = BitIsSet(opcode, 20);
83083dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
83097c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            // TODO: Emulate SUBS PC, LR and related instructions.
83107c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            if (Rd == 15 && setflags)
83117c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen                return false;
83127c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            break;
83137c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        default:
83147c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            return false;
83157c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        }
83167c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
83177c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // Read the first operand.
83187c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
83197c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        if (!success)
83207c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            return false;
83217c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
83227c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // Read the second operand.
83237c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t val2 = ReadCoreReg(Rm, &success);
83247c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        if (!success)
83257c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            return false;
83267c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
83277c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
83282115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t result = val1 | shifted;
83297c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
83307c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        EmulateInstruction::Context context;
83317c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
83327c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        context.SetNoArgs ();
83337c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
83347c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
83357c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen            return false;
83367c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    }
83377c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen    return true;
83387c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen}
83397c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
8340ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8341ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen// the destination register. It can optionally update the condition flags based on the result.
8342ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chenbool
83437bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
8344ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen{
8345ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen#if 0
8346ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    // ARM pseudo code...
8347ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    if ConditionPassed() then
8348ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        EncodingSpecificOperations();
8349ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8350ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
8351ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
8352ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        else
8353ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            R[d] = result;
8354ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            if setflags then
8355ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.N = result<31>;
8356ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.Z = IsZeroBit(result);
8357ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.C = carry;
8358ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.V = overflow;
8359ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen#endif
8360ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8361ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    bool success = false;
8362ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8363ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t Rd; // the destination register
8364ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t Rn; // the first operand
8365ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    bool setflags;
8366ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8367ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    switch (encoding) {
8368ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    case eEncodingT1:
8369ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rd = Bits32(opcode, 2, 0);
8370ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rn = Bits32(opcode, 5, 3);
8371ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        setflags = !InITBlock();
8372ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        imm32 = 0;
8373ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
8374ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    case eEncodingT2:
8375ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rd = Bits32(opcode, 11, 8);
8376ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rn = Bits32(opcode, 19, 16);
8377ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        setflags = BitIsSet(opcode, 20);
8378ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8379ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        if (BadReg(Rd) || BadReg(Rn))
8380ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            return false;
8381ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
8382ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    case eEncodingA1:
8383ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rd = Bits32(opcode, 15, 12);
8384ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rn = Bits32(opcode, 19, 16);
8385ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        setflags = BitIsSet(opcode, 20);
8386ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8387ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8388ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // TODO: Emulate SUBS PC, LR and related instructions.
8389ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        if (Rd == 15 && setflags)
8390ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            return false;
8391ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
8392ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    default:
8393ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        return false;
8394ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    }
8395ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    // Read the register value from the operand register Rn.
8396ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t reg_val = ReadCoreReg(Rn, &success);
8397ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    if (!success)
8398ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        return false;
8399ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8400ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8401ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8402ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    EmulateInstruction::Context context;
8403ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
8404ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    context.SetNoArgs ();
8405ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8406ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8407ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        return false;
8408ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8409ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    return true;
8410ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen}
8411ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8412ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8413ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen// result to the destination register. It can optionally update the condition flags based on the result.
8414ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chenbool
84157bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
8416ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen{
8417ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen#if 0
8418ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    // ARM pseudo code...
8419ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    if ConditionPassed() then
8420ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        EncodingSpecificOperations();
8421ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8422ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8423ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
8424ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
8425ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        else
8426ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            R[d] = result;
8427ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            if setflags then
8428ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.N = result<31>;
8429ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.Z = IsZeroBit(result);
8430ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.C = carry;
8431ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen                APSR.V = overflow;
8432ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen#endif
8433ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8434ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    bool success = false;
8435ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8436ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t Rd; // the destination register
8437ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t Rn; // the first operand
8438ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t Rm; // the second operand
8439ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    bool setflags;
8440ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    ARM_ShifterType shift_t;
8441ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t shift_n; // the shift applied to the value read from Rm
8442ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    switch (encoding) {
8443ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    case eEncodingT1:
8444ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rd = Bits32(opcode, 11, 8);
8445ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rn = Bits32(opcode, 19, 16);
8446ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rm = Bits32(opcode, 3, 0);
8447ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        setflags = BitIsSet(opcode, 20);
8448ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        shift_n = DecodeImmShiftThumb(opcode, shift_t);
8449ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8450ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8451ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            return false;
8452ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
8453ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    case eEncodingA1:
8454ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rd = Bits32(opcode, 15, 12);
8455ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rn = Bits32(opcode, 19, 16);
8456ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        Rm = Bits32(opcode, 3, 0);
8457ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        setflags = BitIsSet(opcode, 20);
8458ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        shift_n = DecodeImmShiftARM(opcode, shift_t);
8459ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8460ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // TODO: Emulate SUBS PC, LR and related instructions.
8461ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        if (Rd == 15 && setflags)
8462ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            return false;
8463ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        break;
8464ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    default:
8465ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        return false;
8466ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    }
8467ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    // Read the register value from register Rn.
8468ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t val1 = ReadCoreReg(Rn, &success);
8469ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    if (!success)
8470ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        return false;
8471ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8472ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    // Read the register value from register Rm.
8473ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t val2 = ReadCoreReg(Rm, &success);
8474ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    if (!success)
8475ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        return false;
8476ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8477ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8478ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8479ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8480ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    EmulateInstruction::Context context;
8481ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
8482ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    context.SetNoArgs();
8483ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8484ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        return false;
8485ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
8486ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen    return true;
8487ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen}
8488ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen
848990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
849090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen// an immediate value, and writes the result to the destination register. It can optionally update the condition
849190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen// flags based on the result.
849290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chenbool
84937bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
849490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen{
849590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen#if 0
849690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    // ARM pseudo code...
849790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    if ConditionPassed() then
849890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        EncodingSpecificOperations();
849990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
850090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        if d == 15 then
850190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
850290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        else
850390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            R[d] = result;
850490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            if setflags then
850590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.N = result<31>;
850690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.Z = IsZeroBit(result);
850790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.C = carry;
850890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.V = overflow;
850990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen#endif
851090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
851190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    bool success = false;
851290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
851390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t Rd; // the destination register
851490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t Rn; // the first operand
851590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    bool setflags;
851690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t imm32; // the immediate value to be added to the value obtained from Rn
851790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    switch (encoding) {
851890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    case eEncodingA1:
851990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        Rd = Bits32(opcode, 15, 12);
852090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        Rn = Bits32(opcode, 19, 16);
852190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        setflags = BitIsSet(opcode, 20);
852290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
852390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
852490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        // TODO: Emulate SUBS PC, LR and related instructions.
852590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        if (Rd == 15 && setflags)
852690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            return false;
852790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        break;
852890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    default:
852990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        return false;
853090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    }
853190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    // Read the register value from the operand register Rn.
853290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t reg_val = ReadCoreReg(Rn, &success);
853390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    if (!success)
853490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        return false;
853590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
853690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
853790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
853890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    EmulateInstruction::Context context;
853990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
854090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    context.SetNoArgs ();
854190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
854290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
854390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        return false;
854490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
854590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    return true;
854690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen}
854790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
854890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
854990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
855090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen// condition flags based on the result.
855190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chenbool
85527bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
855390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen{
855490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen#if 0
855590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    // ARM pseudo code...
855690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    if ConditionPassed() then
855790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        EncodingSpecificOperations();
855890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
855990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
856090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        if d == 15 then
856190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
856290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        else
856390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            R[d] = result;
856490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            if setflags then
856590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.N = result<31>;
856690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.Z = IsZeroBit(result);
856790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.C = carry;
856890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen                APSR.V = overflow;
856990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen#endif
857090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
857190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    bool success = false;
857290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
857390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t Rd; // the destination register
857490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t Rn; // the first operand
857590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t Rm; // the second operand
857690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    bool setflags;
857790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    ARM_ShifterType shift_t;
857890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t shift_n; // the shift applied to the value read from Rm
857990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    switch (encoding) {
858090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    case eEncodingA1:
858190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        Rd = Bits32(opcode, 15, 12);
858290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        Rn = Bits32(opcode, 19, 16);
858390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        Rm = Bits32(opcode, 3, 0);
858490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        setflags = BitIsSet(opcode, 20);
858590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        shift_n = DecodeImmShiftARM(opcode, shift_t);
858690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
858790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        // TODO: Emulate SUBS PC, LR and related instructions.
858890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        if (Rd == 15 && setflags)
858990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen            return false;
859090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        break;
859190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    default:
859290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        return false;
859390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    }
859490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    // Read the register value from register Rn.
859590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t val1 = ReadCoreReg(Rn, &success);
859690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    if (!success)
859790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        return false;
859890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
859990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    // Read the register value from register Rm.
860090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t val2 = ReadCoreReg(Rm, &success);
860190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    if (!success)
860290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        return false;
860390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
860490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
860590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
860690e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
860790e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    EmulateInstruction::Context context;
860890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
860990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    context.SetNoArgs();
861090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
861190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        return false;
861290e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
861390e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen    return true;
861490e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen}
861590e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen
86169b381775c532270fd07a90aa1a98750546a768b7Johnny Chen// Subtract with Carry (immediate) subtracts an immediate value and the value of
86179b381775c532270fd07a90aa1a98750546a768b7Johnny Chen// NOT (Carry flag) from a register value, and writes the result to the destination register.
86189b381775c532270fd07a90aa1a98750546a768b7Johnny Chen// It can optionally update the condition flags based on the result.
86199b381775c532270fd07a90aa1a98750546a768b7Johnny Chenbool
86207bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
86219b381775c532270fd07a90aa1a98750546a768b7Johnny Chen{
86229b381775c532270fd07a90aa1a98750546a768b7Johnny Chen#if 0
86239b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    // ARM pseudo code...
86249b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    if ConditionPassed() then
86259b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        EncodingSpecificOperations();
862615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
86279b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
86289b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
86299b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        else
86309b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            R[d] = result;
86319b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            if setflags then
86329b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.N = result<31>;
86339b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.Z = IsZeroBit(result);
86349b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.C = carry;
86359b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.V = overflow;
86369b381775c532270fd07a90aa1a98750546a768b7Johnny Chen#endif
86379b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
86389b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    bool success = false;
86399b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
86409b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t Rd; // the destination register
86419b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t Rn; // the first operand
86429b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    bool setflags;
86439b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t imm32; // the immediate value to be added to the value obtained from Rn
86449b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    switch (encoding) {
86459b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    case eEncodingT1:
86469b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rd = Bits32(opcode, 11, 8);
86479b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rn = Bits32(opcode, 19, 16);
86489b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        setflags = BitIsSet(opcode, 20);
86499b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
86509b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        if (BadReg(Rd) || BadReg(Rn))
86519b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            return false;
86529b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        break;
86539b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    case eEncodingA1:
86549b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rd = Bits32(opcode, 15, 12);
86559b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rn = Bits32(opcode, 19, 16);
86569b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        setflags = BitIsSet(opcode, 20);
86579b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
86589b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
86599b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // TODO: Emulate SUBS PC, LR and related instructions.
86609b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        if (Rd == 15 && setflags)
86619b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            return false;
86629b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        break;
86639b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    default:
86649b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        return false;
86659b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    }
86669b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    // Read the register value from the operand register Rn.
86679b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t reg_val = ReadCoreReg(Rn, &success);
86689b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    if (!success)
86699b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        return false;
86709b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
86719b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
86729b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
86739b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    EmulateInstruction::Context context;
86749b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
86759b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    context.SetNoArgs ();
86769b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
86779b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
86789b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        return false;
86799b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
86809b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    return true;
86819b381775c532270fd07a90aa1a98750546a768b7Johnny Chen}
86829b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
86839b381775c532270fd07a90aa1a98750546a768b7Johnny Chen// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
86849b381775c532270fd07a90aa1a98750546a768b7Johnny Chen// NOT (Carry flag) from a register value, and writes the result to the destination register.
86859b381775c532270fd07a90aa1a98750546a768b7Johnny Chen// It can optionally update the condition flags based on the result.
86869b381775c532270fd07a90aa1a98750546a768b7Johnny Chenbool
86877bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
86889b381775c532270fd07a90aa1a98750546a768b7Johnny Chen{
86899b381775c532270fd07a90aa1a98750546a768b7Johnny Chen#if 0
86909b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    // ARM pseudo code...
86919b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    if ConditionPassed() then
86929b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        EncodingSpecificOperations();
86939b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
86949b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
86959b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        if d == 15 then         // Can only occur for ARM encoding
86969b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
86979b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        else
86989b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            R[d] = result;
86999b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            if setflags then
87009b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.N = result<31>;
87019b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.Z = IsZeroBit(result);
87029b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.C = carry;
87039b381775c532270fd07a90aa1a98750546a768b7Johnny Chen                APSR.V = overflow;
87049b381775c532270fd07a90aa1a98750546a768b7Johnny Chen#endif
87059b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
87069b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    bool success = false;
87079b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
87089b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t Rd; // the destination register
87099b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t Rn; // the first operand
87109b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t Rm; // the second operand
87119b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    bool setflags;
87129b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    ARM_ShifterType shift_t;
87139b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t shift_n; // the shift applied to the value read from Rm
87149b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    switch (encoding) {
87159b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    case eEncodingT1:
87169b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rd = Rn = Bits32(opcode, 2, 0);
87179b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rm = Bits32(opcode, 5, 3);
87189b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        setflags = !InITBlock();
87199b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        shift_t = SRType_LSL;
87209b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        shift_n = 0;
87219b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        break;
87229b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    case eEncodingT2:
87239b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rd = Bits32(opcode, 11, 8);
87249b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rn = Bits32(opcode, 19, 16);
87259b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rm = Bits32(opcode, 3, 0);
87269b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        setflags = BitIsSet(opcode, 20);
87279b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        shift_n = DecodeImmShiftThumb(opcode, shift_t);
87289b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
87299b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            return false;
87309b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        break;
87319b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    case eEncodingA1:
87329b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rd = Bits32(opcode, 15, 12);
87339b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rn = Bits32(opcode, 19, 16);
87349b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        Rm = Bits32(opcode, 3, 0);
87359b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        setflags = BitIsSet(opcode, 20);
87369b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        shift_n = DecodeImmShiftARM(opcode, shift_t);
87379b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
87389b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // TODO: Emulate SUBS PC, LR and related instructions.
87399b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        if (Rd == 15 && setflags)
87409b381775c532270fd07a90aa1a98750546a768b7Johnny Chen            return false;
87419b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        break;
87429b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    default:
87439b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        return false;
87449b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    }
87459b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    // Read the register value from register Rn.
87469b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t val1 = ReadCoreReg(Rn, &success);
87479b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    if (!success)
87489b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        return false;
87499b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
87509b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    // Read the register value from register Rm.
87519b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t val2 = ReadCoreReg(Rm, &success);
87529b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    if (!success)
87539b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        return false;
87549b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
87559b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
87569b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
87579b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
87589b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    EmulateInstruction::Context context;
87599b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
87609b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    context.SetNoArgs();
87619b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
87629b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        return false;
87639b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
87649b381775c532270fd07a90aa1a98750546a768b7Johnny Chen    return true;
87659b381775c532270fd07a90aa1a98750546a768b7Johnny Chen}
87669b381775c532270fd07a90aa1a98750546a768b7Johnny Chen
876715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen// This instruction subtracts an immediate value from a register value, and writes the result
876815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen// to the destination register.  It can optionally update the condition flags based on the result.
876915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chenbool
87707bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
877115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen{
877215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen#if 0
877315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    // ARM pseudo code...
877415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    if ConditionPassed() then
877515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        EncodingSpecificOperations();
877615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
877715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        R[d] = result;
877815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if setflags then
877915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            APSR.N = result<31>;
878015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            APSR.Z = IsZeroBit(result);
878115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            APSR.C = carry;
878215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            APSR.V = overflow;
878315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen#endif
878415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
878515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    bool success = false;
878615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
878715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t Rd; // the destination register
878815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t Rn; // the first operand
878915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    bool setflags;
879015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
879115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    switch (encoding) {
879215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    case eEncodingT1:
879315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rd = Bits32(opcode, 2, 0);
879415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rn = Bits32(opcode, 5, 3);
879515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        setflags = !InITBlock();
879615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
879715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        break;
879815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    case eEncodingT2:
879915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rd = Rn = Bits32(opcode, 10, 8);
880015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        setflags = !InITBlock();
880115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
880215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        break;
880315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    case eEncodingT3:
880415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rd = Bits32(opcode, 11, 8);
880515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rn = Bits32(opcode, 19, 16);
880615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        setflags = BitIsSet(opcode, 20);
880715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
880815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
880915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // if Rd == '1111' && S == '1' then SEE CMP (immediate);
881015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rd == 15 && setflags)
88117bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            return EmulateCMPImm (opcode, eEncodingT2);
881215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
8813bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if Rn == '1101' then SEE SUB (SP minus immediate);
881415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rn == 13)
88157bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            return EmulateSUBSPImm (opcode, eEncodingT2);
881615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
881715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
881815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
881915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            return false;
882015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        break;
882115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    case eEncodingT4:
882215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rd = Bits32(opcode, 11, 8);
882315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rn = Bits32(opcode, 19, 16);
882415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        setflags = BitIsSet(opcode, 20);
882515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
882615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
882715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // if Rn == '1111' then SEE ADR;
882815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rn == 15)
88297bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            return EmulateADR (opcode, eEncodingT2);
883015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
883115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // if Rn == '1101' then SEE SUB (SP minus immediate);
883215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rn == 13)
88337bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            return EmulateSUBSPImm (opcode, eEncodingT3);
883415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
883515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (BadReg(Rd))
883615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            return false;
883715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        break;
883815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    default:
883915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        return false;
884015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    }
884115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    // Read the register value from the operand register Rn.
884215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t reg_val = ReadCoreReg(Rn, &success);
884315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    if (!success)
884415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        return false;
884515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
884615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
884715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
884815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    EmulateInstruction::Context context;
884915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
885015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    context.SetNoArgs ();
885115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
885215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
885315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        return false;
885415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
885515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    return true;
885615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen}
885715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
885815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen// This instruction subtracts an immediate value from a register value, and writes the result
885915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen// to the destination register.  It can optionally update the condition flags based on the result.
886015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chenbool
88617bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
886215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen{
886315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen#if 0
886415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    // ARM pseudo code...
886515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    if ConditionPassed() then
886615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        EncodingSpecificOperations();
886715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
886815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if d == 15 then
886915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            ALUWritePC(result); // setflags is always FALSE here
887015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        else
887115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            R[d] = result;
887215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            if setflags then
887315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen                APSR.N = result<31>;
887415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen                APSR.Z = IsZeroBit(result);
887515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen                APSR.C = carry;
887615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen                APSR.V = overflow;
887715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen#endif
887815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
887915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    bool success = false;
888015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
888115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t Rd; // the destination register
888215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t Rn; // the first operand
888315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    bool setflags;
888415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
888515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    switch (encoding) {
888615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    case eEncodingA1:
888715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rd = Bits32(opcode, 15, 12);
888815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        Rn = Bits32(opcode, 19, 16);
888915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        setflags = BitIsSet(opcode, 20);
889015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
889115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
8892bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if Rn == '1111' && S == '0' then SEE ADR;
889315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rn == 15 && !setflags)
88947bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            return EmulateADR (opcode, eEncodingA2);
889515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
8896bb48f0bb876db5ef13d6084b28aba1cf21f0bb7cCaroline Tice        // if Rn == '1101' then SEE SUB (SP minus immediate);
889715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rn == 13)
88987bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            return EmulateSUBSPImm (opcode, eEncodingA1);
889915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
890015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
890115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // TODO: Emulate SUBS PC, LR and related instructions.
890215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        if (Rd == 15 && setflags)
890315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen            return false;
890415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        break;
890515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    default:
890615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        return false;
890715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    }
890815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    // Read the register value from the operand register Rn.
890915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    uint32_t reg_val = ReadCoreReg(Rn, &success);
891015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    if (!success)
891115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        return false;
891215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
891315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
891415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
891515a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    EmulateInstruction::Context context;
891615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    context.type = EmulateInstruction::eContextImmediate;
891715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    context.SetNoArgs ();
891815a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
891915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
892015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        return false;
892115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
892215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen    return true;
892315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen}
892415a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen
89252115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
89262115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// immediate value.  It updates the condition flags based on the result, and discards the result.
89272115b4131b0e427341959fb4007e0173bf71778dJohnny Chenbool
89287bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
89292115b4131b0e427341959fb4007e0173bf71778dJohnny Chen{
89302115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#if 0
89312115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    // ARM pseudo code...
89322115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    if ConditionPassed() then
89332115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EncodingSpecificOperations();
89342115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        result = R[n] EOR imm32;
89352115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        APSR.N = result<31>;
89362115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        APSR.Z = IsZeroBit(result);
89372115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        APSR.C = carry;
89382115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // APSR.V unchanged
89392115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#endif
89402115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89412115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    bool success = false;
89422115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89437bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
89442115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    {
89452115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t Rn;
89462115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
89472115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
89482115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        switch (encoding)
89492115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        {
89502115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingT1:
89512115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
89527bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
89532115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (BadReg(Rn))
89542115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                return false;
89552115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
89562115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingA1:
89572115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
89587bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
89592115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
89602115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        default:
89612115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
89622115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        }
89632115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89642115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // Read the first operand.
89652115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
89662115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!success)
89672115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
89682115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89692115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t result = val1 ^ imm32;
89702115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89712115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EmulateInstruction::Context context;
89722115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
89732115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.SetNoArgs ();
89742115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89752115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!WriteFlags(context, result, carry))
89762115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
89772115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    }
89782115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    return true;
89792115b4131b0e427341959fb4007e0173bf71778dJohnny Chen}
89802115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89812115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
89822115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// optionally-shifted register value.  It updates the condition flags based on the result, and discards
89832115b4131b0e427341959fb4007e0173bf71778dJohnny Chen// the result.
89842115b4131b0e427341959fb4007e0173bf71778dJohnny Chenbool
89857bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
89862115b4131b0e427341959fb4007e0173bf71778dJohnny Chen{
89872115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#if 0
89882115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    // ARM pseudo code...
89892115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    if ConditionPassed() then
89902115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EncodingSpecificOperations();
89912115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
89922115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        result = R[n] EOR shifted;
89932115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        APSR.N = result<31>;
89942115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        APSR.Z = IsZeroBit(result);
89952115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        APSR.C = carry;
89962115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // APSR.V unchanged
89972115b4131b0e427341959fb4007e0173bf71778dJohnny Chen#endif
89982115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
89992115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    bool success = false;
90002115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
90017bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
90022115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    {
90032115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t Rn, Rm;
90042115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        ARM_ShifterType shift_t;
90052115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
90062115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t carry;
90072115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        switch (encoding)
90082115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        {
90092115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingT1:
90102115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
90112115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rm = Bits32(opcode, 3, 0);
90123dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
90132115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            if (BadReg(Rn) || BadReg(Rm))
90142115b4131b0e427341959fb4007e0173bf71778dJohnny Chen                return false;
90152115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
90162115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        case eEncodingA1:
90172115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rn = Bits32(opcode, 19, 16);
90182115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            Rm = Bits32(opcode, 3, 0);
90193dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
90202115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            break;
90212115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        default:
90222115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
90232115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        }
90242115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
90252115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // Read the first operand.
90262115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
90272115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!success)
90282115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
90292115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
90302115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // Read the second operand.
90312115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t val2 = ReadCoreReg(Rm, &success);
90322115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!success)
90332115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
90342115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
90352115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
90362115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        uint32_t result = val1 ^ shifted;
90372115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
90382115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        EmulateInstruction::Context context;
90392115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.type = EmulateInstruction::eContextImmediate;
90402115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        context.SetNoArgs ();
90412115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
90422115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        if (!WriteFlags(context, result, carry))
90432115b4131b0e427341959fb4007e0173bf71778dJohnny Chen            return false;
90442115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    }
90452115b4131b0e427341959fb4007e0173bf71778dJohnny Chen    return true;
90462115b4131b0e427341959fb4007e0173bf71778dJohnny Chen}
90472115b4131b0e427341959fb4007e0173bf71778dJohnny Chen
9048de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9049de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen// It updates the condition flags based on the result, and discards the result.
9050de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chenbool
90517bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
9052de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen{
9053de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen#if 0
9054de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    // ARM pseudo code...
9055de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    if ConditionPassed() then
9056de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        EncodingSpecificOperations();
9057de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        result = R[n] AND imm32;
9058de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        APSR.N = result<31>;
9059de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        APSR.Z = IsZeroBit(result);
9060de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        APSR.C = carry;
9061de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // APSR.V unchanged
9062de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen#endif
9063de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9064de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    bool success = false;
9065de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
90667bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
9067de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    {
9068de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t Rn;
9069de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9070de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9071de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        switch (encoding)
9072de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        {
9073de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        case eEncodingT1:
9074de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rn = Bits32(opcode, 19, 16);
9075de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9076de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            if (BadReg(Rn))
9077de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen                return false;
9078de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            break;
9079de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        case eEncodingA1:
9080de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rn = Bits32(opcode, 19, 16);
9081de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9082de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            break;
9083de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        default:
9084de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            return false;
9085de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        }
9086de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9087de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // Read the first operand.
9088de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
9089de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        if (!success)
9090de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            return false;
9091de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9092de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t result = val1 & imm32;
9093de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9094de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        EmulateInstruction::Context context;
9095de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
9096de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        context.SetNoArgs ();
9097de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9098de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        if (!WriteFlags(context, result, carry))
9099de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            return false;
9100de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    }
9101de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    return true;
9102de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen}
9103de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9104de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9105de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen// It updates the condition flags based on the result, and discards the result.
9106de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chenbool
91077bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
9108de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen{
9109de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen#if 0
9110de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    // ARM pseudo code...
9111de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    if ConditionPassed() then
9112de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        EncodingSpecificOperations();
9113de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9114de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        result = R[n] AND shifted;
9115de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        APSR.N = result<31>;
9116de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        APSR.Z = IsZeroBit(result);
9117de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        APSR.C = carry;
9118de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // APSR.V unchanged
9119de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen#endif
9120de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9121de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    bool success = false;
9122de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
91237bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    if (ConditionPassed(opcode))
9124de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    {
9125de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t Rn, Rm;
9126de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        ARM_ShifterType shift_t;
9127de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t shift_n; // the shift applied to the value read from Rm
9128de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t carry;
9129de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        switch (encoding)
9130de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        {
9131de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        case eEncodingT1:
9132de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rn = Bits32(opcode, 2, 0);
9133de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rm = Bits32(opcode, 5, 3);
9134de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            shift_t = SRType_LSL;
9135de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            shift_n = 0;
9136ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen            break;
9137de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        case eEncodingT2:
9138de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rn = Bits32(opcode, 19, 16);
9139de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rm = Bits32(opcode, 3, 0);
91403dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftThumb(opcode, shift_t);
9141de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            if (BadReg(Rn) || BadReg(Rm))
9142de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen                return false;
9143de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            break;
9144de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        case eEncodingA1:
9145de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rn = Bits32(opcode, 19, 16);
9146de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            Rm = Bits32(opcode, 3, 0);
91473dd06057d611b9d73c9b7ce69011c739dc40c6eeJohnny Chen            shift_n = DecodeImmShiftARM(opcode, shift_t);
9148de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            break;
9149de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        default:
9150de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            return false;
9151de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        }
9152de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9153de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // Read the first operand.
9154de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t val1 = ReadCoreReg(Rn, &success);
9155de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        if (!success)
9156de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            return false;
9157de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9158de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // Read the second operand.
9159de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t val2 = ReadCoreReg(Rm, &success);
9160de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        if (!success)
9161de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            return false;
9162de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9163de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9164de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        uint32_t result = val1 & shifted;
9165de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9166de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        EmulateInstruction::Context context;
9167de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        context.type = EmulateInstruction::eContextImmediate;
9168de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        context.SetNoArgs ();
9169de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
9170de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        if (!WriteFlags(context, result, carry))
9171de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen            return false;
9172de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    }
9173de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen    return true;
9174de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen}
9175d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9176d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.216 SUB (SP minus register)
9177d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9178d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9179d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9180d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
9181d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if ConditionPassed() then
9182d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        EncodingSpecificOperations();
9183d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9184d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9185d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        if d == 15 then // Can only occur for ARM encoding
9186d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            ALUWritePC(result); // setflags is always FALSE here
9187d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        else
9188d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            R[d] = result;
9189d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            if setflags then
9190d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                APSR.N = result<31>;
9191d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                APSR.Z = IsZeroBit(result);
9192d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                APSR.C = carry;
9193d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                APSR.V = overflow;
9194d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9195d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9196d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    bool success = false;
9197d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9198d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9199d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
9200d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        uint32_t d;
9201d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        uint32_t m;
9202d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        bool setflags;
9203d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        ARM_ShifterType shift_t;
9204d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        uint32_t shift_n;
9205d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9206d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9207d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
9208d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            case eEncodingT1:
9209d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9210d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                d = Bits32 (opcode, 11, 8);
9211d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                m = Bits32 (opcode, 3, 0);
9212d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                setflags = BitIsSet (opcode, 20);
9213d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9214d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9215d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                shift_n = DecodeImmShiftThumb (opcode, shift_t);
9216d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9217d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9218d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9219d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                    return false;
9220d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9221d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                // if d == 15 || BadReg(m) then UNPREDICTABLE;
9222d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                if ((d == 15) || BadReg (m))
9223d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                    return false;
9224d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                break;
9225d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9226d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            case eEncodingA1:
9227d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9228d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9229d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                d = Bits32 (opcode, 15, 12);
9230d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                m = Bits32 (opcode, 3, 0);
9231d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                setflags = BitIsSet (opcode, 20);
9232d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9233d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9234d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                shift_n = DecodeImmShiftARM (opcode, shift_t);
9235d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                break;
9236d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9237d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            default:
9238d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice                return false;
9239d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
9240d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9241d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9242d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        uint32_t Rm = ReadCoreReg (m, &success);
9243d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        if (!success)
9244d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            return false;
9245d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9246d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9247d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9248d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9249d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9250d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        if (!success)
9251d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            return false;
9252d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9253d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9254d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9255d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        EmulateInstruction::Context context;
9256d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        context.type = eContextSubtraction;
9257d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        Register sp_reg;
9258d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
9259d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        Register dwarf_reg;
9260d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9261d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9262d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9263ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
9264d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice            return false;
9265d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
9266d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
9267d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
9268d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9269d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9270d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.7 ADD (register-shifted register)
9271d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9272c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline TiceEmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
9273d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9274d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
9275c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice    if ConditionPassed() then
9276c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        EncodingSpecificOperations();
9277c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        shift_n = UInt(R[s]<7:0>);
9278c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9279c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9280c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        R[d] = result;
9281c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        if setflags then
9282c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            APSR.N = result<31>;
9283c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            APSR.Z = IsZeroBit(result);
9284c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            APSR.C = carry;
9285c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            APSR.V = overflow;
9286d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9287d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9288c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice    bool success = false;
9289d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9290d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9291d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
9292c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t d;
9293c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t n;
9294c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t m;
9295c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t s;
9296c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        bool setflags;
9297c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        ARM_ShifterType shift_t;
9298c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9299d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9300d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
9301c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            case eEncodingA1:
9302c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9303c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                d = Bits32 (opcode, 15, 12);
9304c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                n = Bits32 (opcode, 19, 16);
9305c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                m = Bits32 (opcode, 3, 0);
9306c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                s = Bits32 (opcode, 11, 8);
9307c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9308c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9309c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                setflags = BitIsSet (opcode, 20);
9310c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9311c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9312c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9313c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9314c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                    return false;
9315c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                break;
9316c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9317c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            default:
9318c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice                return false;
9319d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
9320c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9321c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        // shift_n = UInt(R[s]<7:0>);
9322c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t Rs = ReadCoreReg (s, &success);
9323c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        if (!success)
9324c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            return false;
9325c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9326c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t shift_n = Bits32 (Rs, 7, 0);
9327c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9328c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9329c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t Rm = ReadCoreReg (m, &success);
9330c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        if (!success)
9331c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            return false;
9332c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9333c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9334c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9335c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9336c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
9337c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        if (!success)
9338c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            return false;
9339c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9340c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9341c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9342c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        // R[d] = result;
9343c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        EmulateInstruction::Context context;
9344c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        context.type = eContextAddition;
9345c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        Register reg_n;
93461697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
9347c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        Register reg_m;
93481697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9349c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9350c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        context.SetRegisterRegisterOperands (reg_n, reg_m);
9351c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9352c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9353c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            return false;
9354c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice
9355c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        // if setflags then
9356c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            // APSR.N = result<31>;
9357c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            // APSR.Z = IsZeroBit(result);
9358c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            // APSR.C = carry;
9359c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            // APSR.V = overflow;
9360c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        if (setflags)
9361c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice            return WriteFlags (context, res.result, res.carry_out, res.overflow);
9362d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
9363d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
9364d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
9365d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9366d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.213 SUB (register)
9367d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9368d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9369d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9370d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
93714cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice    if ConditionPassed() then
93724cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        EncodingSpecificOperations();
93734cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
93744cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
93754cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        if d == 15 then // Can only occur for ARM encoding
93764cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            ALUWritePC(result); // setflags is always FALSE here
93774cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        else
93784cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            R[d] = result;
93794cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            if setflags then
93804cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                APSR.N = result<31>;
93814cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                APSR.Z = IsZeroBit(result);
93824cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                APSR.C = carry;
93834cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                APSR.V = overflow;
9384d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9385d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
93864cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice    bool success = false;
9387d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9388d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9389d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
93904cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        uint32_t d;
93914cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        uint32_t n;
93924cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        uint32_t m;
93934cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        bool setflags;
93944cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        ARM_ShifterType shift_t;
93954cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        uint32_t shift_n;
93964cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
9397d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9398d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
93994cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            case eEncodingT1:
94004cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
94014cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                d = Bits32 (opcode, 2, 0);
94024cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                n = Bits32 (opcode, 5, 3);
94034cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                m = Bits32 (opcode, 8, 6);
94044cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                setflags = !InITBlock();
94054cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94064cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // (shift_t, shift_n) = (SRType_LSL, 0);
94074cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                shift_t = SRType_LSL;
94084cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                shift_n = 0;
94094cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94104cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                break;
94114cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94124cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            case eEncodingT2:
94134cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
94144cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // if Rn == ‘1101’ then SEE SUB (SP minus register);
94154cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
94164cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                d = Bits32 (opcode, 11, 8);
94174cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                n = Bits32 (opcode, 19, 16);
94184cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                m = Bits32 (opcode, 3, 0);
94194cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                setflags = BitIsSet (opcode, 20);
94204cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94214cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
94224cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                shift_n = DecodeImmShiftThumb (opcode, shift_t);
94234cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94244cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
94254cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
94264cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                    return false;
94274cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94284cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                break;
94294cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94304cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            case eEncodingA1:
94314cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
94324cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // if Rn == ‘1101’ then SEE SUB (SP minus register);
94334cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
94344cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                d = Bits32 (opcode, 15, 12);
94354cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                n = Bits32 (opcode, 19, 16);
94364cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                m = Bits32 (opcode, 3, 0);
94374cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                setflags = BitIsSet (opcode, 20);
94384cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94394cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
94404cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                shift_n = DecodeImmShiftARM (opcode, shift_t);
94414cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94424cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                break;
94434cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94444cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            default:
94454cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                return false;
9446d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
94474cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94484cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
94494cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        uint32_t Rm = ReadCoreReg (m, &success);
94504cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        if (!success)
94514cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            return false;
94524cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94534cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
94544cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94554cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
94564cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
94574cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        if (!success)
94584cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            return false;
94594cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94604cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
94614cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94624cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        // if d == 15 then // Can only occur for ARM encoding
94634cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            // ALUWritePC(result); // setflags is always FALSE here
94644cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        // else
94654cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            // R[d] = result;
94664cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            // if setflags then
94674cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // APSR.N = result<31>;
94684cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // APSR.Z = IsZeroBit(result);
94694cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // APSR.C = carry;
94704cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice                // APSR.V = overflow;
94714cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
94724cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        EmulateInstruction::Context context;
94734cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        context.type = eContextSubtraction;
94744cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        Register reg_n;
94751697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
94764cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        Register reg_m;
94771697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
94784cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        context.SetRegisterRegisterOperands (reg_n, reg_m);
94794cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
9480ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
94814cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice            return false;
9482d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
9483d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
9484d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
94854cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice
9486d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.202 STREX
94875168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
94885168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice// word from a register to memory if the executing processor has exclusive access to the memory addressed.
9489d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9490d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9491d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9492d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
94935168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice    if ConditionPassed() then
94945168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
94955168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        address = R[n] + imm32;
94965168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        if ExclusiveMonitorsPass(address,4) then
94975168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            MemA[address,4] = R[t];
94985168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            R[d] = 0;
94995168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        else
95005168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            R[d] = 1;
9501d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9502d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
95035168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice    bool success = false;
9504d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9505d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9506d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
95075168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        uint32_t d;
95085168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        uint32_t t;
95095168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        uint32_t n;
95105168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        uint32_t imm32;
95115168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
95125168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
9513d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9514d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
95155168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            case eEncodingT1:
95165168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
95175168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                d = Bits32 (opcode, 11, 8);
95185168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                t = Bits32 (opcode, 15, 12);
95195168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                n = Bits32 (opcode, 19, 16);
95205168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                imm32 = Bits32 (opcode, 7, 0) << 2;
95215168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95225168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
95235168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                if (BadReg (d) || BadReg (t) || (n == 15))
95245168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                  return false;
95255168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95265168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                // if d == n || d == t then UNPREDICTABLE;
95275168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                if ((d == n) || (d == t))
95285168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                  return false;
95295168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95305168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                break;
95315168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95325168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            case eEncodingA1:
95335168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
95345168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                d = Bits32 (opcode, 15, 12);
95355168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                t = Bits32 (opcode, 3, 0);
95365168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                n = Bits32 (opcode, 19, 16);
95375168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                imm32 = 0;
95385168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95395168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
95405168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                if ((d == 15) || (t == 15) || (n == 15))
95415168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                    return false;
95425168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95435168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                // if d == n || d == t then UNPREDICTABLE;
95445168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                if ((d == n) || (d == t))
95455168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                    return false;
95465168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95475168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                break;
95485168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95495168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            default:
95505168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                return false;
95515168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        }
95525168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95535168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        // address = R[n] + imm32;
95545168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
95555168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        if (!success)
95565168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            return false;
95575168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95585168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        addr_t address = Rn + imm32;
95595168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95605168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        Register base_reg;
95615168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
95625168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        Register data_reg;
95635168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
95645168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        EmulateInstruction::Context context;
95655168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        context.type = eContextRegisterStore;
95665168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
95675168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95685168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        // if ExclusiveMonitorsPass(address,4) then
95695168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
95705168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        //                                                         always return true.
95715168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        if (true)
95725168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        {
95735168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            // MemA[address,4] = R[t];
95745168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
95755168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            if (!success)
95765168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                return false;
95775168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95785168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            if (!MemAWrite (context, address, Rt, addr_byte_size))
95795168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                return false;
95805168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice
95815168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            // R[d] = 0;
95825168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
95835168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                return false;
95845168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        }
95855168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        else
95865168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        {
95875168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            // R[d] = 1;
95885168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
95895168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice                return false;
9590d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
9591d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
9592d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
9593d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
9594d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9595d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.197 STRB (immediate, ARM)
9596d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9597d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9598d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9599d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
9600ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice    if ConditionPassed() then
9601ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        EncodingSpecificOperations();
9602ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9603ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        address = if index then offset_addr else R[n];
9604ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        MemU[address,1] = R[t]<7:0>;
9605ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if wback then R[n] = offset_addr;
9606d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9607d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9608ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice    bool success = false;
9609d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9610d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9611d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
9612ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        uint32_t t;
9613ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        uint32_t n;
9614ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        uint32_t imm32;
9615ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        bool index;
9616ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        bool add;
9617ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        bool wback;
9618ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9619d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9620d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
9621ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            case eEncodingA1:
9622ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9623ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9624ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                t = Bits32 (opcode, 15, 12);
9625ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                n = Bits32 (opcode, 19, 16);
9626ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                imm32 = Bits32 (opcode, 11, 0);
9627ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9628ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9629ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                index = BitIsSet (opcode, 24);
9630ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                add = BitIsSet (opcode, 23);
9631ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9632ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9633ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                // if t == 15 then UNPREDICTABLE;
9634ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                if (t == 15)
9635ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                    return false;
9636ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9637ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9638ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                if (wback && ((n == 15) || (n == t)))
9639ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                    return false;
9640ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9641ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                break;
9642ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9643ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            default:
9644ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                return false;
9645ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        }
9646ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9647ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9648ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
9649ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (!success)
9650ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            return false;
9651ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9652ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        addr_t offset_addr;
9653ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (add)
9654ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            offset_addr = Rn + imm32;
9655ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        else
9656ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            offset_addr = Rn - imm32;
9657ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9658ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        // address = if index then offset_addr else R[n];
9659ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        addr_t address;
9660ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (index)
9661ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            address = offset_addr;
9662ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        else
9663ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            address = Rn;
9664ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9665ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        // MemU[address,1] = R[t]<7:0>;
9666ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        uint32_t Rt = ReadCoreReg (t, &success);
9667ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (!success)
9668ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            return false;
9669ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9670ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        Register base_reg;
96711697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9672ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        Register data_reg;
96731697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9674ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        EmulateInstruction::Context context;
9675ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        context.type = eContextRegisterStore;
9676ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9677ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9678ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9679ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            return false;
9680ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice
9681ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        // if wback then R[n] = offset_addr;
9682ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        if (wback)
9683ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        {
9684ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice            if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9685ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice                return false;
9686d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
9687d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
9688d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
9689d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
9690d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9691d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.194 STR (immediate, ARM)
9692d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9693d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9694d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9695d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
9696d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice    if ConditionPassed() then
9697d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        EncodingSpecificOperations();
9698d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9699d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        address = if index then offset_addr else R[n];
9700d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9701d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        if wback then R[n] = offset_addr;
9702d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9703d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9704d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice    bool success = false;
9705d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9706d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9707d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
9708d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        uint32_t t;
9709d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        uint32_t n;
9710d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        uint32_t imm32;
9711d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        bool index;
9712d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        bool add;
9713d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        bool wback;
9714d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9715d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
9716d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9717d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9718d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
9719d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            case eEncodingA1:
9720d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                // if P == ‘0’ && W == ‘1’ then SEE STRT;
9721d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9722d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9723d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                t = Bits32 (opcode, 15, 12);
9724d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                n = Bits32 (opcode, 19, 16);
9725d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                imm32 = Bits32 (opcode, 11, 0);
9726d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9727d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9728d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                index = BitIsSet (opcode, 24);
9729d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                add = BitIsSet (opcode, 23);
9730d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9731d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9732d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9733d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                if (wback && ((n == 15) || (n == t)))
9734d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                    return false;
9735d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9736d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                break;
9737d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9738d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            default:
9739d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                return false;
9740d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        }
9741d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9742d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9743d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
9744d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        if (!success)
9745d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            return false;
9746d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9747d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        addr_t offset_addr;
9748d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        if (add)
9749d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            offset_addr = Rn + imm32;
9750d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        else
9751d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            offset_addr = Rn - imm32;
9752d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9753d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        // address = if index then offset_addr else R[n];
9754d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        addr_t address;
9755d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        if (index)
9756d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            address = offset_addr;
9757d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        else
9758d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            address = Rn;
9759d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9760d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        Register base_reg;
97611697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9762d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        Register data_reg;
97631697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9764d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        EmulateInstruction::Context context;
9765d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        context.type = eContextRegisterStore;
9766d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9767d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9768d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9769d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        uint32_t Rt = ReadCoreReg (t, &success);
9770d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        if (!success)
9771d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            return false;
9772d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9773d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        if (t == 15)
9774d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        {
9775e98b958df160cef9f2e816b4d86342f42a1c4025Caroline Tice            uint32_t pc_value = ReadCoreReg (PC_REG, &success);
9776d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            if (!success)
9777d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                return false;
9778d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9779d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            if (!MemUWrite (context, address, pc_value, addr_byte_size))
9780d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                return false;
9781d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        }
9782d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        else
9783d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        {
9784d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            if (!MemUWrite (context, address, Rt, addr_byte_size))
9785d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                  return false;
9786d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        }
9787d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9788d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        // if wback then R[n] = offset_addr;
9789d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        if (wback)
9790d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        {
9791d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            context.type = eContextAdjustBaseRegister;
9792d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            context.SetImmediate (offset_addr);
9793d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice
9794d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9795d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice                return false;
9796d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
9797d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
9798d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
9799d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
9800d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9801d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.66 LDRD (immediate)
98021697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
98031697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice// words from memory, and writes them to two registers.  It can use offset, post-indexed, or pre-indexed addressing.
9804d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9805d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9806d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9807d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
98081697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice    if ConditionPassed() then
98091697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
98101697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
98111697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        address = if index then offset_addr else R[n];
98121697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        R[t] = MemA[address,4];
98131697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        R[t2] = MemA[address+4,4];
98141697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if wback then R[n] = offset_addr;
9815d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9816d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
98171697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice    bool success = false;
9818d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9819d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9820d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
98211697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        uint32_t t;
98221697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        uint32_t t2;
98231697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        uint32_t n;
98241697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        uint32_t imm32;
98251697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        bool index;
98261697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        bool add;
98271697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        bool wback;
98281697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
9829d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9830d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
98311697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            case eEncodingT1:
98321697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
98331697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if Rn == ‘1111’ then SEE LDRD (literal);
98341697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
98351697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                t = Bits32 (opcode, 15, 12);
98361697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                t2 = Bits32 (opcode, 11, 8);
98371697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                n = Bits32 (opcode, 19, 16);
98381697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                imm32 = Bits32 (opcode, 7, 0) << 2;
98391697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98401697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
98411697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                index = BitIsSet (opcode, 24);
98421697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                add = BitIsSet (opcode, 23);
98431697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                wback = BitIsSet (opcode, 21);
98441697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98451697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if wback && (n == t || n == t2) then UNPREDICTABLE;
98461697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                if (wback && ((n == t) || (n == t2)))
98471697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                    return false;
98481697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98491697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
98501697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                if (BadReg (t) || BadReg (t2) || (t == t2))
98511697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                    return false;
98521697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98531697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                break;
98541697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98551697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            case eEncodingA1:
98561697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if Rn == ‘1111’ then SEE LDRD (literal);
98571697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if Rt<0> == ‘1’ then UNPREDICTABLE;
98581697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
98591697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                t = Bits32 (opcode, 15, 12);
9860eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                if (BitIsSet (t, 0))
9861eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                    return false;
98621697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                t2 = t + 1;
98631697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                n = Bits32 (opcode, 19, 16);
98641697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
98651697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98661697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
98671697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                index = BitIsSet (opcode, 24);
98681697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                add = BitIsSet (opcode, 23);
98691697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
98701697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98711697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
98721697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
98731697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                    return false;
98741697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98751697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if wback && (n == t || n == t2) then UNPREDICTABLE;
98761697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                if (wback && ((n == t) || (n == t2)))
98771697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                    return false;
98781697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98791697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                //if t2 == 15 then UNPREDICTABLE;
98801697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                if (t2 == 15)
98811697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                    return false;
98821697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98831697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                break;
98841697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98851697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            default:
98861697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                return false;
98871697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        }
98881697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98891697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
98901697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
98911697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (!success)
98921697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            return false;
98931697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
98941697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        addr_t offset_addr;
98951697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (add)
98961697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                  offset_addr = Rn + imm32;
98971697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        else
98981697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            offset_addr = Rn - imm32;
98991697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99001697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        //address = if index then offset_addr else R[n];
99011697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        addr_t address;
99021697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (index)
99031697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            address = offset_addr;
99041697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        else
99051697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            address = Rn;
99061697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99071697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        //R[t] = MemA[address,4];
99081697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        Register base_reg;
99091697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
99101697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99111697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        EmulateInstruction::Context context;
99121697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        context.type = eContextRegisterLoad;
99131697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        context.SetRegisterPlusOffset (base_reg, address - Rn);
99141697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99151697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
99161697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
99171697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (!success)
99181697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            return false;
99191697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99201697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
99211697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            return false;
99221697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99231697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        //R[t2] = MemA[address+4,4];
99241697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99251697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
99261697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        data = MemARead (context, address + 4, addr_byte_size, 0, &success);
99271697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (!success)
99281697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            return false;
99291697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99301697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
99311697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            return false;
99321697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99331697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        //if wback then R[n] = offset_addr;
99341697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        if (wback)
99351697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        {
99361697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            context.type = eContextAdjustBaseRegister;
99371697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            context.SetAddress (offset_addr);
99381697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice
99391697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
99401697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice                return false;
9941d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
9942d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
9943d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
9944d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
9945d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9946d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.68 LDRD (register)
9947eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
9948eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice// words from memory, and writes them to two registers.  It can use offset, post-indexed or pre-indexed addressing.
9949d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
9950d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
9951d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
9952d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
9953eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice    if ConditionPassed() then
9954eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        EncodingSpecificOperations();
9955eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
9956eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        address = if index then offset_addr else R[n];
9957eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        R[t] = MemA[address,4];
9958eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        R[t2] = MemA[address+4,4];
9959eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if wback then R[n] = offset_addr;
9960d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
9961d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9962eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice    bool success = false;
9963d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9964d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    if (ConditionPassed(opcode))
9965d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    {
9966eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        uint32_t t;
9967eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        uint32_t t2;
9968eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        uint32_t n;
9969eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        uint32_t m;
9970eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        bool index;
9971eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        bool add;
9972eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        bool wback;
9973d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9974d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        switch (encoding)
9975d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
9976eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            case eEncodingA1:
9977eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                // if Rt<0> == ‘1’ then UNPREDICTABLE;
9978eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
9979eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                t = Bits32 (opcode, 15, 12);
9980eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                if (BitIsSet (t, 0))
9981eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                    return false;
9982eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                t2 = t + 1;
9983eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                n = Bits32 (opcode, 19, 16);
9984eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                m = Bits32 (opcode, 3, 0);
9985d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9986eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9987eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                index = BitIsSet (opcode, 24);
9988eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                add = BitIsSet (opcode, 23);
9989eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9990d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9991eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9992eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                  if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9993eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                  return false;
9994d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9995eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
9996eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                  if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
9997eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                  return false;
9998d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
9999eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10000eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                  if (wback && ((n == 15) || (n == t) || (n == t2)))
10001eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                  return false;
10002d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10003eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10004eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                if ((ArchVersion() < 6) && wback && (m == n))
10005eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                  return false;
10006eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                break;
10007d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10008eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            default:
10009eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                return false;
10010d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
10011d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10012eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        uint32_t Rn = ReadCoreReg (n, &success);
10013eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (!success)
10014eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            return false;
10015eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        Register base_reg;
10016eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10017d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10018eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        uint32_t Rm = ReadCoreReg (m, &success);
10019eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (!success)
10020eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            return false;
10021eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        Register offset_reg;
10022eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
10023d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10024eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10025eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        addr_t offset_addr;
10026eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (add)
10027eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            offset_addr = Rn + Rm;
10028eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        else
10029eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            offset_addr = Rn - Rm;
10030d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10031eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        // address = if index then offset_addr else R[n];
10032eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        addr_t address;
10033eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (index)
10034eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            address = offset_addr;
10035eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        else
10036eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            address = Rn;
10037d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10038eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        EmulateInstruction::Context context;
10039eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        context.type = eContextRegisterLoad;
10040eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10041d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10042eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        // R[t] = MemA[address,4];
10043eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        const uint32_t addr_byte_size = GetAddressByteSize();
10044eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10045eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (!success)
10046eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            return false;
10047d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10048eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10049eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            return false;
10050d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10051eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        // R[t2] = MemA[address+4,4];
10052d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10053eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10054eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (!success)
10055eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            return false;
10056d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10057eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10058eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            return false;
10059d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10060eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        // if wback then R[n] = offset_addr;
10061eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        if (wback)
10062d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        {
10063eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            context.type = eContextAdjustBaseRegister;
10064eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            context.SetAddress (offset_addr);
10065d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10066eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10067eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice                return false;
10068d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        }
10069d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    }
10070d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
10071d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
10072d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10073d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10074d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.200 STRD (immediate)
10075d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
10076d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10077d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
10078d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
10079d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
10080d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10081d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    //bool success = false;
10082d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10083eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//    if (ConditionPassed(opcode))
10084eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//    {
10085eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//        switch (encoding)
10086eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//        {
10087eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//        }
10088eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//    }
10089d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    return true;
10090d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
10091d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10092d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10093d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice// A8.6.201 STRD (register)
10094d05b4903bb95b07e709986961fe387921dd0e029Caroline Ticebool
10095d05b4903bb95b07e709986961fe387921dd0e029Caroline TiceEmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10096d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice{
10097d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#if 0
10098d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice#endif
10099d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10100d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice    //bool success = false;
10101d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
10102eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//    if (ConditionPassed(opcode))
10103eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//    {
10104eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//        switch (encoding)
10105eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//        {
10106eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//        }
10107eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice//    }
1010824bc5d9bfad2a1c562c27e7cf37e1c56d85c45e7Greg Clayton    return true;
10109d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice}
10110d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice
101112b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg ClaytonEmulateInstructionARM::ARMOpcode*
101122b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg ClaytonEmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
1011364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton{
101142b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    static ARMOpcode
101152b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    g_arm_opcodes[] =
101162b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    {
101172b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
101182b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // Prologue instructions
101192b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
101202b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
101212b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // push register(s)
101229f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0x0fff0000, 0x092d0000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
101239f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0x0fff0fff, 0x052d0004, ARMvAll,       eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
101242b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
101252b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // set r7 to point to a stack offset
101269f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0x0ffff000, 0x028d7000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
10127864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        { 0x0ffff000, 0x024c7000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
10128e7cf4206fd3fa57067a9612118250bbfb88a4e68Johnny Chen        // copy the stack pointer to ip
101299f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0x0fffffff, 0x01a0c00d, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
101309f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0x0ffff000, 0x028dc000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
10131864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        { 0x0ffff000, 0x024dc000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
101322b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
101332b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // adjust the stack pointer
10134864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        { 0x0ffff000, 0x024dd000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
10135d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        { 0x0fef0010, 0x004d0000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
101362b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
101372b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // push one register
101382b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
101393e4079716c15760dfd6efc62391d5c1da713cef6Caroline Tice        { 0x0e5f0000, 0x040d0000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
101402b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
101412b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // vector push consecutive extension register(s)
101429b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
101439b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
101442b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
101452b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
10146587a0a4e5341bac8a8936b84fc73d6a7e8ada46fJohnny Chen        // Epilogue instructions
101472b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
101482b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
101499f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0x0fff0000, 0x08bd0000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
101509f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0x0fff0fff, 0x049d0004, ARMvAll,       eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
101519b8d783409b5b80af2cf129c45cbc39c9544cccaJohnny Chen        { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
10152b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
10153b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen
10154b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        //----------------------------------------------------------------------
10155b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        // Supervisor Call (previously Software Interrupt)
10156b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        //----------------------------------------------------------------------
101573b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        { 0x0f000000, 0x0f000000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
101583b620b38cd170c20ea607585021ab2ab50286943Johnny Chen
101593b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        //----------------------------------------------------------------------
101603b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        // Branch instructions
101613b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        //----------------------------------------------------------------------
10162696b4effb53cac2ec14b54a65c695450b4d7f456Johnny Chen        { 0x0f000000, 0x0a000000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
10163383d629938986b4ae4867f08505be8a9147c1308Johnny Chen        // To resolve ambiguity, "blx <label>" should come before "bl <label>".
10164383d629938986b4ae4867f08505be8a9147c1308Johnny Chen        { 0xfe000000, 0xfa000000, ARMV5_ABOVE,   eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
10165383d629938986b4ae4867f08505be8a9147c1308Johnny Chen        { 0x0f000000, 0x0b000000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
10166383d629938986b4ae4867f08505be8a9147c1308Johnny Chen        { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE,   eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
10167ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        // for example, "bx lr"
10168ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        { 0x0ffffff0, 0x012fff10, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
1016959e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        // bxj
1017059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        { 0x0ffffff0, 0x012fff20, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
10171b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen
10172b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        //----------------------------------------------------------------------
1017328070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen        // Data-processing instructions
1017428070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen        //----------------------------------------------------------------------
10175157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // adc (immediate)
10176157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0x0fe00000, 0x02a00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
10177157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // adc (register)
10178157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0x0fe00010, 0x00a00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
101798fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        // add (immediate)
10180157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0x0fe00000, 0x02800000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
101818fa2059234b17e9c377eea49b01f0ea084f66843Johnny Chen        // add (register)
10182157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0x0fe00010, 0x00800000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
10183c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        // add (register-shifted register)
10184c08ed3840e47b2e26ddffe0154b21840c80c91dfCaroline Tice        { 0x0fe00090, 0x00800010, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>m, <Rm>, <type> <RS>"},
10185a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        // adr
10186a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        { 0x0fff0000, 0x028f0000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
10187a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        { 0x0fff0000, 0x024f0000, ARMvAll,       eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
10188e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        // and (immediate)
10189157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0x0fe00000, 0x02000000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
10190e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        // and (register)
10191157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0x0fe00010, 0x00000000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
10192b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        // bic (immediate)
10193b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        { 0x0fe00000, 0x03c00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
10194b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        // bic (register)
10195b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        { 0x0fe00010, 0x01c00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
101962115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // eor (immediate)
101972115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0x0fe00000, 0x02200000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
101982115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // eor (register)
101992115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0x0fe00010, 0x00200000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
102007c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // orr (immediate)
102017c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        { 0x0fe00000, 0x03800000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
102027c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // orr (register)
102037c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        { 0x0fe00010, 0x01800000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
10204ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // rsb (immediate)
10205ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        { 0x0fe00000, 0x02600000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
10206ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // rsb (register)
10207ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        { 0x0fe00010, 0x00600000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
1020890e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        // rsc (immediate)
1020990e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        { 0x0fe00000, 0x02e00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
1021090e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        // rsc (register)
1021190e607bfccc74572e8422ea85d20f10db6f936b9Johnny Chen        { 0x0fe00010, 0x00e00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
102129b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // sbc (immediate)
102139b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        { 0x0fe00000, 0x02c00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
102149b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // sbc (register)
102159b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        { 0x0fe00010, 0x00c00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
1021615a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // sub (immediate, ARM)
1021715a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        { 0x0fe00000, 0x02400000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
10218c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        // sub (sp minus immediate)
10219c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        { 0x0fef0000, 0x024d0000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
102204cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        // sub (register)
102214cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        { 0x0fe00010, 0x00400000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
102222115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // teq (immediate)
102232115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0x0ff0f000, 0x03300000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
102242115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // teq (register)
102252115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0x0ff0f010, 0x01300000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
10226de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // tst (immediate)
10227de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        { 0x0ff0f000, 0x03100000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
10228de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // tst (register)
10229de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        { 0x0ff0f010, 0x01100000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
10230de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
1023189c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice        // mov (immediate)
1023289c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice        { 0x0fef0000, 0x03a00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
1023389c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice        { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
1023401d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen        // mov (register)
1023501d61570a57c96b3dbca0d89bf3039fe7fc99870Johnny Chen        { 0x0fef0ff0, 0x01a00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
10236d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        // mvn (immediate)
10237d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        { 0x0fef0000, 0x03e00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
10238d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        // mvn (register)
10239d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        { 0x0fef0010, 0x01e00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
102403847dadf9d633ead9e7697cb636f0e0210576731Johnny Chen        // cmn (immediate)
102413847dadf9d633ead9e7697cb636f0e0210576731Johnny Chen        { 0x0ff0f000, 0x03700000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
102423847dadf9d633ead9e7697cb636f0e0210576731Johnny Chen        // cmn (register)
102433847dadf9d633ead9e7697cb636f0e0210576731Johnny Chen        { 0x0ff0f010, 0x01700000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
1024434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        // cmp (immediate)
1024534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        { 0x0ff0f000, 0x03500000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
1024634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        // cmp (register)
1024734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        { 0x0ff0f010, 0x01500000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
1024882f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        // asr (immediate)
1024982f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        { 0x0fef0070, 0x01a00040, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
102502ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // asr (register)
10251e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        { 0x0fef00f0, 0x01a00050, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
102522ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsl (immediate)
102532ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0x0fef0070, 0x01a00000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
102542ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsl (register)
102552ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0x0fef00f0, 0x01a00010, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
102562ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsr (immediate)
102572ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0x0fef0070, 0x01a00020, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
102582ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsr (register)
102592ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0x0fef00f0, 0x01a00050, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
10260eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // rrx is a special case encoding of ror (immediate)
10261eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0x0fef0ff0, 0x01a00060, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
10262eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // ror (immediate)
10263eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0x0fef0070, 0x01a00060, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
10264eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // ror (register)
10265eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0x0fef00f0, 0x01a00070, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
102665c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // mul
102675c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        { 0x0fe000f0, 0x00000090, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
1026828070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen
1026928070c30cc87cc9679bb35bc11c42d0cc6ed4b0eJohnny Chen        //----------------------------------------------------------------------
10270b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        // Load instructions
10271b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        //----------------------------------------------------------------------
102720b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        { 0x0fd00000, 0x08900000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
10273713c2665a27096b68f3f8956222375354f1292f8Caroline Tice        { 0x0fd00000, 0x08100000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
1027485aab33e2d866be406aa0ecc96cd37aa7a46a35cCaroline Tice        { 0x0fd00000, 0x09100000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
10275fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        { 0x0fd00000, 0x09900000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
102764d729c559d039181f250e0e3cd444fa73638f26fCaroline Tice        { 0x0e500000, 0x04100000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
10277fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0x0e500010, 0x06100000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
1027830fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        { 0x0e5f0000, 0x045f0000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
102790491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        { 0xfe500010, 0x06500000, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
10280952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        { 0x0e5f00f0, 0x005f00b0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
102810e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        { 0x0e5000f0, 0x001000b0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"  },
10282a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        { 0x0e5000f0, 0x005000d0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
102835f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        { 0x0e5f00f0, 0x005f00d0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
10284672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        { 0x0e5000f0, 0x001000d0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
1028578fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        { 0x0e5000f0, 0x005000f0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
10286291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        { 0x0e5f00f0, 0x005f00f0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
10287291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        { 0x0e5000f0, 0x001000f0, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
102881697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
10289eab301f1d38aa05e88ca33e250c3bf78aebd2b87Caroline Tice        { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
10290fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
10291fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        //----------------------------------------------------------------------
10292fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        // Store instructions
10293fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        //----------------------------------------------------------------------
102941511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice        { 0x0fd00000, 0x08800000, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
10295b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        { 0x0fd00000, 0x08000000, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
10296af556564f80fd417a9158754f5e2ee692e183f6dCaroline Tice        { 0x0fd00000, 0x09000000, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
102973fd63e92ed8fda0007ad645ee3bf6b040f41e71eCaroline Tice        { 0x0fd00000, 0x09800000, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
102986bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        { 0x0e500010, 0x06000000, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
102998ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        { 0x0e5000f0, 0x000000b0, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
103005168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE,  eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
10301ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        { 0x0e500000, 0x04400000, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
10302d42b3cc76caa3d85a0d8dc6c97b89160e95229f9Caroline Tice        { 0x0e500000, 0x04000000, ARMvAll,      eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
103036bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
103046bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        //----------------------------------------------------------------------
103056bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        // Other instructions
103066bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        //----------------------------------------------------------------------
10307868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE,  eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
103088ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE,  eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
1030911555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE,  eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
10310b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE,  eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
10311b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        { 0xfe500000, 0xf8100000, ARMV6_ABOVE,  eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
103121511f50f447c36af933d10910bc3d6cd1f41bfd3Caroline Tice
103132b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    };
103142b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
103152b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103162b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    for (size_t i=0; i<k_num_arm_opcodes; ++i)
103172b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    {
103182b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
103192b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton            return &g_arm_opcodes[i];
103202b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    }
103212b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    return NULL;
103222b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton}
103232b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103242b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103252b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg ClaytonEmulateInstructionARM::ARMOpcode*
103262b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg ClaytonEmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
10327347320d16d98cffaadf3f888569100c43b241068Johnny Chen{
103282b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103292b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    static ARMOpcode
103302b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    g_thumb_opcodes[] =
103312b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    {
103322b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
103332b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // Prologue instructions
103342b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
103352b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103362b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // push register(s)
103379f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xfffffe00, 0x0000b400, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
103389f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
103399f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
103402b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103412b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // set r7 to point to a stack offset
103429f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffffff00, 0x0000af00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
10343e7cf4206fd3fa57067a9612118250bbfb88a4e68Johnny Chen        // copy the stack pointer to r7
103449f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffffffff, 0x0000466f, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
10345e7cf4206fd3fa57067a9612118250bbfb88a4e68Johnny Chen        // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
103469f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffffffc0, 0x00004640, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
103472b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
10348864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        // PC-relative load into register (see also EmulateADDSPRm)
10349c9de910d61f0471d18fced716fc10681ef432010Johnny Chen        { 0xfffff800, 0x00004800, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
103502b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103512b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // adjust the stack pointer
10352864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        { 0xffffff87, 0x00004485, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
10353c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        { 0xffffff80, 0x0000b080, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
10354864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
10355864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
10356d05b4903bb95b07e709986961fe387921dd0e029Caroline Tice        { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
103572b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103582b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // vector push consecutive extension register(s)
10359d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen        { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
10360d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen        { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
103612b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
103622b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
103632b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        // Epilogue instructions
103642b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        //----------------------------------------------------------------------
103652b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
10366e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        { 0xfffff800, 0x0000a800, ARMV4T_ABOVE,   eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
10367864a8e86b9e89d0f52b5020ace524eefebc9b9afJohnny Chen        { 0xffffff80, 0x0000b000, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
103689f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xfffffe00, 0x0000bc00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
103699f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
103709f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
10371d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen        { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
10372d6c13f00a467e7c9357c9fbb4375a0b77d20c6a9Johnny Chen        { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
10373b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen
10374b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        //----------------------------------------------------------------------
10375b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        // Supervisor Call (previously Software Interrupt)
10376b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen        //----------------------------------------------------------------------
10377c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen        { 0xffffff00, 0x0000df00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
10378c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen
10379c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen        //----------------------------------------------------------------------
10380c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen        // If Then makes up to four following instructions conditional.
10381c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen        //----------------------------------------------------------------------
103823b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        { 0xffffff00, 0x0000bf00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
103833b620b38cd170c20ea607585021ab2ab50286943Johnny Chen
103843b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        //----------------------------------------------------------------------
103853b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        // Branch instructions
103863b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        //----------------------------------------------------------------------
103873b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
103883b620b38cd170c20ea607585021ab2ab50286943Johnny Chen        { 0xfffff000, 0x0000d000, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
10389e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        { 0xfffff800, 0x0000e000, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
103909ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
10391696b4effb53cac2ec14b54a65c695450b4d7f456Johnny Chen        { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
10392383d629938986b4ae4867f08505be8a9147c1308Johnny Chen        // J1 == J2 == 1
10393e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        { 0xf800d000, 0xf000d000, ARMV4T_ABOVE,  eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
10394383d629938986b4ae4867f08505be8a9147c1308Johnny Chen        // J1 == J2 == 1
10395e221288aff8b6b97fb39a121f62233eae791295eCaroline Tice        { 0xf800d001, 0xf000c000, ARMV5_ABOVE,   eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
10396383d629938986b4ae4867f08505be8a9147c1308Johnny Chen        { 0xffffff87, 0x00004780, ARMV5_ABOVE,   eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
10397ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        // for example, "bx lr"
10398ab3b3514b639d2cab1cd6c71c317e12059717a17Johnny Chen        { 0xffffff87, 0x00004700, ARMvAll,       eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
1039959e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        // bxj
1040059e6ab70eb0a623fc667f7db9b27007e13b315e2Johnny Chen        { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE,  eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
1040153ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        // compare and branch
1040253ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
1040360299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        // table branch byte
1040460299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
1040560299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        // table branch halfword
1040660299ec172c9bbeab4e1bbffad513d75cd1741deJohnny Chen        { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
10407b77be414a1a4b74827f30e5944a58d4af0445ff4Johnny Chen
10408b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        //----------------------------------------------------------------------
1040926863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        // Data-processing instructions
1041026863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        //----------------------------------------------------------------------
10411157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // adc (immediate)
10412157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
10413157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // adc (register)
10414157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0xffffffc0, 0x00004140, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
10415157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
10416157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        // add (register)
104179f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xfffffe00, 0x00001800, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
1041826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
104199f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffffff00, 0x00004400, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
10420a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        // adr
10421a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        { 0xfffff800, 0x0000a000, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
10422a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
10423a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
10424e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        // and (immediate)
10425157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
10426e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        // and (register)
10427e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        { 0xffffffc0, 0x00004000, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
10428e97c0d5ea7b614b1fb257f63591e122e5651227cJohnny Chen        { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
10429b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        // bic (immediate)
10430b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
10431b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        // bic (register)
10432b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        { 0xffffffc0, 0x00004380, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
10433b9f02cfcd7d85e74981bf7790dce15d9bd1d4df6Johnny Chen        { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
104342115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // eor (immediate)
104352115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
104362115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // eor (register)
104372115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0xffffffc0, 0x00004040, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
104382115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
104397c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // orr (immediate)
104407c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
104417c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // orr (register)
104427c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        { 0xffffffc0, 0x00004300, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
104437c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
10444ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // rsb (immediate)
10445ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        { 0xffffffc0, 0x00004240, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
10446ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
10447ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        // rsb (register)
10448ed32e7cdec9c0c88ad40c9ed3d05e7604599a563Johnny Chen        { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
104499b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // sbc (immediate)
104509b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
104519b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        // sbc (register)
104529b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        { 0xffffffc0, 0x00004180, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
104539b381775c532270fd07a90aa1a98750546a768b7Johnny Chen        { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
10454dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        // add (immediate, Thumb)
10455dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
10456dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        { 0xfffff800, 0x00003000, ARMV4T_ABOVE,  eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
10457dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
10458dcc11b3b8882b3522244a25d2915c9086b44e596Caroline Tice        { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
1045915a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        // sub (immediate, Thumb)
1046015a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        { 0xfffffe00, 0x00001e00, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
1046115a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        { 0xfffff800, 0x00003800, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
1046215a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
1046315a7a6b9b624e5b8a2b058befc4e04aae72ff9c0Johnny Chen        { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
10464c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        // sub (sp minus immediate)
10465c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
10466c9e747f4efa320e366498f02bb9dd791cf86623bJohnny Chen        { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
104674cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        // sub (register)
104684cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
104694cccd53eba9c0ab2b3a4cf4aca42a2669d8834f4Caroline Tice        { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
104702115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // teq (immediate)
104712115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
104722115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        // teq (register)
104732115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
10474de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // tst (immediate)
104752115b4131b0e427341959fb4007e0173bf71778dJohnny Chen        { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
10476de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        // tst (register)
10477de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        { 0xffffffc0, 0x00004200, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
10478de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen        { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
10479de3cce3aa8e10c9e328e15b9210069b77f840b70Johnny Chen
104807c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen
10481338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen        // move from high register to high register
104829f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffffff00, 0x00004600, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
10483338bf54a49633d90f3c5e808847470901f25dee9Johnny Chen        // move from low register to low register
104849f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xffffffc0, 0x00000000, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
104857c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        // mov{s}<c>.w <Rd>, <Rm>
104867c5234db18ead0935e884429b3cace95b3a9dce4Johnny Chen        { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
10487357c30f55eeeca5df8434831c8963ef8fc109227Johnny Chen        // move immediate
104889f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xfffff800, 0x00002000, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
104899f687729f0a2fff5dde65ce789c3a02e84c2ffccJohnny Chen        { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
1049089c6d5830f0584ed2f984e2d557ded17add7f61bCaroline Tice        { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
10491d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        // mvn (immediate)
10492d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
10493d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        // mvn (register)
10494d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        { 0xffffffc0, 0x000043c0, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
10495d642a6ad6b8e3822485a8a08fbbfa8b60a4e97f2Johnny Chen        { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
1049634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        // cmn (immediate)
10497688926f8fb9a56964249ec970b4ae313a5b366d4Johnny Chen        { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
1049834075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        // cmn (register)
1049934075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        { 0xffffffc0, 0x000042c0, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
10500078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
1050134075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        // cmp (immediate)
1050234075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        { 0xfffff800, 0x00002800, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
10503078fbc6d0bcce29a296a1afa91dae01bccf3cff5Johnny Chen        { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
1050434075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        // cmp (register) (Rn and Rm both from r0-r7)
1050534075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        { 0xffffffc0, 0x00004280, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
1050634075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        // cmp (register) (Rn and Rm not both from r0-r7)
1050734075cb14fb56cb350e71cc696179ab0f2744423Johnny Chen        { 0xffffff00, 0x00004500, ARMvAll,       eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
1050882f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        // asr (immediate)
1050982f16aa9f19678ffa20b92a8df926e933940d34dJohnny Chen        { 0xfffff800, 0x00001000, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
105104d896db529a5fef200333ef673976528319279bdJohnny Chen        { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
10511e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        // asr (register)
10512e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        { 0xffffffc0, 0x00004100, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
10513e7f8953988d593882971e4134f8423f4af1cffaaJohnny Chen        { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
105142ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsl (immediate)
105152ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0xfffff800, 0x00000000, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
105162ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
105172ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsl (register)
105182ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0xffffffc0, 0x00004080, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
105192ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
105202ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsr (immediate)
105212ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0xfffff800, 0x00000800, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
105222ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
105232ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        // lsr (register)
10524eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0xffffffc0, 0x000040c0, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
105252ee35bcf1670c112b004736bf8beb672629e3e93Johnny Chen        { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
10526eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // rrx is a special case encoding of ror (immediate)
10527eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
10528eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // ror (immediate)
10529eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
10530eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        // ror (register)
10531eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0xffffffc0, 0x000041c0, ARMvAll,       eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
10532eeab485b0c1197bc4f483a9fdd7d2489703cb5abJohnny Chen        { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
105335c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // mul
105345c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        { 0xffffffc0, 0x00004340, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
105355c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        // mul
105365c1e2edcc5230fbf0995efcc32e9c0548a97a2d2Caroline Tice        { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
105376bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
1053826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        //----------------------------------------------------------------------
10539b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        // Load instructions
10540b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        //----------------------------------------------------------------------
10541b9f76c33ab97dcef2e9c1dbc471097edd6b98a86Caroline Tice        { 0xfffff800, 0x0000c800, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
105420b29e24ecd86048ac5d722dc964e55bab49f72aaCaroline Tice        { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
10543ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen        { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
10544baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        { 0xfffff800, 0x00006800, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
10545baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        { 0xfffff800, 0x00009800, ARMV4T_ABOVE,  eEncodingT2, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
10546baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
10547baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice        { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
10548baf1f648fd0eb9295d8e61567d49d47fb9c28e19Caroline Tice                  // Thumb2 PC-relative load into register
10549fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
10550fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfffffe00, 0x00005800, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
10551fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
1055221b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        { 0xfffff800, 0x00007800, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
1055321b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
1055421b604bbe9b0c6e1ebd275c1beff24aa2fa8732cCaroline Tice        { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
10555f55261f53d56b4911c4c1ce419d893e5250d7150Caroline Tice        { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
1055630fec12a2c2f0fe75c78e9b9f791bc53cd92cdfdCaroline Tice        { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
10557ef440003bffefbe10c960d5eea92193f5269be9aCaroline Tice        { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
105580491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        { 0xfffff800, 0x00008800, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"  },
105590491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
105600491b3b75e1b045ab548f77fd1f76035522debdeCaroline Tice        { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"  },
10561952b53892191222c56003cd60d8a4a71c4384aa7Caroline Tice        { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
105620e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
105630e6bc95dceb0bd29b0029771840e8afc690fe6c1Caroline Tice        { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
10564a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
10565a5e28af7d3ebf0820c62f08c9d0e194767586808Caroline Tice        { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
105665f593915eac4dabdb0c38352b2fd551037e5cc20Caroline Tice        { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
10567672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        { 0xfffffe00, 0x00005600, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
10568672f3110bdd2a088f10ae9f246aaab5daa7b0fa1Caroline Tice        { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"  },
1056978fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
1057078fb5638da9c01a39443f3339ede2f02056822cfCaroline Tice        { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
10571d2fac095321ccd262699a8cce8b9fc897d6dff0dCaroline Tice        { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
10572291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
10573291a3e90e7a275f196bc7aeeb2137acd6d60229fCaroline Tice        { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
105741697dd77af1f72a34cd2ce881e865370cf1593c8Caroline Tice        { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt?, <Rt2>, [<Rn>,#+/-<imm>]!"},
10575fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice
10576fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        //----------------------------------------------------------------------
10577fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        // Store instructions
10578fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        //----------------------------------------------------------------------
10579fa17220ce8b3db56b05317fd5e69c450127f8538Caroline Tice        { 0xfffff800, 0x0000c000, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
10580b6f8d7ec6f0a91a805d4ffa0f6fe8dcd1ae5c4d3Caroline Tice        { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
105817fac857ec72051dc0a91b027719c275ea672a470Caroline Tice        { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
10582fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfffff800, 0x00006000, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
10583fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfffff800, 0x00009000, ARMV4T_ABOVE,  eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
10584fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
10585fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
10586fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfffffe00, 0x00005000, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
10587fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
10588fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfffff800, 0x00007000, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
10589fe4791199f5eb55a1ceecff58364fcbdb2e8cfaaCaroline Tice        { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
105906bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
105918ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        { 0xfffffe00, 0x00005200, ARMV4T_ABOVE,  eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
105928ce836dbf416c4dfdbede109be5cc09b95918fd0Caroline Tice        { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
105935168b6c7119735b6f087ccfcd9ed58811bbb0e32Caroline Tice        { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
105946bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
105956bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        //----------------------------------------------------------------------
105966bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        // Other instructions
105976bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        //----------------------------------------------------------------------
105986bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice        { 0xffffffc0, 0x0000b240, ARMV6_ABOVE,   eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
10599868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE,   eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
10600868198b229fcffbda2b24518007179ef1a45ad1dCaroline Tice        { 0xffffffc0, 0x0000b200, ARMV6_ABOVE,   eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
106018ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
106028ce96d910ba57058e10a563bcaab4448ca9ad571Caroline Tice        { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE,   eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
1060311555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
1060411555f2f0f21beb0312f8ebe40849487d437f493Caroline Tice        { 0xffffffc0, 0x0000b280, ARMV6_ABOVE,   eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
10605b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
10606b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
10607b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
106086bf65165d269c43dc6cfd227c5f1e287c24b5a41Caroline Tice
106092b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    };
106102b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton
106112b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
106122b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    for (size_t i=0; i<k_num_thumb_opcodes; ++i)
106132b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    {
106142b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton        if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
106152b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton            return &g_thumb_opcodes[i];
106162b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    }
106172b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton    return NULL;
106182b8e8b0d1ea00d0076ac20568c2ce2a2a1fe0240Greg Clayton}
1061964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
1062031e2a388b07f337c1bf61de32a39c154f190c06eGreg Claytonbool
10621395fc33dc4b06c048ed35047ec461bc092ef2df3Greg ClaytonEmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
1062231e2a388b07f337c1bf61de32a39c154f190c06eGreg Clayton{
1062331e2a388b07f337c1bf61de32a39c154f190c06eGreg Clayton    m_arm_isa = 0;
10624940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton    const char *arch_cstr = arch.GetArchitectureName ();
10625395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton    if (arch_cstr)
10626395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton    {
10627395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        if      (0 == ::strcasecmp(arch_cstr, "armv4t"))    m_arm_isa = ARMv4T;
10628395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv4"))     m_arm_isa = ARMv4;
10629395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv5tej"))  m_arm_isa = ARMv5TEJ;
10630395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv5te"))   m_arm_isa = ARMv5TE;
10631395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv5t"))    m_arm_isa = ARMv5T;
10632395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv6k"))    m_arm_isa = ARMv6K;
10633395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv6"))     m_arm_isa = ARMv6;
10634395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv6t2"))   m_arm_isa = ARMv6T2;
10635395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv7"))     m_arm_isa = ARMv7;
10636395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        else if (0 == ::strcasecmp(arch_cstr, "armv8"))     m_arm_isa = ARMv8;
1063731e2a388b07f337c1bf61de32a39c154f190c06eGreg Clayton    }
1063831e2a388b07f337c1bf61de32a39c154f190c06eGreg Clayton    return m_arm_isa != 0;
1063931e2a388b07f337c1bf61de32a39c154f190c06eGreg Clayton}
1064031e2a388b07f337c1bf61de32a39c154f190c06eGreg Clayton
1064131e2a388b07f337c1bf61de32a39c154f190c06eGreg Clayton
1064264c8443d255f44267490c8c839f4a9365cf55ea7Greg Claytonbool
1064364c8443d255f44267490c8c839f4a9365cf55ea7Greg ClaytonEmulateInstructionARM::ReadInstruction ()
1064464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton{
1064564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    bool success = false;
10646b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
1064764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    if (success)
1064864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    {
1064964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
1065064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        if (success)
1065164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        {
106529bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            Context read_inst_context;
106539bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            read_inst_context.type = eContextReadOpcode;
106549bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice            read_inst_context.SetNoArgs ();
106559bfe7f219fb47d93c2b866ad5a6342a827d0dbd6Caroline Tice
10656b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            if (m_opcode_cpsr & MASK_CPSR_T)
1065764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            {
10658b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton                m_opcode_mode = eModeThumb;
10659cc96eb5967d878e8225ce61c645eb47857fbb3f2Caroline Tice                uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
1066064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
1066164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                if (success)
1066264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                {
106637bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                    if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
1066464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    {
106657bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                        m_opcode.SetOpcode16 (thumb_opcode);
1066664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    }
1066764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    else
1066864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    {
106697bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                        m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
1067064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                    }
1067164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton                }
1067264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            }
1067364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            else
1067464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            {
10675b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton                m_opcode_mode = eModeARM;
106767bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
1067764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            }
1067864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        }
1067964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    }
1068064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    if (!success)
1068164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    {
10682b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton        m_opcode_mode = eModeInvalid;
10683b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton        m_opcode_pc = LLDB_INVALID_ADDRESS;
1068464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    }
1068564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    return success;
1068664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton}
1068764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
10688ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chenuint32_t
10689ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny ChenEmulateInstructionARM::ArchVersion ()
10690ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen{
10691ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    return m_arm_isa;
10692ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen}
10693ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen
1069464c8443d255f44267490c8c839f4a9365cf55ea7Greg Claytonbool
106957bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::ConditionPassed (const uint32_t opcode)
1069664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton{
10697b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    if (m_opcode_cpsr == 0)
1069864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        return false;
1069964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
107007bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton    const uint32_t cond = CurrentCond (opcode);
1070164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
1070264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    if (cond == UINT32_MAX)
1070364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        return false;
1070464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
1070564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    bool result = false;
1070664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    switch (UnsignedBits(cond, 3, 1))
1070764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    {
10708b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break;
10709b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break;
10710b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break;
10711b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break;
10712b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    case 4: result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); break;
1071364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    case 5:
1071464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        {
10715b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            bool n = (m_opcode_cpsr & MASK_CPSR_N);
10716b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            bool v = (m_opcode_cpsr & MASK_CPSR_V);
1071764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton            result = n == v;
1071864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        }
1071964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        break;
1072064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    case 6:
1072164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        {
10722b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            bool n = (m_opcode_cpsr & MASK_CPSR_N);
10723b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            bool v = (m_opcode_cpsr & MASK_CPSR_V);
10724b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton            result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
1072564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        }
1072664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        break;
1072764c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    case 7:
1072864c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        result = true;
1072964c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        break;
1073064c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    }
1073164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
1073264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    if (cond & 1)
1073364c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton        result = !result;
1073464c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    return result;
1073564c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton}
1073664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
107379ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chenuint32_t
107387bc390873f7c1c798c36c8003c4b82597f67c703Greg ClaytonEmulateInstructionARM::CurrentCond (const uint32_t opcode)
107399ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen{
10740b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    switch (m_opcode_mode)
107419ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    {
107429ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    default:
107439ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    case eModeInvalid:
107449ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        break;
107459ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen
107469ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    case eModeARM:
107477bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton        return UnsignedBits(opcode, 31, 28);
107489ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen
107499ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    case eModeThumb:
107509ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
107519ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        // 'cond' field of the encoding.
107529ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        {
107537bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            const uint32_t byte_size = m_opcode.GetByteSize();
107547bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            if (byte_size == 2)
107557bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            {
107567bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
107577bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                    return Bits32(opcode, 11, 7);
107587bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            }
107597bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            else
107607bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            {
107617bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                assert (byte_size == 4);
107627bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                if (Bits32(opcode, 31, 27) == 0x1e &&
107637bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                    Bits32(opcode, 15, 14) == 0x02 &&
107647bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                    Bits32(opcode, 12, 12) == 0x00 &&
107657bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                    Bits32(opcode, 25, 22) <= 0x0d)
107667bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                {
107677bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                    return Bits32(opcode, 25, 22);
107687bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton                }
107697bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            }
107707bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton
107717bc390873f7c1c798c36c8003c4b82597f67c703Greg Clayton            return m_it_session.GetCond();
107729ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        }
107739ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    }
107749ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    return UINT32_MAX;  // Return invalid value
107759ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen}
107769ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen
107779ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chenbool
10778098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny ChenEmulateInstructionARM::InITBlock()
10779098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen{
10780098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen    return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
10781098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen}
10782098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen
10783098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chenbool
10784098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny ChenEmulateInstructionARM::LastInITBlock()
10785098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen{
10786098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen    return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
10787098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen}
10788098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chen
10789b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Ticebool
10790b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline TiceEmulateInstructionARM::BadMode (uint32_t mode)
10791b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice{
10792b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10793b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    switch (mode)
10794b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    {
10795b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 16: return false; // '10000'
10796b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 17: return false; // '10001'
10797b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 18: return false; // '10010'
10798b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 19: return false; // '10011'
10799b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 22: return false; // '10110'
10800b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 23: return false; // '10111'
10801b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 27: return false; // '11011'
10802b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        case 31: return false; // '11111'
10803b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        default: return true;
10804b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    }
10805b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    return true;
10806b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice}
10807b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10808b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Ticebool
10809b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline TiceEmulateInstructionARM::CurrentModeIsPrivileged ()
10810b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice{
10811b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
10812b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10813b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    if (BadMode (mode))
10814b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        return false;
10815b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10816b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    if (mode == 16)
10817b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice                  return false;
10818b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10819b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    return true;
10820b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice}
10821b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10822b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Ticevoid
10823b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline TiceEmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
10824b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice{
10825b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    bool privileged = CurrentModeIsPrivileged();
10826b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10827b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    uint32_t tmp_cpsr = 0;
10828b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10829b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
10830b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10831b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    if (BitIsSet (bytemask, 3))
10832b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    {
10833b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
10834b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if (affect_execstate)
10835b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
10836b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    }
10837b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10838b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    if (BitIsSet (bytemask, 2))
10839b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    {
10840b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
10841b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    }
10842b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10843b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    if (BitIsSet (bytemask, 1))
10844b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    {
10845b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if (affect_execstate)
10846b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
10847b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
10848b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if (privileged)
10849b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
10850b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    }
10851b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10852b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    if (BitIsSet (bytemask, 0))
10853b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    {
10854b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if (privileged)
10855b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
10856b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if (affect_execstate)
10857b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
10858b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice        if (privileged)
10859b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice            tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
10860b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice    }
10861b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10862b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    m_opcode_cpsr = tmp_cpsr;
10863b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice}
10864b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10865b27771da2fe3256f4a64729ecec05946c27c1a0aCaroline Tice
10866098ae2d54f9b1613e85ecb5f3d0808f102a97859Johnny Chenbool
108679ee056bb17843e8c757461dbf56c49e8de99a65eJohnny ChenEmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
108689ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen{
108699ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    addr_t target;
108709ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen
10871ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    // Check the current instruction set.
10872ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    if (CurrentInstrSet() == eModeARM)
108739ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        target = addr & 0xfffffffc;
10874ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    else
108759ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        target = addr & 0xfffffffe;
10876ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen
108779ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1087853ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        return false;
1087953ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
1088053ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    return true;
108819ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen}
108829ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen
108839ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
108849ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chenbool
10885668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny ChenEmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
108869ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen{
108879ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    addr_t target;
108880f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen    // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
108890f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen    // we want to record it and issue a WriteRegister callback so the clients
108900f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen    // can track the mode changes accordingly.
108910f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen    bool cpsr_changed = false;
108929ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen
108939ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    if (BitIsSet(addr, 0))
108949ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    {
108950f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen        if (CurrentInstrSet() != eModeThumb)
108960f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen        {
108970f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen            SelectInstrSet(eModeThumb);
108980f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen            cpsr_changed = true;
108990f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen        }
109009ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        target = addr & 0xfffffffe;
10901668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen        context.SetMode (eModeThumb);
109029ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    }
109039ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    else if (BitIsClear(addr, 1))
109049ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    {
109050f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen        if (CurrentInstrSet() != eModeARM)
109060f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen        {
109070f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen            SelectInstrSet(eModeARM);
109080f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen            cpsr_changed = true;
109090f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen        }
109109ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        target = addr & 0xfffffffc;
10911668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen        context.SetMode (eModeARM);
109129ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    }
109139ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    else
109149ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen        return false; // address<1:0> == '10' => UNPREDICTABLE
109159ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen
109160f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen    if (cpsr_changed)
109170f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen    {
10918558133bb1d2d89dd4618259ce27b5c06f3970b48Johnny Chen        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
109190f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen            return false;
109200f309db3ba3f297599809bac0bbbb13719f1c860Johnny Chen    }
109219ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen    if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
1092253ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen        return false;
1092353ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen
1092453ebab7a7bed312c496a49d52b225a01a1a02e89Johnny Chen    return true;
109259ee056bb17843e8c757461dbf56c49e8de99a65eJohnny Chen}
1092664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton
10927ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
10928ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chenbool
10929668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny ChenEmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
10930ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen{
10931ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    if (ArchVersion() >= ARMv5T)
10932668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen        return BXWritePC(context, addr);
10933ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    else
10934ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen        return BranchWritePC((const Context)context, addr);
10935ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen}
10936ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen
1093726863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
1093826863dc1d68712415ed56c9953f6fed79b38e131Johnny Chenbool
10939668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny ChenEmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
1094026863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen{
1094126863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
10942668b45124a14cbd03e7b4965b3d86fdbf208d282Johnny Chen        return BXWritePC(context, addr);
1094326863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen    else
1094426863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen        return BranchWritePC((const Context)context, addr);
1094526863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen}
1094626863dc1d68712415ed56c9953f6fed79b38e131Johnny Chen
10947ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny ChenEmulateInstructionARM::Mode
10948ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny ChenEmulateInstructionARM::CurrentInstrSet ()
10949ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen{
10950b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    return m_opcode_mode;
10951ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen}
10952ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen
10953b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton// Set the 'T' bit of our CPSR.  The m_opcode_mode gets updated when the next
10954558133bb1d2d89dd4618259ce27b5c06f3970b48Johnny Chen// ReadInstruction() is performed.  This function has a side effect of updating
10955558133bb1d2d89dd4618259ce27b5c06f3970b48Johnny Chen// the m_new_inst_cpsr member variable if necessary.
10956ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chenbool
10957ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny ChenEmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
10958ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen{
10959b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    m_new_inst_cpsr = m_opcode_cpsr;
10960ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    switch (arm_or_thumb)
10961ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    {
10962ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    default:
10963ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen        return false;
10964ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    eModeARM:
10965ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen        // Clear the T bit.
10966558133bb1d2d89dd4618259ce27b5c06f3970b48Johnny Chen        m_new_inst_cpsr &= ~MASK_CPSR_T;
10967ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen        break;
10968ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    eModeThumb:
10969ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen        // Set the T bit.
10970558133bb1d2d89dd4618259ce27b5c06f3970b48Johnny Chen        m_new_inst_cpsr |= MASK_CPSR_T;
10971ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen        break;
10972ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    }
10973ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen    return true;
10974ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen}
10975ee9b1f7a1b52427f8ac3ae43d8064f10add803b1Johnny Chen
10976ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen// This function returns TRUE if the processor currently provides support for
10977ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
10978ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
10979ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chenbool
10980ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny ChenEmulateInstructionARM::UnalignedSupport()
10981ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen{
10982ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen    return (ArchVersion() >= ARMv7);
10983ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen}
10984ef21b59059720fb14bf169f08c3cc3ffc2c598c8Johnny Chen
10985bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen// The main addition and subtraction instructions can produce status information
10986bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen// about both unsigned carry and signed overflow conditions.  This status
10987bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen// information can be used to synthesize multi-word additions and subtractions.
10988bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny ChenEmulateInstructionARM::AddWithCarryResult
10989bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny ChenEmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
10990bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen{
10991bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    uint32_t result;
10992bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    uint8_t carry_out;
10993bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    uint8_t overflow;
10994bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen
10995bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    uint64_t unsigned_sum = x + y + carry_in;
10996bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
10997bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen
10998bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    result = UnsignedBits(unsigned_sum, 31, 0);
10999bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    carry_out = (result == unsigned_sum ? 0 : 1);
11000bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    overflow = ((int32_t)result == signed_sum ? 0 : 1);
11001bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen
11002bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    AddWithCarryResult res = { result, carry_out, overflow };
11003bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen    return res;
11004bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen}
11005bf6ad173895183797cbd0ebd18710b2364a2c4c8Johnny Chen
11006157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chenuint32_t
11007e39f22d1a369866808b8739c3cec15063d806833Johnny ChenEmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
11008157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen{
11009e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    uint32_t reg_kind, reg_num;
11010e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    switch (num)
11011157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    {
11012e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    case SP_REG:
11013e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        reg_kind = eRegisterKindGeneric;
11014e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        reg_num  = LLDB_REGNUM_GENERIC_SP;
11015e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        break;
11016e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    case LR_REG:
11017e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        reg_kind = eRegisterKindGeneric;
11018e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        reg_num  = LLDB_REGNUM_GENERIC_RA;
11019e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        break;
11020e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    case PC_REG:
11021e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        reg_kind = eRegisterKindGeneric;
11022e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        reg_num  = LLDB_REGNUM_GENERIC_PC;
11023e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        break;
11024e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    default:
110254fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton        if (num < SP_REG)
11026e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        {
11027e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            reg_kind = eRegisterKindDWARF;
11028e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            reg_num  = dwarf_r0 + num;
11029e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        }
11030157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen        else
11031e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        {
11032e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            assert(0 && "Invalid register number");
11033e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            *success = false;
110344fdf7602bedd8be648f3c549074cf13d90a05f03Greg Clayton            return UINT32_MAX;
11035e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        }
11036e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        break;
11037e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    }
11038e39f22d1a369866808b8739c3cec15063d806833Johnny Chen
11039e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    // Read our register.
11040e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
11041e39f22d1a369866808b8739c3cec15063d806833Johnny Chen
11042e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    // When executing an ARM instruction , PC reads as the address of the current
11043e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    // instruction plus 8.
11044e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    // When executing a Thumb instruction , PC reads as the address of the current
11045e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    // instruction plus 4.
11046e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    if (num == 15)
11047e39f22d1a369866808b8739c3cec15063d806833Johnny Chen    {
11048e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        if (CurrentInstrSet() == eModeARM)
11049157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen            val += 8;
11050e39f22d1a369866808b8739c3cec15063d806833Johnny Chen        else
11051e39f22d1a369866808b8739c3cec15063d806833Johnny Chen            val += 4;
11052157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    }
11053157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
11054157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen    return val;
11055157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen}
11056157b959b101cbdddb81a690d00ff0697540d83e7Johnny Chen
11057ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// Write the result to the ARM core register Rd, and optionally update the
11058ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// condition flags based on the result.
11059ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//
11060ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// This helper method tries to encapsulate the following pseudocode from the
11061ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// ARM Architecture Reference Manual:
11062ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//
11063ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// if d == 15 then         // Can only occur for encoding A1
11064ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//     ALUWritePC(result); // setflags is always FALSE here
11065ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// else
11066ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//     R[d] = result;
11067ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//     if setflags then
11068ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//         APSR.N = result<31>;
11069ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//         APSR.Z = IsZeroBit(result);
11070ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//         APSR.C = carry;
11071ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//         // APSR.V unchanged
11072ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen//
11073ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// In the above case, the API client does not pass in the overflow arg, which
11074ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen// defaults to ~0u.
11075ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chenbool
1107610530c2f7bc5030f59563fb877510a218c9cea8fJohnny ChenEmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
1107710530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                                  const uint32_t result,
1107810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                                  const uint32_t Rd,
1107910530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                                  bool setflags,
1108010530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                                  const uint32_t carry,
1108110530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                                  const uint32_t overflow)
11082ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen{
11083ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen    if (Rd == 15)
11084ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen    {
11085ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen        if (!ALUWritePC (context, result))
11086ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            return false;
11087ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen    }
11088ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen    else
11089ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen    {
11090a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        uint32_t reg_kind, reg_num;
11091a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        switch (Rd)
11092a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        {
11093a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        case SP_REG:
11094a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            reg_kind = eRegisterKindGeneric;
11095a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            reg_num  = LLDB_REGNUM_GENERIC_SP;
11096a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            break;
11097a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        case LR_REG:
11098a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            reg_kind = eRegisterKindGeneric;
11099a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            reg_num  = LLDB_REGNUM_GENERIC_RA;
11100a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            break;
11101a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        default:
11102a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            reg_kind = eRegisterKindDWARF;
11103a695f958db37c102d480a9c0780abec262ba8332Johnny Chen            reg_num  = dwarf_r0 + Rd;
11104a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        }
11105a695f958db37c102d480a9c0780abec262ba8332Johnny Chen        if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
11106ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen            return false;
11107ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen        if (setflags)
1110810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen            return WriteFlags (context, result, carry, overflow);
1110910530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    }
1111010530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    return true;
1111110530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen}
1111210530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen
1111310530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// This helper method tries to encapsulate the following pseudocode from the
1111410530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// ARM Architecture Reference Manual:
1111510530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen//
1111610530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// APSR.N = result<31>;
1111710530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// APSR.Z = IsZeroBit(result);
1111810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// APSR.C = carry;
1111910530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// APSR.V = overflow
1112010530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen//
1112110530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// Default arguments can be specified for carry and overflow parameters, which means
1112210530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen// not to update the respective flags.
1112310530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chenbool
1112410530c2f7bc5030f59563fb877510a218c9cea8fJohnny ChenEmulateInstructionARM::WriteFlags (Context &context,
1112510530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                   const uint32_t result,
1112610530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                   const uint32_t carry,
1112710530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen                                   const uint32_t overflow)
1112810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen{
11129b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    m_new_inst_cpsr = m_opcode_cpsr;
1113024348847b93337ad548032e046c71f37e647da26Johnny Chen    SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
1113124348847b93337ad548032e046c71f37e647da26Johnny Chen    SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1113210530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    if (carry != ~0u)
1113324348847b93337ad548032e046c71f37e647da26Johnny Chen        SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
1113410530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    if (overflow != ~0u)
1113524348847b93337ad548032e046c71f37e647da26Johnny Chen        SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
11136b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    if (m_new_inst_cpsr != m_opcode_cpsr)
1113710530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen    {
1113810530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1113910530c2f7bc5030f59563fb877510a218c9cea8fJohnny Chen            return false;
11140ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen    }
11141ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen    return true;
11142ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen}
11143ca67d1c9572ad3890aa73863969a4b664f7781bcJohnny Chen
1114464c8443d255f44267490c8c839f4a9365cf55ea7Greg Claytonbool
1114564c8443d255f44267490c8c839f4a9365cf55ea7Greg ClaytonEmulateInstructionARM::EvaluateInstruction ()
1114664c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton{
11147c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen    // Advance the ITSTATE bits to their values for the next instruction.
11148b344843f75ef893762c93fd0a22d2d45712ce74dGreg Clayton    if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
11149c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen        m_it_session.ITAdvance();
11150c315f860b343cf4a143f43c7d570d151989abb46Johnny Chen
1115164c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton    return false;
1115264c8443d255f44267490c8c839f4a9365cf55ea7Greg Clayton}
11153