1 //===-- RegisterContextPOSIX_mips64.cpp -------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include <cstring> 11 #include <errno.h> 12 #include <stdint.h> 13 14 #include "lldb/Target/Process.h" 15 #include "lldb/Target/Target.h" 16 #include "lldb/Target/Thread.h" 17 #include "lldb/Utility/DataBufferHeap.h" 18 #include "lldb/Utility/DataExtractor.h" 19 #include "lldb/Utility/Endian.h" 20 #include "lldb/Utility/RegisterValue.h" 21 #include "lldb/Utility/Scalar.h" 22 #include "llvm/Support/Compiler.h" 23 24 #include "RegisterContextPOSIX_mips64.h" 25 #include "RegisterContextFreeBSD_mips64.h" 26 #include "RegisterContextLinux_mips64.h" 27 #include "RegisterContextLinux_mips.h" 28 29 using namespace lldb_private; 30 using namespace lldb; 31 32 bool RegisterContextPOSIX_mips64::IsGPR(unsigned reg) { 33 return reg < m_registers_count[gpr_registers_count]; // GPR's come first. 34 } 35 36 bool RegisterContextPOSIX_mips64::IsFPR(unsigned reg) { 37 int set = GetRegisterSetCount(); 38 if (set > 1) 39 return reg < (m_registers_count[fpr_registers_count] 40 + m_registers_count[gpr_registers_count]); 41 return false; 42 } 43 44 RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64( 45 Thread &thread, uint32_t concrete_frame_idx, 46 RegisterInfoInterface *register_info) 47 : RegisterContext(thread, concrete_frame_idx) { 48 m_register_info_ap.reset(register_info); 49 m_num_registers = GetRegisterCount(); 50 int set = GetRegisterSetCount(); 51 52 const RegisterSet *reg_set_ptr; 53 for(int i = 0; i < set; ++i) { 54 reg_set_ptr = GetRegisterSet(i); 55 m_registers_count[i] = reg_set_ptr->num_registers; 56 } 57 58 assert(m_num_registers == 59 static_cast<uint32_t>(m_registers_count[gpr_registers_count] + 60 m_registers_count[fpr_registers_count] + 61 m_registers_count[msa_registers_count])); 62 } 63 64 RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() {} 65 66 void RegisterContextPOSIX_mips64::Invalidate() {} 67 68 void RegisterContextPOSIX_mips64::InvalidateAllRegisters() {} 69 70 unsigned RegisterContextPOSIX_mips64::GetRegisterOffset(unsigned reg) { 71 assert(reg < m_num_registers && "Invalid register number."); 72 return GetRegisterInfo()[reg].byte_offset; 73 } 74 75 unsigned RegisterContextPOSIX_mips64::GetRegisterSize(unsigned reg) { 76 assert(reg < m_num_registers && "Invalid register number."); 77 return GetRegisterInfo()[reg].byte_size; 78 } 79 80 size_t RegisterContextPOSIX_mips64::GetRegisterCount() { 81 return m_register_info_ap->GetRegisterCount(); 82 } 83 84 size_t RegisterContextPOSIX_mips64::GetGPRSize() { 85 return m_register_info_ap->GetGPRSize(); 86 } 87 88 const RegisterInfo *RegisterContextPOSIX_mips64::GetRegisterInfo() { 89 // Commonly, this method is overridden and g_register_infos is copied and 90 // specialized. So, use GetRegisterInfo() rather than g_register_infos in 91 // this scope. 92 return m_register_info_ap->GetRegisterInfo(); 93 } 94 95 const RegisterInfo * 96 RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) { 97 if (reg < m_num_registers) 98 return &GetRegisterInfo()[reg]; 99 else 100 return NULL; 101 } 102 103 size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() { 104 ArchSpec target_arch = m_register_info_ap->GetTargetArchitecture(); 105 switch (target_arch.GetTriple().getOS()) { 106 case llvm::Triple::Linux: { 107 if ((target_arch.GetMachine() == llvm::Triple::mipsel) || 108 (target_arch.GetMachine() == llvm::Triple::mips)) { 109 const auto *context = static_cast<const RegisterContextLinux_mips *> 110 (m_register_info_ap.get()); 111 return context->GetRegisterSetCount(); 112 } 113 const auto *context = static_cast<const RegisterContextLinux_mips64 *> 114 (m_register_info_ap.get()); 115 return context->GetRegisterSetCount(); 116 } 117 default: { 118 const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *> 119 (m_register_info_ap.get()); 120 return context->GetRegisterSetCount(); 121 } 122 123 } 124 } 125 126 const RegisterSet *RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) { 127 ArchSpec target_arch = m_register_info_ap->GetTargetArchitecture(); 128 switch (target_arch.GetTriple().getOS()) { 129 case llvm::Triple::Linux: { 130 if ((target_arch.GetMachine() == llvm::Triple::mipsel) || 131 (target_arch.GetMachine() == llvm::Triple::mips)) { 132 const auto *context = static_cast<const RegisterContextLinux_mips *> 133 (m_register_info_ap.get()); 134 return context->GetRegisterSet(set); 135 } 136 const auto *context = static_cast<const RegisterContextLinux_mips64 *> 137 (m_register_info_ap.get()); 138 return context->GetRegisterSet(set); 139 } 140 default: { 141 const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *> 142 (m_register_info_ap.get()); 143 return context->GetRegisterSet(set); 144 } 145 } 146 } 147 148 const char *RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg) { 149 assert(reg < m_num_registers && "Invalid register offset."); 150 return GetRegisterInfo()[reg].name; 151 } 152 153 lldb::ByteOrder RegisterContextPOSIX_mips64::GetByteOrder() { 154 // Get the target process whose privileged thread was used for the register 155 // read. 156 lldb::ByteOrder byte_order = eByteOrderInvalid; 157 Process *process = CalculateProcess().get(); 158 159 if (process) 160 byte_order = process->GetByteOrder(); 161 return byte_order; 162 } 163 164 bool RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) { 165 size_t num_sets = GetRegisterSetCount(); 166 167 return (set_index < num_sets); 168 } 169 170 // Used when parsing DWARF and EH frame information and any other object file 171 // sections that contain register numbers in them. 172 uint32_t RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber( 173 lldb::RegisterKind kind, uint32_t num) { 174 const uint32_t num_regs = m_num_registers; 175 176 assert(kind < kNumRegisterKinds); 177 for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { 178 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); 179 180 if (reg_info->kinds[kind] == num) 181 return reg_idx; 182 } 183 184 return LLDB_INVALID_REGNUM; 185 } 186