11c3bbb01SEd Maste //===-- RegisterContextLinux_mips64.cpp ------------------------*- C++ -*-===//
21c3bbb01SEd Maste //
31c3bbb01SEd Maste //                     The LLVM Compiler Infrastructure
41c3bbb01SEd Maste //
51c3bbb01SEd Maste // This file is distributed under the University of Illinois Open Source
61c3bbb01SEd Maste // License. See LICENSE.TXT for details.
71c3bbb01SEd Maste //
81c3bbb01SEd Maste //===---------------------------------------------------------------------===//
91c3bbb01SEd Maste 
101c3bbb01SEd Maste 
111c3bbb01SEd Maste #include <stddef.h>
12435933ddSDimitry Andric #include <vector>
131c3bbb01SEd Maste 
149f2f44ceSEd Maste // For eh_frame and DWARF Register numbers
151c3bbb01SEd Maste #include "RegisterContextLinux_mips64.h"
161c3bbb01SEd Maste 
17b6c25e0eSDimitry Andric // For GP and FP buffers
18b6c25e0eSDimitry Andric #include "RegisterContext_mips.h"
19b6c25e0eSDimitry Andric 
20b6c25e0eSDimitry Andric // Internal codes for all mips32 and mips64 registers
21b6c25e0eSDimitry Andric #include "lldb-mips-linux-register-enums.h"
221c3bbb01SEd Maste 
231c3bbb01SEd Maste using namespace lldb;
241c3bbb01SEd Maste using namespace lldb_private;
251c3bbb01SEd Maste 
261c3bbb01SEd Maste //---------------------------------------------------------------------------
27435933ddSDimitry Andric // Include RegisterInfos_mips64 to declare our g_register_infos_mips64
28435933ddSDimitry Andric // structure.
291c3bbb01SEd Maste //---------------------------------------------------------------------------
301c3bbb01SEd Maste #define DECLARE_REGISTER_INFOS_MIPS64_STRUCT
31b6c25e0eSDimitry Andric #define LINUX_MIPS64
321c3bbb01SEd Maste #include "RegisterInfos_mips64.h"
33b6c25e0eSDimitry Andric #undef LINUX_MIPS64
341c3bbb01SEd Maste #undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
351c3bbb01SEd Maste 
361c3bbb01SEd Maste //---------------------------------------------------------------------------
371c3bbb01SEd Maste // Include RegisterInfos_mips to declare our g_register_infos_mips structure.
381c3bbb01SEd Maste //---------------------------------------------------------------------------
391c3bbb01SEd Maste #define DECLARE_REGISTER_INFOS_MIPS_STRUCT
401c3bbb01SEd Maste #include "RegisterInfos_mips.h"
411c3bbb01SEd Maste #undef DECLARE_REGISTER_INFOS_MIPS_STRUCT
421c3bbb01SEd Maste 
43*f678e45dSDimitry Andric // mips64 general purpose registers.
44*f678e45dSDimitry Andric const uint32_t g_gp_regnums_mips64[] = {
45*f678e45dSDimitry Andric     gpr_zero_mips64,    gpr_r1_mips64,    gpr_r2_mips64,
46*f678e45dSDimitry Andric     gpr_r3_mips64,      gpr_r4_mips64,    gpr_r5_mips64,
47*f678e45dSDimitry Andric     gpr_r6_mips64,      gpr_r7_mips64,    gpr_r8_mips64,
48*f678e45dSDimitry Andric     gpr_r9_mips64,      gpr_r10_mips64,   gpr_r11_mips64,
49*f678e45dSDimitry Andric     gpr_r12_mips64,     gpr_r13_mips64,   gpr_r14_mips64,
50*f678e45dSDimitry Andric     gpr_r15_mips64,     gpr_r16_mips64,   gpr_r17_mips64,
51*f678e45dSDimitry Andric     gpr_r18_mips64,     gpr_r19_mips64,   gpr_r20_mips64,
52*f678e45dSDimitry Andric     gpr_r21_mips64,     gpr_r22_mips64,   gpr_r23_mips64,
53*f678e45dSDimitry Andric     gpr_r24_mips64,     gpr_r25_mips64,   gpr_r26_mips64,
54*f678e45dSDimitry Andric     gpr_r27_mips64,     gpr_gp_mips64,    gpr_sp_mips64,
55*f678e45dSDimitry Andric     gpr_r30_mips64,     gpr_ra_mips64,    gpr_sr_mips64,
56*f678e45dSDimitry Andric     gpr_mullo_mips64,   gpr_mulhi_mips64, gpr_badvaddr_mips64,
57*f678e45dSDimitry Andric     gpr_cause_mips64,   gpr_pc_mips64,    gpr_config5_mips64,
58*f678e45dSDimitry Andric     LLDB_INVALID_REGNUM // register sets need to end with this flag
59*f678e45dSDimitry Andric };
60*f678e45dSDimitry Andric 
61*f678e45dSDimitry Andric static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) -
62*f678e45dSDimitry Andric                       1 ==
63*f678e45dSDimitry Andric                   k_num_gpr_registers_mips64,
64*f678e45dSDimitry Andric               "g_gp_regnums_mips64 has wrong number of register infos");
65*f678e45dSDimitry Andric 
66*f678e45dSDimitry Andric // mips64 floating point registers.
67*f678e45dSDimitry Andric const uint32_t g_fp_regnums_mips64[] = {
68*f678e45dSDimitry Andric     fpr_f0_mips64,      fpr_f1_mips64,  fpr_f2_mips64,      fpr_f3_mips64,
69*f678e45dSDimitry Andric     fpr_f4_mips64,      fpr_f5_mips64,  fpr_f6_mips64,      fpr_f7_mips64,
70*f678e45dSDimitry Andric     fpr_f8_mips64,      fpr_f9_mips64,  fpr_f10_mips64,     fpr_f11_mips64,
71*f678e45dSDimitry Andric     fpr_f12_mips64,     fpr_f13_mips64, fpr_f14_mips64,     fpr_f15_mips64,
72*f678e45dSDimitry Andric     fpr_f16_mips64,     fpr_f17_mips64, fpr_f18_mips64,     fpr_f19_mips64,
73*f678e45dSDimitry Andric     fpr_f20_mips64,     fpr_f21_mips64, fpr_f22_mips64,     fpr_f23_mips64,
74*f678e45dSDimitry Andric     fpr_f24_mips64,     fpr_f25_mips64, fpr_f26_mips64,     fpr_f27_mips64,
75*f678e45dSDimitry Andric     fpr_f28_mips64,     fpr_f29_mips64, fpr_f30_mips64,     fpr_f31_mips64,
76*f678e45dSDimitry Andric     fpr_fcsr_mips64,    fpr_fir_mips64, fpr_config5_mips64,
77*f678e45dSDimitry Andric     LLDB_INVALID_REGNUM // register sets need to end with this flag
78*f678e45dSDimitry Andric };
79*f678e45dSDimitry Andric 
80*f678e45dSDimitry Andric static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) -
81*f678e45dSDimitry Andric                       1 ==
82*f678e45dSDimitry Andric                   k_num_fpr_registers_mips64,
83*f678e45dSDimitry Andric               "g_fp_regnums_mips64 has wrong number of register infos");
84*f678e45dSDimitry Andric 
85*f678e45dSDimitry Andric // mips64 MSA registers.
86*f678e45dSDimitry Andric const uint32_t g_msa_regnums_mips64[] = {
87*f678e45dSDimitry Andric     msa_w0_mips64,      msa_w1_mips64,  msa_w2_mips64,   msa_w3_mips64,
88*f678e45dSDimitry Andric     msa_w4_mips64,      msa_w5_mips64,  msa_w6_mips64,   msa_w7_mips64,
89*f678e45dSDimitry Andric     msa_w8_mips64,      msa_w9_mips64,  msa_w10_mips64,  msa_w11_mips64,
90*f678e45dSDimitry Andric     msa_w12_mips64,     msa_w13_mips64, msa_w14_mips64,  msa_w15_mips64,
91*f678e45dSDimitry Andric     msa_w16_mips64,     msa_w17_mips64, msa_w18_mips64,  msa_w19_mips64,
92*f678e45dSDimitry Andric     msa_w20_mips64,     msa_w21_mips64, msa_w22_mips64,  msa_w23_mips64,
93*f678e45dSDimitry Andric     msa_w24_mips64,     msa_w25_mips64, msa_w26_mips64,  msa_w27_mips64,
94*f678e45dSDimitry Andric     msa_w28_mips64,     msa_w29_mips64, msa_w30_mips64,  msa_w31_mips64,
95*f678e45dSDimitry Andric     msa_fcsr_mips64,    msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64,
96*f678e45dSDimitry Andric     msa_config5_mips64,
97*f678e45dSDimitry Andric     LLDB_INVALID_REGNUM // register sets need to end with this flag
98*f678e45dSDimitry Andric };
99*f678e45dSDimitry Andric 
100*f678e45dSDimitry Andric static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) -
101*f678e45dSDimitry Andric                       1 ==
102*f678e45dSDimitry Andric                   k_num_msa_registers_mips64,
103*f678e45dSDimitry Andric               "g_msa_regnums_mips64 has wrong number of register infos");
104*f678e45dSDimitry Andric 
105*f678e45dSDimitry Andric // Number of register sets provided by this context.
106*f678e45dSDimitry Andric constexpr size_t k_num_register_sets = 3;
107*f678e45dSDimitry Andric 
108*f678e45dSDimitry Andric // Register sets for mips64.
109*f678e45dSDimitry Andric static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = {
110*f678e45dSDimitry Andric     {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64,
111*f678e45dSDimitry Andric      g_gp_regnums_mips64},
112*f678e45dSDimitry Andric     {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64,
113*f678e45dSDimitry Andric      g_fp_regnums_mips64},
114*f678e45dSDimitry Andric     {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64},
115*f678e45dSDimitry Andric };
116*f678e45dSDimitry Andric 
117*f678e45dSDimitry Andric const RegisterSet *
GetRegisterSet(size_t set) const118*f678e45dSDimitry Andric RegisterContextLinux_mips64::GetRegisterSet(size_t set) const {
119*f678e45dSDimitry Andric   if (set >= k_num_register_sets)
120*f678e45dSDimitry Andric     return nullptr;
121*f678e45dSDimitry Andric 
122*f678e45dSDimitry Andric   switch (m_target_arch.GetMachine()) {
123*f678e45dSDimitry Andric   case llvm::Triple::mips64:
124*f678e45dSDimitry Andric   case llvm::Triple::mips64el:
125*f678e45dSDimitry Andric     return &g_reg_sets_mips64[set];
126*f678e45dSDimitry Andric   default:
127*f678e45dSDimitry Andric     assert(false && "Unhandled target architecture.");
128*f678e45dSDimitry Andric     return nullptr;
129*f678e45dSDimitry Andric   }
130*f678e45dSDimitry Andric   return nullptr;
131*f678e45dSDimitry Andric }
132*f678e45dSDimitry Andric 
133*f678e45dSDimitry Andric size_t
GetRegisterSetCount() const134*f678e45dSDimitry Andric RegisterContextLinux_mips64::GetRegisterSetCount() const {
135*f678e45dSDimitry Andric   return k_num_register_sets;
136*f678e45dSDimitry Andric }
137*f678e45dSDimitry Andric 
GetRegisterInfoPtr(const ArchSpec & target_arch)138435933ddSDimitry Andric static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) {
139435933ddSDimitry Andric   switch (target_arch.GetMachine()) {
1401c3bbb01SEd Maste   case llvm::Triple::mips64:
1411c3bbb01SEd Maste   case llvm::Triple::mips64el:
1421c3bbb01SEd Maste     return g_register_infos_mips64;
1431c3bbb01SEd Maste   case llvm::Triple::mips:
1441c3bbb01SEd Maste   case llvm::Triple::mipsel:
1451c3bbb01SEd Maste     return g_register_infos_mips;
1461c3bbb01SEd Maste   default:
1471c3bbb01SEd Maste     assert(false && "Unhandled target architecture.");
1481c3bbb01SEd Maste     return nullptr;
1491c3bbb01SEd Maste   }
1501c3bbb01SEd Maste }
1511c3bbb01SEd Maste 
GetRegisterInfoCount(const ArchSpec & target_arch)152435933ddSDimitry Andric static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) {
153435933ddSDimitry Andric   switch (target_arch.GetMachine()) {
1541c3bbb01SEd Maste   case llvm::Triple::mips64:
1551c3bbb01SEd Maste   case llvm::Triple::mips64el:
156435933ddSDimitry Andric     return static_cast<uint32_t>(sizeof(g_register_infos_mips64) /
157435933ddSDimitry Andric                                  sizeof(g_register_infos_mips64[0]));
1581c3bbb01SEd Maste   case llvm::Triple::mips:
1591c3bbb01SEd Maste   case llvm::Triple::mipsel:
160435933ddSDimitry Andric     return static_cast<uint32_t>(sizeof(g_register_infos_mips) /
161435933ddSDimitry Andric                                  sizeof(g_register_infos_mips[0]));
1621c3bbb01SEd Maste   default:
1631c3bbb01SEd Maste     assert(false && "Unhandled target architecture.");
1641c3bbb01SEd Maste     return 0;
1651c3bbb01SEd Maste   }
1661c3bbb01SEd Maste }
1671c3bbb01SEd Maste 
GetUserRegisterInfoCount(const ArchSpec & target_arch,bool msa_present)168435933ddSDimitry Andric uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch,
169435933ddSDimitry Andric                                   bool msa_present) {
170435933ddSDimitry Andric   switch (target_arch.GetMachine()) {
171b6c25e0eSDimitry Andric   case llvm::Triple::mips:
172b6c25e0eSDimitry Andric   case llvm::Triple::mipsel:
1739f2f44ceSEd Maste     if (msa_present)
174b6c25e0eSDimitry Andric       return static_cast<uint32_t>(k_num_user_registers_mips);
175435933ddSDimitry Andric     return static_cast<uint32_t>(k_num_user_registers_mips -
176435933ddSDimitry Andric                                  k_num_msa_registers_mips);
177b6c25e0eSDimitry Andric   case llvm::Triple::mips64el:
178b6c25e0eSDimitry Andric   case llvm::Triple::mips64:
1799f2f44ceSEd Maste     if (msa_present)
180b6c25e0eSDimitry Andric       return static_cast<uint32_t>(k_num_user_registers_mips64);
181435933ddSDimitry Andric     return static_cast<uint32_t>(k_num_user_registers_mips64 -
182435933ddSDimitry Andric                                  k_num_msa_registers_mips64);
183b6c25e0eSDimitry Andric   default:
184b6c25e0eSDimitry Andric     assert(false && "Unhandled target architecture.");
185b6c25e0eSDimitry Andric     return 0;
186b6c25e0eSDimitry Andric   }
187b6c25e0eSDimitry Andric }
188b6c25e0eSDimitry Andric 
RegisterContextLinux_mips64(const ArchSpec & target_arch,bool msa_present)189435933ddSDimitry Andric RegisterContextLinux_mips64::RegisterContextLinux_mips64(
190435933ddSDimitry Andric     const ArchSpec &target_arch, bool msa_present)
191435933ddSDimitry Andric     : lldb_private::RegisterInfoInterface(target_arch),
1921c3bbb01SEd Maste       m_register_info_p(GetRegisterInfoPtr(target_arch)),
193b6c25e0eSDimitry Andric       m_register_info_count(GetRegisterInfoCount(target_arch)),
194435933ddSDimitry Andric       m_user_register_count(
195435933ddSDimitry Andric           GetUserRegisterInfoCount(target_arch, msa_present)) {}
1961c3bbb01SEd Maste 
GetGPRSize() const197435933ddSDimitry Andric size_t RegisterContextLinux_mips64::GetGPRSize() const {
198b6c25e0eSDimitry Andric   return sizeof(GPR_linux_mips);
1991c3bbb01SEd Maste }
2001c3bbb01SEd Maste 
GetRegisterInfo() const201435933ddSDimitry Andric const RegisterInfo *RegisterContextLinux_mips64::GetRegisterInfo() const {
2021c3bbb01SEd Maste   return m_register_info_p;
2031c3bbb01SEd Maste }
2041c3bbb01SEd Maste 
GetRegisterCount() const205435933ddSDimitry Andric uint32_t RegisterContextLinux_mips64::GetRegisterCount() const {
2061c3bbb01SEd Maste   return m_register_info_count;
2071c3bbb01SEd Maste }
2081c3bbb01SEd Maste 
GetUserRegisterCount() const209435933ddSDimitry Andric uint32_t RegisterContextLinux_mips64::GetUserRegisterCount() const {
210b6c25e0eSDimitry Andric   return m_user_register_count;
211b6c25e0eSDimitry Andric }
212b6c25e0eSDimitry Andric 
213