aboutsummaryrefslogtreecommitdiffstats
path: root/source/Plugins
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2015-07-03 16:57:06 +0000
committerEd Maste <emaste@FreeBSD.org>2015-07-03 16:57:06 +0000
commit5e95aa85bb660d45e9905ef1d7180b2678280660 (patch)
tree3c2e41c3be19b7fc7666ed45a5f91ec3b6e35f2a /source/Plugins
parent12bd4897ff0678fa663e09d78ebc22dd255ceb86 (diff)
downloadsrc-5e95aa85bb660d45e9905ef1d7180b2678280660.tar.gz
src-5e95aa85bb660d45e9905ef1d7180b2678280660.zip
Import LLDB as of upstream SVN 241361 (git 612c075f)vendor/lldb/lldb-r241361
Notes
Notes: svn path=/vendor/lldb/dist/; revision=285101 svn path=/vendor/lldb/lldb-r241361/; revision=285102; tag=vendor/lldb/lldb-r241361
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp27
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp24
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp12
-rw-r--r--source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp916
-rw-r--r--source/Plugins/ABI/SysV-arm/ABISysV_arm.h121
-rw-r--r--source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp1081
-rw-r--r--source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h125
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp13
-rw-r--r--source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp815
-rw-r--r--source/Plugins/ABI/SysV-i386/ABISysV_i386.h138
-rw-r--r--source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp590
-rw-r--r--source/Plugins/ABI/SysV-mips/ABISysV_mips.h123
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp570
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h133
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp21
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp21
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp24
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp105
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h2
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp4
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp1
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp60
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h23
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp102
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h6
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp441
-rw-r--r--source/Plugins/Instruction/ARM/EmulationStateARM.cpp2
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp389
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h43
-rw-r--r--source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp2918
-rw-r--r--source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h313
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp2920
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h313
-rw-r--r--source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp55
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp9
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp51
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h6
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp1191
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h232
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp7
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.cpp5
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp451
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h94
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp1
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp184
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.h23
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp445
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h303
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp91
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h84
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp319
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h232
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.cpp1
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp (renamed from source/Plugins/Process/POSIX/POSIXStopInfo.cpp)0
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXStopInfo.h (renamed from source/Plugins/Process/POSIX/POSIXStopInfo.h)0
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXThread.cpp (renamed from source/Plugins/Process/POSIX/POSIXThread.cpp)70
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXThread.h (renamed from source/Plugins/Process/POSIX/POSIXThread.h)33
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp19
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp68
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h35
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp (renamed from source/Plugins/Process/POSIX/ProcessPOSIX.cpp)177
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessPOSIX.h (renamed from source/Plugins/Process/POSIX/ProcessPOSIX.h)68
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp322
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h95
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.cpp)8
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_arm64.h)0
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp)5
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h)0
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp)3
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h)0
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp)9
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h (renamed from source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h)0
-rw-r--r--source/Plugins/Process/POSIX/CrashReason.cpp42
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp19
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIXLog.h6
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp629
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.h14
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.cpp70
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp9
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.h5
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.cpp103
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.h8
-rw-r--r--source/Plugins/Process/Utility/MipsLinuxSignals.cpp95
-rw-r--r--source/Plugins/Process/Utility/MipsLinuxSignals.h37
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp88
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h75
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.cpp86
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h78
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp7
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.cpp25
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp192
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp87
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm.h76
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp3
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp102
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips.h32
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp143
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips64.h40
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp13
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp287
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h121
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp3
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h159
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h54
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp3
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_mips64.h232
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm.h303
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm64.h16
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_i386.h14
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_mips.h122
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_mips64.h86
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_x86_64.h17
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.cpp7
-rw-r--r--source/Plugins/Process/Utility/ThreadMemory.cpp2
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp1
-rw-r--r--source/Plugins/Process/Utility/lldb-arm-register-enums.h153
-rw-r--r--source/Plugins/Process/Utility/lldb-arm64-register-enums.h172
-rw-r--r--source/Plugins/Process/Utility/lldb-mips64-register-enums.h199
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp18
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.h39
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp94
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h60
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp94
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h60
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp24
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp655
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h126
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp1095
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h239
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp4458
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h523
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp1341
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h216
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp2787
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h307
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp376
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h102
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp22
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h77
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp2292
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h243
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp19
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h21
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp60
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h74
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp56
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp22
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp65
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/NameToDIE.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp388
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h53
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp244
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h105
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp8
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h3
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp226
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h11
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp143
161 files changed, 28986 insertions, 8907 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 42acba232de1..700d223fbc6d 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -184,13 +184,19 @@ ABIMacOSX_arm::CreateInstance (const ArchSpec &arch)
{
static ABISP g_abi_sp;
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
- if ((arch_type == llvm::Triple::arm) ||
- (arch_type == llvm::Triple::thumb))
+ const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
+
+ if (vendor_type == llvm::Triple::Apple)
{
- if (!g_abi_sp)
- g_abi_sp.reset (new ABIMacOSX_arm);
- return g_abi_sp;
+ if ((arch_type == llvm::Triple::arm) ||
+ (arch_type == llvm::Triple::thumb))
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABIMacOSX_arm);
+ return g_abi_sp;
+ }
}
+
return ABISP();
}
@@ -334,11 +340,11 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,
size_t bit_width = 0;
if (clang_type.IsIntegerType (is_signed))
{
- bit_width = clang_type.GetBitSize(nullptr);
+ bit_width = clang_type.GetBitSize(&thread);
}
else if (clang_type.IsPointerOrReferenceType ())
{
- bit_width = clang_type.GetBitSize(nullptr);
+ bit_width = clang_type.GetBitSize(&thread);
}
else
{
@@ -437,7 +443,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
if (clang_type.IsIntegerType (is_signed))
{
- size_t bit_width = clang_type.GetBitSize(nullptr);
+ size_t bit_width = clang_type.GetBitSize(&thread);
switch (bit_width)
{
@@ -587,7 +593,7 @@ ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->SetCFARegister (sp_reg_num);
+ row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
// The previous PC is in the LR
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
@@ -613,8 +619,7 @@ ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
- row->SetCFARegister (fp_reg_num);
- row->SetCFAOffset (2 * ptr_size);
+ row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index c2ba165afb4a..04b96180deb3 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -219,12 +219,19 @@ ABISP
ABIMacOSX_arm64::CreateInstance (const ArchSpec &arch)
{
static ABISP g_abi_sp;
- if (arch.GetTriple().getArch() == llvm::Triple::aarch64)
+ const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
+ const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
+
+ if (vendor_type == llvm::Triple::Apple)
{
- if (!g_abi_sp)
- g_abi_sp.reset (new ABIMacOSX_arm64);
- return g_abi_sp;
+ if (arch_type == llvm::Triple::aarch64)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABIMacOSX_arm64);
+ return g_abi_sp;
+ }
}
+
return ABISP();
}
@@ -322,11 +329,11 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const
size_t bit_width = 0;
if (value_type.IsIntegerType (is_signed))
{
- bit_width = value_type.GetBitSize(nullptr);
+ bit_width = value_type.GetBitSize(&thread);
}
else if (value_type.IsPointerOrReferenceType ())
{
- bit_width = value_type.GetBitSize(nullptr);
+ bit_width = value_type.GetBitSize(&thread);
}
else
{
@@ -562,7 +569,7 @@ ABIMacOSX_arm64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our previous Call Frame Address is the stack pointer
- row->SetCFARegister (sp_reg_num);
+ row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
// Our previous PC is in the LR
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
@@ -589,8 +596,7 @@ ABIMacOSX_arm64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->SetCFARegister (fp_reg_num);
- row->SetCFAOffset (2 * ptr_size);
+ row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index ee5b9298721b..0853fe286963 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -552,7 +552,7 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread,
if (clang_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
is_signed,
thread.GetProcess().get(),
current_stack_argument);
@@ -560,7 +560,7 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread,
else if (clang_type.IsPointerType())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
false,
thread.GetProcess().get(),
current_stack_argument);
@@ -672,7 +672,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
if (clang_type.IsIntegerType (is_signed))
{
- size_t bit_width = clang_type.GetBitSize(nullptr);
+ size_t bit_width = clang_type.GetBitSize(&thread);
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
@@ -746,8 +746,7 @@ ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
uint32_t pc_reg_num = dwarf_eip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
- row->SetCFARegister (sp_reg_num);
- row->SetCFAOffset (4);
+ row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 4);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow (row);
@@ -774,8 +773,7 @@ ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
- row->SetCFARegister (fp_reg_num);
- row->SetCFAOffset (2 * ptr_size);
+ row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
new file mode 100644
index 000000000000..50a9863d83e7
--- /dev/null
+++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -0,0 +1,916 @@
+//===-- ABISysV_arm.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_arm.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+#include "Utility/ARM_DWARF_Registers.h"
+#include "Utility/ARM_GCC_Registers.h"
+#include "Plugins/Process/Utility/ARMDefines.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static RegisterInfo g_register_infos[] =
+{
+ // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== ===============
+ { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13_usr", "sp_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14_usr", "lr_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13_fiq", "sp_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14_fiq", "lr_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13_irq", "sp_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14_irq", "lr_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13_abt", "sp_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14_abt", "lr_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13_und", "sp_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14_und", "lr_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13_svc", "sp_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14_svc", "lr_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}
+};
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABISysV_arm::GetRegisterInfoArray (uint32_t &count)
+{
+ // Make the C-string names and alt_names for the register infos into const
+ // C-string values by having the ConstString unique the names in the global
+ // constant C-string pool.
+ if (!g_register_info_names_constified)
+ {
+ g_register_info_names_constified = true;
+ for (uint32_t i=0; i<k_num_register_infos; ++i)
+ {
+ if (g_register_infos[i].name)
+ g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+ if (g_register_infos[i].alt_name)
+ g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+ }
+ }
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+
+size_t
+ABISysV_arm::GetRedZoneSize () const
+{
+ return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_arm::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
+ const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
+
+ if (vendor_type != llvm::Triple::Apple)
+ {
+ if ((arch_type == llvm::Triple::arm) ||
+ (arch_type == llvm::Triple::thumb))
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_arm);
+ return g_abi_sp;
+ }
+ }
+
+ return ABISP();
+}
+
+bool
+ABISysV_arm::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t function_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ const uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ const uint32_t ra_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+
+ RegisterValue reg_value;
+
+ const uint8_t reg_names[] = { LLDB_REGNUM_GENERIC_ARG1, LLDB_REGNUM_GENERIC_ARG2, LLDB_REGNUM_GENERIC_ARG3, LLDB_REGNUM_GENERIC_ARG4 };
+
+ llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
+
+ for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i)
+ {
+ if (ai == ae)
+ break;
+
+ reg_value.SetUInt32(*ai);
+ if (!reg_ctx->WriteRegister(reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_names[i]), reg_value))
+ return false;
+
+ ++ai;
+ }
+
+ if (ai != ae)
+ {
+ // Spill onto the stack
+ size_t num_stack_regs = ae - ai;
+
+ sp -= (num_stack_regs * 4);
+ // Keep the stack 8 byte aligned, not that we need to
+ sp &= ~(8ull-1ull);
+
+ // just using arg1 to get the right size
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+
+ addr_t arg_pos = sp;
+
+ for (; ai != ae; ++ai)
+ {
+ reg_value.SetUInt32(*ai);
+ if (reg_ctx->WriteRegisterValueToMemory(reg_info, arg_pos, reg_info->byte_size, reg_value).Fail())
+ return false;
+ arg_pos += reg_info->byte_size;
+ }
+ }
+
+ TargetSP target_sp (thread.CalculateTarget());
+ Address so_addr;
+
+ // Figure out if our return address is ARM or Thumb by using the
+ // Address::GetCallableLoadAddress(Target*) which will figure out the ARM
+ // thumb-ness and set the correct address bits for us.
+ so_addr.SetLoadAddress (return_addr, target_sp.get());
+ return_addr = so_addr.GetCallableLoadAddress (target_sp.get());
+
+ // Set "lr" to the return address
+ if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_num, return_addr))
+ return false;
+
+ // Set "sp" to the requested value
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
+ return false;
+
+ // If bit zero or 1 is set, this must be a thumb function, no need to figure
+ // this out from the symbols.
+ so_addr.SetLoadAddress (function_addr, target_sp.get());
+ function_addr = so_addr.GetCallableLoadAddress (target_sp.get());
+
+ const RegisterInfo *cpsr_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+ const uint32_t curr_cpsr = reg_ctx->ReadRegisterAsUnsigned(cpsr_reg_info, 0);
+
+ // Make a new CPSR and mask out any Thumb IT (if/then) bits
+ uint32_t new_cpsr = curr_cpsr & ~MASK_CPSR_IT_MASK;
+ // If bit zero or 1 is set, this must be thumb...
+ if (function_addr & 1ull)
+ new_cpsr |= MASK_CPSR_T; // Set T bit in CPSR
+ else
+ new_cpsr &= ~MASK_CPSR_T; // Clear T bit in CPSR
+
+ if (new_cpsr != curr_cpsr)
+ {
+ if (!reg_ctx->WriteRegisterFromUnsigned (cpsr_reg_info, new_cpsr))
+ return false;
+ }
+
+ function_addr &= ~1ull; // clear bit zero since the CPSR will take care of the mode for us
+
+ // Set "pc" to the address requested
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, function_addr))
+ return false;
+
+ return true;
+}
+
+bool
+ABISysV_arm::GetArgumentValues (Thread &thread,
+ ValueList &values) const
+{
+ uint32_t num_values = values.GetSize();
+
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ // For now, assume that the types in the AST values come from the Target's
+ // scratch AST.
+
+ // Extract the register context so we can read arguments from registers
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ addr_t sp = 0;
+
+ for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx)
+ {
+ // We currently only support extracting values with Clang QualTypes.
+ // Do we care about others?
+ Value *value = values.GetValueAtIndex(value_idx);
+
+ if (!value)
+ return false;
+
+ ClangASTType clang_type = value->GetClangType();
+ if (clang_type)
+ {
+ bool is_signed = false;
+ size_t bit_width = 0;
+ if (clang_type.IsIntegerType (is_signed))
+ {
+ bit_width = clang_type.GetBitSize(&thread);
+ }
+ else if (clang_type.IsPointerOrReferenceType ())
+ {
+ bit_width = clang_type.GetBitSize(&thread);
+ }
+ else
+ {
+ // We only handle integer, pointer and reference types currently...
+ return false;
+ }
+
+ if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8))
+ {
+ if (value_idx < 4)
+ {
+ // Arguments 1-4 are in r0-r3...
+ const RegisterInfo *arg_reg_info = NULL;
+ arg_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);
+ if (arg_reg_info)
+ {
+ RegisterValue reg_value;
+
+ if (reg_ctx->ReadRegister(arg_reg_info, reg_value))
+ {
+ if (is_signed)
+ reg_value.SignExtend(bit_width);
+ if (!reg_value.GetScalarValue(value->GetScalar()))
+ return false;
+ continue;
+ }
+ }
+ return false;
+ }
+ else
+ {
+ if (sp == 0)
+ {
+ // Read the stack pointer if it already hasn't been read
+ sp = reg_ctx->GetSP(0);
+ if (sp == 0)
+ return false;
+ }
+
+ // Arguments 5 on up are on the stack
+ const uint32_t arg_byte_size = (bit_width + (8-1)) / 8;
+ Error error;
+ if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error))
+ return false;
+
+ sp += arg_byte_size;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+ValueObjectSP
+ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
+ lldb_private::ClangASTType &clang_type) const
+{
+ Value value;
+ ValueObjectSP return_valobj_sp;
+
+ if (!clang_type)
+ return return_valobj_sp;
+
+ clang::ASTContext *ast_context = clang_type.GetASTContext();
+ if (!ast_context)
+ return return_valobj_sp;
+
+ //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
+ value.SetClangType (clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ bool is_signed;
+ bool is_complex;
+ uint32_t float_count;
+
+ // Get the pointer to the first stack argument so we have a place to start
+ // when reading data
+
+ const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ size_t bit_width = clang_type.GetBitSize(&thread);
+
+ if (clang_type.IsIntegerType (is_signed))
+ {
+ switch (bit_width)
+ {
+ default:
+ return return_valobj_sp;
+ case 64:
+ {
+ const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
+ uint64_t raw_value;
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+ raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
+ if (is_signed)
+ value.GetScalar() = (int64_t)raw_value;
+ else
+ value.GetScalar() = (uint64_t)raw_value;
+ }
+ break;
+ case 32:
+ if (is_signed)
+ value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
+ break;
+ case 16:
+ if (is_signed)
+ value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
+ break;
+ case 8:
+ if (is_signed)
+ value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
+ break;
+ }
+ }
+ else if (clang_type.IsPointerType ())
+ {
+ uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+ value.GetScalar() = ptr;
+ }
+ else if (clang_type.IsFloatingPointType(float_count, is_complex))
+ {
+ if (float_count == 1 && !is_complex)
+ {
+ switch (bit_width)
+ {
+ default:
+ return return_valobj_sp;
+ case 64:
+ {
+ static_assert(sizeof(double) == sizeof(uint64_t), "");
+ const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
+ uint64_t raw_value;
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+ raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
+ value.GetScalar() = *reinterpret_cast<double*>(&raw_value);
+ break;
+ }
+ case 16: // Half precision returned after a conversion to single precision
+ case 32:
+ {
+ static_assert(sizeof(float) == sizeof(uint32_t), "");
+ uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+ value.GetScalar() = *reinterpret_cast<float*>(&raw_value);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // not handled yet
+ return return_valobj_sp;
+ }
+ }
+ else if (clang_type.IsAggregateType())
+ {
+ size_t byte_size = clang_type.GetByteSize(&thread);
+ if (byte_size <= 4)
+ {
+ RegisterValue r0_reg_value;
+ uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+ value.SetBytes(&raw_value, byte_size);
+ }
+ else
+ {
+ RegisterValue r0_reg_value;
+ uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+
+ Error error;
+ DataBufferHeap buffer(byte_size, 0);
+ thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error);
+
+ if (error.Success())
+ value.SetBytes(buffer.GetBytes(), buffer.GetByteSize());
+ else
+ return return_valobj_sp;
+ }
+ }
+ else
+ {
+ // not handled yet
+ return return_valobj_sp;
+ }
+
+ // If we get here, we have a valid Value, so make our ValueObject out of it:
+
+ return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ return return_valobj_sp;
+}
+
+Error
+ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType clang_type = new_value_sp->GetClangType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ {
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ const RegisterInfo *r0_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ if (num_bytes <= 4)
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, 4);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+ {
+ const RegisterInfo *r1_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value))
+ set_it_simple = true;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+ }
+ else if (clang_type.IsFloatingPointType (count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ error.SetErrorString ("We don't support returning float values at present");
+ }
+
+ if (!set_it_simple)
+ error.SetErrorString ("We only support setting simple integer return types at present.");
+
+ return error;
+}
+
+bool
+ABISysV_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t lr_reg_num = dwarf_lr;
+ uint32_t sp_reg_num = dwarf_sp;
+ uint32_t pc_reg_num = dwarf_pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
+
+ // The previous PC is in the LR
+ row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("arm at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+ return true;
+}
+
+bool
+ABISysV_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear ();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ //TODO: Handle thumb
+ uint32_t fp_reg_num = dwarf_r11;
+ uint32_t pc_reg_num = dwarf_pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ const int32_t ptr_size = 4;
+
+ row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
+ row->SetOffset (0);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("arm default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+
+ return true;
+}
+
+// cf. "ARMv6 Function Calling Conventions"
+
+// ARMv7 on GNU/Linux general purpose reg rules:
+// r0-r3 not preserved (used for argument passing)
+// r4-r11 preserved (v1-v8)
+// r12 not presrved
+// r13 preserved (stack pointer)
+// r14 preserved (link register)
+// r15 preserved (pc)
+// cpsr not preserved (different rules for different bits)
+
+// ARMv7 VFP register rules:
+// d0-d7 not preserved (aka s0-s15, q0-q3)
+// d8-d15 preserved (aka s16-s31, q4-q7)
+// d16-d31 not preserved (aka q8-q15)
+
+bool
+ABISysV_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Volatile registers are: r0, r1, r2, r3, r9, r12, r13 (aka sp)
+ const char *name = reg_info->name;
+ if (name[0] == 'r')
+ {
+ switch (name[1])
+ {
+ case '0': return name[2] == '\0'; // r0
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // r1
+ case '2':
+ return name[3] == '\0'; // r12
+ default:
+ break;
+ }
+ break;
+
+ case '2': return name[2] == '\0'; // r2
+ case '3': return name[2] == '\0'; // r3
+ default:
+ break;
+ }
+ }
+ else if (name[0] == 'd')
+ {
+ switch (name[1])
+ {
+ case '0':
+ return name[2] == '\0'; // d0 is volatile
+
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // d1 is volatile
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return name[3] == '\0'; // d16 - d19 are volatile
+ default:
+ break;
+ }
+ break;
+
+ case '2':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // d2 is volatile
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return name[3] == '\0'; // d20 - d29 are volatile
+ default:
+ break;
+ }
+ break;
+
+ case '3':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // d3 is volatile
+ case '0':
+ case '1':
+ return name[3] == '\0'; // d30 - d31 are volatile
+ default:
+ break;
+ }
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ return name[2] == '\0'; // d4 - d7 are volatile
+
+ default:
+ break;
+ }
+ }
+ else if (name[0] == 's')
+ {
+ switch (name[1])
+ {
+ case '0':
+ return name[2] == '\0'; // s0 is volatile
+
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // s1 is volatile
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ return name[3] == '\0'; // s10 - s15 are volatile
+ default:
+ break;
+ }
+ break;
+
+ case '2':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // s2 is volatile
+ default:
+ break;
+ }
+ break;
+
+ case '3':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // s3 is volatile
+ default:
+ break;
+ }
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return name[2] == '\0'; // s4 - s9 are volatile
+
+ default:
+ break;
+ }
+ }
+ else if (name[0] == 'q')
+ {
+ switch (name[1])
+ {
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // q1 is volatile
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ return true; // q10-q15 are volatile
+ default:
+ break;
+ };
+ case '0':
+ case '2':
+ case '3':
+ return name[2] == '\0'; // q0-q3 are volatile
+ case '8':
+ case '9':
+ return name[2] == '\0'; // q8-q9 are volatile
+ default:
+ break;
+ }
+ }
+ else if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')
+ return true;
+ }
+ return false;
+}
+
+void
+ABISysV_arm::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "SysV ABI for arm targets",
+ CreateInstance);
+}
+
+void
+ABISysV_arm::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_arm::GetPluginNameStatic()
+{
+ static ConstString g_name("SysV-arm");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_arm::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_arm::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
new file mode 100644
index 000000000000..69becd6ec0c2
--- /dev/null
+++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
@@ -0,0 +1,121 @@
+//===-- ABISysV_arm.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABISysV_arm_h_
+#define liblldb_ABISysV_arm_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_arm : public lldb_private::ABI
+{
+public:
+ ~ABISysV_arm() { }
+
+ size_t
+ GetRedZoneSize () const override;
+
+ bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t func_addr,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
+
+ bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
+
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
+
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const override;
+
+public:
+ bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
+
+ bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
+
+ bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info) override;
+
+ bool
+ CallFrameAddressIsValid (lldb::addr_t cfa) override
+ {
+ // Make sure the stack call frame addresses are are 4 byte aligned
+ if (cfa & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+ if (cfa == 0)
+ return false; // Zero is not a valid stack address
+ return true;
+ }
+
+ bool
+ CodeAddressIsValid (lldb::addr_t pc) override
+ {
+ // Just make sure the address is a valid 32 bit address. Bit zero
+ // might be set due to Thumb function calls, so don't enforce 2 byte
+ // alignment
+ return pc <= UINT32_MAX;
+ }
+
+ lldb::addr_t
+ FixCodeAddress (lldb::addr_t pc) override
+ {
+ // ARM uses bit zero to signify a code address is thumb, so we must
+ // strip bit zero in any code addresses.
+ return pc & ~(lldb::addr_t)1;
+ }
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count) override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+protected:
+private:
+ ABISysV_arm() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
+};
+
+#endif // liblldb_ABISysV_arm_h_
diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
new file mode 100644
index 000000000000..ed058ff19d99
--- /dev/null
+++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
@@ -0,0 +1,1081 @@
+//===-- ABISysV_arm64.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_arm64.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+#include "Utility/ARM64_DWARF_Registers.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static RegisterInfo g_register_infos[] =
+{
+ // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
+ // ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ======================
+ { "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x2", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x3", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x4", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x5", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x6", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x7", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x8", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x9", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x10", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x11", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x12", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x13", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x14", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x15", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x16", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x17", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x18", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x19", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x20", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x21", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x22", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x23", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x24", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x25", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x26", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x27", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "x28", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "fp", "x29", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "pc", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "v0", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v1", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v2", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v3", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v4", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v5", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v6", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v7", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v8", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v9", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v10", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v11", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v12", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v13", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v14", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v15", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v16", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v17", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v18", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v19", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v20", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v21", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v22", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v23", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v24", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v25", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v26", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v27", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v28", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v29", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v30", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "v31", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "fpsr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "fpcr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABISysV_arm64::GetRegisterInfoArray (uint32_t &count)
+{
+ // Make the C-string names and alt_names for the register infos into const
+ // C-string values by having the ConstString unique the names in the global
+ // constant C-string pool.
+ if (!g_register_info_names_constified)
+ {
+ g_register_info_names_constified = true;
+ for (uint32_t i=0; i<k_num_register_infos; ++i)
+ {
+ if (g_register_infos[i].name)
+ g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+ if (g_register_infos[i].alt_name)
+ g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+ }
+ }
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+size_t
+ABISysV_arm64::GetRedZoneSize () const
+{
+ return 128;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_arm64::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
+ const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
+
+ if (vendor_type != llvm::Triple::Apple)
+ {
+ if (arch_type == llvm::Triple::aarch64)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_arm64);
+ return g_abi_sp;
+ }
+ }
+
+ return ABISP();
+}
+
+bool
+ABISysV_arm64::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_x86_64::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+ thread.GetID(),
+ (uint64_t)sp,
+ (uint64_t)func_addr,
+ (uint64_t)return_addr);
+
+ for (size_t i = 0; i < args.size(); ++i)
+ s.Printf (", arg%d = 0x%" PRIx64, static_cast<int>(i + 1), args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ // x0 - x7 contain first 8 simple args
+ if (args.size() > 8)
+ return false;
+
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%d (0x%" PRIx64 ") into %s",
+ static_cast<int>(i + 1), args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+ }
+
+ // Set "lr" to the return address
+ if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA), return_addr))
+ return false;
+
+ // Set "sp" to the requested value
+ if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP), sp))
+ return false;
+
+ // Set "pc" to the address requested
+ if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC), func_addr))
+ return false;
+
+ return true;
+}
+
+//TODO: We dont support fp/SIMD arguments in v0-v7
+bool
+ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const
+{
+ uint32_t num_values = values.GetSize();
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+
+ // Extract the register context so we can read arguments from registers
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ addr_t sp = 0;
+
+ for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx)
+ {
+ // We currently only support extracting values with Clang QualTypes.
+ // Do we care about others?
+ Value *value = values.GetValueAtIndex(value_idx);
+
+ if (!value)
+ return false;
+
+ ClangASTType value_type = value->GetClangType();
+ if (value_type)
+ {
+ bool is_signed = false;
+ size_t bit_width = 0;
+ if (value_type.IsIntegerType (is_signed))
+ {
+ bit_width = value_type.GetBitSize(&thread);
+ }
+ else if (value_type.IsPointerOrReferenceType ())
+ {
+ bit_width = value_type.GetBitSize(&thread);
+ }
+ else
+ {
+ // We only handle integer, pointer and reference types currently...
+ return false;
+ }
+
+ if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8))
+ {
+ if (value_idx < 8)
+ {
+ // Arguments 1-8 are in x0-x7...
+ const RegisterInfo *reg_info = NULL;
+ reg_info= reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);
+
+ if (reg_info)
+ {
+ RegisterValue reg_value;
+
+ if (reg_ctx->ReadRegister(reg_info, reg_value))
+ {
+ if (is_signed)
+ reg_value.SignExtend(bit_width);
+ if (!reg_value.GetScalarValue(value->GetScalar()))
+ return false;
+ continue;
+ }
+ }
+ return false;
+ }
+ else
+ {
+ //TODO: Verify for stack layout for SysV
+ if (sp == 0)
+ {
+ // Read the stack pointer if we already haven't read it
+ sp = reg_ctx->GetSP(0);
+ if (sp == 0)
+ return false;
+ }
+
+ // Arguments 5 on up are on the stack
+ const uint32_t arg_byte_size = (bit_width + (8-1)) / 8;
+ Error error;
+ if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error))
+ return false;
+
+ sp += arg_byte_size;
+ // Align up to the next 8 byte boundary if needed
+ if (sp % 8)
+ {
+ sp >>= 3;
+ sp += 1;
+ sp <<= 3;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+Error
+ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType return_value_type = new_value_sp->GetClangType();
+ if (!return_value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ if (reg_ctx)
+ {
+ DataExtractor data;
+ Error data_error;
+ const uint64_t byte_size = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ const uint32_t type_flags = return_value_type.GetTypeInfo (NULL);
+ if (type_flags & eTypeIsScalar ||
+ type_flags & eTypeIsPointer)
+ {
+ if (type_flags & eTypeIsInteger ||
+ type_flags & eTypeIsPointer )
+ {
+ // Extract the register context so we can read arguments from registers
+ lldb::offset_t offset = 0;
+ if (byte_size <= 16)
+ {
+ const RegisterInfo *x0_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ if (byte_size <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, byte_size);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (x0_info, raw_value))
+ error.SetErrorString ("failed to write register x0");
+ }
+ else
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, 8);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (x0_info, raw_value))
+ {
+ const RegisterInfo *x1_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
+ raw_value = data.GetMaxU64(&offset, byte_size - offset);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (x1_info, raw_value))
+ error.SetErrorString ("failed to write register x1");
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 128 bit integer values at present.");
+ }
+ }
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ error.SetErrorString ("returning complex float values are not supported");
+ }
+ else
+ {
+ const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+
+ if (v0_info)
+ {
+ if (byte_size <= 16)
+ {
+ if (byte_size <= RegisterValue::GetMaxByteSize())
+ {
+ RegisterValue reg_value;
+ error = reg_value.SetValueFromData (v0_info, data, 0, true);
+ if (error.Success())
+ {
+ if (!reg_ctx->WriteRegister (v0_info, reg_value))
+ error.SetErrorString ("failed to write register v0");
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("returning float values with a byte size of %" PRIu64 " are not supported", byte_size);
+ }
+ }
+ else
+ {
+ error.SetErrorString("returning float values longer than 128 bits are not supported");
+ }
+ }
+ else
+ {
+ error.SetErrorString("v0 register is not available on this target");
+ }
+ }
+ }
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ if (byte_size > 0)
+ {
+ const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+
+ if (v0_info)
+ {
+ if (byte_size <= v0_info->byte_size)
+ {
+ RegisterValue reg_value;
+ error = reg_value.SetValueFromData (v0_info, data, 0, true);
+ if (error.Success())
+ {
+ if (!reg_ctx->WriteRegister (v0_info, reg_value))
+ error.SetErrorString ("failed to write register v0");
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("no registers are available");
+ }
+
+ return error;
+}
+
+bool
+ABISysV_arm64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t lr_reg_num = arm64_dwarf::lr;
+ uint32_t sp_reg_num = arm64_dwarf::sp;
+ uint32_t pc_reg_num = arm64_dwarf::pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our previous Call Frame Address is the stack pointer
+ row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
+
+ // Our previous PC is in the LR
+ row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("arm64 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+ return true;
+}
+
+bool
+ABISysV_arm64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t fp_reg_num = arm64_dwarf::fp;
+ uint32_t pc_reg_num = arm64_dwarf::pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ const int32_t ptr_size = 8;
+
+ row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
+ row->SetOffset (0);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("arm64 default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+
+ return true;
+}
+
+// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says
+// registers x19 through x28 and sp are callee preserved.
+// v8-v15 are non-volatile (and specifically only the lower 8 bytes of these regs),
+// the rest of the fp/SIMD registers are volatile.
+
+// We treat x29 as callee preserved also, else the unwinder won't try to
+// retrieve fp saves.
+
+bool
+ABISysV_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ const char *name = reg_info->name;
+
+ // Sometimes we'll be called with the "alternate" name for these registers;
+ // recognize them as non-volatile.
+
+ if (name[0] == 'p' && name[1] == 'c') // pc
+ return false;
+ if (name[0] == 'f' && name[1] == 'p') // fp
+ return false;
+ if (name[0] == 's' && name[1] == 'p') // sp
+ return false;
+ if (name[0] == 'l' && name[1] == 'r') // lr
+ return false;
+
+ if (name[0] == 'x')
+ {
+ // Volatile registers: x0-x18
+ // Although documentation says only x19-28 + sp are callee saved
+ // We ll also have to treat x30 as non-volatile.
+ // Each dwarf frame has its own value of lr.
+ // Return false for the non-volatile gpr regs, true for everything else
+ switch (name[1])
+ {
+ case '1':
+ switch (name[2])
+ {
+ case '9':
+ return false; // x19 is non-volatile
+ default:
+ return true;
+ }
+ break;
+ case '2':
+ switch (name[2])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ return false; // x20 - 28 are non-volatile
+ case '9':
+ return false; // x29 aka fp treat as non-volatile
+ default:
+ return true;
+ }
+ case '3': // x30 (lr) and x31 (sp) treat as non-volatile
+ if (name[2] == '0' || name[2] == '1')
+ return false;
+ default:
+ return true; // all volatile cases not handled above fall here.
+ }
+ }
+ else if (name[0] == 'v' || name[0] == 's' || name[0] == 'd')
+ {
+ // Volatile registers: v0-7, v16-v31
+ // Return false for non-volatile fp/SIMD regs, true for everything else
+ switch (name[1])
+ {
+ case '8':
+ case '9':
+ return false; // v8-v9 are non-volatile
+ case '1':
+ switch (name[2])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ return false; // v10-v15 are non-volatile
+ default:
+ return true;
+ }
+ default:
+ return true;
+ }
+ }
+ }
+ return true;
+}
+
+static bool
+LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
+ RegisterContext *reg_ctx,
+ const ClangASTType &value_type,
+ bool is_return_value, // false => parameter, true => return value
+ uint32_t &NGRN, // NGRN (see ABI documentation)
+ uint32_t &NSRN, // NSRN (see ABI documentation)
+ DataExtractor &data)
+{
+ const size_t byte_size = value_type.GetByteSize(nullptr);
+
+ if (byte_size == 0)
+ return false;
+
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
+ Error error;
+
+ ClangASTType base_type;
+ const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);
+ if (homogeneous_count > 0 && homogeneous_count <= 8)
+ {
+ printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);
+ // Make sure we have enough registers
+ if (NSRN < 8 && (8-NSRN) >= homogeneous_count)
+ {
+ if (!base_type)
+ return false;
+ const size_t base_byte_size = base_type.GetByteSize(nullptr);
+ printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);
+ uint32_t data_offset = 0;
+
+ for (uint32_t i=0; i<homogeneous_count; ++i)
+ {
+ char v_name[8];
+ ::snprintf (v_name, sizeof(v_name), "v%u", NSRN);
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(v_name, 0);
+ if (reg_info == NULL)
+ return false;
+
+ if (base_byte_size > reg_info->byte_size)
+ return false;
+
+ RegisterValue reg_value;
+
+ if (!reg_ctx->ReadRegister(reg_info, reg_value))
+ return false;
+
+ // Make sure we have enough room in "heap_data_ap"
+ if ((data_offset + base_byte_size) <= heap_data_ap->GetByteSize())
+ {
+ const size_t bytes_copied = reg_value.GetAsMemoryData (reg_info,
+ heap_data_ap->GetBytes()+data_offset,
+ base_byte_size,
+ byte_order,
+ error);
+ if (bytes_copied != base_byte_size)
+ return false;
+ data_offset += bytes_copied;
+ ++NSRN;
+ }
+ else
+ return false;
+ }
+ data.SetByteOrder(byte_order);
+ data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());
+ data.SetData(DataBufferSP (heap_data_ap.release()));
+ return true;
+ }
+ }
+
+ const size_t max_reg_byte_size = 16;
+ if (byte_size <= max_reg_byte_size)
+ {
+ size_t bytes_left = byte_size;
+ uint32_t data_offset = 0;
+ while (data_offset < byte_size)
+ {
+ if (NGRN >= 8)
+ return false;
+
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);
+ if (reg_info == NULL)
+ return false;
+
+ RegisterValue reg_value;
+
+ if (!reg_ctx->ReadRegister(reg_info, reg_value))
+ return false;
+
+ const size_t curr_byte_size = std::min<size_t>(8,bytes_left);
+ const size_t bytes_copied = reg_value.GetAsMemoryData (reg_info, heap_data_ap->GetBytes()+data_offset, curr_byte_size, byte_order, error);
+ if (bytes_copied == 0)
+ return false;
+ if (bytes_copied >= bytes_left)
+ break;
+ data_offset += bytes_copied;
+ bytes_left -= bytes_copied;
+ ++NGRN;
+ }
+ }
+ else
+ {
+ const RegisterInfo *reg_info = NULL;
+ if (is_return_value)
+ {
+ // We are assuming we are decoding this immediately after returning
+ // from a function call and that the address of the structure is in x8
+ reg_info = reg_ctx->GetRegisterInfoByName("x8", 0);
+ }
+ else
+ {
+ // We are assuming we are stopped at the first instruction in a function
+ // and that the ABI is being respected so all parameters appear where they
+ // should be (functions with no external linkage can legally violate the ABI).
+ if (NGRN >= 8)
+ return false;
+
+ reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN);
+ if (reg_info == NULL)
+ return false;
+ ++NGRN;
+ }
+
+ if (reg_info == NULL)
+ return false;
+
+ const lldb::addr_t value_addr = reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS);
+
+ if (value_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (exe_ctx.GetProcessRef().ReadMemory (value_addr,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ error) != heap_data_ap->GetByteSize())
+ {
+ return false;
+ }
+ }
+
+ data.SetByteOrder(byte_order);
+ data.SetAddressByteSize(exe_ctx.GetProcessRef().GetAddressByteSize());
+ data.SetData(DataBufferSP (heap_data_ap.release()));
+ return true;
+}
+
+ValueObjectSP
+ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
+ return return_valobj_sp;
+
+ //value.SetContext (Value::eContextTypeClangType, return_clang_type);
+ value.SetClangType(return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+
+ const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+ if (type_flags & eTypeIsScalar ||
+ type_flags & eTypeIsPointer)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & eTypeIsInteger ||
+ type_flags & eTypeIsPointer )
+ {
+ // Extract the register context so we can read arguments from registers
+ if (byte_size <= 8)
+ {
+ const RegisterInfo *x0_reg_info = NULL;
+ x0_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ if (x0_reg_info)
+ {
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info, 0);
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+ case 16: // uint128_t
+ // In register x0 and x1
+ {
+ const RegisterInfo *x1_reg_info = NULL;
+ x1_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
+
+ if (x1_reg_info)
+ {
+ if (byte_size <= x0_reg_info->byte_size + x1_reg_info->byte_size)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
+ RegisterValue x0_reg_value;
+ RegisterValue x1_reg_value;
+ if (reg_ctx->ReadRegister(x0_reg_info, x0_reg_value) &&
+ reg_ctx->ReadRegister(x1_reg_info, x1_reg_value))
+ {
+ Error error;
+ if (x0_reg_value.GetAsMemoryData (x0_reg_info, heap_data_ap->GetBytes()+0, 8, byte_order, error) &&
+ x1_reg_value.GetAsMemoryData (x1_reg_info, heap_data_ap->GetBytes()+8, 8, byte_order, error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ exe_ctx.GetProcessRef().GetAddressByteSize());
+
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ return return_valobj_sp;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case sizeof(uint64_t):
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
+ }
+ }
+ }
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ if (byte_size <= sizeof(long double))
+ {
+ const RegisterInfo *v0_reg_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+ RegisterValue v0_value;
+ if (reg_ctx->ReadRegister (v0_reg_info, v0_value))
+ {
+ DataExtractor data;
+ if (v0_value.GetData(data))
+ {
+ lldb::offset_t offset = 0;
+ if (byte_size == sizeof(float))
+ {
+ value.GetScalar() = data.GetFloat(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ value.GetScalar() = data.GetDouble(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(long double))
+ {
+ value.GetScalar() = data.GetLongDouble(&offset);
+ success = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ if (byte_size > 0)
+ {
+
+ const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
+
+ if (v0_info)
+ {
+ if (byte_size <= v0_info->byte_size)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(v0_info, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (v0_info,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ exe_ctx.GetProcessRef().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (type_flags & eTypeIsStructUnion ||
+ type_flags & eTypeIsClass)
+ {
+ DataExtractor data;
+
+ uint32_t NGRN = 0; // Search ABI docs for NGRN
+ uint32_t NSRN = 0; // Search ABI docs for NSRN
+ const bool is_return_value = true;
+ if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data))
+ {
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ return return_valobj_sp;
+}
+
+void
+ABISysV_arm64::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "SysV ABI for AArch64 targets",
+ CreateInstance);
+}
+
+void
+ABISysV_arm64::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_arm64::GetPluginNameStatic()
+{
+ static ConstString g_name("SysV-arm64");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+ABISysV_arm64::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_arm64::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
new file mode 100644
index 000000000000..08c8682d8fa4
--- /dev/null
+++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
@@ -0,0 +1,125 @@
+//===-- ABISysV_arm64.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABISysV_arm64_h_
+#define liblldb_ABISysV_arm64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_arm64 : public lldb_private::ABI
+{
+public:
+ ~ABISysV_arm64() { }
+
+ size_t
+ GetRedZoneSize () const override;
+
+ bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
+
+ bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
+
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
+
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const override;
+
+public:
+ bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
+
+ bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
+
+ bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info) override;
+
+ // The arm64 ABI requires that stack frames be 16 byte aligned.
+ // When there is a trap handler on the stack, e.g. _sigtramp in userland
+ // code, we've seen that the stack pointer is often not aligned properly
+ // before the handler is invoked. This means that lldb will stop the unwind
+ // early -- before the function which caused the trap.
+ //
+ // To work around this, we relax that alignment to be just word-size (8-bytes).
+ // Whitelisting the trap handlers for user space would be easy (_sigtramp) but
+ // in other environments there can be a large number of different functions
+ // involved in async traps.
+
+ bool
+ CallFrameAddressIsValid (lldb::addr_t cfa) override
+ {
+ // Make sure the stack call frame addresses are are 8 byte aligned
+ if (cfa & (8ull - 1ull))
+ return false; // Not 8 byte aligned
+ if (cfa == 0)
+ return false; // Zero is not a valid stack address
+ return true;
+ }
+
+ bool
+ CodeAddressIsValid (lldb::addr_t pc) override
+ {
+ if (pc & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+
+ // Anything else if fair game..
+ return true;
+ }
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count) override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+protected:
+private:
+ ABISysV_arm64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
+};
+
+#endif // liblldb_ABISysV_arm64_h_
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
index 0f01c568ed3e..e9e68bc0e949 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -263,13 +263,12 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
// update the argument with the target pointer
//XXX: This is a gross hack for getting around the const
- *((size_t*)(&arg.value)) = sp;
+ *const_cast<lldb::addr_t*>(&arg.value) = sp;
}
-
#if HEX_ABI_DEBUG
// print the original stack pointer
- printf( "sp : %04lx \n", sp );
+ printf( "sp : %04" PRIx64 " \n", sp );
#endif
// make sure number of parameters matches prototype
@@ -337,7 +336,7 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
uint32_t data = 0;
lldb::addr_t addr = sp + i * 4;
proc->ReadMemory( addr, (void*)&data, sizeof( data ), error );
- printf( "\n0x%04lx 0x%08x ", addr, data );
+ printf( "\n0x%04" PRIx64 " 0x%08x ", addr, data );
if ( i == 0 ) printf( "<<-- sp" );
}
printf( "\n" );
@@ -385,8 +384,7 @@ ABISysV_hexagon::CreateFunctionEntryUnwindPlan ( UnwindPlan &unwind_plan )
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->SetCFARegister(LLDB_REGNUM_GENERIC_SP);
- row->SetCFAOffset(4);
+ row->GetCFAValue().SetIsRegisterPlusOffset (LLDB_REGNUM_GENERIC_SP, 4);
row->SetOffset(0);
// The previous PC is in the LR
@@ -410,8 +408,7 @@ ABISysV_hexagon::CreateDefaultUnwindPlan ( UnwindPlan &unwind_plan )
UnwindPlan::RowSP row(new UnwindPlan::Row);
- row->SetCFARegister(LLDB_REGNUM_GENERIC_FP);
- row->SetCFAOffset(8);
+ row->GetCFAValue().SetIsRegisterPlusOffset (LLDB_REGNUM_GENERIC_FP, 8);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num,-8, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num,-4, true);
diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
new file mode 100644
index 000000000000..26da9aeb370d
--- /dev/null
+++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
@@ -0,0 +1,815 @@
+//===----------------------- ABISysV_i386.cpp -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source License.
+// See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_i386.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+// This source file uses the following document as a reference:
+//====================================================================
+// System V Application Binary Interface
+// Intel386 Architecture Processor Supplement, Version 1.0
+// Edited by
+// H.J. Lu, David L Kreitzer, Milind Girkar, Zia Ansari
+//
+// (Based on
+// System V Application Binary Interface,
+// AMD64 Architecture Processor Supplement,
+// Edited by
+// H.J. Lu, Michael Matz, Milind Girkar, Jan Hubicka,
+// Andreas Jaeger, Mark Mitchell)
+//
+// February 3, 2015
+//====================================================================
+
+
+
+// DWARF Register Number Mapping
+// See Table 2.14 of the reference document (specified on top of this file)
+// Comment: Table 2.14 is followed till 'mm' entries.
+// After that, all entries are ignored here.
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_eax = 0,
+ gcc_dwarf_ecx,
+ gcc_dwarf_edx,
+ gcc_dwarf_ebx,
+ gcc_dwarf_esp,
+ gcc_dwarf_ebp,
+ gcc_dwarf_esi,
+ gcc_dwarf_edi,
+ gcc_dwarf_eip,
+ gcc_dwarf_eflags,
+
+ gcc_dwarf_st0 = 11,
+ gcc_dwarf_st1,
+ gcc_dwarf_st2,
+ gcc_dwarf_st3,
+ gcc_dwarf_st4,
+ gcc_dwarf_st5,
+ gcc_dwarf_st6,
+ gcc_dwarf_st7,
+
+ gcc_dwarf_xmm0 = 21,
+ gcc_dwarf_xmm1,
+ gcc_dwarf_xmm2,
+ gcc_dwarf_xmm3,
+ gcc_dwarf_xmm4,
+ gcc_dwarf_xmm5,
+ gcc_dwarf_xmm6,
+ gcc_dwarf_xmm7,
+ gcc_dwarf_ymm0 = gcc_dwarf_xmm0,
+ gcc_dwarf_ymm1 = gcc_dwarf_xmm1,
+ gcc_dwarf_ymm2 = gcc_dwarf_xmm2,
+ gcc_dwarf_ymm3 = gcc_dwarf_xmm3,
+ gcc_dwarf_ymm4 = gcc_dwarf_xmm4,
+ gcc_dwarf_ymm5 = gcc_dwarf_xmm5,
+ gcc_dwarf_ymm6 = gcc_dwarf_xmm6,
+ gcc_dwarf_ymm7 = gcc_dwarf_xmm7,
+
+ gcc_dwarf_mm0 = 29,
+ gcc_dwarf_mm1,
+ gcc_dwarf_mm2,
+ gcc_dwarf_mm3,
+ gcc_dwarf_mm4,
+ gcc_dwarf_mm5,
+ gcc_dwarf_mm6,
+ gcc_dwarf_mm7
+};
+
+
+enum gdb_regnums
+{
+ gdb_eax = 0,
+ gdb_ecx = 1,
+ gdb_edx = 2,
+ gdb_ebx = 3,
+ gdb_esp = 4,
+ gdb_ebp = 5,
+ gdb_esi = 6,
+ gdb_edi = 7,
+ gdb_eip = 8,
+ gdb_eflags = 9,
+ gdb_cs = 10,
+ gdb_ss = 11,
+ gdb_ds = 12,
+ gdb_es = 13,
+ gdb_fs = 14,
+ gdb_gs = 15,
+ gdb_st0 = 16,
+ gdb_st1 = 17,
+ gdb_st2 = 18,
+ gdb_st3 = 19,
+ gdb_st4 = 20,
+ gdb_st5 = 21,
+ gdb_st6 = 22,
+ gdb_st7 = 23,
+ gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
+ gdb_fstat = 25, gdb_fsw = gdb_fstat,
+ gdb_ftag = 26, gdb_ftw = gdb_ftag,
+ gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
+ gdb_fioff = 28, gdb_ip = gdb_fioff,
+ gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
+ gdb_fooff = 30, gdb_dp = gdb_fooff,
+ gdb_fop = 31,
+ gdb_xmm0 = 32,
+ gdb_xmm1 = 33,
+ gdb_xmm2 = 34,
+ gdb_xmm3 = 35,
+ gdb_xmm4 = 36,
+ gdb_xmm5 = 37,
+ gdb_xmm6 = 38,
+ gdb_xmm7 = 39,
+ gdb_mxcsr = 40,
+ gdb_mm0 = 41,
+ gdb_mm1 = 42,
+ gdb_mm2 = 43,
+ gdb_mm3 = 44,
+ gdb_mm4 = 45,
+ gdb_mm5 = 46,
+ gdb_mm6 = 47,
+ gdb_mm7 = 48,
+ gdb_ymm0 = gdb_xmm0,
+ gdb_ymm1 = gdb_xmm1,
+ gdb_ymm2 = gdb_xmm2,
+ gdb_ymm3 = gdb_xmm3,
+ gdb_ymm4 = gdb_xmm4,
+ gdb_ymm5 = gdb_xmm5,
+ gdb_ymm6 = gdb_xmm6,
+ gdb_ymm7 = gdb_xmm7
+};
+
+
+static RegisterInfo g_register_infos[] =
+{
+ // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== ===============
+ { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eax , gcc_dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebx , gcc_dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ecx , gcc_dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edx , gcc_dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esi , gcc_dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edi , gcc_dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebp , gcc_dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esp , gcc_dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eip , gcc_dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st0 , LLDB_INVALID_REGNUM , gdb_st0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st1 , LLDB_INVALID_REGNUM , gdb_st1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st2 , LLDB_INVALID_REGNUM , gdb_st2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st3 , LLDB_INVALID_REGNUM , gdb_st3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st4 , LLDB_INVALID_REGNUM , gdb_st4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st5 , LLDB_INVALID_REGNUM , gdb_st5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st6 , LLDB_INVALID_REGNUM , gdb_st6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st7 , LLDB_INVALID_REGNUM , gdb_st7 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr}
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABISysV_i386::GetRegisterInfoArray (uint32_t &count)
+{
+ // Make the C-string names and alt_names for the register infos into const
+ // C-string values by having the ConstString unique the names in the global
+ // constant C-string pool.
+ if (!g_register_info_names_constified)
+ {
+ g_register_info_names_constified = true;
+ for (uint32_t i=0; i<k_num_register_infos; ++i)
+ {
+ if (g_register_infos[i].name)
+ g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+ if (g_register_infos[i].alt_name)
+ g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+ }
+ }
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_i386::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
+ arch.GetTriple().isOSLinux())
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_i386);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_i386::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+
+ // While using register info to write a register value to memory, the register info
+ // just needs to have the correct size of a 32 bit register, the actual register it
+ // pertains to is not important, just the size needs to be correct.
+ // "eax" is used here for this purpose.
+ const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
+ if (!reg_info_32)
+ return false; // TODO this should actually never happen
+
+ Error error;
+ RegisterValue reg_value;
+
+ // Make room for the argument(s) on the stack
+ sp -= 4 * args.size();
+
+ // SP Alignment
+ sp &= ~(16ull-1ull); // 16-byte alignment
+
+ // Write arguments onto the stack
+ addr_t arg_pos = sp;
+ for (addr_t arg : args)
+ {
+ reg_value.SetUInt32(arg);
+ error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
+ arg_pos,
+ reg_info_32->byte_size,
+ reg_value);
+ if (error.Fail())
+ return false;
+ arg_pos += 4;
+ }
+
+ // The return address is pushed onto the stack
+ sp -= 4;
+ reg_value.SetUInt32(return_addr);
+ error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
+ sp,
+ reg_info_32->byte_size,
+ reg_value);
+ if (error.Fail())
+ return false;
+
+ // Setting %esp to the actual stack value.
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
+ return false;
+
+ // Setting %eip to the address of the called function.
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr))
+ return false;
+
+ return true;
+}
+
+
+static bool
+ReadIntegerArgument (Scalar &scalar,
+ unsigned int bit_width,
+ bool is_signed,
+ Process *process,
+ addr_t &current_stack_argument)
+{
+ uint32_t byte_size = (bit_width + (8-1))/8;
+ Error error;
+
+ if (!process)
+ return false;
+
+ if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
+ {
+ current_stack_argument += byte_size;
+ return true;
+ }
+ return false;
+}
+
+
+bool
+ABISysV_i386::GetArgumentValues (Thread &thread,
+ ValueList &values) const
+{
+ unsigned int num_values = values.GetSize();
+ unsigned int value_index;
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ // Get pointer to the first stack argument
+ addr_t sp = reg_ctx->GetSP(0);
+ if (!sp)
+ return false;
+
+ addr_t current_stack_argument = sp + 4; // jump over return address
+
+ for (value_index = 0;
+ value_index < num_values;
+ ++value_index)
+ {
+ Value *value = values.GetValueAtIndex(value_index);
+
+ if (!value)
+ return false;
+
+ // Currently: Support for extracting values with Clang QualTypes only.
+ ClangASTType clang_type (value->GetClangType());
+ if (clang_type)
+ {
+ bool is_signed;
+ if (clang_type.IsIntegerType (is_signed))
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(&thread),
+ is_signed,
+ thread.GetProcess().get(),
+ current_stack_argument);
+ }
+ else if (clang_type.IsPointerType())
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(&thread),
+ false,
+ thread.GetProcess().get(),
+ current_stack_argument);
+ }
+ }
+ }
+ return true;
+}
+
+
+
+Error
+ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ //ToDo: Yet to be implemented
+ error.SetErrorString("ABISysV_i386::SetReturnValueObject(): Not implemented yet");
+ return error;
+}
+
+
+ValueObjectSP
+ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
+ ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ value.SetClangType (return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+
+ unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+ unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
+
+
+ // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
+ // The terminology 'Fundamental Data Types' used here is adopted from
+ // Table 2.1 of the reference document (specified on top of this file)
+
+ if (type_flags & eTypeIsPointer) // 'Pointer'
+ {
+ uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
+ value.SetValueType(Value::eValueTypeScalar);
+ value.GetScalar() = ptr;
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+
+ else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+ const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ bool success = false;
+
+ if (type_flags & eTypeIsInteger) // 'Integral' except enum
+ {
+ const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
+ raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
+
+ switch (byte_size)
+ {
+ default:
+ break;
+
+ case 16:
+ // For clang::BuiltinType::UInt128 & Int128
+ // ToDo: Need to decide how to handle it
+ break ;
+
+ case 8:
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case 4:
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case 2:
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case 1:
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+
+ else if (type_flags & eTypeIsEnumeration) // handles enum
+ {
+ uint32_t enm = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
+ value.SetValueType(Value::eValueTypeScalar);
+ value.GetScalar() = enm;
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+
+ else if (type_flags & eTypeIsFloat) // 'Floating Point'
+ {
+ if (byte_size <= 12) // handles float, double, long double, __float80
+ {
+ const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
+ RegisterValue st0_value;
+
+ if (reg_ctx->ReadRegister (st0_info, st0_value))
+ {
+ DataExtractor data;
+ if (st0_value.GetData(data))
+ {
+ lldb::offset_t offset = 0;
+ long double value_long_double = data.GetLongDouble(&offset);
+
+ if (byte_size == 4) // float is 4 bytes
+ {
+ float value_float = (float)value_long_double;
+ value.GetScalar() = value_float;
+ success = true;
+ }
+ else if (byte_size == 8) // double is 8 bytes
+ {
+ // On Android Platform: long double is also 8 bytes
+ // It will be handled here only.
+ double value_double = (double)value_long_double;
+ value.GetScalar() = value_double;
+ success = true;
+ }
+ else if (byte_size == 12) // long double and __float80 are 12 bytes on i386
+ {
+ value.GetScalar() = value_long_double;
+ success = true;
+ }
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+ else if(byte_size == 16) // handles __float128
+ {
+ lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (storage_addr, nullptr),
+ return_clang_type);
+ }
+ }
+
+ else // Neither 'Integral' nor 'Floating Point'
+ {
+ // If flow reaches here then check type_flags
+ // This type_flags is unhandled
+ }
+ }
+
+ else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
+ {
+ // ToDo: Yet to be implemented
+ }
+
+ else if (type_flags & eTypeIsVector) // 'Packed'
+ {
+ const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ if (byte_size > 0)
+ {
+ const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0);
+ if (vec_reg == nullptr)
+ {
+ vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+ if (vec_reg == nullptr)
+ vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
+ }
+
+ if (vec_reg)
+ {
+ if (byte_size <= vec_reg->byte_size)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(vec_reg, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (vec_reg,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ else // 'Decimal Floating Point'
+ {
+ //ToDo: Yet to be implemented
+ }
+ return return_valobj_sp;
+}
+
+
+ValueObjectSP
+ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ if (return_valobj_sp)
+ return return_valobj_sp;
+
+ RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+ if (!reg_ctx_sp)
+ return return_valobj_sp;
+
+ if (return_clang_type.IsAggregateType())
+ {
+ unsigned eax_id = reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+ lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (storage_addr, nullptr),
+ return_clang_type);
+ }
+
+ return return_valobj_sp;
+}
+
+// This defines CFA as esp+4
+// The saved pc is at CFA-4 (i.e. esp+0)
+// The saved esp is CFA+0
+
+bool
+ABISysV_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t sp_reg_num = gcc_dwarf_esp;
+ uint32_t pc_reg_num = gcc_dwarf_eip;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("i386 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ return true;
+}
+
+// This defines CFA as ebp+8
+// The saved pc is at CFA-4 (i.e. ebp+4)
+// The saved ebp is at CFA-8 (i.e. ebp+0)
+// The saved esp is CFA+0
+
+bool
+ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t fp_reg_num = gcc_dwarf_ebp;
+ uint32_t sp_reg_num = gcc_dwarf_esp;
+ uint32_t pc_reg_num = gcc_dwarf_eip;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ const int32_t ptr_size = 4;
+
+ row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
+ row->SetOffset (0);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("i386 default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ return true;
+}
+
+
+// According to "Register Usage" in reference document (specified on top
+// of this source file) ebx, ebp, esi, edi and esp registers are preserved
+// i.e. non-volatile i.e. callee-saved on i386
+bool
+ABISysV_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (!reg_info)
+ return false;
+
+ // Saved registers are ebx, ebp, esi, edi, esp, eip
+ const char *name = reg_info->name;
+ if (name[0] == 'e')
+ {
+ switch (name[1])
+ {
+ case 'b':
+ if (name[2] == 'x' || name[2] == 'p')
+ return name[3] == '\0';
+ break;
+ case 'd':
+ if (name[2] == 'i')
+ return name[3] == '\0';
+ break;
+ case 'i':
+ if (name[2] == 'p')
+ return name[3] == '\0';
+ break;
+ case 's':
+ if (name[2] == 'i' || name[2] == 'p')
+ return name[3] == '\0';
+ break;
+ }
+ }
+
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
+ return true;
+ if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
+ return true;
+
+ return false;
+}
+
+
+void
+ABISysV_i386::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for i386 targets",
+ CreateInstance);
+}
+
+
+void
+ABISysV_i386::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_i386::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-i386");
+ return g_name;
+}
+
+
+lldb_private::ConstString
+ABISysV_i386::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
new file mode 100644
index 000000000000..9612f900d2ce
--- /dev/null
+++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
@@ -0,0 +1,138 @@
+//===------------------- ABISysV_i386.h -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABISysV_i386_h_
+#define liblldb_ABISysV_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_i386 :
+ public lldb_private::ABI
+{
+public:
+
+ ~ABISysV_i386()
+ {
+ }
+
+ size_t
+ GetRedZoneSize () const override
+ {
+ return 0; // There is no red zone for i386 Architecture
+ }
+
+ bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
+
+ bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
+
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
+
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const;
+
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+public:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &type) const override;
+
+ bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
+
+ bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
+
+ bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info) override
+ {
+ return !RegisterIsCalleeSaved (reg_info);
+ }
+
+ // The SysV i386 ABI requires that stack frames be 16 byte aligned.
+ // When there is a trap handler on the stack, e.g. _sigtramp in userland
+ // code, we've seen that the stack pointer is often not aligned properly
+ // before the handler is invoked. This means that lldb will stop the unwind
+ // early -- before the function which caused the trap.
+ //
+ // To work around this, we relax that alignment to be just word-size (4-bytes).
+ // Whitelisting the trap handlers for user space would be easy (_sigtramp) but
+ // in other environments there can be a large number of different functions
+ // involved in async traps.
+
+ // ToDo: When __m256 arguments are passed then stack frames should be
+ // 32 byte aligned. Decide what to do for 32 byte alignment checking
+ bool
+ CallFrameAddressIsValid (lldb::addr_t cfa) override
+ {
+ // Make sure the stack call frame addresses are 4 byte aligned
+ if (cfa & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+ if (cfa == 0)
+ return false; // Zero is not a valid stack address
+ return true;
+ }
+
+ bool
+ CodeAddressIsValid (lldb::addr_t pc) override
+ {
+ // Check whether the address is a valid 32 bit address
+ return (pc <= UINT32_MAX);
+ }
+
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count) override;
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+private:
+ ABISysV_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+#endif // liblldb_ABI_h
diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
new file mode 100644
index 000000000000..e1fc13a691af
--- /dev/null
+++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
@@ -0,0 +1,590 @@
+//===-- ABISysV_mips.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_mips.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_r0 = 0,
+ gcc_dwarf_r1,
+ gcc_dwarf_r2,
+ gcc_dwarf_r3,
+ gcc_dwarf_r4,
+ gcc_dwarf_r5,
+ gcc_dwarf_r6,
+ gcc_dwarf_r7,
+ gcc_dwarf_r8,
+ gcc_dwarf_r9,
+ gcc_dwarf_r10,
+ gcc_dwarf_r11,
+ gcc_dwarf_r12,
+ gcc_dwarf_r13,
+ gcc_dwarf_r14,
+ gcc_dwarf_r15,
+ gcc_dwarf_r16,
+ gcc_dwarf_r17,
+ gcc_dwarf_r18,
+ gcc_dwarf_r19,
+ gcc_dwarf_r20,
+ gcc_dwarf_r21,
+ gcc_dwarf_r22,
+ gcc_dwarf_r23,
+ gcc_dwarf_r24,
+ gcc_dwarf_r25,
+ gcc_dwarf_r26,
+ gcc_dwarf_r27,
+ gcc_dwarf_r28,
+ gcc_dwarf_r29,
+ gcc_dwarf_r30,
+ gcc_dwarf_r31,
+ gcc_dwarf_sr,
+ gcc_dwarf_lo,
+ gcc_dwarf_hi,
+ gcc_dwarf_bad,
+ gcc_dwarf_cause,
+ gcc_dwarf_pc
+};
+
+enum gdb_regnums
+{
+ gdb_r0 = 0,
+ gdb_r1,
+ gdb_r2,
+ gdb_r3,
+ gdb_r4,
+ gdb_r5,
+ gdb_r6,
+ gdb_r7,
+ gdb_r8,
+ gdb_r9,
+ gdb_r10,
+ gdb_r11,
+ gdb_r12,
+ gdb_r13,
+ gdb_r14,
+ gdb_r15,
+ gdb_r16,
+ gdb_r17,
+ gdb_r18,
+ gdb_r19,
+ gdb_r20,
+ gdb_r21,
+ gdb_r22,
+ gdb_r23,
+ gdb_r24,
+ gdb_r25,
+ gdb_r26,
+ gdb_r27,
+ gdb_r28,
+ gdb_r29,
+ gdb_r30,
+ gdb_r31,
+ gdb_sr,
+ gdb_lo,
+ gdb_hi,
+ gdb_bad,
+ gdb_cause,
+ gdb_pc
+};
+
+static const RegisterInfo
+g_register_infos[] =
+{
+ // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== ===============
+ { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_INVALID_REGNUM, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_INVALID_REGNUM, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_INVALID_REGNUM, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+
+const lldb_private::RegisterInfo *
+ABISysV_mips::GetRegisterInfoArray (uint32_t &count)
+{
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+size_t
+ABISysV_mips::GetRedZoneSize () const
+{
+ return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_mips::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
+ if ((arch_type == llvm::Triple::mips) ||
+ (arch_type == llvm::Triple::mipsel))
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_mips);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_mips::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+ thread.GetID(),
+ (uint64_t)sp,
+ (uint64_t)func_addr,
+ (uint64_t)return_addr);
+
+ for (size_t i = 0; i < args.size(); ++i)
+ s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ const RegisterInfo *reg_info = NULL;
+
+ RegisterValue reg_value;
+
+ // Argument registers
+ const char *reg_names[] = { "r4", "r5", "r6", "r7" };
+
+ llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
+
+ // Write arguments to registers
+ for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i)
+ {
+ if (ai == ae)
+ break;
+
+ reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+
+ ++ai;
+ }
+
+ // If we have more than 4 arguments --Spill onto the stack
+ if (ai != ae)
+ {
+ // No of arguments to go on stack
+ size_t num_stack_regs = args.size();
+
+ // Allocate needed space for args on the stack
+ sp -= (num_stack_regs * 4);
+
+ // Keep the stack 8 byte aligned
+ sp &= ~(8ull-1ull);
+
+ // just using arg1 to get the right size
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+
+ addr_t arg_pos = sp+16;
+
+ size_t i = 4;
+ for (; ai != ae; ++ai)
+ {
+ reg_value.SetUInt32(*ai);
+ if (log)
+ log->Printf("About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "", i+1, args[i], arg_pos);
+
+ if (reg_ctx->WriteRegisterValueToMemory(reg_info, arg_pos, reg_info->byte_size, reg_value).Fail())
+ return false;
+ arg_pos += reg_info->byte_size;
+ i++;
+ }
+ }
+
+ Error error;
+ const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+
+ if (log)
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
+
+ // Set "sp" to the requested value
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
+ return false;
+
+ if (log)
+ log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
+
+ // Set "ra" to the return address
+ if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_info, return_addr))
+ return false;
+
+ if (log)
+ log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
+
+ // Set pc to the address of the called function.
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
+ return false;
+
+ return true;
+}
+
+bool
+ABISysV_mips::GetArgumentValues (Thread &thread, ValueList &values) const
+{
+ return false;
+}
+
+Error
+ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType clang_type = new_value_sp->GetClangType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ {
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ if (num_bytes <= 4)
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, 4);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
+ {
+ const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value))
+ set_it_simple = true;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+ }
+ else if (clang_type.IsFloatingPointType (count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ error.SetErrorString ("We don't support returning float values at present");
+ }
+
+ if (!set_it_simple)
+ error.SetErrorString ("We only support setting simple integer return types at present.");
+
+ return error;
+}
+
+
+ValueObjectSP
+ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
+ return return_valobj_sp;
+
+ value.SetClangType(return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ bool is_signed;
+
+ // In MIPS register "r2" (v0) holds the integer function return values
+ const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+
+ if (return_clang_type.IsIntegerType (is_signed))
+ {
+ size_t bit_width = return_clang_type.GetBitSize(&thread);
+
+ switch (bit_width)
+ {
+ default:
+ return return_valobj_sp;
+ case 64:
+ {
+ const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+ uint64_t raw_value;
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
+ raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) & UINT32_MAX)) << 32;
+ if (is_signed)
+ value.GetScalar() = (int64_t)raw_value;
+ else
+ value.GetScalar() = (uint64_t)raw_value;
+ }
+ break;
+ case 32:
+ if (is_signed)
+ value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
+ break;
+ case 16:
+ if (is_signed)
+ value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
+ break;
+ case 8:
+ if (is_signed)
+ value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
+ break;
+ }
+ }
+ else if (return_clang_type.IsPointerType ())
+ {
+ uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
+ value.GetScalar() = ptr;
+ }
+ else
+ {
+ // not handled yet
+ return return_valobj_sp;
+ }
+
+ // If we get here, we have a valid Value, so make our ValueObject out of it:
+
+ return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ return return_valobj_sp;
+}
+
+bool
+ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+
+ // The previous PC is in the RA
+ row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("mips at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31);
+ return true;
+}
+
+bool
+ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+
+ row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("mips default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ return true;
+}
+
+bool
+ABISysV_mips::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return !RegisterIsCalleeSaved (reg_info);
+}
+
+bool
+ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Preserved registers are :
+ // r16-r23, r28, r29, r30, r31
+
+ int reg = ((reg_info->byte_offset) / 4);
+
+ bool save = (reg >= 16) && (reg <= 23);
+ save |= (reg >= 28) && (reg <= 31);
+
+ return save;
+ }
+ return false;
+}
+
+void
+ABISysV_mips::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for mips targets",
+ CreateInstance);
+}
+
+void
+ABISysV_mips::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_mips::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-mips");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_mips::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_mips::GetPluginVersion()
+{
+ return 1;
+}
diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
new file mode 100644
index 000000000000..ad47ac222932
--- /dev/null
+++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
@@ -0,0 +1,123 @@
+//===-- ABISysV_mips.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABISysV_mips_h_
+#define liblldb_ABISysV_mips_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_mips :
+ public lldb_private::ABI
+{
+public:
+
+ ~ABISysV_mips()
+ {
+ }
+
+ virtual size_t
+ GetRedZoneSize () const;
+
+ virtual bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const;
+
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const;
+
+public:
+ virtual lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &type) const;
+
+ virtual bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+
+ virtual bool
+ CallFrameAddressIsValid (lldb::addr_t cfa)
+ {
+ // Make sure the stack call frame addresses are 8 byte aligned
+ if (cfa & (8ull - 1ull))
+ return false; // Not 8 byte aligned
+ if (cfa == 0)
+ return false; // Zero is not a valid stack address
+ return true;
+ }
+
+ virtual bool
+ CodeAddressIsValid (lldb::addr_t pc)//must- check
+ {
+ if (pc & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+
+ // Anything else if fair game..
+ return true;
+ }
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count);
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+protected:
+ void
+ CreateRegisterMapIfNeeded ();
+
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+ ABISysV_mips() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+#endif // liblldb_ABI_h_
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
new file mode 100644
index 000000000000..c790fa7e7bdd
--- /dev/null
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
@@ -0,0 +1,570 @@
+//===-- ABISysV_mips64.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_mips64.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_r0 = 0,
+ gcc_dwarf_r1,
+ gcc_dwarf_r2,
+ gcc_dwarf_r3,
+ gcc_dwarf_r4,
+ gcc_dwarf_r5,
+ gcc_dwarf_r6,
+ gcc_dwarf_r7,
+ gcc_dwarf_r8,
+ gcc_dwarf_r9,
+ gcc_dwarf_r10,
+ gcc_dwarf_r11,
+ gcc_dwarf_r12,
+ gcc_dwarf_r13,
+ gcc_dwarf_r14,
+ gcc_dwarf_r15,
+ gcc_dwarf_r16,
+ gcc_dwarf_r17,
+ gcc_dwarf_r18,
+ gcc_dwarf_r19,
+ gcc_dwarf_r20,
+ gcc_dwarf_r21,
+ gcc_dwarf_r22,
+ gcc_dwarf_r23,
+ gcc_dwarf_r24,
+ gcc_dwarf_r25,
+ gcc_dwarf_r26,
+ gcc_dwarf_r27,
+ gcc_dwarf_r28,
+ gcc_dwarf_r29,
+ gcc_dwarf_r30,
+ gcc_dwarf_r31,
+ gcc_dwarf_sr,
+ gcc_dwarf_lo,
+ gcc_dwarf_hi,
+ gcc_dwarf_bad,
+ gcc_dwarf_cause,
+ gcc_dwarf_pc
+};
+
+enum gdb_regnums
+{
+ gdb_r0 = 0,
+ gdb_r1,
+ gdb_r2,
+ gdb_r3,
+ gdb_r4,
+ gdb_r5,
+ gdb_r6,
+ gdb_r7,
+ gdb_r8,
+ gdb_r9,
+ gdb_r10,
+ gdb_r11,
+ gdb_r12,
+ gdb_r13,
+ gdb_r14,
+ gdb_r15,
+ gdb_r16,
+ gdb_r17,
+ gdb_r18,
+ gdb_r19,
+ gdb_r20,
+ gdb_r21,
+ gdb_r22,
+ gdb_r23,
+ gdb_r24,
+ gdb_r25,
+ gdb_r26,
+ gdb_r27,
+ gdb_r28,
+ gdb_r29,
+ gdb_r30,
+ gdb_r31,
+ gdb_sr,
+ gdb_lo,
+ gdb_hi,
+ gdb_bad,
+ gdb_cause,
+ gdb_pc
+};
+
+static const RegisterInfo
+g_register_infos_mips64[] =
+{
+ // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== ===============
+ { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos_mips64);
+
+const lldb_private::RegisterInfo *
+ABISysV_mips64::GetRegisterInfoArray (uint32_t &count)
+{
+ count = k_num_register_infos;
+ return g_register_infos_mips64;
+}
+
+size_t
+ABISysV_mips64::GetRedZoneSize () const
+{
+ return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_mips64::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
+ if ((arch_type == llvm::Triple::mips64) ||
+ (arch_type == llvm::Triple::mips64el))
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_mips64);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_mips64::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+ thread.GetID(),
+ (uint64_t)sp,
+ (uint64_t)func_addr,
+ (uint64_t)return_addr);
+
+ for (size_t i = 0; i < args.size(); ++i)
+ s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ const RegisterInfo *reg_info = NULL;
+
+ if (args.size() > 8) // TODO handle more than 8 arguments
+ return false;
+
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+ }
+
+ // First, align the SP
+
+ if (log)
+ log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull));
+
+ sp &= ~(0xfull); // 16-byte alignment
+
+ Error error;
+ const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+
+ if (log)
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
+
+ // Set "sp" to the requested value
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
+ return false;
+
+ if (log)
+ log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
+
+ // Set "ra" to the return address
+ if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_info, return_addr))
+ return false;
+
+ if (log)
+ log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
+
+ // Set pc to the address of the called function.
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
+ return false;
+
+ return true;
+}
+
+bool
+ABISysV_mips64::GetArgumentValues (Thread &thread, ValueList &values) const
+{
+ return false;
+}
+
+Error
+ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType clang_type = new_value_sp->GetClangType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ if (!reg_ctx)
+ error.SetErrorString("no registers are available");
+
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ const uint32_t type_flags = clang_type.GetTypeInfo (NULL);
+
+ if (type_flags & eTypeIsScalar ||
+ type_flags & eTypeIsPointer)
+ {
+ if (type_flags & eTypeIsInteger ||
+ type_flags & eTypeIsPointer )
+ {
+ lldb::offset_t offset = 0;
+
+ if (num_bytes <= 16)
+ {
+ const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ if (num_bytes <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
+ error.SetErrorString ("failed to write register r2");
+ }
+ else
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, 8);
+ if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
+ {
+ const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+ raw_value = data.GetMaxU64(&offset, num_bytes - offset);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value))
+ error.SetErrorString ("failed to write register r3");
+ }
+ else
+ error.SetErrorString ("failed to write register r2");
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 128 bit integer values at present.");
+ }
+ }
+ else if (type_flags & eTypeIsFloat)
+ {
+ error.SetErrorString("TODO: Handle Float Types.");
+ }
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ error.SetErrorString("returning vector values are not supported");
+ }
+
+ return error;
+}
+
+
+ValueObjectSP
+ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
+ return return_valobj_sp;
+
+ value.SetClangType(return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+
+ if (type_flags & eTypeIsScalar)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & eTypeIsInteger)
+ {
+ // Extract the register context so we can read arguments from registers
+ // In MIPS register "r2" (v0) holds the integer function return values
+
+ uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+
+ case sizeof(uint64_t):
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+ else if (type_flags & eTypeIsPointer)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+ uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+ value.GetScalar() = (uint64_t)(raw_value);
+
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ // TODO: Handle vector types
+ }
+ return return_valobj_sp;
+}
+
+bool
+ABISysV_mips64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+
+ // The previous PC is in the RA
+ row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("mips64 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31);
+ return true;
+}
+
+bool
+ABISysV_mips64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+
+ row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("mips64 default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ return true;
+}
+
+bool
+ABISysV_mips64::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return !RegisterIsCalleeSaved (reg_info);
+}
+
+bool
+ABISysV_mips64::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Preserved registers are :
+ // r16-r23, r28, r29, r30, r31
+
+ int reg = ((reg_info->byte_offset) / 8);
+
+ bool save = (reg >= 16) && (reg <= 23);
+ save |= (reg >= 28) && (reg <= 31);
+
+ return save;
+ }
+ return false;
+}
+
+void
+ABISysV_mips64::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for mips64 targets",
+ CreateInstance);
+}
+
+void
+ABISysV_mips64::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_mips64::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-mips64");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_mips64::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_mips64::GetPluginVersion()
+{
+ return 1;
+}
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
new file mode 100644
index 000000000000..c37e717e0938
--- /dev/null
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
@@ -0,0 +1,133 @@
+//===-- ABISysV_mips64.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABISysV_mips64_h_
+#define liblldb_ABISysV_mips64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_mips64 :
+ public lldb_private::ABI
+{
+public:
+
+ ~ABISysV_mips64()
+ {
+ }
+
+ virtual size_t
+ GetRedZoneSize () const;
+
+ virtual bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const;
+
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &ast_type) const;
+
+public:
+ virtual lldb::ValueObjectSP
+ GetReturnValueObjectImpl (lldb_private::Thread &thread,
+ lldb_private::ClangASTType &type) const;
+
+ virtual bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+
+ // The SysV mips ABI requires that stack frames be 16 byte aligned.
+ // When there is a trap handler on the stack, e.g. _sigtramp in userland
+ // code, we've seen that the stack pointer is often not aligned properly
+ // before the handler is invoked. This means that lldb will stop the unwind
+ // early -- before the function which caused the trap.
+ //
+ // To work around this, we relax that alignment to be just word-size (8-bytes).
+ // Whitelisting the trap handlers for user space would be easy (_sigtramp) but
+ // in other environments there can be a large number of different functions
+ // involved in async traps.
+ virtual bool
+ CallFrameAddressIsValid (lldb::addr_t cfa)
+ {
+ // Make sure the stack call frame addresses are 8 byte aligned
+ if (cfa & (8ull - 1ull))
+ return false; // Not 8 byte aligned
+ if (cfa == 0)
+ return false; // Zero is not a valid stack address
+ return true;
+ }
+
+ virtual bool
+ CodeAddressIsValid (lldb::addr_t pc)
+ {
+ if (pc & (4ull - 1ull))
+ return false; // Not 4 byte aligned
+
+ // Anything else if fair game..
+ return true;
+ }
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfoArray (uint32_t &count);
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+protected:
+ void
+ CreateRegisterMapIfNeeded ();
+
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+ ABISysV_mips64() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+#endif // liblldb_ABI_h_
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
index 741afebfcb8b..08416dc25b08 100644
--- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -250,7 +250,7 @@ ABISysV_ppc::PrepareTrivialCall (Thread &thread,
(uint64_t)return_addr);
for (size_t i = 0; i < args.size(); ++i)
- s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.Printf (", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1), args[i]);
s.PutCString (")");
log->PutCString(s.GetString().c_str());
}
@@ -268,7 +268,7 @@ ABISysV_ppc::PrepareTrivialCall (Thread &thread,
{
reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
if (log)
- log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", static_cast<uint64_t>(i + 1), args[i], reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
return false;
}
@@ -390,7 +390,7 @@ static bool ReadIntegerArgument(Scalar &scalar,
bool
ABISysV_ppc::GetArgumentValues (Thread &thread,
- ValueList &values) const
+ ValueList &values) const
{
unsigned int num_values = values.GetSize();
unsigned int value_index;
@@ -444,7 +444,7 @@ ABISysV_ppc::GetArgumentValues (Thread &thread,
if (clang_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
@@ -454,7 +454,7 @@ ABISysV_ppc::GetArgumentValues (Thread &thread,
else if (clang_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -524,7 +524,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(nullptr);
+ size_t bit_width = clang_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
DataExtractor data;
@@ -740,7 +740,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(nullptr);
+ const size_t bit_width = return_clang_type.GetBitSize(&thread);
if (return_clang_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
@@ -782,7 +782,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
uint32_t count;
ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(nullptr);
+ const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
@@ -985,7 +985,7 @@ ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->SetCFARegister (sp_reg_num);
+ row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
// The previous PC is in the LR
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
@@ -1011,8 +1011,7 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
- row->SetCFARegister (sp_reg_num);
- row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
+ row->GetCFAValue().SetIsRegisterDereferenced (sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
index 88c18fb6f202..eb0d7c00070f 100644
--- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -250,7 +250,7 @@ ABISysV_ppc64::PrepareTrivialCall (Thread &thread,
(uint64_t)return_addr);
for (size_t i = 0; i < args.size(); ++i)
- s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.Printf (", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1), args[i]);
s.PutCString (")");
log->PutCString(s.GetString().c_str());
}
@@ -268,7 +268,7 @@ ABISysV_ppc64::PrepareTrivialCall (Thread &thread,
{
reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
if (log)
- log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", static_cast<uint64_t>(i + 1), args[i], reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
return false;
}
@@ -390,7 +390,7 @@ static bool ReadIntegerArgument(Scalar &scalar,
bool
ABISysV_ppc64::GetArgumentValues (Thread &thread,
- ValueList &values) const
+ ValueList &values) const
{
unsigned int num_values = values.GetSize();
unsigned int value_index;
@@ -444,7 +444,7 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread,
if (clang_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
@@ -454,7 +454,7 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread,
else if (clang_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -524,7 +524,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(nullptr);
+ size_t bit_width = clang_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
DataExtractor data;
@@ -740,7 +740,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(nullptr);
+ const size_t bit_width = return_clang_type.GetBitSize(&thread);
if (return_clang_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
@@ -782,7 +782,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
uint32_t count;
ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(nullptr);
+ const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
@@ -985,7 +985,7 @@ ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->SetCFARegister (sp_reg_num);
+ row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
// The previous PC is in the LR
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
@@ -1011,8 +1011,7 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->SetCFARegister (sp_reg_num);
- row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
+ row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index 71d99c8c65d2..1d63628466c2 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -318,7 +318,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
(uint64_t)return_addr);
for (size_t i = 0; i < args.size(); ++i)
- s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.Printf (", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1), args[i]);
s.PutCString (")");
log->PutCString(s.GetString().c_str());
}
@@ -336,7 +336,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
{
reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
if (log)
- log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", static_cast<uint64_t>(i + 1), args[i], reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
return false;
}
@@ -510,7 +510,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
if (clang_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
@@ -520,7 +520,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
else if (clang_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(nullptr),
+ clang_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -590,7 +590,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(nullptr);
+ size_t bit_width = clang_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
@@ -821,7 +821,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(nullptr);
+ const size_t bit_width = return_clang_type.GetBitSize(&thread);
if (return_clang_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
@@ -869,8 +869,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
uint32_t count;
ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(nullptr);
+ const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
+ // if we don't know the size of the field (e.g. invalid type), just bail out
+ if (field_bit_width == 0)
+ break;
+
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
{
@@ -1084,8 +1088,7 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
uint32_t pc_reg_num = gcc_dwarf_rip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
- row->SetCFARegister (sp_reg_num);
- row->SetCFAOffset (8);
+ row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow (row);
@@ -1112,8 +1115,7 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->SetCFARegister (gcc_dwarf_rbp);
- row->SetCFAOffset (2 * ptr_size);
+ row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_rbp, 2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index 2f9012222c02..75ee8aa4c580 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -415,7 +415,7 @@ protected:
-DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner):
+DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, unsigned flavor, DisassemblerLLVMC &owner):
m_is_valid(true)
{
std::string Error;
@@ -431,7 +431,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
std::string features_str;
- m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
+ m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, cpu,
features_str));
std::unique_ptr<llvm::MCRegisterInfo> reg_info(curr_target->createMCRegInfo(triple));
@@ -469,11 +469,11 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
asm_printer_variant = flavor;
}
- m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant,
+ m_instr_printer_ap.reset(curr_target->createMCInstPrinter(llvm::Triple{triple},
+ asm_printer_variant,
*m_asm_info_ap.get(),
*m_instr_info_ap.get(),
- *m_reg_info_ap.get(),
- *m_subtarget_info_ap.get()));
+ *m_reg_info_ap.get()));
if (m_instr_printer_ap.get() == NULL)
{
m_disasm_ap.reset();
@@ -518,7 +518,8 @@ DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
llvm::StringRef unused_annotations;
llvm::SmallString<64> inst_string;
llvm::raw_svector_ostream inst_stream(inst_string);
- m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations);
+ m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations,
+ *m_subtarget_info_ap);
inst_stream.flush();
const size_t output_size = std::min(dst_len - 1, inst_string.size());
std::memcpy(dst, inst_string.data(), output_size);
@@ -533,8 +534,8 @@ DisassemblerLLVMC::LLVMCDisassembler::SetStyle (bool use_hex_immed, HexImmediate
m_instr_printer_ap->setPrintImmHex(use_hex_immed);
switch(hex_style)
{
- case eHexStyleC: m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::C); break;
- case eHexStyleAsm: m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::Asm); break;
+ case eHexStyleC: m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::C); break;
+ case eHexStyleAsm: m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::Asm); break;
}
}
@@ -636,7 +637,45 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
triple = thumb_arch.GetTriple().getTriple().c_str();
}
- m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this));
+ const char *cpu = "";
+
+ switch (arch.GetCore())
+ {
+ case ArchSpec::eCore_mips32:
+ case ArchSpec::eCore_mips32el:
+ cpu = "mips32"; break;
+ case ArchSpec::eCore_mips32r2:
+ case ArchSpec::eCore_mips32r2el:
+ cpu = "mips32r2"; break;
+ case ArchSpec::eCore_mips32r3:
+ case ArchSpec::eCore_mips32r3el:
+ cpu = "mips32r3"; break;
+ case ArchSpec::eCore_mips32r5:
+ case ArchSpec::eCore_mips32r5el:
+ cpu = "mips32r5"; break;
+ case ArchSpec::eCore_mips32r6:
+ case ArchSpec::eCore_mips32r6el:
+ cpu = "mips32r6"; break;
+ case ArchSpec::eCore_mips64:
+ case ArchSpec::eCore_mips64el:
+ cpu = "mips64"; break;
+ case ArchSpec::eCore_mips64r2:
+ case ArchSpec::eCore_mips64r2el:
+ cpu = "mips64r2"; break;
+ case ArchSpec::eCore_mips64r3:
+ case ArchSpec::eCore_mips64r3el:
+ cpu = "mips64r3"; break;
+ case ArchSpec::eCore_mips64r5:
+ case ArchSpec::eCore_mips64r5el:
+ cpu = "mips64r5"; break;
+ case ArchSpec::eCore_mips64r6:
+ case ArchSpec::eCore_mips64r6el:
+ cpu = "mips64r6"; break;
+ default:
+ cpu = ""; break;
+ }
+
+ m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, flavor, *this));
if (!m_disasm_ap->IsValid())
{
// We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
@@ -648,7 +687,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
- m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this));
+ m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", flavor, *this));
if (!m_alternate_disasm_ap->IsValid())
{
m_disasm_ap.reset();
@@ -792,25 +831,63 @@ const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
//std::string remove_this_prior_to_checkin;
Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
Address value_so_addr;
+ Address pc_so_addr;
if (m_inst->UsingFileAddress())
{
ModuleSP module_sp(m_inst->GetAddress().GetModule());
if (module_sp)
+ {
module_sp->ResolveFileAddress(value, value_so_addr);
+ module_sp->ResolveFileAddress(pc, pc_so_addr);
+ }
}
else if (target && !target->GetSectionLoadList().IsEmpty())
{
target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
+ target->GetSectionLoadList().ResolveLoadAddress(pc, pc_so_addr);
+ }
+
+ SymbolContext sym_ctx;
+ const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
+ if (pc_so_addr.IsValid() && pc_so_addr.GetModule())
+ {
+ pc_so_addr.GetModule()->ResolveSymbolContextForAddress (pc_so_addr, resolve_scope, sym_ctx);
}
if (value_so_addr.IsValid() && value_so_addr.GetSection())
{
StreamString ss;
- value_so_addr.Dump (&ss,
- target,
- Address::DumpStyleResolvedDescriptionNoFunctionArguments,
- Address::DumpStyleSectionNameOffset);
+ bool format_omitting_current_func_name = false;
+ if (sym_ctx.symbol || sym_ctx.function)
+ {
+ AddressRange range;
+ if (sym_ctx.GetAddressRange (resolve_scope, 0, false, range)
+ && range.GetBaseAddress().IsValid()
+ && range.ContainsLoadAddress (value_so_addr, target))
+ {
+ format_omitting_current_func_name = true;
+ }
+ }
+
+ // If the "value" address (the target address we're symbolicating)
+ // is inside the same SymbolContext as the current instruction pc
+ // (pc_so_addr), don't print the full function name - just print it
+ // with DumpStyleNoFunctionName style, e.g. "<+36>".
+ if (format_omitting_current_func_name)
+ {
+ value_so_addr.Dump (&ss,
+ target,
+ Address::DumpStyleNoFunctionName,
+ Address::DumpStyleSectionNameOffset);
+ }
+ else
+ {
+ value_so_addr.Dump (&ss,
+ target,
+ Address::DumpStyleResolvedDescriptionNoFunctionArguments,
+ Address::DumpStyleSectionNameOffset);
+ }
if (!ss.GetString().empty())
{
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index 6ab9e9ae2625..4c32e25781d3 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -41,7 +41,7 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
class LLVMCDisassembler
{
public:
- LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner);
+ LLVMCDisassembler (const char *triple, const char *cpu, unsigned flavor, DisassemblerLLVMC &owner);
~LLVMCDisassembler();
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index c79d96abafa2..bbafcf73fa16 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -64,7 +64,7 @@ static lldb::addr_t findSymbolAddress( Process *proc, ConstString findName )
if ( ConstString::Compare( findName, symName ) == 0 )
{
- Address addr = sym->GetAddress( );
+ Address addr = sym->GetAddress();
return addr.GetLoadAddress( & proc->GetTarget() );
}
}
@@ -401,7 +401,7 @@ DynamicLoaderHexagonDYLD::RendezvousBreakpointHit(void *baton,
dyld_instance->m_rendezvous.SetRendezvousAddress( structAddr );
if ( log )
- log->Printf( "Found _rtld_debug structure @ 0x%08lx", structAddr );
+ log->Printf( "Found _rtld_debug structure @ 0x%08" PRIx64, structAddr );
}
else
{
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
index 5035e9d8bb17..61f9b3d441ce 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
@@ -15,6 +15,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index a504e801daac..8b1dd283394b 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -119,9 +120,10 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
if (exe_mod)
{
- exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+ m_exe_file_spec = exe_mod->GetPlatformFileSpec();
if (log)
- log->Printf ("DYLDRendezvous::%s exe module executable path set: '%s'", __FUNCTION__, m_exe_path);
+ log->Printf ("DYLDRendezvous::%s exe module executable path set: '%s'",
+ __FUNCTION__, m_exe_file_spec.GetCString());
}
else
{
@@ -146,7 +148,7 @@ DYLDRendezvous::Resolve()
address_size = m_process->GetAddressByteSize();
padding = address_size - word_size;
if (log)
- log->Printf ("DYLDRendezvous::%s address size: %zu, padding %zu", __FUNCTION__, address_size, padding);
+ log->Printf ("DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64, __FUNCTION__, uint64_t(address_size), uint64_t(padding));
if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
cursor = info_addr = ResolveRendezvousAddress(m_process);
@@ -205,7 +207,12 @@ DYLDRendezvous::UpdateSOEntries()
// state and take a snapshot of the currently loaded images.
if (m_current.state == eAdd || m_current.state == eDelete)
{
- assert(m_previous.state == eConsistent || (m_previous.state == eAdd && m_current.state == eDelete));
+ // Some versions of the android dynamic linker might send two
+ // notifications with state == eAdd back to back. Ignore them
+ // until we get an eConsistent notification.
+ if (!(m_previous.state == eConsistent || (m_previous.state == eAdd && m_current.state == eDelete)))
+ return false;
+
m_soentries.clear();
m_added_soentries.clear();
m_removed_soentries.clear();
@@ -280,8 +287,7 @@ bool
DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)
{
// On Linux the executable is indicated by an empty path in the entry. On
- // FreeBSD it is the full path to the executable. On Android, it is the
- // basename of the executable.
+ // FreeBSD and on Android it is the full path to the executable.
auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
auto os_type = triple.getOS();
@@ -289,10 +295,14 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)
switch (os_type) {
case llvm::Triple::FreeBSD:
- return ::strcmp(entry.path.c_str(), m_exe_path) == 0;
+ return entry.file_spec == m_exe_file_spec;
case llvm::Triple::Linux:
- return entry.path.empty() || (env_type == llvm::Triple::Android &&
- llvm::sys::path::filename(m_exe_path) == entry.path);
+ switch (env_type) {
+ case llvm::Triple::Android:
+ return entry.file_spec == m_exe_file_spec;
+ default:
+ return !entry.file_spec;
+ }
default:
return false;
}
@@ -306,6 +316,9 @@ DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
if (m_current.map_addr == 0)
return false;
+ // Clear previous entries since we are about to obtain an up to date list.
+ entry_list.clear();
+
for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
{
if (!ReadSOEntryFromMemory(cursor, entry))
@@ -373,10 +386,11 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
// FreeBSD and NetBSD (need to validate other OSes).
// http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
- if (arch.GetCore() == ArchSpec::eCore_mips64)
+ if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD
+ || arch.GetTriple().getOS() == llvm::Triple::NetBSD) &&
+ (arch.GetMachine() == llvm::Triple::mips || arch.GetMachine() == llvm::Triple::mipsel
+ || arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::mips64el))
{
- assert (arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
- arch.GetTriple().getOS() == llvm::Triple::NetBSD);
addr_t mips_l_offs;
if (!(addr = ReadPointer(addr, &mips_l_offs)))
return false;
@@ -395,9 +409,23 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
if (!(addr = ReadPointer(addr, &entry.prev)))
return false;
-
- entry.path = ReadStringFromMemory(entry.path_addr);
-
+
+ std::string file_path = ReadStringFromMemory(entry.path_addr);
+ entry.file_spec.SetFile(file_path, false);
+
+ // On Android L (5.0, 5.1) the load address of the "/system/bin/linker" isn't filled in
+ // correctly. To get the correct load address we fetch the load address of the file from the
+ // proc file system.
+ if (arch.GetTriple().getEnvironment() == llvm::Triple::Android && entry.base_addr == 0 &&
+ (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64"))
+ {
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+ bool is_loaded = false;
+ Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
+ if (error.Success() && is_loaded)
+ entry.base_addr = load_addr;
+ }
+
return true;
}
@@ -473,7 +501,7 @@ DYLDRendezvous::DumpToLog(Log *log) const
for (int i = 1; I != E; ++I, ++i)
{
- log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
+ log->Printf("\n SOEntry [%d] %s", i, I->file_spec.GetCString());
log->Printf(" Base : %" PRIx64, I->base_addr);
log->Printf(" Path : %" PRIx64, I->path_addr);
log->Printf(" Dyn : %" PRIx64, I->dyn_addr);
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 51fcd9b7d397..ec5af945ee7b 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -18,6 +18,7 @@
// Other libraries and framework includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
+#include "lldb/Host/FileSpec.h"
namespace lldb_private {
class Process;
@@ -142,18 +143,18 @@ public:
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
struct SOEntry {
- lldb::addr_t link_addr; ///< Address of this link_map.
- lldb::addr_t base_addr; ///< Base address of the loaded object.
- lldb::addr_t path_addr; ///< String naming the shared object.
- lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
- lldb::addr_t next; ///< Address of next so_entry.
- lldb::addr_t prev; ///< Address of previous so_entry.
- std::string path; ///< File name of shared object.
+ lldb::addr_t link_addr; ///< Address of this link_map.
+ lldb::addr_t base_addr; ///< Base address of the loaded object.
+ lldb::addr_t path_addr; ///< String naming the shared object.
+ lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
+ lldb::addr_t next; ///< Address of next so_entry.
+ lldb::addr_t prev; ///< Address of previous so_entry.
+ lldb_private::FileSpec file_spec; ///< File spec of shared object.
SOEntry() { clear(); }
bool operator ==(const SOEntry &entry) {
- return this->path == entry.path;
+ return file_spec == entry.file_spec;
}
void clear() {
@@ -163,7 +164,7 @@ public:
dyn_addr = 0;
next = 0;
prev = 0;
- path.clear();
+ file_spec.Clear();
}
};
@@ -190,8 +191,8 @@ public:
protected:
lldb_private::Process *m_process;
- // Cached copy of executable pathname
- char m_exe_path[PATH_MAX];
+ // Cached copy of executable file spec
+ lldb_private::FileSpec m_exe_file_spec;
/// Location of the r_debug structure in the inferiors address space.
lldb::addr_t m_rendezvous_addr;
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index fdef1026f3c6..6330b42ca14a 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
@@ -119,24 +120,41 @@ DynamicLoaderPOSIXDYLD::DidAttach()
if (log)
log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID);
- ModuleSP executable_sp = GetTargetExecutable();
- ModuleSpec process_module_spec;
- if (GetProcessModuleSpec(process_module_spec))
- {
- if (executable_sp == nullptr || !executable_sp->MatchesModuleSpec(process_module_spec))
- {
- executable_sp.reset(new Module(process_module_spec));
- assert(m_process != nullptr);
- m_process->GetTarget().SetExecutableModule(executable_sp, false);
- }
- }
+ // ask the process if it can load any of its own modules
+ m_process->LoadModules ();
+
+ ModuleSP executable_sp = GetTargetExecutable ();
+ ResolveExecutableModule (executable_sp);
- addr_t load_offset = ComputeLoadOffset();
+ // find the main process load offset
+ addr_t load_offset = ComputeLoadOffset ();
if (log)
log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "<null executable>", load_offset);
+ // if we dont have a load address we cant re-base
+ bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true;
+
+ // if we have a valid executable
+ if (executable_sp.get())
+ {
+ lldb_private::ObjectFile * obj = executable_sp->GetObjectFile();
+ if (obj)
+ {
+ // don't rebase if the module already has a load address
+ Target & target = m_process->GetTarget ();
+ Address addr = obj->GetImageInfoAddress (&target);
+ if (addr.GetLoadAddress (&target) != LLDB_INVALID_ADDRESS)
+ rebase_exec = false;
+ }
+ }
+ else
+ {
+ // no executable, nothing to re-base
+ rebase_exec = false;
+ }
- if (executable_sp && load_offset != LLDB_INVALID_ADDRESS)
+ // if the target executable should be re-based
+ if (rebase_exec)
{
ModuleList module_list;
@@ -396,8 +414,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
E = m_rendezvous.loaded_end();
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
- FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded(module_sp);
@@ -414,9 +431,8 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
E = m_rendezvous.unloaded_end();
for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
{
- FileSpec file(I->path.c_str(), true);
- ModuleSpec module_spec (file);
- ModuleSP module_sp =
+ ModuleSpec module_spec{I->file_spec};
+ ModuleSP module_sp =
loaded_modules.FindFirstModule (module_spec);
if (module_sp.get())
@@ -507,9 +523,7 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
{
- const char *module_path = I->path.c_str();
- FileSpec file(module_path, false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
if (module_sp.get())
{
module_list.Append(module_sp);
@@ -519,7 +533,7 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
log->Printf("DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64,
- __FUNCTION__, module_path, I->base_addr);
+ __FUNCTION__, I->file_spec.GetCString(), I->base_addr);
}
}
@@ -625,17 +639,45 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l
return tls_block;
}
-bool
-DynamicLoaderPOSIXDYLD::GetProcessModuleSpec (ModuleSpec& module_spec)
+void
+DynamicLoaderPOSIXDYLD::ResolveExecutableModule (lldb::ModuleSP &module_sp)
{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
if (m_process == nullptr)
- return false;
+ return;
+
+ auto &target = m_process->GetTarget ();
+ const auto platform_sp = target.GetPlatform ();
- auto& target = m_process->GetTarget ();
ProcessInstanceInfo process_info;
- if (!target.GetPlatform ()->GetProcessInfo (m_process->GetID (), process_info))
- return false;
+ if (!platform_sp->GetProcessInfo (m_process->GetID (), process_info))
+ {
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s - failed to get process info for pid %" PRIu64,
+ __FUNCTION__, m_process->GetID ());
+ return;
+ }
+
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s",
+ __FUNCTION__, m_process->GetID (), process_info.GetExecutableFile ().GetPath ().c_str ());
+
+ ModuleSpec module_spec (process_info.GetExecutableFile (), process_info.GetArchitecture ());
+ if (module_sp && module_sp->MatchesModuleSpec (module_spec))
+ return;
+
+ auto error = platform_sp->ResolveExecutable (module_spec, module_sp, nullptr);
+ if (error.Fail ())
+ {
+ StreamString stream;
+ module_spec.Dump (stream);
+
+ if (log)
+ log->Printf ("DynamicLoaderPOSIXDYLD::%s - failed to resolve executable with module spec \"%s\": %s",
+ __FUNCTION__, stream.GetString ().c_str (), error.AsCString ());
+ return;
+ }
- module_spec = ModuleSpec (process_info.GetExecutableFile (), process_info.GetArchitecture ());
- return true;
+ target.SetExecutableModule (module_sp, false);
}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 747ff3f2be36..68d3059cb4be 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -168,9 +168,9 @@ protected:
lldb::addr_t
GetEntryPoint();
- /// Loads ModuleSpec data from inferior process.
- bool
- GetProcessModuleSpec(lldb_private::ModuleSpec& module_spec);
+ /// Loads Module from inferior process.
+ void
+ ResolveExecutableModule(lldb::ModuleSP &module_sp);
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index bc358a985248..95ae549e0e4b 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -290,6 +290,9 @@ EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t re
uint32_t
EmulateInstructionARM::GetFramePointerRegisterNumber () const
{
+ if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android)
+ return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
+
bool is_apple = false;
if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
is_apple = true;
@@ -660,9 +663,12 @@ EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncodi
}
addr_t sp_offset = imm32;
addr_t addr = sp + sp_offset; // a pointer to the stack area
-
+
EmulateInstruction::Context context;
- context.type = eContextSetFramePointer;
+ if (Rd == GetFramePointerRegisterNumber())
+ context.type = eContextSetFramePointer;
+ else
+ context.type = EmulateInstruction::eContextRegisterPlusOffset;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
context.SetRegisterPlusOffset (sp_reg, sp_offset);
@@ -809,13 +815,16 @@ EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding
uint32_t result = ReadCoreReg(Rm, &success);
if (!success)
return false;
-
+
// The context specifies that Rm is to be moved into Rd.
EmulateInstruction::Context context;
- context.type = EmulateInstruction::eContextRegisterLoad;
+ if (Rd == 13)
+ context.type = EmulateInstruction::eContextAdjustStackPointer;
+ else
+ context.type = EmulateInstruction::eContextRegisterPlusOffset;
RegisterInfo dwarf_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
- context.SetRegister (dwarf_reg);
+ context.SetRegisterPlusOffset (dwarf_reg, 0);
if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
return false;
@@ -1333,53 +1342,86 @@ EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding
return false;
uint32_t imm32; // the immediate operand
uint32_t d;
- //bool setflags = false; // Add this back if/when support eEncodingT3 eEncodingA1
- switch (encoding)
+ bool setflags;
+ switch (encoding)
{
case eEncodingT1:
// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
d = Bits32 (opcode, 10, 8);
imm32 = (Bits32 (opcode, 7, 0) << 2);
-
+ setflags = false;
break;
-
+
case eEncodingT2:
// d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
d = 13;
- imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
-
+ imm32 = ThumbImm7Scaled (opcode); // imm32 = ZeroExtend(imm7:'00', 32)
+ setflags = false;
break;
-
+
+ case eEncodingT3:
+ // d = UInt(Rd); setflags = (S == "1"); imm32 = ThumbExpandImm(i:imm3:imm8);
+ d = Bits32 (opcode, 11, 8);
+ imm32 = ThumbExpandImm (opcode);
+ setflags = Bit32 (opcode, 20);
+
+ // if Rd == "1111" && S == "1" then SEE CMN (immediate);
+ if (d == 15 && setflags == 1)
+ return false; // CMN (immediate) not yet supported
+
+ // if d == 15 && S == "0" then UNPREDICTABLE;
+ if (d == 15 && setflags == 0)
+ return false;
+ break;
+
+ case eEncodingT4:
+ {
+ // if Rn == '1111' then SEE ADR;
+ // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
+ d = Bits32 (opcode, 11, 8);
+ setflags = false;
+ uint32_t i = Bit32 (opcode, 26);
+ uint32_t imm3 = Bits32 (opcode, 14, 12);
+ uint32_t imm8 = Bits32 (opcode, 7, 0);
+ imm32 = (i << 11) | (imm3 << 8) | imm8;
+
+ // if d == 15 then UNPREDICTABLE;
+ if (d == 15)
+ return false;
+ }
+ break;
+
default:
return false;
}
- addr_t sp_offset = imm32;
- addr_t addr = sp + sp_offset; // the adjusted stack pointer value
-
+ // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
+ AddWithCarryResult res = AddWithCarry (sp, imm32, 0);
+
EmulateInstruction::Context context;
- context.type = EmulateInstruction::eContextAdjustStackPointer;
+ if (d == 13)
+ context.type = EmulateInstruction::eContextAdjustStackPointer;
+ else
+ context.type = EmulateInstruction::eContextRegisterPlusOffset;
+
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
- context.SetRegisterPlusOffset (sp_reg, sp_offset);
-
+ context.SetRegisterPlusOffset (sp_reg, res.result - sp);
+
if (d == 15)
{
- if (!ALUWritePC (context, addr))
+ if (!ALUWritePC (context, res.result))
return false;
}
else
{
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
+ // R[d] = result;
+ // if setflags then
+ // APSR.N = result<31>;
+ // APSR.Z = IsZeroBit(result);
+ // APSR.C = carry;
+ // APSR.V = overflow;
+ if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
return false;
-
- // Add this back if/when support eEncodingT3 eEncodingA1
- //if (setflags)
- //{
- // APSR.N = result<31>;
- // APSR.Z = IsZeroBit(result);
- // APSR.C = carry;
- // APSR.V = overflow;
- //}
}
}
return true;
@@ -1496,6 +1538,7 @@ EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEnco
uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
imm32 = llvm::SignExtend32<25>(imm25);
target = pc + imm32;
+ SelectInstrSet (eModeThumb);
context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
if (InITBlock() && !LastInITBlock())
return false;
@@ -1514,6 +1557,7 @@ EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEnco
uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
imm32 = llvm::SignExtend32<25>(imm25);
target = Align(pc, 4) + imm32;
+ SelectInstrSet (eModeARM);
context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
if (InITBlock() && !LastInITBlock())
return false;
@@ -1523,12 +1567,14 @@ EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEnco
lr = pc - 4; // return address
imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
target = Align(pc, 4) + imm32;
+ SelectInstrSet (eModeARM);
context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
break;
case eEncodingA2:
lr = pc - 4; // return address
imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
target = pc + imm32;
+ SelectInstrSet (eModeThumb);
context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
break;
default:
@@ -1538,6 +1584,9 @@ EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEnco
return false;
if (!BranchWritePC(context, target))
return false;
+ if (m_opcode_cpsr != m_new_inst_cpsr)
+ if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
+ return false;
}
return true;
}
@@ -2301,13 +2350,16 @@ EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encodi
context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
break;
case eEncodingT2:
- imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
+ imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
target = pc + imm32;
context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
break;
case eEncodingT3:
// The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
{
+ if (Bits32(opcode, 25, 23) == 7)
+ return false; // See Branches and miscellaneous control on page A6-235.
+
uint32_t S = Bit32(opcode, 26);
uint32_t imm6 = Bits32(opcode, 21, 16);
uint32_t J1 = Bit32(opcode, 13);
@@ -2387,7 +2439,7 @@ EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encod
default:
return false;
}
- if (nonzero ^ (reg_val == 0))
+ if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
if (!BranchWritePC(context, target))
return false;
@@ -2417,55 +2469,58 @@ EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encod
bool success = false;
- uint32_t Rn; // the base register which contains the address of the table of branch lengths
- uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
- bool is_tbh; // true if table branch halfword
- switch (encoding) {
- case eEncodingT1:
- Rn = Bits32(opcode, 19, 16);
- Rm = Bits32(opcode, 3, 0);
- is_tbh = BitIsSet(opcode, 4);
- if (Rn == 13 || BadReg(Rm))
- return false;
- if (InITBlock() && !LastInITBlock())
+ if (ConditionPassed(opcode))
+ {
+ uint32_t Rn; // the base register which contains the address of the table of branch lengths
+ uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
+ bool is_tbh; // true if table branch halfword
+ switch (encoding) {
+ case eEncodingT1:
+ Rn = Bits32(opcode, 19, 16);
+ Rm = Bits32(opcode, 3, 0);
+ is_tbh = BitIsSet(opcode, 4);
+ if (Rn == 13 || BadReg(Rm))
+ return false;
+ if (InITBlock() && !LastInITBlock())
+ return false;
+ break;
+ default:
return false;
- break;
- default:
- return false;
- }
+ }
- // Read the address of the table from the operand register Rn.
- // The PC can be used, in which case the table immediately follows this instruction.
- uint32_t base = ReadCoreReg(Rm, &success);
- if (!success)
- return false;
+ // Read the address of the table from the operand register Rn.
+ // The PC can be used, in which case the table immediately follows this instruction.
+ uint32_t base = ReadCoreReg(Rn, &success);
+ if (!success)
+ return false;
- // the table index
- uint32_t index = ReadCoreReg(Rm, &success);
- if (!success)
- return false;
+ // the table index
+ uint32_t index = ReadCoreReg(Rm, &success);
+ if (!success)
+ return false;
- // the offsetted table address
- addr_t addr = base + (is_tbh ? index*2 : index);
+ // the offsetted table address
+ addr_t addr = base + (is_tbh ? index*2 : index);
- // PC-relative offset to branch forward
- EmulateInstruction::Context context;
- context.type = EmulateInstruction::eContextTableBranchReadMemory;
- uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
- if (!success)
- return false;
+ // PC-relative offset to branch forward
+ EmulateInstruction::Context context;
+ context.type = EmulateInstruction::eContextTableBranchReadMemory;
+ uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
+ if (!success)
+ return false;
- const uint32_t pc = ReadCoreReg(PC_REG, &success);
- if (!success)
- return false;
+ const uint32_t pc = ReadCoreReg(PC_REG, &success);
+ if (!success)
+ return false;
- // target address
- addr_t target = pc + offset;
- context.type = EmulateInstruction::eContextRelativeBranchImmediate;
- context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
+ // target address
+ addr_t target = pc + offset;
+ context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+ context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
- if (!BranchWritePC(context, target))
- return false;
+ if (!BranchWritePC(context, target))
+ return false;
+ }
return true;
}
@@ -2481,14 +2536,14 @@ EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncod
(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
R[d] = result;
if setflags then
- APSR.N = result<31>;
- APSR.Z = IsZeroBit(result);
- APSR.C = carry;
+ APSR.N = result<31>;
+ APSR.Z = IsZeroBit(result);
+ APSR.C = carry;
APSR.V = overflow;
#endif
-
+
bool success = false;
-
+
if (ConditionPassed(opcode))
{
uint32_t d;
@@ -2496,8 +2551,8 @@ EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncod
bool setflags;
uint32_t imm32;
uint32_t carry_out;
-
- //EncodingSpecificOperations();
+
+ //EncodingSpecificOperations();
switch (encoding)
{
case eEncodingT1:
@@ -2506,7 +2561,7 @@ EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncod
n = Bits32 (opcode, 5, 3);
setflags = !InITBlock();
imm32 = Bits32 (opcode, 8,6);
-
+
break;
case eEncodingT2:
@@ -2515,28 +2570,30 @@ EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncod
n = Bits32 (opcode, 10, 8);
setflags = !InITBlock();
imm32 = Bits32 (opcode, 7, 0);
-
+
break;
-
+
case eEncodingT3:
// if Rd == '1111' && S == '1' then SEE CMN (immediate);
- // if Rn == '1101' then SEE ADD (SP plus immediate);
// d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
d = Bits32 (opcode, 11, 8);
n = Bits32 (opcode, 19, 16);
setflags = BitIsSet (opcode, 20);
imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
-
+
+ // if Rn == '1101' then SEE ADD (SP plus immediate);
+ if (n == 13)
+ return EmulateADDSPImm(opcode, eEncodingT3);
+
// if BadReg(d) || n == 15 then UNPREDICTABLE;
if (BadReg (d) || (n == 15))
return false;
-
+
break;
-
+
case eEncodingT4:
{
// if Rn == '1111' then SEE ADR;
- // if Rn == '1101' then SEE ADD (SP plus immediate);
// d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
d = Bits32 (opcode, 11, 8);
n = Bits32 (opcode, 19, 16);
@@ -2545,31 +2602,36 @@ EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncod
uint32_t imm3 = Bits32 (opcode, 14, 12);
uint32_t imm8 = Bits32 (opcode, 7, 0);
imm32 = (i << 11) | (imm3 << 8) | imm8;
-
+
+ // if Rn == '1101' then SEE ADD (SP plus immediate);
+ if (n == 13)
+ return EmulateADDSPImm(opcode, eEncodingT4);
+
// if BadReg(d) then UNPREDICTABLE;
if (BadReg (d))
return false;
-
+
break;
- }
+ }
+
default:
return false;
}
-
+
uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
if (!success)
return false;
-
+
//(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
-
+
RegisterInfo reg_n;
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
-
+
EmulateInstruction::Context context;
context.type = eContextArithmetic;
context.SetRegisterPlusOffset (reg_n, imm32);
-
+
//R[d] = result;
//if setflags then
//APSR.N = result<31>;
@@ -2578,7 +2640,7 @@ EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncod
//APSR.V = overflow;
if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
return false;
-
+
}
return true;
}
@@ -2631,7 +2693,13 @@ EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncodin
AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
EmulateInstruction::Context context;
- context.type = eContextArithmetic;
+ if (Rd == 13)
+ context.type = EmulateInstruction::eContextAdjustStackPointer;
+ else if (Rd == GetFramePointerRegisterNumber())
+ context.type = EmulateInstruction::eContextSetFramePointer;
+ else
+ context.type = EmulateInstruction::eContextRegisterPlusOffset;
+
RegisterInfo dwarf_reg;
GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
context.SetRegisterPlusOffset (dwarf_reg, imm32);
@@ -2947,6 +3015,13 @@ EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding e
if (Rn == 15 || Rm == 15)
return false;
break;
+ case eEncodingT3:
+ Rn = Bits32(opcode, 19, 16);
+ Rm = Bits32(opcode, 3, 0);
+ shift_n = DecodeImmShiftThumb(opcode, shift_t);
+ if (Rn == 15 || BadReg(Rm))
+ return false;
+ break;
case eEncodingA1:
Rn = Bits32(opcode, 19, 16);
Rm = Bits32(opcode, 3, 0);
@@ -3995,8 +4070,22 @@ EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncodi
if (wback)
{
EmulateInstruction::Context ctx;
- ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
- ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
+ if (Rn == 13)
+ {
+ ctx.type = eContextAdjustStackPointer;
+ ctx.SetImmediateSigned((int32_t) (offset_addr - base));
+ }
+ else if (Rn == GetFramePointerRegisterNumber())
+ {
+ ctx.type = eContextSetFramePointer;
+ ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
+ }
+ else
+ {
+ ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
+ ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
+ }
+
if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
return false;
@@ -6195,8 +6284,6 @@ EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEnc
break;
case eEncodingT2:
- // if Rt == '1111' then SEE PLD;
- // if Rn == '1111' then SEE LDRB (literal);
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
@@ -6206,7 +6293,15 @@ EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEnc
index = true;
add = true;
wback = false;
-
+
+ // if Rt == '1111' then SEE PLD;
+ if (t == 15)
+ return false; // PLD is not implemented yet
+
+ // if Rn == '1111' then SEE LDRB (literal);
+ if (n == 15)
+ return EmulateLDRBLiteral(opcode, eEncodingT1);
+
// if t == 13 then UNPREDICTABLE;
if (t == 13)
return false;
@@ -6214,14 +6309,12 @@ EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEnc
break;
case eEncodingT3:
- // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
- // if Rn == '1111' then SEE LDRB (literal);
// if P == '1' && U == '1' && W == '0' then SEE LDRBT;
// if P == '0' && W == '0' then UNDEFINED;
if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
return false;
- // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
+ // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0);
@@ -6230,7 +6323,15 @@ EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEnc
index = BitIsSet (opcode, 10);
add = BitIsSet (opcode, 9);
wback = BitIsSet (opcode, 8);
-
+
+ // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
+ if (t == 15)
+ return false; // PLD is not implemented yet
+
+ // if Rn == '1111' then SEE LDRB (literal);
+ if (n == 15)
+ return EmulateLDRBLiteral(opcode, eEncodingT1);
+
// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
if (BadReg (t) || (wback && (n == t)))
return false;
@@ -6312,11 +6413,14 @@ EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncod
switch (encoding)
{
case eEncodingT1:
- // if Rt == '1111' then SEE PLD;
// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
t = Bits32 (opcode, 15, 12);
imm32 = Bits32 (opcode, 11, 0);
add = BitIsSet (opcode, 23);
+
+ // if Rt == '1111' then SEE PLD;
+ if (t == 15)
+ return false; // PLD is not implemented yet
// if t == 13 then UNPREDICTABLE;
if (t == 13)
@@ -6417,8 +6521,6 @@ EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEnco
break;
case eEncodingT2:
- // if Rt == '1111' then SEE PLD;
- // if Rn == '1111' then SEE LDRB (literal);
// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
@@ -6432,6 +6534,14 @@ EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEnco
// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
shift_t = SRType_LSL;
shift_n = Bits32 (opcode, 5, 4);
+
+ // if Rt == '1111' then SEE PLD;
+ if (t == 15)
+ return false; // PLD is not implemented yet
+
+ // if Rn == '1111' then SEE LDRB (literal);
+ if (n == 15)
+ return EmulateLDRBLiteral(opcode, eEncodingT1);
// if t == 13 || BadReg(m) then UNPREDICTABLE;
if ((t == 13) || BadReg (m))
@@ -9154,46 +9264,55 @@ EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncodin
bool success = false;
- uint32_t Rd; // the destination register
- uint32_t Rn; // the first operand
- bool setflags;
- uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
- switch (encoding) {
- case eEncodingA1:
- Rd = Bits32(opcode, 15, 12);
- Rn = Bits32(opcode, 19, 16);
- setflags = BitIsSet(opcode, 20);
- imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+ if (ConditionPassed(opcode))
+ {
+ uint32_t Rd; // the destination register
+ uint32_t Rn; // the first operand
+ bool setflags;
+ uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
+ switch (encoding) {
+ case eEncodingA1:
+ Rd = Bits32(opcode, 15, 12);
+ Rn = Bits32(opcode, 19, 16);
+ setflags = BitIsSet(opcode, 20);
+ imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
- // if Rn == '1111' && S == '0' then SEE ADR;
- if (Rn == 15 && !setflags)
- return EmulateADR (opcode, eEncodingA2);
+ // if Rn == '1111' && S == '0' then SEE ADR;
+ if (Rn == 15 && !setflags)
+ return EmulateADR (opcode, eEncodingA2);
- // if Rn == '1101' then SEE SUB (SP minus immediate);
- if (Rn == 13)
- return EmulateSUBSPImm (opcode, eEncodingA1);
+ // if Rn == '1101' then SEE SUB (SP minus immediate);
+ if (Rn == 13)
+ return EmulateSUBSPImm (opcode, eEncodingA1);
- // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
- if (Rd == 15 && setflags)
- return EmulateSUBSPcLrEtc (opcode, encoding);
- break;
- default:
- return false;
- }
- // Read the register value from the operand register Rn.
- uint32_t reg_val = ReadCoreReg(Rn, &success);
- if (!success)
- return false;
-
- AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
+ // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+ if (Rd == 15 && setflags)
+ return EmulateSUBSPcLrEtc (opcode, encoding);
+ break;
+ default:
+ return false;
+ }
+ // Read the register value from the operand register Rn.
+ uint32_t reg_val = ReadCoreReg(Rn, &success);
+ if (!success)
+ return false;
- EmulateInstruction::Context context;
- context.type = EmulateInstruction::eContextImmediate;
- context.SetNoArgs ();
+ AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
- return false;
+ EmulateInstruction::Context context;
+ if (Rd == 13)
+ context.type = EmulateInstruction::eContextAdjustStackPointer;
+ else
+ context.type = EmulateInstruction::eContextRegisterPlusOffset;
+
+ RegisterInfo dwarf_reg;
+ GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
+ int64_t imm32_signed = imm32;
+ context.SetRegisterPlusOffset (dwarf_reg, -imm32_signed);
+ if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+ return false;
+ }
return true;
}
@@ -9696,14 +9815,20 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e
break;
case eEncodingT2:
- // if Rd == 1111 && S == 1 then SEE CMP (register);
- // if Rn == 1101 then SEE SUB (SP minus register);
- // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == 1);
+ // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
d = Bits32 (opcode, 11, 8);
n = Bits32 (opcode, 19, 16);
m = Bits32 (opcode, 3, 0);
setflags = BitIsSet (opcode, 20);
+
+ // if Rd == "1111" && S == "1" then SEE CMP (register);
+ if (d == 15 && setflags == 1)
+ return EmulateCMPImm (opcode, eEncodingT3);
+ // if Rn == "1101" then SEE SUB (SP minus register);
+ if (n == 13)
+ return EmulateSUBSPReg (opcode, eEncodingT1);
+
// (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
shift_n = DecodeImmShiftThumb (opcode, shift_t);
@@ -12338,9 +12463,9 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32
//----------------------------------------------------------------------
// Branch instructions
//----------------------------------------------------------------------
- { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
- // To resolve ambiguity, "blx <label>" should come before "bl <label>".
+ // To resolve ambiguity, "blx <label>" should come before "b #imm24" and "bl <label>".
{ 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
+ { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
{ 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
{ 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
// for example, "bx lr"
@@ -12600,7 +12725,7 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint
{ 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
{ 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
// for example, "bx lr"
- { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
+ { 0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
// bxj
{ 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
// compare and branch
@@ -12710,6 +12835,7 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint
{ 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
// cmp (register) (Rn and Rm not both from r0-r7)
{ 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
+ { 0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
// asr (immediate)
{ 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
{ 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
@@ -13025,8 +13151,7 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio
// opcodes different meanings, but always means execution happens.
if (is_conditional)
*is_conditional = false;
- result = true;
- break;
+ return true;
}
if (cond & 1)
@@ -13052,8 +13177,8 @@ EmulateInstructionARM::CurrentCond (const uint32_t opcode)
const uint32_t byte_size = m_opcode.GetByteSize();
if (byte_size == 2)
{
- if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
- return Bits32(opcode, 11, 7);
+ if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
+ return Bits32(opcode, 11, 8);
}
else if (byte_size == 4)
{
@@ -13643,16 +13768,12 @@ EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our previous Call Frame Address is the stack pointer
- row->SetCFARegister (dwarf_sp);
-
- // Our previous PC is in the LR
- row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
- unwind_plan.AppendRow (row);
+ row->GetCFAValue().SetIsRegisterPlusOffset (dwarf_sp, 0);
- // All other registers are the same.
-
+ unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("EmulateInstructionARM");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister (dwarf_lr);
return true;
}
diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
index bad4118971e0..6072264f1efc 100644
--- a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
@@ -233,7 +233,7 @@ EmulationStateARM::WritePseudoMemory (EmulateInstruction *instruction,
bool success;
EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
- uint64_t value = *((uint64_t *) dst);
+ uint64_t value = *((const uint64_t *) dst);
success = pseudo_state->StoreToPseudoAddress (addr, value, length);
if (success)
return length;
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
index 3900af9b00d0..992df1fba59e 100644
--- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
@@ -183,10 +183,10 @@ EmulateInstructionARM64::SetTargetTriple (const ArchSpec &arch)
return true;
else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
return true;
-
+
return false;
}
-
+
bool
EmulateInstructionARM64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
{
@@ -236,23 +236,53 @@ EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode)
{ 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
{ 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
-
{ 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
{ 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
{ 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
{ 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
-
- { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
-
- { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
+
+ { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
+
+ { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B <label>" },
+ { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>" },
+ { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBZ <Wt>, <label>" },
+ { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBNZ <Wt>, <label>" },
+ { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBZ <R><t>, #<imm>, <label>" },
+ { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBNZ <R><t>, #<imm>, <label>" },
};
static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes);
@@ -262,10 +292,10 @@ EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode)
if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
return &g_opcodes[i];
}
- return NULL;
+ return nullptr;
}
-bool
+bool
EmulateInstructionARM64::ReadInstruction ()
{
bool success = false;
@@ -346,25 +376,139 @@ EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
UnwindPlan::RowSP row(new UnwindPlan::Row);
- const bool can_replace = false;
// Our previous Call Frame Address is the stack pointer
- row->SetCFARegister (arm64_dwarf::sp);
-
- // Our previous PC is in the LR
- row->SetRegisterLocationToRegister(arm64_dwarf::pc, arm64_dwarf::lr, can_replace);
+ row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, 0);
unwind_plan.AppendRow (row);
-
- // All other registers are the same.
-
unwind_plan.SetSourceName ("EmulateInstructionARM64");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister (arm64_dwarf::lr);
return true;
}
+uint32_t
+EmulateInstructionARM64::GetFramePointerRegisterNumber () const
+{
+ if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android)
+ return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
+ return arm64_dwarf::sp;
+}
+
+bool
+EmulateInstructionARM64::UsingAArch32()
+{
+ bool aarch32 = m_opcode_pstate.RW == 1;
+ // if !HaveAnyAArch32() then assert !aarch32;
+ // if HighestELUsingAArch32() then assert aarch32;
+ return aarch32;
+}
+
+bool
+EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t target)
+{
+#if 0
+ // Set program counter to a new address, with a branch reason hint
+ // for possible use by hardware fetching the next instruction.
+ BranchTo(bits(N) target, BranchType branch_type)
+ Hint_Branch(branch_type);
+ if N == 32 then
+ assert UsingAArch32();
+ _PC = ZeroExtend(target);
+ else
+ assert N == 64 && !UsingAArch32();
+ // Remove the tag bits from a tagged target
+ case PSTATE.EL of
+ when EL0, EL1
+ if target<55> == '1' && TCR_EL1.TBI1 == '1' then
+ target<63:56> = '11111111';
+ if target<55> == '0' && TCR_EL1.TBI0 == '1' then
+ target<63:56> = '00000000';
+ when EL2
+ if TCR_EL2.TBI == '1' then
+ target<63:56> = '00000000';
+ when EL3
+ if TCR_EL3.TBI == '1' then
+ target<63:56> = '00000000';
+ _PC = target<63:0>;
+ return;
+#endif
+
+ addr_t addr;
+
+ //Hint_Branch(branch_type);
+ if (N == 32)
+ {
+ if (!UsingAArch32())
+ return false;
+ addr = target;
+ }
+ else if (N == 64)
+ {
+ if (UsingAArch32())
+ return false;
+ // TODO: Remove the tag bits from a tagged target
+ addr = target;
+ }
+ else
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, addr))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_conditional)
+{
+ // If we are ignoring conditions, then always return true.
+ // this allows us to iterate over disassembly code and still
+ // emulate an instruction even if we don't have all the right
+ // bits set in the CPSR register...
+ if (m_ignore_conditions)
+ return true;
+
+ if (is_conditional)
+ *is_conditional = true;
+
+ bool result = false;
+ switch (UnsignedBits(cond, 3, 1))
+ {
+ case 0:
+ result = (m_opcode_pstate.Z == 1);
+ break;
+ case 1:
+ result = (m_opcode_pstate.C == 1);
+ break;
+ case 2:
+ result = (m_opcode_pstate.N == 1);
+ break;
+ case 3:
+ result = (m_opcode_pstate.V == 1);
+ break;
+ case 4:
+ result = (m_opcode_pstate.C == 1 && m_opcode_pstate.Z == 0);
+ break;
+ case 5:
+ result = (m_opcode_pstate.N == m_opcode_pstate.V);
+ break;
+ case 6:
+ result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0);
+ break;
+ case 7:
+ result = true;
+ if (is_conditional)
+ *is_conditional = false;
+ break;
+ }
+
+ if (cond & 1 && cond != 15)
+ result = !result;
+ return result;
+}
bool
EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
@@ -460,13 +604,13 @@ EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
if (arm64_dwarf::GetRegisterInfo (n, reg_info_Rn))
context.SetRegisterPlusOffset (reg_info_Rn, imm);
- if ((n == arm64_dwarf::sp || n == arm64_dwarf::fp) &&
+ if ((n == arm64_dwarf::sp || n == GetFramePointerRegisterNumber()) &&
d == arm64_dwarf::sp &&
!setflags)
{
context.type = EmulateInstruction::eContextAdjustStackPointer;
}
- else if (d == arm64_dwarf::fp &&
+ else if (d == GetFramePointerRegisterNumber() &&
n == arm64_dwarf::sp &&
!setflags)
{
@@ -476,8 +620,11 @@ EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
{
context.type = EmulateInstruction::eContextImmediate;
}
- WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x0 + d, result);
-
+
+ // If setflags && d == arm64_dwarf::sp then d = WZR/XZR. See CMN, CMP
+ if (!setflags || d != arm64_dwarf::sp)
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x0 + d, result);
+
return false;
}
@@ -487,7 +634,6 @@ EmulateInstructionARM64::Emulate_ldstpair_off (const uint32_t opcode)
return Emulate_ldstpair (opcode, AddrMode_OFF);
}
-
bool
EmulateInstructionARM64::Emulate_ldstpair_pre (const uint32_t opcode)
{
@@ -495,6 +641,12 @@ EmulateInstructionARM64::Emulate_ldstpair_pre (const uint32_t opcode)
}
bool
+EmulateInstructionARM64::Emulate_ldstpair_post (const uint32_t opcode)
+{
+ return Emulate_ldstpair (opcode, AddrMode_POST);
+}
+
+bool
EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode)
{
uint32_t opc = Bits32(opcode, 31, 30);
@@ -623,26 +775,24 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
Context context_t;
Context context_t2;
-
- if (n == 31 || n == 29) // if this store is based off of the sp or fp register
- {
- context_t.type = eContextPushRegisterOnStack;
- context_t2.type = eContextPushRegisterOnStack;
- }
- else
- {
- context_t.type = eContextRegisterPlusOffset;
- context_t2.type = eContextRegisterPlusOffset;
- }
+
+ context_t.type = eContextRegisterPlusOffset;
+ context_t2.type = eContextRegisterPlusOffset;
context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
Error error;
-
+
switch (memop)
{
case MemOp_STORE:
{
+ if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register
+ {
+ context_t.type = eContextPushRegisterOnStack;
+ context_t2.type = eContextPushRegisterOnStack;
+ }
+
if (!ReadRegister (&reg_info_Rt, data_Rt))
return false;
@@ -665,6 +815,12 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
case MemOp_LOAD:
{
+ if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is based off of the sp or fp register
+ {
+ context_t.type = eContextPopRegisterOffStack;
+ context_t2.type = eContextPopRegisterOffStack;
+ }
+
if (rt_unknown)
memset (buffer, 'U', reg_info_Rt.byte_size);
else
@@ -717,3 +873,152 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
}
return true;
}
+
+bool
+EmulateInstructionARM64::EmulateB (const uint32_t opcode)
+{
+#if 0
+ // ARM64 pseudo code...
+ if branch_type == BranchType_CALL then X[30] = PC[] + 4;
+ BranchTo(PC[] + offset, branch_type);
+#endif
+
+ bool success = false;
+
+ EmulateInstruction::Context context;
+ context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+ const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
+ if (!success)
+ return false;
+
+ int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2);
+ BranchType branch_type = Bit32(opcode, 31) ? BranchType_CALL : BranchType_JMP;
+ addr_t target = pc + offset;
+ context.SetImmediateSigned(offset);
+
+ switch (branch_type)
+ {
+ case BranchType_CALL:
+ {
+ addr_t x30 = pc + 4;
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x30, x30))
+ return false;
+ }
+ break;
+ case BranchType_JMP:
+ break;
+ default:
+ return false;
+ }
+
+ if (!BranchTo(context, 64, target))
+ return false;
+ return true;
+}
+
+bool
+EmulateInstructionARM64::EmulateBcond (const uint32_t opcode)
+{
+#if 0
+ // ARM64 pseudo code...
+ bits(64) offset = SignExtend(imm19:'00', 64);
+ bits(4) condition = cond;
+ if ConditionHolds(condition) then
+ BranchTo(PC[] + offset, BranchType_JMP);
+#endif
+
+ if (ConditionHolds(Bits32(opcode, 3, 0)))
+ {
+ bool success = false;
+
+ const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
+ if (!success)
+ return false;
+
+ int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);
+ addr_t target = pc + offset;
+
+ EmulateInstruction::Context context;
+ context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+ context.SetImmediateSigned(offset);
+ if (!BranchTo(context, 64, target))
+ return false;
+ }
+ return true;
+}
+
+bool
+EmulateInstructionARM64::EmulateCBZ (const uint32_t opcode)
+{
+#if 0
+ integer t = UInt(Rt);
+ integer datasize = if sf == '1' then 64 else 32;
+ boolean iszero = (op == '0');
+ bits(64) offset = SignExtend(imm19:'00', 64);
+
+ bits(datasize) operand1 = X[t];
+ if IsZero(operand1) == iszero then
+ BranchTo(PC[] + offset, BranchType_JMP);
+#endif
+
+ bool success = false;
+
+ uint32_t t = Bits32(opcode, 4, 0);
+ bool is_zero = Bit32(opcode, 24) == 0;
+ int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);
+
+ const uint64_t operand = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success);
+ if (!success)
+ return false;
+
+ if (m_ignore_conditions || ((operand == 0) == is_zero))
+ {
+ const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
+ if (!success)
+ return false;
+
+ EmulateInstruction::Context context;
+ context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+ context.SetImmediateSigned(offset);
+ if (!BranchTo(context, 64, pc + offset))
+ return false;
+ }
+ return true;
+}
+
+bool
+EmulateInstructionARM64::EmulateTBZ (const uint32_t opcode)
+{
+#if 0
+ integer t = UInt(Rt);
+ integer datasize = if b5 == '1' then 64 else 32;
+ integer bit_pos = UInt(b5:b40);
+ bit bit_val = op;
+ bits(64) offset = SignExtend(imm14:'00', 64);
+#endif
+
+ bool success = false;
+
+ uint32_t t = Bits32(opcode, 4, 0);
+ uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19));
+ uint32_t bit_val = Bit32(opcode, 24);
+ int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2);
+
+ const uint64_t operand = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success);
+ if (!success)
+ return false;
+
+ if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val)
+ {
+ const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
+ if (!success)
+ return false;
+
+ EmulateInstruction::Context context;
+ context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+ context.SetImmediateSigned(offset);
+ if (!BranchTo(context, 64, pc + offset))
+ return false;
+ }
+ return true;
+}
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
index 7e18d09a0ee2..b74eddeaaf63 100644
--- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
@@ -265,30 +265,45 @@ protected:
static Opcode*
GetOpcodeForInstruction (const uint32_t opcode);
+ uint32_t
+ GetFramePointerRegisterNumber() const;
+
+ bool
+ BranchTo (const Context &context, uint32_t N, lldb::addr_t target);
+
+ bool
+ ConditionHolds (const uint32_t cond, bool *is_conditional = nullptr);
+
+ bool
+ UsingAArch32 ();
+
bool
Emulate_addsub_imm (const uint32_t opcode);
-
-// bool
-// Emulate_STP_Q_ldstpair_off (const uint32_t opcode);
-//
-// bool
-// Emulate_STP_S_ldstpair_off (const uint32_t opcode);
-//
-// bool
-// Emulate_STP_32_ldstpair_off (const uint32_t opcode);
-//
-// bool
-// Emulate_STP_D_ldstpair_off (const uint32_t opcode);
-//
+
bool
Emulate_ldstpair_off (const uint32_t opcode);
bool
Emulate_ldstpair_pre (const uint32_t opcode);
-
+
+ bool
+ Emulate_ldstpair_post (const uint32_t opcode);
+
bool
Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode);
+ bool
+ EmulateB (const uint32_t opcode);
+
+ bool
+ EmulateBcond (const uint32_t opcode);
+
+ bool
+ EmulateCBZ (const uint32_t opcode);
+
+ bool
+ EmulateTBZ (const uint32_t opcode);
+
ProcState m_opcode_pstate;
ProcState m_emulated_pstate; // This can get updated by the opcode.
bool m_ignore_conditions;
diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
new file mode 100644
index 000000000000..1af25dc817c5
--- /dev/null
+++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -0,0 +1,2918 @@
+//===-- EmulateInstructionMIPS.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulateInstructionMIPS.h"
+
+#include <stdlib.h>
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Opcode.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/UnwindPlan.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+#include "Plugins/Process/Utility/RegisterContext_mips64.h" //mips32 has same registers nos as mips64
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define UInt(x) ((uint64_t)x)
+#define integer int64_t
+
+
+//----------------------------------------------------------------------
+//
+// EmulateInstructionMIPS implementation
+//
+//----------------------------------------------------------------------
+
+#ifdef __mips__
+extern "C" {
+ void LLVMInitializeMipsTargetInfo ();
+ void LLVMInitializeMipsTarget ();
+ void LLVMInitializeMipsAsmPrinter ();
+ void LLVMInitializeMipsTargetMC ();
+ void LLVMInitializeMipsDisassembler ();
+}
+#endif
+
+EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &arch) :
+ EmulateInstruction (arch)
+{
+ /* Create instance of llvm::MCDisassembler */
+ std::string Error;
+ llvm::Triple triple = arch.GetTriple();
+ const llvm::Target *target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error);
+
+ /*
+ * If we fail to get the target then we haven't registered it. The SystemInitializerCommon
+ * does not initialize targets, MCs and disassemblers. However we need the MCDisassembler
+ * to decode the instructions so that the decoding complexity stays with LLVM.
+ * Initialize the MIPS targets and disassemblers.
+ */
+#ifdef __mips__
+ if (!target)
+ {
+ LLVMInitializeMipsTargetInfo ();
+ LLVMInitializeMipsTarget ();
+ LLVMInitializeMipsAsmPrinter ();
+ LLVMInitializeMipsTargetMC ();
+ LLVMInitializeMipsDisassembler ();
+ target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error);
+ }
+#endif
+
+ assert (target);
+
+ llvm::StringRef cpu;
+
+ switch (arch.GetCore())
+ {
+ case ArchSpec::eCore_mips32:
+ case ArchSpec::eCore_mips32el:
+ cpu = "mips32"; break;
+ case ArchSpec::eCore_mips32r2:
+ case ArchSpec::eCore_mips32r2el:
+ cpu = "mips32r2"; break;
+ case ArchSpec::eCore_mips32r3:
+ case ArchSpec::eCore_mips32r3el:
+ cpu = "mips32r3"; break;
+ case ArchSpec::eCore_mips32r5:
+ case ArchSpec::eCore_mips32r5el:
+ cpu = "mips32r5"; break;
+ case ArchSpec::eCore_mips32r6:
+ case ArchSpec::eCore_mips32r6el:
+ cpu = "mips32r6"; break;
+ case ArchSpec::eCore_mips64:
+ case ArchSpec::eCore_mips64el:
+ cpu = "mips64"; break;
+ case ArchSpec::eCore_mips64r2:
+ case ArchSpec::eCore_mips64r2el:
+ cpu = "mips64r2"; break;
+ case ArchSpec::eCore_mips64r3:
+ case ArchSpec::eCore_mips64r3el:
+ cpu = "mips64r3"; break;
+ case ArchSpec::eCore_mips64r5:
+ case ArchSpec::eCore_mips64r5el:
+ cpu = "mips64r5"; break;
+ case ArchSpec::eCore_mips64r6:
+ case ArchSpec::eCore_mips64r6el:
+ cpu = "mips64r6"; break;
+ default:
+ cpu = "generic"; break;
+ }
+
+ m_reg_info.reset (target->createMCRegInfo (triple.getTriple()));
+ assert (m_reg_info.get());
+
+ m_insn_info.reset (target->createMCInstrInfo());
+ assert (m_insn_info.get());
+
+ m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple()));
+ m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, ""));
+ assert (m_asm_info.get() && m_subtype_info.get());
+
+ m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr));
+ assert (m_context.get());
+
+ m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context));
+ assert (m_disasm.get());
+}
+
+void
+EmulateInstructionMIPS::Initialize ()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic (),
+ GetPluginDescriptionStatic (),
+ CreateInstance);
+}
+
+void
+EmulateInstructionMIPS::Terminate ()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+ConstString
+EmulateInstructionMIPS::GetPluginNameStatic ()
+{
+ ConstString g_plugin_name ("lldb.emulate-instruction.mips32");
+ return g_plugin_name;
+}
+
+lldb_private::ConstString
+EmulateInstructionMIPS::GetPluginName()
+{
+ static ConstString g_plugin_name ("EmulateInstructionMIPS");
+ return g_plugin_name;
+}
+
+const char *
+EmulateInstructionMIPS::GetPluginDescriptionStatic ()
+{
+ return "Emulate instructions for the MIPS32 architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionMIPS::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
+{
+ if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
+ {
+ if (arch.GetTriple().getArch() == llvm::Triple::mips
+ || arch.GetTriple().getArch() == llvm::Triple::mipsel)
+ {
+ std::auto_ptr<EmulateInstructionMIPS> emulate_insn_ap (new EmulateInstructionMIPS (arch));
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionMIPS::SetTargetTriple (const ArchSpec &arch)
+{
+ if (arch.GetTriple().getArch () == llvm::Triple::mips
+ || arch.GetTriple().getArch () == llvm::Triple::mipsel)
+ return true;
+ return false;
+}
+
+const char *
+EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name)
+{
+ if (alternate_name)
+ {
+ switch (reg_num)
+ {
+ case gcc_dwarf_sp_mips: return "r29";
+ case gcc_dwarf_r30_mips: return "r30";
+ case gcc_dwarf_ra_mips: return "r31";
+ case gcc_dwarf_f0_mips: return "f0";
+ case gcc_dwarf_f1_mips: return "f1";
+ case gcc_dwarf_f2_mips: return "f2";
+ case gcc_dwarf_f3_mips: return "f3";
+ case gcc_dwarf_f4_mips: return "f4";
+ case gcc_dwarf_f5_mips: return "f5";
+ case gcc_dwarf_f6_mips: return "f6";
+ case gcc_dwarf_f7_mips: return "f7";
+ case gcc_dwarf_f8_mips: return "f8";
+ case gcc_dwarf_f9_mips: return "f9";
+ case gcc_dwarf_f10_mips: return "f10";
+ case gcc_dwarf_f11_mips: return "f11";
+ case gcc_dwarf_f12_mips: return "f12";
+ case gcc_dwarf_f13_mips: return "f13";
+ case gcc_dwarf_f14_mips: return "f14";
+ case gcc_dwarf_f15_mips: return "f15";
+ case gcc_dwarf_f16_mips: return "f16";
+ case gcc_dwarf_f17_mips: return "f17";
+ case gcc_dwarf_f18_mips: return "f18";
+ case gcc_dwarf_f19_mips: return "f19";
+ case gcc_dwarf_f20_mips: return "f20";
+ case gcc_dwarf_f21_mips: return "f21";
+ case gcc_dwarf_f22_mips: return "f22";
+ case gcc_dwarf_f23_mips: return "f23";
+ case gcc_dwarf_f24_mips: return "f24";
+ case gcc_dwarf_f25_mips: return "f25";
+ case gcc_dwarf_f26_mips: return "f26";
+ case gcc_dwarf_f27_mips: return "f27";
+ case gcc_dwarf_f28_mips: return "f28";
+ case gcc_dwarf_f29_mips: return "f29";
+ case gcc_dwarf_f30_mips: return "f30";
+ case gcc_dwarf_f31_mips: return "f31";
+ default:
+ break;
+ }
+ return nullptr;
+ }
+
+ switch (reg_num)
+ {
+ case gcc_dwarf_zero_mips: return "r0";
+ case gcc_dwarf_r1_mips: return "r1";
+ case gcc_dwarf_r2_mips: return "r2";
+ case gcc_dwarf_r3_mips: return "r3";
+ case gcc_dwarf_r4_mips: return "r4";
+ case gcc_dwarf_r5_mips: return "r5";
+ case gcc_dwarf_r6_mips: return "r6";
+ case gcc_dwarf_r7_mips: return "r7";
+ case gcc_dwarf_r8_mips: return "r8";
+ case gcc_dwarf_r9_mips: return "r9";
+ case gcc_dwarf_r10_mips: return "r10";
+ case gcc_dwarf_r11_mips: return "r11";
+ case gcc_dwarf_r12_mips: return "r12";
+ case gcc_dwarf_r13_mips: return "r13";
+ case gcc_dwarf_r14_mips: return "r14";
+ case gcc_dwarf_r15_mips: return "r15";
+ case gcc_dwarf_r16_mips: return "r16";
+ case gcc_dwarf_r17_mips: return "r17";
+ case gcc_dwarf_r18_mips: return "r18";
+ case gcc_dwarf_r19_mips: return "r19";
+ case gcc_dwarf_r20_mips: return "r20";
+ case gcc_dwarf_r21_mips: return "r21";
+ case gcc_dwarf_r22_mips: return "r22";
+ case gcc_dwarf_r23_mips: return "r23";
+ case gcc_dwarf_r24_mips: return "r24";
+ case gcc_dwarf_r25_mips: return "r25";
+ case gcc_dwarf_r26_mips: return "r26";
+ case gcc_dwarf_r27_mips: return "r27";
+ case gcc_dwarf_gp_mips: return "gp";
+ case gcc_dwarf_sp_mips: return "sp";
+ case gcc_dwarf_r30_mips: return "fp";
+ case gcc_dwarf_ra_mips: return "ra";
+ case gcc_dwarf_sr_mips: return "sr";
+ case gcc_dwarf_lo_mips: return "lo";
+ case gcc_dwarf_hi_mips: return "hi";
+ case gcc_dwarf_bad_mips: return "bad";
+ case gcc_dwarf_cause_mips: return "cause";
+ case gcc_dwarf_pc_mips: return "pc";
+ case gcc_dwarf_f0_mips: return "fp_reg[0]";
+ case gcc_dwarf_f1_mips: return "fp_reg[1]";
+ case gcc_dwarf_f2_mips: return "fp_reg[2]";
+ case gcc_dwarf_f3_mips: return "fp_reg[3]";
+ case gcc_dwarf_f4_mips: return "fp_reg[4]";
+ case gcc_dwarf_f5_mips: return "fp_reg[5]";
+ case gcc_dwarf_f6_mips: return "fp_reg[6]";
+ case gcc_dwarf_f7_mips: return "fp_reg[7]";
+ case gcc_dwarf_f8_mips: return "fp_reg[8]";
+ case gcc_dwarf_f9_mips: return "fp_reg[9]";
+ case gcc_dwarf_f10_mips: return "fp_reg[10]";
+ case gcc_dwarf_f11_mips: return "fp_reg[11]";
+ case gcc_dwarf_f12_mips: return "fp_reg[12]";
+ case gcc_dwarf_f13_mips: return "fp_reg[13]";
+ case gcc_dwarf_f14_mips: return "fp_reg[14]";
+ case gcc_dwarf_f15_mips: return "fp_reg[15]";
+ case gcc_dwarf_f16_mips: return "fp_reg[16]";
+ case gcc_dwarf_f17_mips: return "fp_reg[17]";
+ case gcc_dwarf_f18_mips: return "fp_reg[18]";
+ case gcc_dwarf_f19_mips: return "fp_reg[19]";
+ case gcc_dwarf_f20_mips: return "fp_reg[20]";
+ case gcc_dwarf_f21_mips: return "fp_reg[21]";
+ case gcc_dwarf_f22_mips: return "fp_reg[22]";
+ case gcc_dwarf_f23_mips: return "fp_reg[23]";
+ case gcc_dwarf_f24_mips: return "fp_reg[24]";
+ case gcc_dwarf_f25_mips: return "fp_reg[25]";
+ case gcc_dwarf_f26_mips: return "fp_reg[26]";
+ case gcc_dwarf_f27_mips: return "fp_reg[27]";
+ case gcc_dwarf_f28_mips: return "fp_reg[28]";
+ case gcc_dwarf_f29_mips: return "fp_reg[29]";
+ case gcc_dwarf_f30_mips: return "fp_reg[30]";
+ case gcc_dwarf_f31_mips: return "fp_reg[31]";
+ case gcc_dwarf_fcsr_mips: return "fcsr";
+ case gcc_dwarf_fir_mips: return "fir";
+ }
+ return nullptr;
+}
+
+bool
+EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
+{
+ if (reg_kind == eRegisterKindGeneric)
+ {
+ switch (reg_num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips; break;
+ case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips; break;
+ case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips; break;
+ case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips; break;
+ case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips; break;
+ default:
+ return false;
+ }
+ }
+
+ if (reg_kind == eRegisterKindDWARF)
+ {
+ ::memset (&reg_info, 0, sizeof(RegisterInfo));
+ ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
+
+ if (reg_num == gcc_dwarf_sr_mips || reg_num == gcc_dwarf_fcsr_mips || reg_num == gcc_dwarf_fir_mips)
+ {
+ reg_info.byte_size = 4;
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ }
+ else if ((int)reg_num >= gcc_dwarf_zero_mips && (int)reg_num <= gcc_dwarf_f31_mips)
+ {
+ reg_info.byte_size = 4;
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ }
+ else
+ {
+ return false;
+ }
+
+ reg_info.name = GetRegisterName (reg_num, false);
+ reg_info.alt_name = GetRegisterName (reg_num, true);
+ reg_info.kinds[eRegisterKindDWARF] = reg_num;
+
+ switch (reg_num)
+ {
+ case gcc_dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
+ case gcc_dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
+ case gcc_dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
+ case gcc_dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
+ case gcc_dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
+ default: break;
+ }
+ return true;
+ }
+ return false;
+}
+
+EmulateInstructionMIPS::MipsOpcode*
+EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
+{
+ static EmulateInstructionMIPS::MipsOpcode
+ g_opcodes[] =
+ {
+ //----------------------------------------------------------------------
+ // Prologue/Epilogue instructions
+ //----------------------------------------------------------------------
+ { "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt,rs,immediate" },
+ { "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt,offset(rs)" },
+ { "LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt,offset(base)" },
+
+ //----------------------------------------------------------------------
+ // Branch instructions
+ //----------------------------------------------------------------------
+ { "BEQ", &EmulateInstructionMIPS::Emulate_BEQ, "BEQ rs,rt,offset" },
+ { "BNE", &EmulateInstructionMIPS::Emulate_BNE, "BNE rs,rt,offset" },
+ { "BEQL", &EmulateInstructionMIPS::Emulate_BEQL, "BEQL rs,rt,offset" },
+ { "BNEL", &EmulateInstructionMIPS::Emulate_BNEL, "BNEL rs,rt,offset" },
+ { "BGEZALL", &EmulateInstructionMIPS::Emulate_BGEZALL, "BGEZALL rt,offset" },
+ { "BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset" },
+ { "BGEZAL", &EmulateInstructionMIPS::Emulate_BGEZAL, "BGEZAL rs,offset" },
+ { "BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset" },
+ { "BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset" },
+ { "BGEZ", &EmulateInstructionMIPS::Emulate_BGEZ, "BGEZ rs,offset" },
+ { "BLEZALC", &EmulateInstructionMIPS::Emulate_BLEZALC, "BLEZALC rs,offset" },
+ { "BGEZALC", &EmulateInstructionMIPS::Emulate_BGEZALC, "BGEZALC rs,offset" },
+ { "BLTZALC", &EmulateInstructionMIPS::Emulate_BLTZALC, "BLTZALC rs,offset" },
+ { "BGTZALC", &EmulateInstructionMIPS::Emulate_BGTZALC, "BGTZALC rs,offset" },
+ { "BEQZALC", &EmulateInstructionMIPS::Emulate_BEQZALC, "BEQZALC rs,offset" },
+ { "BNEZALC", &EmulateInstructionMIPS::Emulate_BNEZALC, "BNEZALC rs,offset" },
+ { "BEQC", &EmulateInstructionMIPS::Emulate_BEQC, "BEQC rs,rt,offset" },
+ { "BNEC", &EmulateInstructionMIPS::Emulate_BNEC, "BNEC rs,rt,offset" },
+ { "BLTC", &EmulateInstructionMIPS::Emulate_BLTC, "BLTC rs,rt,offset" },
+ { "BGEC", &EmulateInstructionMIPS::Emulate_BGEC, "BGEC rs,rt,offset" },
+ { "BLTUC", &EmulateInstructionMIPS::Emulate_BLTUC, "BLTUC rs,rt,offset" },
+ { "BGEUC", &EmulateInstructionMIPS::Emulate_BGEUC, "BGEUC rs,rt,offset" },
+ { "BLTZC", &EmulateInstructionMIPS::Emulate_BLTZC, "BLTZC rt,offset" },
+ { "BLEZC", &EmulateInstructionMIPS::Emulate_BLEZC, "BLEZC rt,offset" },
+ { "BGEZC", &EmulateInstructionMIPS::Emulate_BGEZC, "BGEZC rt,offset" },
+ { "BGTZC", &EmulateInstructionMIPS::Emulate_BGTZC, "BGTZC rt,offset" },
+ { "BEQZC", &EmulateInstructionMIPS::Emulate_BEQZC, "BEQZC rt,offset" },
+ { "BNEZC", &EmulateInstructionMIPS::Emulate_BNEZC, "BNEZC rt,offset" },
+ { "BGEZL", &EmulateInstructionMIPS::Emulate_BGEZL, "BGEZL rt,offset" },
+ { "BGTZ", &EmulateInstructionMIPS::Emulate_BGTZ, "BGTZ rt,offset" },
+ { "BGTZL", &EmulateInstructionMIPS::Emulate_BGTZL, "BGTZL rt,offset" },
+ { "BLEZ", &EmulateInstructionMIPS::Emulate_BLEZ, "BLEZ rt,offset" },
+ { "BLEZL", &EmulateInstructionMIPS::Emulate_BLEZL, "BLEZL rt,offset" },
+ { "BLTZ", &EmulateInstructionMIPS::Emulate_BLTZ, "BLTZ rt,offset" },
+ { "BLTZAL", &EmulateInstructionMIPS::Emulate_BLTZAL, "BLTZAL rt,offset" },
+ { "BLTZALL", &EmulateInstructionMIPS::Emulate_BLTZALL, "BLTZALL rt,offset" },
+ { "BLTZL", &EmulateInstructionMIPS::Emulate_BLTZL, "BLTZL rt,offset" },
+ { "BOVC", &EmulateInstructionMIPS::Emulate_BOVC, "BOVC rs,rt,offset" },
+ { "BNVC", &EmulateInstructionMIPS::Emulate_BNVC, "BNVC rs,rt,offset" },
+ { "J", &EmulateInstructionMIPS::Emulate_J, "J target" },
+ { "JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target" },
+ { "JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target" },
+ { "JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target" },
+ { "JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target" },
+ { "JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset" },
+ { "JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset" },
+ { "JR", &EmulateInstructionMIPS::Emulate_JR, "JR target" },
+ { "JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target" },
+ { "BC1F", &EmulateInstructionMIPS::Emulate_BC1F, "BC1F cc, offset" },
+ { "BC1T", &EmulateInstructionMIPS::Emulate_BC1T, "BC1T cc, offset" },
+ { "BC1FL", &EmulateInstructionMIPS::Emulate_BC1FL, "BC1FL cc, offset" },
+ { "BC1TL", &EmulateInstructionMIPS::Emulate_BC1TL, "BC1TL cc, offset" },
+ { "BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset" },
+ { "BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset" },
+ { "BC1ANY2F", &EmulateInstructionMIPS::Emulate_BC1ANY2F, "BC1ANY2F cc, offset" },
+ { "BC1ANY2T", &EmulateInstructionMIPS::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" },
+ { "BC1ANY4F", &EmulateInstructionMIPS::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" },
+ { "BC1ANY4T", &EmulateInstructionMIPS::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" },
+ };
+
+ static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
+
+ for (size_t i = 0; i < k_num_mips_opcodes; ++i)
+ {
+ if (! strcasecmp (g_opcodes[i].op_name, op_name))
+ return &g_opcodes[i];
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionMIPS::ReadInstruction ()
+{
+ bool success = false;
+ m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
+ if (success)
+ {
+ Context read_inst_context;
+ read_inst_context.type = eContextReadOpcode;
+ read_inst_context.SetNoArgs ();
+ m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder());
+ }
+ if (!success)
+ m_addr = LLDB_INVALID_ADDRESS;
+ return success;
+}
+
+bool
+EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
+{
+ bool success = false;
+ llvm::MCInst mc_insn;
+ uint64_t insn_size;
+ DataExtractor data;
+
+ /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */
+ if (m_opcode.GetData (data))
+ {
+ llvm::MCDisassembler::DecodeStatus decode_status;
+ llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize());
+ decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ if (decode_status != llvm::MCDisassembler::Success)
+ return false;
+ }
+
+ /*
+ * mc_insn.getOpcode() returns decoded opcode. However to make use
+ * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
+ */
+ const char *op_name = m_insn_info->getName (mc_insn.getOpcode ());
+
+ if (op_name == NULL)
+ return false;
+
+ /*
+ * Decoding has been done already. Just get the call-back function
+ * and emulate the instruction.
+ */
+ MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name);
+
+ if (opcode_data == NULL)
+ return false;
+
+ uint64_t old_pc = 0, new_pc = 0;
+ const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+
+ if (auto_advance_pc)
+ {
+ old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+ }
+
+ /* emulate instruction */
+ success = (this->*opcode_data->callback) (mc_insn);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc)
+ {
+ new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* If we haven't changed the PC, change it here */
+ if (old_pc == new_pc)
+ {
+ new_pc += 4;
+ Context context;
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, new_pc))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ const bool can_replace = false;
+
+ // Our previous Call Frame Address is the stack pointer
+ row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips, 0);
+
+ // Our previous PC is in the RA
+ row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips, gcc_dwarf_ra_mips, can_replace);
+
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+ unwind_plan.SetSourceName ("EmulateInstructionMIPS");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::nonvolatile_reg_p (uint32_t regnum)
+{
+ switch (regnum)
+ {
+ case gcc_dwarf_r16_mips:
+ case gcc_dwarf_r17_mips:
+ case gcc_dwarf_r18_mips:
+ case gcc_dwarf_r19_mips:
+ case gcc_dwarf_r20_mips:
+ case gcc_dwarf_r21_mips:
+ case gcc_dwarf_r22_mips:
+ case gcc_dwarf_r23_mips:
+ case gcc_dwarf_gp_mips:
+ case gcc_dwarf_sp_mips:
+ case gcc_dwarf_r30_mips:
+ case gcc_dwarf_ra_mips:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
+{
+ bool success = false;
+ const uint32_t imm16 = insn.getOperand(2).getImm();
+ uint32_t imm = SignedBits(imm16, 15, 0);
+ uint64_t result;
+ uint32_t src, dst;
+
+ dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ /* Check if this is addiu sp,<src>,imm16 */
+ if (dst == gcc_dwarf_sp_mips)
+ {
+ /* read <src> register */
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, 0, &success);
+ if (!success)
+ return false;
+
+ result = src_opd_val + imm;
+
+ Context context;
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm);
+
+ /* We are allocating bytes on stack */
+ context.type = eContextAdjustStackPointer;
+
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips, result);
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t imm16 = insn.getOperand(2).getImm();
+ uint32_t imm = SignedBits(imm16, 15, 0);
+ uint32_t src, base;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ /* We look for sp based non-volatile register stores */
+ if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src))
+ {
+ uint32_t address;
+ RegisterInfo reg_info_base;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, reg_info_base)
+ || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src))
+ return false;
+
+ /* read SP */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ Context context;
+ RegisterValue data_src;
+ context.type = eContextPushRegisterOnStack;
+ context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
+
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
+
+ if (!ReadRegister (&reg_info_base, data_src))
+ return false;
+
+ if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
+{
+ uint32_t src, base;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src))
+ {
+ RegisterValue data_src;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src))
+ return false;
+
+ Context context;
+ context.type = eContextRegisterLoad;
+
+ if (!WriteRegister (context, &reg_info_src, data_src))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BEQ rs, rt, offset
+ * condition <- (GPR[rs] = GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BNE rs, rt, offset
+ * condition <- (GPR[rs] != GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BEQL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BEQL rs, rt, offset
+ * condition <- (GPR[rs] = GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNEL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BNEL rs, rt, offset
+ * condition <- (GPR[rs] != GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGEZL rs, offset
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLTZL rs, offset
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGTZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGTZL rs, offset
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLEZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLEZL rs, offset
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGTZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGTZ rs, offset
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLEZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLEZ rs, offset
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLTZ rs, offset
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEZALL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGEZALL rt, offset
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ int32_t offset, pc, target;
+
+ /*
+ * BAL offset
+ * offset = sign_ext (offset << 2)
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ target = pc + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ int32_t offset, pc, target;
+
+ /*
+ * BALC offset
+ * offset = sign_ext (offset << 2)
+ * RA = PC + 4
+ * PC = PC + 4 + offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ target = pc + 4 + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEZAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGEZAL rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if ((int32_t) rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTZAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLTZAL rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if ((int32_t) rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTZALL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLTZALL rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ return false;
+
+ return true;
+}
+
+
+bool
+EmulateInstructionMIPS::Emulate_BLEZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLEZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGEZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLTZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGTZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGTZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BEQZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target, rs_val;
+
+ /*
+ * BEQZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] == 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val == 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNEZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target, rs_val;
+
+ /*
+ * BNEZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] != 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val != 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target, rs_val;
+
+ /*
+ * BGEZ rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn)
+{
+ bool success = false;
+ int32_t offset, pc, target;
+
+ /*
+ * BC offset
+ * offset = sign_ext (offset << 2)
+ * PC = PC + 4 + offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ target = pc + 4 + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BEQC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BEQC rs, rt, offset
+ * condition <- (GPR[rs] = GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNEC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BNEC rs, rt, offset
+ * condition <- (GPR[rs] != GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target;
+ int32_t rs_val, rt_val;
+
+ /*
+ * BLTC rs, rt, offset
+ * condition <- (GPR[rs] < GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target;
+ int32_t rs_val, rt_val;
+
+ /*
+ * BGEC rs, rt, offset
+ * condition <- (GPR[rs] > GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTUC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target;
+ uint32_t rs_val, rt_val;
+
+ /*
+ * BLTUC rs, rt, offset
+ * condition <- (GPR[rs] < GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEUC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target;
+ uint32_t rs_val, rt_val;
+
+ /*
+ * BGEUC rs, rt, offset
+ * condition <- (GPR[rs] > GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLTZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLTZC rs, offset
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BLEZC rs, offset
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val <= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGEZC rs, offset
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val >= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ int32_t rs_val;
+
+ /*
+ * BGTZC rs, offset
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ uint32_t rs_val;
+
+ /*
+ * BEQZC rs, offset
+ * condition <- (GPR[rs] = 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int32_t offset, pc, target;
+ uint32_t rs_val;
+
+ /*
+ * BNEZC rs, offset
+ * condition <- (GPR[rs] != 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+static int
+IsAdd64bitOverflow (int32_t a, int32_t b)
+{
+ int32_t r = (uint32_t) a + (uint32_t) b;
+ return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BOVC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target;
+ int32_t rs_val, rt_val;
+
+ /*
+ * BOVC rs, rt, offset
+ * condition <- overflow(GPR[rs] + GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int32_t offset, pc, target;
+ int32_t rs_val, rt_val;
+
+ /*
+ * BNVC rs, rt, offset
+ * condition <- overflow(GPR[rs] + GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (! IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t offset, pc;
+
+ /*
+ * J offset
+ * offset = sign_ext (offset << 2)
+ * PC = PC[63-28] | offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* This is a PC-region branch and not PC-relative */
+ pc = (pc & 0xF0000000UL) | offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, pc))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t offset, target, pc;
+
+ /*
+ * JAL offset
+ * offset = sign_ext (offset << 2)
+ * PC = PC[63-28] | offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* This is a PC-region branch and not PC-relative */
+ target = (pc & 0xF0000000UL) | offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_JALR (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ uint32_t pc, rs_val;
+
+ /*
+ * JALR rt, rs
+ * GPR[rt] = PC + 8
+ * PC = GPR[rs]
+ */
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rt;
+ int32_t target, offset, pc, rt_val;
+
+ /*
+ * JIALC rt, offset
+ * offset = sign_ext (offset)
+ * PC = GPR[rt] + offset
+ * RA = PC + 4
+ */
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ target = rt_val + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rt;
+ int32_t target, offset, rt_val;
+
+ /*
+ * JIC rt, offset
+ * offset = sign_ext (offset)
+ * PC = GPR[rt] + offset
+ */
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ if (!success)
+ return false;
+
+ target = rt_val + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ uint32_t rs_val;
+
+ /*
+ * JR rs
+ * PC = GPR[rs]
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1F cc, offset
+ * condition <- (FPConditionCode(cc) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) == 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1T cc, offset
+ * condition <- (FPConditionCode(cc) != 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1F cc, offset
+ * condition <- (FPConditionCode(cc) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) == 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1T cc, offset
+ * condition <- (FPConditionCode(cc) != 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t ft;
+ uint32_t ft_val;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1EQZ ft, offset
+ * condition <- (FPR[ft].bit0 == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + 4 + offset
+ */
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success);
+ if (!success)
+ return false;
+
+ if ((ft_val & 1) == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t ft;
+ uint32_t ft_val;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1NEZ ft, offset
+ * condition <- (FPR[ft].bit0 != 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + 4 + offset
+ */
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success);
+ if (!success)
+ return false;
+
+ if ((ft_val & 1) != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1ANY2F cc, offset
+ * condition <- (FPConditionCode(cc) == 0
+ * || FPConditionCode(cc+1) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 3) != 3)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1ANY2T cc, offset
+ * condition <- (FPConditionCode(cc) == 1
+ * || FPConditionCode(cc+1) == 1)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 3) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1ANY4F cc, offset
+ * condition <- (FPConditionCode(cc) == 0
+ * || FPConditionCode(cc+1) == 0)
+ * || FPConditionCode(cc+2) == 0)
+ * || FPConditionCode(cc+3) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 0xf) != 0xf)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int32_t target, pc, offset;
+
+ /*
+ * BC1ANY4T cc, offset
+ * condition <- (FPConditionCode(cc) == 1
+ * || FPConditionCode(cc+1) == 1)
+ * || FPConditionCode(cc+2) == 1)
+ * || FPConditionCode(cc+3) == 1)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 0xf) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
new file mode 100644
index 000000000000..25d8fc8891d5
--- /dev/null
+++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
@@ -0,0 +1,313 @@
+//===-- EmulateInstructionMIPS.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EmulateInstructionMIPS_h_
+#define EmulateInstructionMIPS_h_
+
+namespace llvm
+{
+ class MCDisassembler;
+ class MCSubtargetInfo;
+ class MCRegisterInfo;
+ class MCAsmInfo;
+ class MCContext;
+ class MCInstrInfo;
+ class MCInst;
+}
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+class EmulateInstructionMIPS : public lldb_private::EmulateInstruction
+{
+public:
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetPluginDescriptionStatic ();
+
+ static lldb_private::EmulateInstruction *
+ CreateInstance (const lldb_private::ArchSpec &arch,
+ lldb_private::InstructionType inst_type);
+
+ static bool
+ SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type)
+ {
+ switch (inst_type)
+ {
+ case lldb_private::eInstructionTypeAny:
+ case lldb_private::eInstructionTypePrologueEpilogue:
+ case lldb_private::eInstructionTypePCModifying:
+ return true;
+
+ case lldb_private::eInstructionTypeAll:
+ return false;
+ }
+ return false;
+ }
+
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual lldb_private::ConstString
+ GetShortPluginName()
+ {
+ return GetPluginNameStatic();
+ }
+
+ virtual uint32_t
+ GetPluginVersion()
+ {
+ return 1;
+ }
+
+ bool
+ SetTargetTriple (const lldb_private::ArchSpec &arch);
+
+ EmulateInstructionMIPS (const lldb_private::ArchSpec &arch);
+
+ virtual bool
+ SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ {
+ return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
+ }
+
+ virtual bool
+ ReadInstruction ();
+
+ virtual bool
+ EvaluateInstruction (uint32_t evaluate_options);
+
+ virtual bool
+ TestEmulation (lldb_private::Stream *out_stream,
+ lldb_private::ArchSpec &arch,
+ lldb_private::OptionValueDictionary *test_data)
+ {
+ return false;
+ }
+
+ virtual bool
+ GetRegisterInfo (lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ lldb_private::RegisterInfo &reg_info);
+
+ virtual bool
+ CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+
+
+protected:
+
+ typedef struct
+ {
+ const char *op_name;
+ bool (EmulateInstructionMIPS::*callback) (llvm::MCInst& insn);
+ const char *insn_name;
+ } MipsOpcode;
+
+ static MipsOpcode*
+ GetOpcodeForInstruction (const char *op_name);
+
+ bool
+ Emulate_ADDiu (llvm::MCInst& insn);
+
+ bool
+ Emulate_SW (llvm::MCInst& insn);
+
+ bool
+ Emulate_LW (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNE (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZALL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTUC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEUC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZALL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BOVC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNVC (llvm::MCInst& insn);
+
+ bool
+ Emulate_J (llvm::MCInst& insn);
+
+ bool
+ Emulate_JAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_JALR (llvm::MCInst& insn);
+
+ bool
+ Emulate_JIALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_JIC (llvm::MCInst& insn);
+
+ bool
+ Emulate_JR (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1F (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1T (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1FL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1TL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1EQZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1NEZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY2F (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY2T (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY4F (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY4T (llvm::MCInst& insn);
+
+ bool
+ nonvolatile_reg_p (uint32_t regnum);
+
+ const char *
+ GetRegisterName (unsigned reg_num, bool altnernate_name);
+
+private:
+ std::unique_ptr<llvm::MCDisassembler> m_disasm;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info;
+ std::unique_ptr<llvm::MCRegisterInfo> m_reg_info;
+ std::unique_ptr<llvm::MCAsmInfo> m_asm_info;
+ std::unique_ptr<llvm::MCContext> m_context;
+ std::unique_ptr<llvm::MCInstrInfo> m_insn_info;
+};
+
+#endif // EmulateInstructionMIPS_h_
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
new file mode 100644
index 000000000000..7abf687342c1
--- /dev/null
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -0,0 +1,2920 @@
+//===-- EmulateInstructionMIPS64.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulateInstructionMIPS64.h"
+
+#include <stdlib.h>
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Opcode.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/UnwindPlan.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+#include "Plugins/Process/Utility/RegisterContext_mips64.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define UInt(x) ((uint64_t)x)
+#define integer int64_t
+
+
+//----------------------------------------------------------------------
+//
+// EmulateInstructionMIPS64 implementation
+//
+//----------------------------------------------------------------------
+
+#ifdef __mips__
+extern "C" {
+ void LLVMInitializeMipsTargetInfo ();
+ void LLVMInitializeMipsTarget ();
+ void LLVMInitializeMipsAsmPrinter ();
+ void LLVMInitializeMipsTargetMC ();
+ void LLVMInitializeMipsDisassembler ();
+}
+#endif
+
+EmulateInstructionMIPS64::EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch) :
+ EmulateInstruction (arch)
+{
+ /* Create instance of llvm::MCDisassembler */
+ std::string Error;
+ llvm::Triple triple = arch.GetTriple();
+ const llvm::Target *target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error);
+
+ /*
+ * If we fail to get the target then we haven't registered it. The SystemInitializerCommon
+ * does not initialize targets, MCs and disassemblers. However we need the MCDisassembler
+ * to decode the instructions so that the decoding complexity stays with LLVM.
+ * Initialize the MIPS targets and disassemblers.
+ */
+#ifdef __mips__
+ if (!target)
+ {
+ LLVMInitializeMipsTargetInfo ();
+ LLVMInitializeMipsTarget ();
+ LLVMInitializeMipsAsmPrinter ();
+ LLVMInitializeMipsTargetMC ();
+ LLVMInitializeMipsDisassembler ();
+ target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error);
+ }
+#endif
+
+ assert (target);
+
+ llvm::StringRef cpu;
+
+ switch (arch.GetCore())
+ {
+ case ArchSpec::eCore_mips32:
+ case ArchSpec::eCore_mips32el:
+ cpu = "mips32"; break;
+ case ArchSpec::eCore_mips32r2:
+ case ArchSpec::eCore_mips32r2el:
+ cpu = "mips32r2"; break;
+ case ArchSpec::eCore_mips32r3:
+ case ArchSpec::eCore_mips32r3el:
+ cpu = "mips32r3"; break;
+ case ArchSpec::eCore_mips32r5:
+ case ArchSpec::eCore_mips32r5el:
+ cpu = "mips32r5"; break;
+ case ArchSpec::eCore_mips32r6:
+ case ArchSpec::eCore_mips32r6el:
+ cpu = "mips32r6"; break;
+ case ArchSpec::eCore_mips64:
+ case ArchSpec::eCore_mips64el:
+ cpu = "mips64"; break;
+ case ArchSpec::eCore_mips64r2:
+ case ArchSpec::eCore_mips64r2el:
+ cpu = "mips64r2"; break;
+ case ArchSpec::eCore_mips64r3:
+ case ArchSpec::eCore_mips64r3el:
+ cpu = "mips64r3"; break;
+ case ArchSpec::eCore_mips64r5:
+ case ArchSpec::eCore_mips64r5el:
+ cpu = "mips64r5"; break;
+ case ArchSpec::eCore_mips64r6:
+ case ArchSpec::eCore_mips64r6el:
+ cpu = "mips64r6"; break;
+ default:
+ cpu = "generic"; break;
+ }
+
+ m_reg_info.reset (target->createMCRegInfo (triple.getTriple()));
+ assert (m_reg_info.get());
+
+ m_insn_info.reset (target->createMCInstrInfo());
+ assert (m_insn_info.get());
+
+ m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple()));
+ m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, ""));
+ assert (m_asm_info.get() && m_subtype_info.get());
+
+ m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr));
+ assert (m_context.get());
+
+ m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context));
+ assert (m_disasm.get());
+}
+
+void
+EmulateInstructionMIPS64::Initialize ()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic (),
+ GetPluginDescriptionStatic (),
+ CreateInstance);
+}
+
+void
+EmulateInstructionMIPS64::Terminate ()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+ConstString
+EmulateInstructionMIPS64::GetPluginNameStatic ()
+{
+ ConstString g_plugin_name ("lldb.emulate-instruction.mips64");
+ return g_plugin_name;
+}
+
+lldb_private::ConstString
+EmulateInstructionMIPS64::GetPluginName()
+{
+ static ConstString g_plugin_name ("EmulateInstructionMIPS64");
+ return g_plugin_name;
+}
+
+const char *
+EmulateInstructionMIPS64::GetPluginDescriptionStatic ()
+{
+ return "Emulate instructions for the MIPS64 architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionMIPS64::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
+{
+ if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
+ {
+ if (arch.GetTriple().getArch() == llvm::Triple::mips64
+ || arch.GetTriple().getArch() == llvm::Triple::mips64el)
+ {
+ std::auto_ptr<EmulateInstructionMIPS64> emulate_insn_ap (new EmulateInstructionMIPS64 (arch));
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionMIPS64::SetTargetTriple (const ArchSpec &arch)
+{
+ if (arch.GetTriple().getArch () == llvm::Triple::mips64
+ || arch.GetTriple().getArch () == llvm::Triple::mips64el)
+ return true;
+ return false;
+}
+
+const char *
+EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name)
+{
+ if (alternate_name)
+ {
+ switch (reg_num)
+ {
+ case gcc_dwarf_sp_mips64: return "r29";
+ case gcc_dwarf_r30_mips64: return "r30";
+ case gcc_dwarf_ra_mips64: return "r31";
+ case gcc_dwarf_f0_mips64: return "f0";
+ case gcc_dwarf_f1_mips64: return "f1";
+ case gcc_dwarf_f2_mips64: return "f2";
+ case gcc_dwarf_f3_mips64: return "f3";
+ case gcc_dwarf_f4_mips64: return "f4";
+ case gcc_dwarf_f5_mips64: return "f5";
+ case gcc_dwarf_f6_mips64: return "f6";
+ case gcc_dwarf_f7_mips64: return "f7";
+ case gcc_dwarf_f8_mips64: return "f8";
+ case gcc_dwarf_f9_mips64: return "f9";
+ case gcc_dwarf_f10_mips64: return "f10";
+ case gcc_dwarf_f11_mips64: return "f11";
+ case gcc_dwarf_f12_mips64: return "f12";
+ case gcc_dwarf_f13_mips64: return "f13";
+ case gcc_dwarf_f14_mips64: return "f14";
+ case gcc_dwarf_f15_mips64: return "f15";
+ case gcc_dwarf_f16_mips64: return "f16";
+ case gcc_dwarf_f17_mips64: return "f17";
+ case gcc_dwarf_f18_mips64: return "f18";
+ case gcc_dwarf_f19_mips64: return "f19";
+ case gcc_dwarf_f20_mips64: return "f20";
+ case gcc_dwarf_f21_mips64: return "f21";
+ case gcc_dwarf_f22_mips64: return "f22";
+ case gcc_dwarf_f23_mips64: return "f23";
+ case gcc_dwarf_f24_mips64: return "f24";
+ case gcc_dwarf_f25_mips64: return "f25";
+ case gcc_dwarf_f26_mips64: return "f26";
+ case gcc_dwarf_f27_mips64: return "f27";
+ case gcc_dwarf_f28_mips64: return "f28";
+ case gcc_dwarf_f29_mips64: return "f29";
+ case gcc_dwarf_f30_mips64: return "f30";
+ case gcc_dwarf_f31_mips64: return "f31";
+ default:
+ break;
+ }
+ return nullptr;
+ }
+
+ switch (reg_num)
+ {
+ case gcc_dwarf_zero_mips64: return "r0";
+ case gcc_dwarf_r1_mips64: return "r1";
+ case gcc_dwarf_r2_mips64: return "r2";
+ case gcc_dwarf_r3_mips64: return "r3";
+ case gcc_dwarf_r4_mips64: return "r4";
+ case gcc_dwarf_r5_mips64: return "r5";
+ case gcc_dwarf_r6_mips64: return "r6";
+ case gcc_dwarf_r7_mips64: return "r7";
+ case gcc_dwarf_r8_mips64: return "r8";
+ case gcc_dwarf_r9_mips64: return "r9";
+ case gcc_dwarf_r10_mips64: return "r10";
+ case gcc_dwarf_r11_mips64: return "r11";
+ case gcc_dwarf_r12_mips64: return "r12";
+ case gcc_dwarf_r13_mips64: return "r13";
+ case gcc_dwarf_r14_mips64: return "r14";
+ case gcc_dwarf_r15_mips64: return "r15";
+ case gcc_dwarf_r16_mips64: return "r16";
+ case gcc_dwarf_r17_mips64: return "r17";
+ case gcc_dwarf_r18_mips64: return "r18";
+ case gcc_dwarf_r19_mips64: return "r19";
+ case gcc_dwarf_r20_mips64: return "r20";
+ case gcc_dwarf_r21_mips64: return "r21";
+ case gcc_dwarf_r22_mips64: return "r22";
+ case gcc_dwarf_r23_mips64: return "r23";
+ case gcc_dwarf_r24_mips64: return "r24";
+ case gcc_dwarf_r25_mips64: return "r25";
+ case gcc_dwarf_r26_mips64: return "r26";
+ case gcc_dwarf_r27_mips64: return "r27";
+ case gcc_dwarf_gp_mips64: return "gp";
+ case gcc_dwarf_sp_mips64: return "sp";
+ case gcc_dwarf_r30_mips64: return "fp";
+ case gcc_dwarf_ra_mips64: return "ra";
+ case gcc_dwarf_sr_mips64: return "sr";
+ case gcc_dwarf_lo_mips64: return "lo";
+ case gcc_dwarf_hi_mips64: return "hi";
+ case gcc_dwarf_bad_mips64: return "bad";
+ case gcc_dwarf_cause_mips64: return "cause";
+ case gcc_dwarf_pc_mips64: return "pc";
+ case gcc_dwarf_f0_mips64: return "fp_reg[0]";
+ case gcc_dwarf_f1_mips64: return "fp_reg[1]";
+ case gcc_dwarf_f2_mips64: return "fp_reg[2]";
+ case gcc_dwarf_f3_mips64: return "fp_reg[3]";
+ case gcc_dwarf_f4_mips64: return "fp_reg[4]";
+ case gcc_dwarf_f5_mips64: return "fp_reg[5]";
+ case gcc_dwarf_f6_mips64: return "fp_reg[6]";
+ case gcc_dwarf_f7_mips64: return "fp_reg[7]";
+ case gcc_dwarf_f8_mips64: return "fp_reg[8]";
+ case gcc_dwarf_f9_mips64: return "fp_reg[9]";
+ case gcc_dwarf_f10_mips64: return "fp_reg[10]";
+ case gcc_dwarf_f11_mips64: return "fp_reg[11]";
+ case gcc_dwarf_f12_mips64: return "fp_reg[12]";
+ case gcc_dwarf_f13_mips64: return "fp_reg[13]";
+ case gcc_dwarf_f14_mips64: return "fp_reg[14]";
+ case gcc_dwarf_f15_mips64: return "fp_reg[15]";
+ case gcc_dwarf_f16_mips64: return "fp_reg[16]";
+ case gcc_dwarf_f17_mips64: return "fp_reg[17]";
+ case gcc_dwarf_f18_mips64: return "fp_reg[18]";
+ case gcc_dwarf_f19_mips64: return "fp_reg[19]";
+ case gcc_dwarf_f20_mips64: return "fp_reg[20]";
+ case gcc_dwarf_f21_mips64: return "fp_reg[21]";
+ case gcc_dwarf_f22_mips64: return "fp_reg[22]";
+ case gcc_dwarf_f23_mips64: return "fp_reg[23]";
+ case gcc_dwarf_f24_mips64: return "fp_reg[24]";
+ case gcc_dwarf_f25_mips64: return "fp_reg[25]";
+ case gcc_dwarf_f26_mips64: return "fp_reg[26]";
+ case gcc_dwarf_f27_mips64: return "fp_reg[27]";
+ case gcc_dwarf_f28_mips64: return "fp_reg[28]";
+ case gcc_dwarf_f29_mips64: return "fp_reg[29]";
+ case gcc_dwarf_f30_mips64: return "fp_reg[30]";
+ case gcc_dwarf_f31_mips64: return "fp_reg[31]";
+ case gcc_dwarf_fcsr_mips64: return "fcsr";
+ case gcc_dwarf_fir_mips64: return "fir";
+ }
+ return nullptr;
+}
+
+bool
+EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
+{
+ if (reg_kind == eRegisterKindGeneric)
+ {
+ switch (reg_num)
+ {
+ case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips64; break;
+ case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips64; break;
+ case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips64; break;
+ case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips64; break;
+ case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips64; break;
+ default:
+ return false;
+ }
+ }
+
+ if (reg_kind == eRegisterKindDWARF)
+ {
+ ::memset (&reg_info, 0, sizeof(RegisterInfo));
+ ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
+
+ if (reg_num == gcc_dwarf_sr_mips64 || reg_num == gcc_dwarf_fcsr_mips64 || reg_num == gcc_dwarf_fir_mips64)
+ {
+ reg_info.byte_size = 4;
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ }
+ else if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_f31_mips64)
+ {
+ reg_info.byte_size = 8;
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ }
+ else
+ {
+ return false;
+ }
+
+ reg_info.name = GetRegisterName (reg_num, false);
+ reg_info.alt_name = GetRegisterName (reg_num, true);
+ reg_info.kinds[eRegisterKindDWARF] = reg_num;
+
+ switch (reg_num)
+ {
+ case gcc_dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
+ case gcc_dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
+ case gcc_dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
+ case gcc_dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
+ case gcc_dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
+ default: break;
+ }
+ return true;
+ }
+ return false;
+}
+
+EmulateInstructionMIPS64::MipsOpcode*
+EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)
+{
+ static EmulateInstructionMIPS64::MipsOpcode
+ g_opcodes[] =
+ {
+ //----------------------------------------------------------------------
+ // Prologue/Epilogue instructions
+ //----------------------------------------------------------------------
+ { "DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "DADDIU rt,rs,immediate" },
+ { "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt,offset(rs)" },
+ { "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt,offset(base)" },
+
+ //----------------------------------------------------------------------
+ // Branch instructions
+ //----------------------------------------------------------------------
+ { "BEQ", &EmulateInstructionMIPS64::Emulate_BEQ, "BEQ rs,rt,offset" },
+ { "BNE", &EmulateInstructionMIPS64::Emulate_BNE, "BNE rs,rt,offset" },
+ { "BEQL", &EmulateInstructionMIPS64::Emulate_BEQL, "BEQL rs,rt,offset" },
+ { "BNEL", &EmulateInstructionMIPS64::Emulate_BNEL, "BNEL rs,rt,offset" },
+ { "BGEZALL", &EmulateInstructionMIPS64::Emulate_BGEZALL, "BGEZALL rt,offset" },
+ { "BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset" },
+ { "BGEZAL", &EmulateInstructionMIPS64::Emulate_BGEZAL, "BGEZAL rs,offset" },
+ { "BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset" },
+ { "BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset" },
+ { "BGEZ", &EmulateInstructionMIPS64::Emulate_BGEZ, "BGEZ rs,offset" },
+ { "BLEZALC", &EmulateInstructionMIPS64::Emulate_BLEZALC, "BLEZALC rs,offset" },
+ { "BGEZALC", &EmulateInstructionMIPS64::Emulate_BGEZALC, "BGEZALC rs,offset" },
+ { "BLTZALC", &EmulateInstructionMIPS64::Emulate_BLTZALC, "BLTZALC rs,offset" },
+ { "BGTZALC", &EmulateInstructionMIPS64::Emulate_BGTZALC, "BGTZALC rs,offset" },
+ { "BEQZALC", &EmulateInstructionMIPS64::Emulate_BEQZALC, "BEQZALC rs,offset" },
+ { "BNEZALC", &EmulateInstructionMIPS64::Emulate_BNEZALC, "BNEZALC rs,offset" },
+ { "BEQC", &EmulateInstructionMIPS64::Emulate_BEQC, "BEQC rs,rt,offset" },
+ { "BNEC", &EmulateInstructionMIPS64::Emulate_BNEC, "BNEC rs,rt,offset" },
+ { "BLTC", &EmulateInstructionMIPS64::Emulate_BLTC, "BLTC rs,rt,offset" },
+ { "BGEC", &EmulateInstructionMIPS64::Emulate_BGEC, "BGEC rs,rt,offset" },
+ { "BLTUC", &EmulateInstructionMIPS64::Emulate_BLTUC, "BLTUC rs,rt,offset" },
+ { "BGEUC", &EmulateInstructionMIPS64::Emulate_BGEUC, "BGEUC rs,rt,offset" },
+ { "BLTZC", &EmulateInstructionMIPS64::Emulate_BLTZC, "BLTZC rt,offset" },
+ { "BLEZC", &EmulateInstructionMIPS64::Emulate_BLEZC, "BLEZC rt,offset" },
+ { "BGEZC", &EmulateInstructionMIPS64::Emulate_BGEZC, "BGEZC rt,offset" },
+ { "BGTZC", &EmulateInstructionMIPS64::Emulate_BGTZC, "BGTZC rt,offset" },
+ { "BEQZC", &EmulateInstructionMIPS64::Emulate_BEQZC, "BEQZC rt,offset" },
+ { "BNEZC", &EmulateInstructionMIPS64::Emulate_BNEZC, "BNEZC rt,offset" },
+ { "BGEZL", &EmulateInstructionMIPS64::Emulate_BGEZL, "BGEZL rt,offset" },
+ { "BGTZ", &EmulateInstructionMIPS64::Emulate_BGTZ, "BGTZ rt,offset" },
+ { "BGTZL", &EmulateInstructionMIPS64::Emulate_BGTZL, "BGTZL rt,offset" },
+ { "BLEZ", &EmulateInstructionMIPS64::Emulate_BLEZ, "BLEZ rt,offset" },
+ { "BLEZL", &EmulateInstructionMIPS64::Emulate_BLEZL, "BLEZL rt,offset" },
+ { "BLTZ", &EmulateInstructionMIPS64::Emulate_BLTZ, "BLTZ rt,offset" },
+ { "BLTZAL", &EmulateInstructionMIPS64::Emulate_BLTZAL, "BLTZAL rt,offset" },
+ { "BLTZALL", &EmulateInstructionMIPS64::Emulate_BLTZALL, "BLTZALL rt,offset" },
+ { "BLTZL", &EmulateInstructionMIPS64::Emulate_BLTZL, "BLTZL rt,offset" },
+ { "BOVC", &EmulateInstructionMIPS64::Emulate_BOVC, "BOVC rs,rt,offset" },
+ { "BNVC", &EmulateInstructionMIPS64::Emulate_BNVC, "BNVC rs,rt,offset" },
+ { "J", &EmulateInstructionMIPS64::Emulate_J, "J target" },
+ { "JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target" },
+ { "JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target" },
+ { "JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target" },
+ { "JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target" },
+ { "JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset" },
+ { "JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset" },
+ { "JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target" },
+ { "JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target" },
+ { "BC1F", &EmulateInstructionMIPS64::Emulate_BC1F, "BC1F cc, offset" },
+ { "BC1T", &EmulateInstructionMIPS64::Emulate_BC1T, "BC1T cc, offset" },
+ { "BC1FL", &EmulateInstructionMIPS64::Emulate_BC1FL, "BC1FL cc, offset" },
+ { "BC1TL", &EmulateInstructionMIPS64::Emulate_BC1TL, "BC1TL cc, offset" },
+ { "BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, "BC1EQZ ft, offset" },
+ { "BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, "BC1NEZ ft, offset" },
+ { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_BC1ANY2F, "BC1ANY2F cc, offset" },
+ { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" },
+ { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" },
+ { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" },
+ };
+
+ static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
+
+ for (size_t i = 0; i < k_num_mips_opcodes; ++i)
+ {
+ if (! strcasecmp (g_opcodes[i].op_name, op_name))
+ return &g_opcodes[i];
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionMIPS64::ReadInstruction ()
+{
+ bool success = false;
+ m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
+ if (success)
+ {
+ Context read_inst_context;
+ read_inst_context.type = eContextReadOpcode;
+ read_inst_context.SetNoArgs ();
+ m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder());
+ }
+ if (!success)
+ m_addr = LLDB_INVALID_ADDRESS;
+ return success;
+}
+
+bool
+EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
+{
+ bool success = false;
+ llvm::MCInst mc_insn;
+ uint64_t insn_size;
+ DataExtractor data;
+
+ /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */
+ if (m_opcode.GetData (data))
+ {
+ llvm::MCDisassembler::DecodeStatus decode_status;
+ llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize());
+ decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ if (decode_status != llvm::MCDisassembler::Success)
+ return false;
+ }
+
+ /*
+ * mc_insn.getOpcode() returns decoded opcode. However to make use
+ * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
+ */
+ const char *op_name = m_insn_info->getName (mc_insn.getOpcode ());
+
+ if (op_name == NULL)
+ return false;
+
+ /*
+ * Decoding has been done already. Just get the call-back function
+ * and emulate the instruction.
+ */
+ MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name);
+
+ if (opcode_data == NULL)
+ return false;
+
+ uint64_t old_pc = 0, new_pc = 0;
+ const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+
+ if (auto_advance_pc)
+ {
+ old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+ }
+
+ /* emulate instruction */
+ success = (this->*opcode_data->callback) (mc_insn);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc)
+ {
+ new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* If we haven't changed the PC, change it here */
+ if (old_pc == new_pc)
+ {
+ new_pc += 4;
+ Context context;
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, new_pc))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+ const bool can_replace = false;
+
+ // Our previous Call Frame Address is the stack pointer
+ row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips64, 0);
+
+ // Our previous PC is in the RA
+ row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips64, gcc_dwarf_ra_mips64, can_replace);
+
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+ unwind_plan.SetSourceName ("EmulateInstructionMIPS64");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum)
+{
+ switch (regnum)
+ {
+ case gcc_dwarf_r16_mips64:
+ case gcc_dwarf_r17_mips64:
+ case gcc_dwarf_r18_mips64:
+ case gcc_dwarf_r19_mips64:
+ case gcc_dwarf_r20_mips64:
+ case gcc_dwarf_r21_mips64:
+ case gcc_dwarf_r22_mips64:
+ case gcc_dwarf_r23_mips64:
+ case gcc_dwarf_gp_mips64:
+ case gcc_dwarf_sp_mips64:
+ case gcc_dwarf_r30_mips64:
+ case gcc_dwarf_ra_mips64:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn)
+{
+ bool success = false;
+ const uint32_t imm16 = insn.getOperand(2).getImm();
+ uint64_t imm = SignedBits(imm16, 15, 0);
+ uint64_t result;
+ uint32_t src, dst;
+
+ dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ /* Check if this is daddiu sp,<src>,imm16 */
+ if (dst == gcc_dwarf_sp_mips64)
+ {
+ /* read <src> register */
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success);
+ if (!success)
+ return false;
+
+ result = src_opd_val + imm;
+
+ Context context;
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm);
+
+ /* We are allocating bytes on stack */
+ context.type = eContextAdjustStackPointer;
+
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result);
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t imm16 = insn.getOperand(2).getImm();
+ uint64_t imm = SignedBits(imm16, 15, 0);
+ uint32_t src, base;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ /* We look for sp based non-volatile register stores */
+ if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ {
+ uint64_t address;
+ RegisterInfo reg_info_base;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
+ || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ return false;
+
+ /* read SP */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ Context context;
+ RegisterValue data_src;
+ context.type = eContextPushRegisterOnStack;
+ context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
+
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
+
+ if (!ReadRegister (&reg_info_base, data_src))
+ return false;
+
+ if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn)
+{
+ uint32_t src, base;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ {
+ RegisterValue data_src;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ return false;
+
+ Context context;
+ context.type = eContextRegisterLoad;
+
+ if (!WriteRegister (context, &reg_info_src, data_src))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BEQ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BEQ rs, rt, offset
+ * condition <- (GPR[rs] = GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ * else
+ * PC = PC + 4
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNE (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BNE rs, rt, offset
+ * condition <- (GPR[rs] != GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BEQL rs, rt, offset
+ * condition <- (GPR[rs] = GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNEL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BNEL rs, rt, offset
+ * condition <- (GPR[rs] != GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGEZL rs, offset
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLTZL rs, offset
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGTZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGTZL rs, offset
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLEZL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLEZL rs, offset
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGTZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGTZ rs, offset
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLEZ rs, offset
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLTZ rs, offset
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEZALL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGEZALL rt, offset
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ int64_t offset, pc, target;
+
+ /*
+ * BAL offset
+ * offset = sign_ext (offset << 2)
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ target = pc + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ int64_t offset, pc, target;
+
+ /*
+ * BALC offset
+ * offset = sign_ext (offset << 2)
+ * RA = PC + 4
+ * PC = PC + 4 + offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ target = pc + 4 + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEZAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGEZAL rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if ((int64_t) rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLTZAL rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if ((int64_t) rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTZALL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLTZALL rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * RA = PC + 8
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ return false;
+
+ return true;
+}
+
+
+bool
+EmulateInstructionMIPS64::Emulate_BLEZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLEZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGEZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLTZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGTZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGTZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target, rs_val;
+
+ /*
+ * BEQZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] == 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val == 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target, rs_val;
+
+ /*
+ * BNEZALC rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] != 0)
+ * if condition then
+ * RA = PC + 4
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val != 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target, rs_val;
+
+ /*
+ * BGEZ rs,offset
+ * offset = sign_ext (offset << 2)
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + offset
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)
+{
+ bool success = false;
+ int64_t offset, pc, target;
+
+ /*
+ * BC offset
+ * offset = sign_ext (offset << 2)
+ * PC = PC + 4 + offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ target = pc + 4 + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BEQC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BEQC rs, rt, offset
+ * condition <- (GPR[rs] = GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNEC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target, rs_val, rt_val;
+
+ /*
+ * BNEC rs, rt, offset
+ * condition <- (GPR[rs] != GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target;
+ int64_t rs_val, rt_val;
+
+ /*
+ * BLTC rs, rt, offset
+ * condition <- (GPR[rs] < GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target;
+ int64_t rs_val, rt_val;
+
+ /*
+ * BGEC rs, rt, offset
+ * condition <- (GPR[rs] > GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTUC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target;
+ uint64_t rs_val, rt_val;
+
+ /*
+ * BLTUC rs, rt, offset
+ * condition <- (GPR[rs] < GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEUC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target;
+ uint64_t rs_val, rt_val;
+
+ /*
+ * BGEUC rs, rt, offset
+ * condition <- (GPR[rs] > GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLTZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLTZC rs, offset
+ * condition <- (GPR[rs] < 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val < 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BLEZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BLEZC rs, offset
+ * condition <- (GPR[rs] <= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val <= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGEZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGEZC rs, offset
+ * condition <- (GPR[rs] >= 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val >= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BGTZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ int64_t rs_val;
+
+ /*
+ * BGTZC rs, offset
+ * condition <- (GPR[rs] > 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val > 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BEQZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ uint64_t rs_val;
+
+ /*
+ * BEQZC rs, offset
+ * condition <- (GPR[rs] = 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNEZC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ int64_t offset, pc, target;
+ uint64_t rs_val;
+
+ /*
+ * BNEZC rs, offset
+ * condition <- (GPR[rs] != 0)
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (rs_val != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+static int
+IsAdd64bitOverflow (int64_t a, int64_t b)
+{
+ int64_t r = (uint64_t) a + (uint64_t) b;
+ return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target;
+ int64_t rs_val, rt_val;
+
+ /*
+ * BOVC rs, rt, offset
+ * condition <- overflow(GPR[rs] + GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ int64_t offset, pc, target;
+ int64_t rs_val, rt_val;
+
+ /*
+ * BNVC rs, rt, offset
+ * condition <- overflow(GPR[rs] + GPR[rt])
+ * if condition then
+ * PC = PC + sign_ext (offset << 2)
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ offset = insn.getOperand(2).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ if (! IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + offset;
+ else
+ target = pc + 4;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint64_t offset, pc;
+
+ /*
+ * J offset
+ * offset = sign_ext (offset << 2)
+ * PC = PC[63-28] | offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* This is a PC-region branch and not PC-relative */
+ pc = (pc & 0xFFFFFFFFF0000000ULL) | offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, pc))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint64_t offset, target, pc;
+
+ /*
+ * JAL offset
+ * offset = sign_ext (offset << 2)
+ * PC = PC[63-28] | offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* This is a PC-region branch and not PC-relative */
+ target = (pc & 0xFFFFFFFFF0000000ULL) | offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_JALR (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs, rt;
+ uint64_t pc, rs_val;
+
+ /*
+ * JALR rt, rs
+ * GPR[rt] = PC + 8
+ * PC = GPR[rs]
+ */
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, pc + 8))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rt;
+ int64_t target, offset, pc, rt_val;
+
+ /*
+ * JIALC rt, offset
+ * offset = sign_ext (offset)
+ * PC = GPR[rt] + offset
+ * RA = PC + 4
+ */
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ target = rt_val + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rt;
+ int64_t target, offset, rt_val;
+
+ /*
+ * JIC rt, offset
+ * offset = sign_ext (offset)
+ * PC = GPR[rt] + offset
+ */
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ if (!success)
+ return false;
+
+ target = rt_val + offset;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs;
+ uint64_t rs_val;
+
+ /*
+ * JR rs
+ * PC = GPR[rs]
+ */
+ rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1F cc, offset
+ * condition <- (FPConditionCode(cc) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) == 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1T cc, offset
+ * condition <- (FPConditionCode(cc) != 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1F cc, offset
+ * condition <- (FPConditionCode(cc) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) == 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1T cc, offset
+ * condition <- (FPConditionCode(cc) != 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ if ((fcsr & (1 << cc)) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8; /* skip delay slot */
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t ft;
+ uint64_t ft_val;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1EQZ ft, offset
+ * condition <- (FPR[ft].bit0 == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + 4 + offset
+ */
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success);
+ if (!success)
+ return false;
+
+ if ((ft_val & 1) == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t ft;
+ uint64_t ft_val;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1NEZ ft, offset
+ * condition <- (FPR[ft].bit0 != 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + 4 + offset
+ */
+ ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success);
+ if (!success)
+ return false;
+
+ if ((ft_val & 1) != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1ANY2F cc, offset
+ * condition <- (FPConditionCode(cc) == 0
+ * || FPConditionCode(cc+1) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 3) != 3)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1ANY2T cc, offset
+ * condition <- (FPConditionCode(cc) == 1
+ * || FPConditionCode(cc+1) == 1)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 3) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1ANY4F cc, offset
+ * condition <- (FPConditionCode(cc) == 0
+ * || FPConditionCode(cc+1) == 0)
+ * || FPConditionCode(cc+2) == 0)
+ * || FPConditionCode(cc+3) == 0)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 0xf) != 0xf)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t cc, fcsr;
+ int64_t target, pc, offset;
+
+ /*
+ * BC1ANY4T cc, offset
+ * condition <- (FPConditionCode(cc) == 1
+ * || FPConditionCode(cc+1) == 1)
+ * || FPConditionCode(cc+2) == 1)
+ * || FPConditionCode(cc+3) == 1)
+ * if condition then
+ * offset = sign_ext (offset)
+ * PC = PC + offset
+ */
+ cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ offset = insn.getOperand(1).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* fcsr[23], fcsr[25-31] are vaild condition bits */
+ fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 0xf) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
new file mode 100644
index 000000000000..178417c196fa
--- /dev/null
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
@@ -0,0 +1,313 @@
+//===-- EmulateInstructionMIPS64.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EmulateInstructionMIPS64_h_
+#define EmulateInstructionMIPS64_h_
+
+namespace llvm
+{
+ class MCDisassembler;
+ class MCSubtargetInfo;
+ class MCRegisterInfo;
+ class MCAsmInfo;
+ class MCContext;
+ class MCInstrInfo;
+ class MCInst;
+}
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+class EmulateInstructionMIPS64 : public lldb_private::EmulateInstruction
+{
+public:
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetPluginDescriptionStatic ();
+
+ static lldb_private::EmulateInstruction *
+ CreateInstance (const lldb_private::ArchSpec &arch,
+ lldb_private::InstructionType inst_type);
+
+ static bool
+ SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type)
+ {
+ switch (inst_type)
+ {
+ case lldb_private::eInstructionTypeAny:
+ case lldb_private::eInstructionTypePrologueEpilogue:
+ case lldb_private::eInstructionTypePCModifying:
+ return true;
+
+ case lldb_private::eInstructionTypeAll:
+ return false;
+ }
+ return false;
+ }
+
+ virtual lldb_private::ConstString
+ GetPluginName();
+
+ virtual lldb_private::ConstString
+ GetShortPluginName()
+ {
+ return GetPluginNameStatic();
+ }
+
+ virtual uint32_t
+ GetPluginVersion()
+ {
+ return 1;
+ }
+
+ bool
+ SetTargetTriple (const lldb_private::ArchSpec &arch);
+
+ EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch);
+
+ virtual bool
+ SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ {
+ return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
+ }
+
+ virtual bool
+ ReadInstruction ();
+
+ virtual bool
+ EvaluateInstruction (uint32_t evaluate_options);
+
+ virtual bool
+ TestEmulation (lldb_private::Stream *out_stream,
+ lldb_private::ArchSpec &arch,
+ lldb_private::OptionValueDictionary *test_data)
+ {
+ return false;
+ }
+
+ virtual bool
+ GetRegisterInfo (lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ lldb_private::RegisterInfo &reg_info);
+
+ virtual bool
+ CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+
+
+protected:
+
+ typedef struct
+ {
+ const char *op_name;
+ bool (EmulateInstructionMIPS64::*callback) (llvm::MCInst& insn);
+ const char *insn_name;
+ } MipsOpcode;
+
+ static MipsOpcode*
+ GetOpcodeForInstruction (const char *op_name);
+
+ bool
+ Emulate_DADDiu (llvm::MCInst& insn);
+
+ bool
+ Emulate_SD (llvm::MCInst& insn);
+
+ bool
+ Emulate_LD (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNE (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZALL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEZALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTUC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEUC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BEQZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNEZC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGEZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BGTZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLEZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZALL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BLTZL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BOVC (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNVC (llvm::MCInst& insn);
+
+ bool
+ Emulate_J (llvm::MCInst& insn);
+
+ bool
+ Emulate_JAL (llvm::MCInst& insn);
+
+ bool
+ Emulate_JALR (llvm::MCInst& insn);
+
+ bool
+ Emulate_JIALC (llvm::MCInst& insn);
+
+ bool
+ Emulate_JIC (llvm::MCInst& insn);
+
+ bool
+ Emulate_JR (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1F (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1T (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1FL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1TL (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1EQZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1NEZ (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY2F (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY2T (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY4F (llvm::MCInst& insn);
+
+ bool
+ Emulate_BC1ANY4T (llvm::MCInst& insn);
+
+ bool
+ nonvolatile_reg_p (uint64_t regnum);
+
+ const char *
+ GetRegisterName (unsigned reg_num, bool altnernate_name);
+
+private:
+ std::unique_ptr<llvm::MCDisassembler> m_disasm;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info;
+ std::unique_ptr<llvm::MCRegisterInfo> m_reg_info;
+ std::unique_ptr<llvm::MCAsmInfo> m_asm_info;
+ std::unique_ptr<llvm::MCContext> m_context;
+ std::unique_ptr<llvm::MCInstrInfo> m_insn_info;
+};
+
+#endif // EmulateInstructionMIPS64_h_
diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
index 96754ff78787..9b72ceb71bd0 100644
--- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Stream.h"
@@ -130,26 +131,34 @@ AddressSanitizerRuntime::IsActive()
const char *
address_sanitizer_retrieve_report_data_command = R"(
- struct {
- int present;
- void *pc, *bp, *sp, *address;
- int access_type;
- size_t access_size;
- const char *description;
- } t;
+int __asan_report_present();
+void *__asan_get_report_pc();
+void *__asan_get_report_bp();
+void *__asan_get_report_sp();
+void *__asan_get_report_address();
+const char *__asan_get_report_description();
+int __asan_get_report_access_type();
+size_t __asan_get_report_access_size();
+struct {
+ int present;
+ int access_type;
+ void *pc;
+ void *bp;
+ void *sp;
+ void *address;
+ size_t access_size;
+ const char *description;
+} t;
- t.present = ((int (*) ())__asan_report_present)();
- t.pc = ((void * (*) ())__asan_get_report_pc)();
- /* commented out because rdar://problem/18533301
- t.bp = ((void * (*) ())__asan_get_report_bp)();
- t.sp = ((void * (*) ())__asan_get_report_sp)();
- */
- t.address = ((void * (*) ())__asan_get_report_address)();
- t.description = ((const char * (*) ())__asan_get_report_description)();
- t.access_type = ((int (*) ())__asan_get_report_access_type)();
- t.access_size = ((size_t (*) ())__asan_get_report_access_size)();
-
- t;
+t.present = __asan_report_present();
+t.access_type = __asan_get_report_access_type();
+t.pc = __asan_get_report_pc();
+t.bp = __asan_get_report_bp();
+t.sp = __asan_get_report_sp();
+t.address = __asan_get_report_address();
+t.access_size = __asan_get_report_access_size();
+t.description = __asan_get_report_description();
+t
)";
StructuredData::ObjectSP
@@ -177,8 +186,10 @@ AddressSanitizerRuntime::RetrieveReportData()
return StructuredData::ObjectSP();
addr_t pc = return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0);
+ /* commented out because rdar://problem/18533301
addr_t bp = return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0);
addr_t sp = return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0);
+ */
addr_t address = return_value_sp->GetValueForExpressionPath(".address")->GetValueAsUnsigned(0);
addr_t access_type = return_value_sp->GetValueForExpressionPath(".access_type")->GetValueAsUnsigned(0);
addr_t access_size = return_value_sp->GetValueForExpressionPath(".access_size")->GetValueAsUnsigned(0);
@@ -191,8 +202,10 @@ AddressSanitizerRuntime::RetrieveReportData()
dict->AddStringItem("instrumentation_class", "AddressSanitizer");
dict->AddStringItem("stop_type", "fatal_error");
dict->AddIntegerItem("pc", pc);
+ /* commented out because rdar://problem/18533301
dict->AddIntegerItem("bp", bp);
dict->AddIntegerItem("sp", sp);
+ */
dict->AddIntegerItem("address", address);
dict->AddIntegerItem("access_type", access_type);
dict->AddIntegerItem("access_size", access_size);
@@ -274,11 +287,11 @@ AddressSanitizerRuntime::Activate()
if (symbol == NULL)
return;
- if (!symbol->GetAddress().IsValid())
+ if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
return;
Target &target = m_process->GetTarget();
- addr_t symbol_address = symbol->GetAddress().GetOpcodeLoadAddress(&target);
+ addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
if (symbol_address == LLDB_INVALID_ADDRESS)
return;
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
index cd303cb0768f..8e454e712fe8 100644
--- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
@@ -16,10 +16,11 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Symbol/SymbolVendor.h"
#include "JITLoaderGDB.h"
@@ -435,10 +436,10 @@ JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, const ConstString &name,
SymbolContext sym_ctx;
target_symbols.GetContextAtIndex(0, sym_ctx);
- const Address *jit_descriptor_addr = &sym_ctx.symbol->GetAddress();
- if (!jit_descriptor_addr || !jit_descriptor_addr->IsValid())
+ const Address jit_descriptor_addr = sym_ctx.symbol->GetAddress();
+ if (!jit_descriptor_addr.IsValid())
return LLDB_INVALID_ADDRESS;
- const addr_t jit_addr = jit_descriptor_addr->GetLoadAddress(&target);
+ const addr_t jit_addr = jit_descriptor_addr.GetLoadAddress(&target);
return jit_addr;
}
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 50537eb119f2..7d21b779ebd2 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -281,6 +281,46 @@ ItaniumABILanguageRuntime::IsVTableName (const char *name)
return false;
}
+static std::map<ConstString, std::vector<ConstString> >&
+GetAlternateManglingPrefixes()
+{
+ static std::map<ConstString, std::vector<ConstString> > g_alternate_mangling_prefixes;
+ return g_alternate_mangling_prefixes;
+}
+
+
+size_t
+ItaniumABILanguageRuntime::GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates)
+{
+ if (!mangled)
+ return static_cast<size_t>(0);
+
+ alternates.clear();
+ const char *mangled_cstr = mangled.AsCString();
+ std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes();
+ for (std::map<ConstString, std::vector<ConstString> >::iterator it = alternate_mangling_prefixes.begin();
+ it != alternate_mangling_prefixes.end();
+ ++it)
+ {
+ const char *prefix_cstr = it->first.AsCString();
+ if (strncmp(mangled_cstr, prefix_cstr, strlen(prefix_cstr)) == 0)
+ {
+ const std::vector<ConstString> &alternate_prefixes = it->second;
+ for (size_t i = 0; i < alternate_prefixes.size(); ++i)
+ {
+ std::string alternate_mangling(alternate_prefixes[i].AsCString());
+ alternate_mangling.append(mangled_cstr + strlen(prefix_cstr));
+
+ alternates.push_back(ConstString(alternate_mangling.c_str()));
+ }
+
+ return alternates.size();
+ }
+ }
+
+ return static_cast<size_t>(0);
+}
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -304,6 +344,17 @@ ItaniumABILanguageRuntime::Initialize()
PluginManager::RegisterPlugin (GetPluginNameStatic(),
"Itanium ABI for the C++ language",
CreateInstance);
+
+ // Alternate manglings for std::basic_string<...>
+ std::vector<ConstString> basic_string_alternates;
+ basic_string_alternates.push_back(ConstString("_ZNSs"));
+ basic_string_alternates.push_back(ConstString("_ZNKSs"));
+ std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes();
+
+ alternate_mangling_prefixes[ConstString("_ZNSbIcSt17char_traits<char>St15allocator<char>E")] =
+ basic_string_alternates;
+ alternate_mangling_prefixes[ConstString("_ZNKSbIcSt17char_traits<char>St15allocator<char>E")] =
+ basic_string_alternates;
}
void
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
index cd0a4b2c15eb..bc5d83be4bf5 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -20,6 +20,9 @@
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Core/Value.h"
+#include <map>
+#include <vector>
+
namespace lldb_private {
class ItaniumABILanguageRuntime :
@@ -82,6 +85,9 @@ namespace lldb_private {
virtual lldb::SearchFilterSP
CreateExceptionSearchFilter ();
+ virtual size_t
+ GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates);
+
protected:
lldb::BreakpointResolverSP
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
new file mode 100644
index 000000000000..2490cf31409b
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -0,0 +1,1191 @@
+//===-- RenderScriptRuntime.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RenderScriptRuntime.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "lldb/Symbol/VariableList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+LanguageRuntime *
+RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
+{
+
+ if (language == eLanguageTypeExtRenderScript)
+ return new RenderScriptRuntime(process);
+ else
+ return NULL;
+}
+
+void
+RenderScriptRuntime::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject);
+}
+
+void
+RenderScriptRuntime::Terminate()
+{
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString
+RenderScriptRuntime::GetPluginNameStatic()
+{
+ static ConstString g_name("renderscript");
+ return g_name;
+}
+
+RenderScriptRuntime::ModuleKind
+RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
+{
+ if (module_sp)
+ {
+ // Is this a module containing renderscript kernels?
+ const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
+ if (info_sym)
+ {
+ return eModuleKindKernelObj;
+ }
+
+ // Is this the main RS runtime library
+ const ConstString rs_lib("libRS.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_lib)
+ {
+ return eModuleKindLibRS;
+ }
+
+ const ConstString rs_driverlib("libRSDriver.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_driverlib)
+ {
+ return eModuleKindDriver;
+ }
+
+ const ConstString rs_cpureflib("libRSCPURef.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
+ {
+ return eModuleKindImpl;
+ }
+
+ }
+ return eModuleKindIgnored;
+}
+
+bool
+RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
+{
+ return GetModuleKind(module_sp) != eModuleKindIgnored;
+}
+
+
+void
+RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
+{
+ Mutex::Locker locker (module_list.GetMutex ());
+
+ size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; i++)
+ {
+ auto mod = module_list.GetModuleAtIndex (i);
+ if (IsRenderScriptModule (mod))
+ {
+ LoadModule(mod);
+ }
+ }
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+RenderScriptRuntime::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+RenderScriptRuntime::GetPluginVersion()
+{
+ return 1;
+}
+
+bool
+RenderScriptRuntime::IsVTableName(const char *name)
+{
+ return false;
+}
+
+bool
+RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address)
+{
+ return false;
+}
+
+bool
+RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
+{
+ return false;
+}
+
+lldb::BreakpointResolverSP
+RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
+{
+ BreakpointResolverSP resolver_sp;
+ return resolver_sp;
+}
+
+
+const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
+{
+ //rsdScript
+ {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureScriptInit1},
+ {"rsdScriptInvokeForEach", "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+ {"rsdScriptInvokeForEachMulti", "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+ {"rsdScriptInvokeFunction", "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+ {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1},
+
+ //rsdAllocation
+ {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureAllocationInit1},
+ {"rsdAllocationRead2D", "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+};
+const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
+
+
+bool
+RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
+{
+ RuntimeHook* hook_info = (RuntimeHook*)baton;
+ ExecutionContext context(ctx->exe_ctx_ref);
+
+ RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+
+ lang_rt->HookCallback(hook_info, context);
+
+ return false;
+}
+
+
+void
+RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if(log)
+ log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);
+
+ if (hook_info->defn->grabber)
+ {
+ (this->*(hook_info->defn->grabber))(hook_info, context);
+ }
+}
+
+
+bool
+RenderScriptRuntime::GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!data)
+ return false;
+
+ Error error;
+ RegisterContext* reg_ctx = context.GetRegisterContext();
+ Process* process = context.GetProcessPtr();
+
+ if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::x86)
+ {
+ uint64_t sp = reg_ctx->GetSP();
+ {
+ uint32_t offset = (1 + arg) * sizeof(uint32_t);
+ process->ReadMemory(sp + offset, data, sizeof(uint32_t), error);
+ if(error.Fail())
+ {
+ if(log)
+ log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading X86 stack: %s.", error.AsCString());
+ }
+ }
+ }
+ else if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::arm)
+ {
+ if (arg < 4)
+ {
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
+ RegisterValue rVal;
+ reg_ctx->ReadRegister(rArg, rVal);
+ (*data) = rVal.GetAsUInt32();
+ }
+ else
+ {
+ uint64_t sp = reg_ctx->GetSP();
+ {
+ uint32_t offset = (arg-4) * sizeof(uint32_t);
+ process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
+ if(error.Fail())
+ {
+ if(log)
+ log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading ARM stack: %s.", error.AsCString());
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void
+RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ //Context, Script, int, data, length
+
+ Error error;
+
+ uint32_t rs_context_u32 = 0U;
+ uint32_t rs_script_u32 = 0U;
+ uint32_t rs_id_u32 = 0U;
+ uint32_t rs_data_u32 = 0U;
+ uint32_t rs_length_u32 = 0U;
+
+ std::string resname;
+ std::string cachedir;
+
+ GetArg32Simple(context, 0, &rs_context_u32);
+ GetArg32Simple(context, 1, &rs_script_u32);
+ GetArg32Simple(context, 2, &rs_id_u32);
+ GetArg32Simple(context, 3, &rs_data_u32);
+ GetArg32Simple(context, 4, &rs_length_u32);
+
+ if(log)
+ {
+ log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
+ (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, (uint64_t)rs_id_u32, (uint64_t)rs_data_u32, (uint64_t)rs_length_u32);
+
+ addr_t script_addr = (addr_t)rs_script_u32;
+ if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
+ {
+ auto rsm = m_scriptMappings[script_addr];
+ if (rs_id_u32 < rsm->m_globals.size())
+ {
+ auto rsg = rsm->m_globals[rs_id_u32];
+ log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
+ rsm->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ }
+}
+
+void
+RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ //Context, Alloc, bool
+
+ Error error;
+
+ uint32_t rs_context_u32 = 0U;
+ uint32_t rs_alloc_u32 = 0U;
+ uint32_t rs_forceZero_u32 = 0U;
+
+ GetArg32Simple(context, 0, &rs_context_u32);
+ GetArg32Simple(context, 1, &rs_alloc_u32);
+ GetArg32Simple(context, 2, &rs_forceZero_u32);
+
+ if(log)
+ log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
+ (uint64_t)rs_context_u32, (uint64_t)rs_alloc_u32, (uint64_t)rs_forceZero_u32);
+}
+
+void
+RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ //Context, Script, resname Str, cachedir Str
+ Error error;
+ Process* process = context.GetProcessPtr();
+
+ uint32_t rs_context_u32 = 0U;
+ uint32_t rs_script_u32 = 0U;
+ uint32_t rs_resnameptr_u32 = 0U;
+ uint32_t rs_cachedirptr_u32 = 0U;
+
+ std::string resname;
+ std::string cachedir;
+
+ GetArg32Simple(context, 0, &rs_context_u32);
+ GetArg32Simple(context, 1, &rs_script_u32);
+ GetArg32Simple(context, 2, &rs_resnameptr_u32);
+ GetArg32Simple(context, 3, &rs_cachedirptr_u32);
+
+ process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u32, resname, error);
+ if (error.Fail())
+ {
+ if(log)
+ log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
+
+ }
+
+ process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u32, cachedir, error);
+ if (error.Fail())
+ {
+ if(log)
+ log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
+ }
+
+ if (log)
+ log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
+ (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, resname.c_str(), cachedir.c_str());
+
+ if (resname.size() > 0)
+ {
+ StreamString strm;
+ strm.Printf("librs.%s.so", resname.c_str());
+
+ ScriptDetails script;
+ script.cachedir = cachedir;
+ script.resname = resname;
+ script.scriptDyLib.assign(strm.GetData());
+ script.script = rs_script_u32;
+ script.context = rs_context_u32;
+
+ m_scripts.push_back(script);
+
+ if (log)
+ log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
+ strm.GetData(), (uint64_t)rs_context_u32, (uint64_t)rs_script_u32);
+ }
+ else if (log)
+ {
+ log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
+ }
+
+}
+
+
+void
+RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!module)
+ {
+ return;
+ }
+
+ if ((GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::x86)
+ && (GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::arm))
+ {
+ if (log)
+ log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently.");
+
+ return;
+ }
+
+ Target &target = GetProcess()->GetTarget();
+
+ for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
+ {
+ const HookDefn* hook_defn = &s_runtimeHookDefns[idx];
+ if (hook_defn->kind != kind) {
+ continue;
+ }
+
+ const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(hook_defn->symbol_name), eSymbolTypeCode);
+
+ addr_t addr = sym->GetLoadAddress(&target);
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ if(log)
+ log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
+ hook_defn->name, hook_defn->symbol_name);
+ continue;
+ }
+
+ RuntimeHookSP hook(new RuntimeHook());
+ hook->address = addr;
+ hook->defn = hook_defn;
+ hook->bp_sp = target.CreateBreakpoint(addr, true, false);
+ hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
+ m_runtimeHooks[addr] = hook;
+ if (log)
+ {
+ log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
+ hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
+ }
+ }
+}
+
+void
+RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
+{
+ if (!rsmodule_sp)
+ return;
+
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ const ModuleSP module = rsmodule_sp->m_module;
+ const FileSpec& file = module->GetPlatformFileSpec();
+
+ for (const auto &rs_script : m_scripts)
+ {
+ if (file.GetFilename() == ConstString(rs_script.scriptDyLib.c_str()))
+ {
+ if (m_scriptMappings.find( rs_script.script ) != m_scriptMappings.end())
+ {
+ if (m_scriptMappings[rs_script.script] != rsmodule_sp)
+ {
+ if (log)
+ {
+ log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
+ (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ }
+ else
+ {
+ m_scriptMappings[rs_script.script] = rsmodule_sp;
+ rsmodule_sp->m_resname = rs_script.resname;
+ if (log)
+ {
+ log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
+ (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ }
+ }
+
+}
+
+bool
+RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (module_sp)
+ {
+ for (const auto &rs_module : m_rsmodules)
+ {
+ if (rs_module->m_module == module_sp)
+ return false;
+ }
+ bool module_loaded = false;
+ switch (GetModuleKind(module_sp))
+ {
+ case eModuleKindKernelObj:
+ {
+ RSModuleDescriptorSP module_desc;
+ module_desc.reset(new RSModuleDescriptor(module_sp));
+ if (module_desc->ParseRSInfo())
+ {
+ m_rsmodules.push_back(module_desc);
+ module_loaded = true;
+ }
+ if (module_loaded)
+ {
+ FixupScriptDetails(module_desc);
+ }
+ break;
+ }
+ case eModuleKindDriver:
+ {
+ if (!m_libRSDriver)
+ {
+ m_libRSDriver = module_sp;
+ LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
+ }
+ break;
+ }
+ case eModuleKindImpl:
+ {
+ m_libRSCpuRef = module_sp;
+ break;
+ }
+ case eModuleKindLibRS:
+ {
+ if (!m_libRS)
+ {
+ m_libRS = module_sp;
+ static ConstString gDbgPresentStr("gDebuggerPresent");
+ const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
+ if (debug_present)
+ {
+ Error error;
+ uint32_t flag = 0x00000001U;
+ Target &target = GetProcess()->GetTarget();
+ addr_t addr = debug_present->GetLoadAddress(&target);
+ GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
+ if(error.Success())
+ {
+ if (log)
+ log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee");
+
+ m_debuggerPresentFlagged = true;
+ }
+ else if (log)
+ {
+ log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString());
+ }
+ }
+ else if (log)
+ {
+ log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found");
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (module_loaded)
+ Update();
+ return module_loaded;
+ }
+ return false;
+}
+
+void
+RenderScriptRuntime::Update()
+{
+ if (m_rsmodules.size() > 0)
+ {
+ if (!m_initiated)
+ {
+ Initiate();
+ }
+ }
+}
+
+
+// The maximum line length of an .rs.info packet
+#define MAXLINE 500
+
+// The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
+// The string is basic and is parsed on a line by line basis.
+bool
+RSModuleDescriptor::ParseRSInfo()
+{
+ const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
+ if (info_sym)
+ {
+ const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
+ const addr_t size = info_sym->GetByteSize();
+ const FileSpec fs = m_module->GetFileSpec();
+
+ DataBufferSP buffer = fs.ReadFileContents(addr, size);
+
+ if (!buffer)
+ return false;
+
+ std::string info((const char *)buffer->GetBytes());
+
+ std::vector<std::string> info_lines;
+ size_t lpos = info.find_first_of("\n");
+ while (lpos != std::string::npos)
+ {
+ info_lines.push_back(info.substr(0, lpos));
+ info = info.substr(lpos + 1);
+ lpos = info.find_first_of("\n");
+ }
+ size_t offset = 0;
+ while (offset < info_lines.size())
+ {
+ std::string line = info_lines[offset];
+ // Parse directives
+ uint32_t numDefns = 0;
+ if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
+ {
+ while (numDefns--)
+ m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str()));
+ }
+ else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
+ {
+ }
+ else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
+ {
+ char name[MAXLINE];
+ while (numDefns--)
+ {
+ uint32_t slot = 0;
+ name[0] = '\0';
+ if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
+ {
+ m_kernels.push_back(RSKernelDescriptor(this, name, slot));
+ }
+ }
+ }
+ else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
+ {
+ char name[MAXLINE];
+ char value[MAXLINE];
+ while (numDefns--)
+ {
+ name[0] = '\0';
+ value[0] = '\0';
+ if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
+ && (name[0] != '\0'))
+ {
+ m_pragmas[std::string(name)] = value;
+ }
+ }
+ }
+ else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
+ {
+ }
+
+ offset++;
+ }
+ return m_kernels.size() > 0;
+ }
+ return false;
+}
+
+bool
+RenderScriptRuntime::ProbeModules(const ModuleList module_list)
+{
+ bool rs_found = false;
+ size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; i++)
+ {
+ auto module = module_list.GetModuleAtIndex(i);
+ rs_found |= LoadModule(module);
+ }
+ return rs_found;
+}
+
+void
+RenderScriptRuntime::Status(Stream &strm) const
+{
+ if (m_libRS)
+ {
+ strm.Printf("Runtime Library discovered.");
+ strm.EOL();
+ }
+ if (m_libRSDriver)
+ {
+ strm.Printf("Runtime Driver discovered.");
+ strm.EOL();
+ }
+ if (m_libRSCpuRef)
+ {
+ strm.Printf("CPU Reference Implementation discovered.");
+ strm.EOL();
+ }
+
+ if (m_runtimeHooks.size())
+ {
+ strm.Printf("Runtime functions hooked:");
+ strm.EOL();
+ for (auto b : m_runtimeHooks)
+ {
+ strm.Indent(b.second->defn->name);
+ strm.EOL();
+ }
+ strm.EOL();
+ }
+ else
+ {
+ strm.Printf("Runtime is not hooked.");
+ strm.EOL();
+ }
+}
+
+void
+RenderScriptRuntime::DumpContexts(Stream &strm) const
+{
+ strm.Printf("Inferred RenderScript Contexts:");
+ strm.EOL();
+ strm.IndentMore();
+
+ std::map<addr_t, uint64_t> contextReferences;
+
+ for (const auto &script : m_scripts)
+ {
+ if (contextReferences.find(script.context) != contextReferences.end())
+ {
+ contextReferences[script.context]++;
+ }
+ else
+ {
+ contextReferences[script.context] = 1;
+ }
+ }
+
+ for (const auto& cRef : contextReferences)
+ {
+ strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
+ strm.EOL();
+ }
+ strm.IndentLess();
+}
+
+void
+RenderScriptRuntime::DumpKernels(Stream &strm) const
+{
+ strm.Printf("RenderScript Kernels:");
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &module : m_rsmodules)
+ {
+ strm.Printf("Resource '%s':",module->m_resname.c_str());
+ strm.EOL();
+ for (const auto &kernel : module->m_kernels)
+ {
+ strm.Indent(kernel.m_name.AsCString());
+ strm.EOL();
+ }
+ }
+ strm.IndentLess();
+}
+
+void
+RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error)
+{
+ if (!name)
+ {
+ error.SetErrorString("invalid kernel name");
+ return;
+ }
+
+ bool kernels_found;
+ ConstString kernel_name(name);
+ for (const auto &module : m_rsmodules)
+ {
+ for (const auto &kernel : module->m_kernels)
+ {
+ if (kernel.m_name == kernel_name)
+ {
+ //Attempt to set a breakpoint on this symbol, within the module library
+ //If it's not found, it's likely debug info is unavailable - set a
+ //breakpoint on <name>.expand and emit a warning.
+
+ const Symbol* kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(kernel_name, eSymbolTypeCode);
+
+ if (!kernel_sym)
+ {
+ std::string kernel_name_expanded(name);
+ kernel_name_expanded.append(".expand");
+ kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
+
+ if (kernel_sym)
+ {
+ strm.Printf("Kernel '%s' could not be found, but expansion exists. ", name);
+ strm.Printf("Breakpoint placed on expanded kernel. Have you compiled in debug mode?");
+ strm.EOL();
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("Could not locate symbols for loaded kernel '%s'.", name);
+ return;
+ }
+ }
+
+ addr_t bp_addr = kernel_sym->GetLoadAddress(&GetProcess()->GetTarget());
+ if (bp_addr == LLDB_INVALID_ADDRESS)
+ {
+ error.SetErrorStringWithFormat("Could not locate load address for symbols of kernel '%s'.", name);
+ return;
+ }
+
+ BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(bp_addr, false, false);
+ strm.Printf("Breakpoint %" PRIu64 ": kernel '%s' within script '%s'", (uint64_t)bp->GetID(), name, module->m_resname.c_str());
+ strm.EOL();
+
+ kernels_found = true;
+ }
+ }
+ }
+
+ if (!kernels_found)
+ {
+ error.SetErrorString("kernel name not found");
+ }
+ return;
+}
+
+void
+RenderScriptRuntime::DumpModules(Stream &strm) const
+{
+ strm.Printf("RenderScript Modules:");
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &module : m_rsmodules)
+ {
+ module->Dump(strm);
+ }
+ strm.IndentLess();
+}
+
+void
+RSModuleDescriptor::Dump(Stream &strm) const
+{
+ strm.Indent();
+ m_module->GetFileSpec().Dump(&strm);
+ m_module->ParseAllDebugSymbols();
+ if(m_module->GetNumCompileUnits())
+ {
+ strm.Indent("Debug info loaded.");
+ }
+ else
+ {
+ strm.Indent("Debug info does not exist.");
+ }
+ strm.EOL();
+ strm.IndentMore();
+ strm.Indent();
+ strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &global : m_globals)
+ {
+ global.Dump(strm);
+ }
+ strm.IndentLess();
+ strm.Indent();
+ strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &kernel : m_kernels)
+ {
+ kernel.Dump(strm);
+ }
+ strm.Printf("Pragmas: %" PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &key_val : m_pragmas)
+ {
+ strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
+ strm.EOL();
+ }
+ strm.IndentLess(4);
+}
+
+void
+RSGlobalDescriptor::Dump(Stream &strm) const
+{
+ strm.Indent(m_name.AsCString());
+ VariableList var_list;
+ m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
+ if (var_list.GetSize() == 1)
+ {
+ auto var = var_list.GetVariableAtIndex(0);
+ auto type = var->GetType();
+ if(type)
+ {
+ strm.Printf(" - ");
+ type->DumpTypeName(&strm);
+ }
+ else
+ {
+ strm.Printf(" - Unknown Type");
+ }
+ }
+ else
+ {
+ strm.Printf(" - variable identified, but not found in binary");
+ const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
+ if (s)
+ {
+ strm.Printf(" (symbol exists) ");
+ }
+ }
+
+ strm.EOL();
+}
+
+void
+RSKernelDescriptor::Dump(Stream &strm) const
+{
+ strm.Indent(m_name.AsCString());
+ strm.EOL();
+}
+
+class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript module probe",
+ "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
+ "renderscript module probe",
+ eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeModuleProbe() {}
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0)
+ {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ auto module_list = target->GetImages();
+ bool new_rs_details = runtime->ProbeModules(module_list);
+ if (new_rs_details)
+ {
+ result.AppendMessage("New renderscript modules added to runtime model.");
+ }
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+ result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript module dump",
+ "Dumps renderscript specific information for all modules.", "renderscript module dump",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeModuleDump() {}
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result)
+ {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ runtime->DumpModules(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
+ NULL)
+ {
+ LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
+ LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeModule() {}
+};
+
+class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript kernel list",
+ "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernelList() {}
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result)
+ {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ runtime->DumpKernels(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectParsed
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript kernel breakpoint",
+ "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result)
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 1)
+ {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+
+ Error error;
+ runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0), error);
+
+ if (error.Success())
+ {
+ result.AppendMessage("Breakpoint(s) created");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ result.SetStatus(eReturnStatusFailed);
+ result.AppendErrorWithFormat("Error: %s", error.AsCString());
+ return false;
+ }
+
+ result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
+ NULL)
+ {
+ LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
+ LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernel() {}
+};
+
+class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript context dump",
+ "Dumps renderscript context information.", "renderscript context dump",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeContextDump() {}
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result)
+ {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ runtime->DumpContexts(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
+ NULL)
+ {
+ LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeContext() {}
+};
+
+class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
+{
+ private:
+ public:
+ CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript status",
+ "Displays current renderscript runtime status.", "renderscript status",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeStatus() {}
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result)
+ {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ runtime->Status(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
+{
+ public:
+ CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
+ "renderscript <subcommand> [<subcommand-options>]")
+ {
+ LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
+ LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
+ LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
+ LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntime() {}
+};
+
+void
+RenderScriptRuntime::Initiate()
+{
+ assert(!m_initiated);
+}
+
+RenderScriptRuntime::RenderScriptRuntime(Process *process)
+ : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false)
+{
+ ModulesDidLoad(process->GetTarget().GetImages());
+}
+
+lldb::CommandObjectSP
+RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
+{
+ static CommandObjectSP command_object;
+ if(!command_object)
+ {
+ command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
+ }
+ return command_object;
+}
+
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
new file mode 100644
index 000000000000..2a01e744e976
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -0,0 +1,232 @@
+//===-- RenderScriptRuntime.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RenderScriptRuntime_h_
+#define liblldb_RenderScriptRuntime_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Core/Module.h"
+
+namespace lldb_private
+{
+
+typedef uint32_t RSSlot;
+class RSModuleDescriptor;
+struct RSGlobalDescriptor;
+struct RSKernelDescriptor;
+
+typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP;
+typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;
+typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP;
+
+
+
+struct RSKernelDescriptor
+{
+ public:
+ RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)
+ : m_module(module)
+ , m_name(name)
+ , m_slot(slot)
+ {
+ }
+
+ void Dump(Stream &strm) const;
+
+ const RSModuleDescriptor *m_module;
+ ConstString m_name;
+ RSSlot m_slot;
+};
+
+struct RSGlobalDescriptor
+{
+ public:
+ RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name )
+ : m_module(module)
+ , m_name(name)
+ {
+ }
+
+ void Dump(Stream &strm) const;
+
+ const RSModuleDescriptor *m_module;
+ ConstString m_name;
+};
+
+class RSModuleDescriptor
+{
+ public:
+ RSModuleDescriptor(const lldb::ModuleSP &module)
+ : m_module(module)
+ {
+ }
+
+ ~RSModuleDescriptor() {}
+
+ bool ParseRSInfo();
+
+ void Dump(Stream &strm) const;
+
+ const lldb::ModuleSP m_module;
+ std::vector<RSKernelDescriptor> m_kernels;
+ std::vector<RSGlobalDescriptor> m_globals;
+ std::map<std::string, std::string> m_pragmas;
+ std::string m_resname;
+};
+
+class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
+{
+ public:
+
+ enum ModuleKind
+ {
+ eModuleKindIgnored,
+ eModuleKindLibRS,
+ eModuleKindDriver,
+ eModuleKindImpl,
+ eModuleKindKernelObj
+ };
+
+
+ ~RenderScriptRuntime() {}
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::LanguageRuntime *CreateInstance(Process *process, lldb::LanguageType language);
+
+ static lldb::CommandObjectSP GetCommandObject(CommandInterpreter& interpreter);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp);
+
+ static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp);
+
+ static void ModulesDidLoad(const lldb::ProcessSP& process_sp, const ModuleList &module_list );
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual lldb_private::ConstString GetPluginName();
+
+ virtual uint32_t GetPluginVersion();
+
+ virtual bool IsVTableName(const char *name);
+
+ virtual bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address);
+
+ virtual bool CouldHaveDynamicValue(ValueObject &in_value);
+
+ virtual lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp);
+
+ bool LoadModule(const lldb::ModuleSP &module_sp);
+
+ bool ProbeModules(const ModuleList module_list);
+
+ void DumpModules(Stream &strm) const;
+
+ void DumpContexts(Stream &strm) const;
+
+ void DumpKernels(Stream &strm) const;
+
+ void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error);
+
+ void Status(Stream &strm) const;
+
+ virtual size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) {
+ return static_cast<size_t>(0);
+ }
+
+ virtual void ModulesDidLoad(const ModuleList &module_list );
+
+ void Update();
+
+ void Initiate();
+
+ protected:
+
+ void FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp);
+
+ void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
+
+ struct RuntimeHook;
+ typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context); // Please do this!
+
+ struct HookDefn
+ {
+ const char * name;
+ const char * symbol_name;
+ uint32_t version;
+ ModuleKind kind;
+ CaptureStateFn grabber;
+ };
+
+ struct RuntimeHook
+ {
+ lldb::addr_t address;
+ const HookDefn *defn;
+ lldb::BreakpointSP bp_sp;
+ };
+
+ typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
+
+ struct ScriptDetails
+ {
+ std::string resname;
+ std::string scriptDyLib;
+ std::string cachedir;
+ lldb::addr_t context;
+ lldb::addr_t script;
+ };
+
+ lldb::ModuleSP m_libRS;
+ lldb::ModuleSP m_libRSDriver;
+ lldb::ModuleSP m_libRSCpuRef;
+ std::vector<RSModuleDescriptorSP> m_rsmodules;
+ std::vector<ScriptDetails> m_scripts;
+
+ std::map<lldb::addr_t, RSModuleDescriptorSP> m_scriptMappings;
+ std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
+
+ bool m_initiated;
+ bool m_debuggerPresentFlagged;
+ static const HookDefn s_runtimeHookDefns[];
+ static const size_t s_runtimeHookCount;
+
+ private:
+ RenderScriptRuntime(Process *process); // Call CreateInstance instead.
+
+ static bool HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ void HookCallback(RuntimeHook* hook_info, ExecutionContext& context);
+
+ bool GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data);
+
+ void CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context);
+ void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context);
+ void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_RenderScriptRuntime_h_
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 1e2a0c721ff6..8209d23c0aee 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -364,7 +364,7 @@ ObjectContainerBSDArchive::CreateInstance
// Map the entire .a file to be sure that we don't lose any data if the file
// gets updated by a new build while this .a file is being used for debugging
- DataBufferSP archive_data_sp (file->MemoryMapFileContents(file_offset, length));
+ DataBufferSP archive_data_sp (file->MemoryMapFileContentsIfLocal(file_offset, length));
lldb::offset_t archive_data_offset = 0;
Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file,
@@ -570,7 +570,7 @@ ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec
if (!archive_sp)
{
set_archive_arch = true;
- DataBufferSP data_sp (file.MemoryMapFileContents(file_offset, file_size));
+ DataBufferSP data_sp (file.MemoryMapFileContentsIfLocal(file_offset, file_size));
data.SetData (data_sp, 0, data_sp->GetByteSize());
archive_sp = Archive::ParseAndCacheArchiveForFile(file, ArchSpec(), file_mod_time, file_offset, data);
}
@@ -595,7 +595,8 @@ ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec
TimeValue object_mod_time;
object_mod_time.OffsetWithSeconds(object->ar_date);
spec.GetObjectName () = object->ar_name;
- spec.SetObjectOffset(object_file_offset);
+ spec.SetObjectOffset (object_file_offset)