1 //===-- RegisterContextPOSIX_x86.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/Core/DataBufferHeap.h"
15 #include "lldb/Core/DataExtractor.h"
16 #include "lldb/Core/RegisterValue.h"
17 #include "lldb/Core/Scalar.h"
18 #include "lldb/Host/Endian.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "llvm/Support/Compiler.h"
23 
24 #include "RegisterContext_s390x.h"
25 #include "RegisterContextPOSIX_s390x.h"
26 
27 using namespace lldb_private;
28 using namespace lldb;
29 
30 // s390x 64-bit general purpose registers.
31 static const uint32_t g_gpr_regnums_s390x[] =
32 {
33     lldb_r0_s390x,
34     lldb_r1_s390x,
35     lldb_r2_s390x,
36     lldb_r3_s390x,
37     lldb_r4_s390x,
38     lldb_r5_s390x,
39     lldb_r6_s390x,
40     lldb_r7_s390x,
41     lldb_r8_s390x,
42     lldb_r9_s390x,
43     lldb_r10_s390x,
44     lldb_r11_s390x,
45     lldb_r12_s390x,
46     lldb_r13_s390x,
47     lldb_r14_s390x,
48     lldb_r15_s390x,
49     lldb_acr0_s390x,
50     lldb_acr1_s390x,
51     lldb_acr2_s390x,
52     lldb_acr3_s390x,
53     lldb_acr4_s390x,
54     lldb_acr5_s390x,
55     lldb_acr6_s390x,
56     lldb_acr7_s390x,
57     lldb_acr8_s390x,
58     lldb_acr9_s390x,
59     lldb_acr10_s390x,
60     lldb_acr11_s390x,
61     lldb_acr12_s390x,
62     lldb_acr13_s390x,
63     lldb_acr14_s390x,
64     lldb_acr15_s390x,
65     lldb_pswm_s390x,
66     lldb_pswa_s390x,
67     LLDB_INVALID_REGNUM // register sets need to end with this flag
68 };
69 static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x,
70               "g_gpr_regnums_s390x has wrong number of register infos");
71 
72 // s390x 64-bit floating point registers.
73 static const uint32_t g_fpu_regnums_s390x[] =
74 {
75     lldb_f0_s390x,
76     lldb_f1_s390x,
77     lldb_f2_s390x,
78     lldb_f3_s390x,
79     lldb_f4_s390x,
80     lldb_f5_s390x,
81     lldb_f6_s390x,
82     lldb_f7_s390x,
83     lldb_f8_s390x,
84     lldb_f9_s390x,
85     lldb_f10_s390x,
86     lldb_f11_s390x,
87     lldb_f12_s390x,
88     lldb_f13_s390x,
89     lldb_f14_s390x,
90     lldb_f15_s390x,
91     lldb_fpc_s390x,
92     LLDB_INVALID_REGNUM // register sets need to end with this flag
93 };
94 static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x,
95               "g_fpu_regnums_s390x has wrong number of register infos");
96 
97 // Number of register sets provided by this context.
98 enum
99 {
100     k_num_register_sets = 2
101 };
102 
103 // Register sets for s390x 64-bit.
104 static const RegisterSet g_reg_sets_s390x[k_num_register_sets] =
105 {
106     { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x },
107     { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x },
108 };
109 
110 bool
111 RegisterContextPOSIX_s390x::IsGPR(unsigned reg)
112 {
113     return reg <= m_reg_info.last_gpr; // GPRs come first.
114 }
115 
116 bool
117 RegisterContextPOSIX_s390x::IsFPR(unsigned reg)
118 {
119     return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
120 }
121 
122 RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x(Thread &thread, uint32_t concrete_frame_idx,
123                                                        RegisterInfoInterface *register_info)
124     : RegisterContext(thread, concrete_frame_idx)
125 {
126     m_register_info_ap.reset(register_info);
127 
128     switch (register_info->m_target_arch.GetMachine())
129     {
130         case llvm::Triple::systemz:
131             m_reg_info.num_registers = k_num_registers_s390x;
132             m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x;
133             m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x;
134             m_reg_info.last_gpr = k_last_gpr_s390x;
135             m_reg_info.first_fpr = k_first_fpr_s390x;
136             m_reg_info.last_fpr = k_last_fpr_s390x;
137             break;
138         default:
139             assert(false && "Unhandled target architecture.");
140             break;
141     }
142 }
143 
144 RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x()
145 {
146 }
147 
148 void
149 RegisterContextPOSIX_s390x::Invalidate()
150 {
151 }
152 
153 void
154 RegisterContextPOSIX_s390x::InvalidateAllRegisters()
155 {
156 }
157 
158 const RegisterInfo *
159 RegisterContextPOSIX_s390x::GetRegisterInfo()
160 {
161     return m_register_info_ap->GetRegisterInfo();
162 }
163 
164 const RegisterInfo *
165 RegisterContextPOSIX_s390x::GetRegisterInfoAtIndex(size_t reg)
166 {
167     if (reg < m_reg_info.num_registers)
168         return &GetRegisterInfo()[reg];
169     else
170         return NULL;
171 }
172 
173 size_t
174 RegisterContextPOSIX_s390x::GetRegisterCount()
175 {
176     return m_reg_info.num_registers;
177 }
178 
179 unsigned
180 RegisterContextPOSIX_s390x::GetRegisterOffset(unsigned reg)
181 {
182     assert(reg < m_reg_info.num_registers && "Invalid register number.");
183     return GetRegisterInfo()[reg].byte_offset;
184 }
185 
186 unsigned
187 RegisterContextPOSIX_s390x::GetRegisterSize(unsigned reg)
188 {
189     assert(reg < m_reg_info.num_registers && "Invalid register number.");
190     return GetRegisterInfo()[reg].byte_size;
191 }
192 
193 const char *
194 RegisterContextPOSIX_s390x::GetRegisterName(unsigned reg)
195 {
196     assert(reg < m_reg_info.num_registers && "Invalid register offset.");
197     return GetRegisterInfo()[reg].name;
198 }
199 
200 bool
201 RegisterContextPOSIX_s390x::IsRegisterSetAvailable(size_t set_index)
202 {
203     return set_index < k_num_register_sets;
204 }
205 
206 size_t
207 RegisterContextPOSIX_s390x::GetRegisterSetCount()
208 {
209     size_t sets = 0;
210     for (size_t set = 0; set < k_num_register_sets; ++set)
211     {
212         if (IsRegisterSetAvailable(set))
213             ++sets;
214     }
215 
216     return sets;
217 }
218 
219 const RegisterSet *
220 RegisterContextPOSIX_s390x::GetRegisterSet(size_t set)
221 {
222     if (IsRegisterSetAvailable(set))
223     {
224         switch (m_register_info_ap->m_target_arch.GetMachine())
225         {
226             case llvm::Triple::systemz:
227                 return &g_reg_sets_s390x[set];
228             default:
229                 assert(false && "Unhandled target architecture.");
230                 return NULL;
231         }
232     }
233     return NULL;
234 }
235 
236 lldb::ByteOrder
237 RegisterContextPOSIX_s390x::GetByteOrder()
238 {
239     // Get the target process whose privileged thread was used for the register read.
240     lldb::ByteOrder byte_order = eByteOrderInvalid;
241     Process *process = CalculateProcess().get();
242 
243     if (process)
244         byte_order = process->GetByteOrder();
245     return byte_order;
246 }
247 
248 // Used when parsing DWARF and EH frame information and any other
249 // object file sections that contain register numbers in them.
250 uint32_t
251 RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)
252 {
253     const uint32_t num_regs = GetRegisterCount();
254 
255     assert(kind < kNumRegisterKinds);
256     for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
257     {
258         const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
259 
260         if (reg_info->kinds[kind] == num)
261             return reg_idx;
262     }
263 
264     return LLDB_INVALID_REGNUM;
265 }
266