1 //===-- ABISysV_s390x.cpp -------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "ABISysV_s390x.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/TargetParser/Triple.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Value.h"
17 #include "lldb/Symbol/UnwindPlan.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/StackFrame.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Utility/ConstString.h"
24 #include "lldb/Utility/DataExtractor.h"
25 #include "lldb/Utility/LLDBLog.h"
26 #include "lldb/Utility/Log.h"
27 #include "lldb/Utility/RegisterValue.h"
28 #include "lldb/Utility/Status.h"
29 #include "lldb/ValueObject/ValueObjectConstResult.h"
30 #include "lldb/ValueObject/ValueObjectMemory.h"
31 #include "lldb/ValueObject/ValueObjectRegister.h"
35 using namespace lldb_private
;
37 LLDB_PLUGIN_DEFINE_ADV(ABISysV_s390x
, ABISystemZ
)
40 // General Purpose Registers
57 // Floating Point Registers / Vector Registers 0-15
75 dwarf_acr0_s390x
= 48,
91 // Program Status Word
92 dwarf_pswm_s390x
= 64,
94 // Vector Registers 16-31
113 // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
115 #define DEFINE_REG(name, size, alt, generic) \
117 #name, alt, size, 0, eEncodingUint, eFormatHex, \
118 {dwarf_##name##_s390x, dwarf_##name##_s390x, generic, \
119 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, \
120 nullptr, nullptr, nullptr, \
123 static const RegisterInfo g_register_infos
[] = {
124 DEFINE_REG(r0
, 8, nullptr, LLDB_INVALID_REGNUM
),
125 DEFINE_REG(r1
, 8, nullptr, LLDB_INVALID_REGNUM
),
126 DEFINE_REG(r2
, 8, nullptr, LLDB_REGNUM_GENERIC_ARG1
),
127 DEFINE_REG(r3
, 8, nullptr, LLDB_REGNUM_GENERIC_ARG2
),
128 DEFINE_REG(r4
, 8, nullptr, LLDB_REGNUM_GENERIC_ARG3
),
129 DEFINE_REG(r5
, 8, nullptr, LLDB_REGNUM_GENERIC_ARG4
),
130 DEFINE_REG(r6
, 8, nullptr, LLDB_REGNUM_GENERIC_ARG5
),
131 DEFINE_REG(r7
, 8, nullptr, LLDB_INVALID_REGNUM
),
132 DEFINE_REG(r8
, 8, nullptr, LLDB_INVALID_REGNUM
),
133 DEFINE_REG(r9
, 8, nullptr, LLDB_INVALID_REGNUM
),
134 DEFINE_REG(r10
, 8, nullptr, LLDB_INVALID_REGNUM
),
135 DEFINE_REG(r11
, 8, nullptr, LLDB_REGNUM_GENERIC_FP
),
136 DEFINE_REG(r12
, 8, nullptr, LLDB_INVALID_REGNUM
),
137 DEFINE_REG(r13
, 8, nullptr, LLDB_INVALID_REGNUM
),
138 DEFINE_REG(r14
, 8, nullptr, LLDB_INVALID_REGNUM
),
139 DEFINE_REG(r15
, 8, "sp", LLDB_REGNUM_GENERIC_SP
),
140 DEFINE_REG(acr0
, 4, nullptr, LLDB_INVALID_REGNUM
),
141 DEFINE_REG(acr1
, 4, nullptr, LLDB_INVALID_REGNUM
),
142 DEFINE_REG(acr2
, 4, nullptr, LLDB_INVALID_REGNUM
),
143 DEFINE_REG(acr3
, 4, nullptr, LLDB_INVALID_REGNUM
),
144 DEFINE_REG(acr4
, 4, nullptr, LLDB_INVALID_REGNUM
),
145 DEFINE_REG(acr5
, 4, nullptr, LLDB_INVALID_REGNUM
),
146 DEFINE_REG(acr6
, 4, nullptr, LLDB_INVALID_REGNUM
),
147 DEFINE_REG(acr7
, 4, nullptr, LLDB_INVALID_REGNUM
),
148 DEFINE_REG(acr8
, 4, nullptr, LLDB_INVALID_REGNUM
),
149 DEFINE_REG(acr9
, 4, nullptr, LLDB_INVALID_REGNUM
),
150 DEFINE_REG(acr10
, 4, nullptr, LLDB_INVALID_REGNUM
),
151 DEFINE_REG(acr11
, 4, nullptr, LLDB_INVALID_REGNUM
),
152 DEFINE_REG(acr12
, 4, nullptr, LLDB_INVALID_REGNUM
),
153 DEFINE_REG(acr13
, 4, nullptr, LLDB_INVALID_REGNUM
),
154 DEFINE_REG(acr14
, 4, nullptr, LLDB_INVALID_REGNUM
),
155 DEFINE_REG(acr15
, 4, nullptr, LLDB_INVALID_REGNUM
),
156 DEFINE_REG(pswm
, 8, nullptr, LLDB_REGNUM_GENERIC_FLAGS
),
157 DEFINE_REG(pswa
, 8, nullptr, LLDB_REGNUM_GENERIC_PC
),
158 DEFINE_REG(f0
, 8, nullptr, LLDB_INVALID_REGNUM
),
159 DEFINE_REG(f1
, 8, nullptr, LLDB_INVALID_REGNUM
),
160 DEFINE_REG(f2
, 8, nullptr, LLDB_INVALID_REGNUM
),
161 DEFINE_REG(f3
, 8, nullptr, LLDB_INVALID_REGNUM
),
162 DEFINE_REG(f4
, 8, nullptr, LLDB_INVALID_REGNUM
),
163 DEFINE_REG(f5
, 8, nullptr, LLDB_INVALID_REGNUM
),
164 DEFINE_REG(f6
, 8, nullptr, LLDB_INVALID_REGNUM
),
165 DEFINE_REG(f7
, 8, nullptr, LLDB_INVALID_REGNUM
),
166 DEFINE_REG(f8
, 8, nullptr, LLDB_INVALID_REGNUM
),
167 DEFINE_REG(f9
, 8, nullptr, LLDB_INVALID_REGNUM
),
168 DEFINE_REG(f10
, 8, nullptr, LLDB_INVALID_REGNUM
),
169 DEFINE_REG(f11
, 8, nullptr, LLDB_INVALID_REGNUM
),
170 DEFINE_REG(f12
, 8, nullptr, LLDB_INVALID_REGNUM
),
171 DEFINE_REG(f13
, 8, nullptr, LLDB_INVALID_REGNUM
),
172 DEFINE_REG(f14
, 8, nullptr, LLDB_INVALID_REGNUM
),
173 DEFINE_REG(f15
, 8, nullptr, LLDB_INVALID_REGNUM
),
176 static const uint32_t k_num_register_infos
= std::size(g_register_infos
);
178 const lldb_private::RegisterInfo
*
179 ABISysV_s390x::GetRegisterInfoArray(uint32_t &count
) {
180 count
= k_num_register_infos
;
181 return g_register_infos
;
184 size_t ABISysV_s390x::GetRedZoneSize() const { return 0; }
189 ABISysV_s390x::CreateInstance(lldb::ProcessSP process_sp
, const ArchSpec
&arch
) {
190 if (arch
.GetTriple().getArch() == llvm::Triple::systemz
) {
191 return ABISP(new ABISysV_s390x(std::move(process_sp
), MakeMCRegisterInfo(arch
)));
196 bool ABISysV_s390x::PrepareTrivialCall(Thread
&thread
, addr_t sp
,
197 addr_t func_addr
, addr_t return_addr
,
198 llvm::ArrayRef
<addr_t
> args
) const {
199 Log
*log
= GetLog(LLDBLog::Expressions
);
203 s
.Printf("ABISysV_s390x::PrepareTrivialCall (tid = 0x%" PRIx64
204 ", sp = 0x%" PRIx64
", func_addr = 0x%" PRIx64
205 ", return_addr = 0x%" PRIx64
,
206 thread
.GetID(), (uint64_t)sp
, (uint64_t)func_addr
,
207 (uint64_t)return_addr
);
209 for (size_t i
= 0; i
< args
.size(); ++i
)
210 s
.Printf(", arg%" PRIu64
" = 0x%" PRIx64
, static_cast<uint64_t>(i
+ 1),
213 log
->PutString(s
.GetString());
216 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
220 const RegisterInfo
*pc_reg_info
=
221 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
222 const RegisterInfo
*sp_reg_info
=
223 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
224 const RegisterInfo
*ra_reg_info
= reg_ctx
->GetRegisterInfoByName("r14", 0);
225 ProcessSP
process_sp(thread
.GetProcess());
227 // Allocate a new stack frame and space for stack arguments if necessary
230 if (args
.size() > 5) {
231 sp
-= 8 * (args
.size() - 5);
239 for (size_t i
= 0; i
< args
.size(); ++i
) {
241 const RegisterInfo
*reg_info
= reg_ctx
->GetRegisterInfo(
242 eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG1
+ i
);
243 LLDB_LOGF(log
, "About to write arg%" PRIu64
" (0x%" PRIx64
") into %s",
244 static_cast<uint64_t>(i
+ 1), args
[i
], reg_info
->name
);
245 if (!reg_ctx
->WriteRegisterFromUnsigned(reg_info
, args
[i
]))
249 LLDB_LOGF(log
, "About to write arg%" PRIu64
" (0x%" PRIx64
") onto stack",
250 static_cast<uint64_t>(i
+ 1), args
[i
]);
251 if (!process_sp
->WritePointerToMemory(arg_pos
, args
[i
], error
))
257 // %r14 is set to the return address
259 LLDB_LOGF(log
, "Writing RA: 0x%" PRIx64
, (uint64_t)return_addr
);
261 if (!reg_ctx
->WriteRegisterFromUnsigned(ra_reg_info
, return_addr
))
264 // %r15 is set to the actual stack value.
266 LLDB_LOGF(log
, "Writing SP: 0x%" PRIx64
, (uint64_t)sp
);
268 if (!reg_ctx
->WriteRegisterFromUnsigned(sp_reg_info
, sp
))
271 // %pc is set to the address of the called function.
273 LLDB_LOGF(log
, "Writing PC: 0x%" PRIx64
, (uint64_t)func_addr
);
275 if (!reg_ctx
->WriteRegisterFromUnsigned(pc_reg_info
, func_addr
))
281 static bool ReadIntegerArgument(Scalar
&scalar
, unsigned int bit_width
,
282 bool is_signed
, Thread
&thread
,
283 uint32_t *argument_register_ids
,
284 unsigned int ¤t_argument_register
,
285 addr_t
¤t_stack_argument
) {
287 return false; // Scalar can't hold large integer arguments
289 if (current_argument_register
< 5) {
290 scalar
= thread
.GetRegisterContext()->ReadRegisterAsUnsigned(
291 argument_register_ids
[current_argument_register
], 0);
292 current_argument_register
++;
294 scalar
.SignExtend(bit_width
);
296 uint32_t byte_size
= (bit_width
+ (8 - 1)) / 8;
298 if (thread
.GetProcess()->ReadScalarIntegerFromMemory(
299 current_stack_argument
+ 8 - byte_size
, byte_size
, is_signed
,
301 current_stack_argument
+= 8;
309 bool ABISysV_s390x::GetArgumentValues(Thread
&thread
, ValueList
&values
) const {
310 unsigned int num_values
= values
.GetSize();
311 unsigned int value_index
;
313 // Extract the register context so we can read arguments from registers
315 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
320 // Get the pointer to the first stack argument so we have a place to start
323 addr_t sp
= reg_ctx
->GetSP(0);
328 addr_t current_stack_argument
= sp
+ 160;
330 uint32_t argument_register_ids
[5];
332 argument_register_ids
[0] =
333 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG1
)
334 ->kinds
[eRegisterKindLLDB
];
335 argument_register_ids
[1] =
336 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG2
)
337 ->kinds
[eRegisterKindLLDB
];
338 argument_register_ids
[2] =
339 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG3
)
340 ->kinds
[eRegisterKindLLDB
];
341 argument_register_ids
[3] =
342 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG4
)
343 ->kinds
[eRegisterKindLLDB
];
344 argument_register_ids
[4] =
345 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_ARG5
)
346 ->kinds
[eRegisterKindLLDB
];
348 unsigned int current_argument_register
= 0;
350 for (value_index
= 0; value_index
< num_values
; ++value_index
) {
351 Value
*value
= values
.GetValueAtIndex(value_index
);
356 // We currently only support extracting values with Clang QualTypes. Do we
357 // care about others?
358 CompilerType compiler_type
= value
->GetCompilerType();
359 std::optional
<uint64_t> bit_size
= compiler_type
.GetBitSize(&thread
);
364 if (compiler_type
.IsIntegerOrEnumerationType(is_signed
)) {
365 ReadIntegerArgument(value
->GetScalar(), *bit_size
, is_signed
, thread
,
366 argument_register_ids
, current_argument_register
,
367 current_stack_argument
);
368 } else if (compiler_type
.IsPointerType()) {
369 ReadIntegerArgument(value
->GetScalar(), *bit_size
, false, thread
,
370 argument_register_ids
, current_argument_register
,
371 current_stack_argument
);
378 Status
ABISysV_s390x::SetReturnValueObject(lldb::StackFrameSP
&frame_sp
,
379 lldb::ValueObjectSP
&new_value_sp
) {
382 error
= Status::FromErrorString("Empty value object for return value.");
386 CompilerType compiler_type
= new_value_sp
->GetCompilerType();
387 if (!compiler_type
) {
388 error
= Status::FromErrorString("Null clang type for return value.");
392 Thread
*thread
= frame_sp
->GetThread().get();
398 RegisterContext
*reg_ctx
= thread
->GetRegisterContext().get();
400 bool set_it_simple
= false;
401 if (compiler_type
.IsIntegerOrEnumerationType(is_signed
) ||
402 compiler_type
.IsPointerType()) {
403 const RegisterInfo
*reg_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
407 size_t num_bytes
= new_value_sp
->GetData(data
, data_error
);
408 if (data_error
.Fail()) {
409 error
= Status::FromErrorStringWithFormat(
410 "Couldn't convert return value to raw data: %s",
411 data_error
.AsCString());
414 lldb::offset_t offset
= 0;
415 if (num_bytes
<= 8) {
416 uint64_t raw_value
= data
.GetMaxU64(&offset
, num_bytes
);
418 if (reg_ctx
->WriteRegisterFromUnsigned(reg_info
, raw_value
))
419 set_it_simple
= true;
421 error
= Status::FromErrorString(
422 "We don't support returning longer than 64 bit "
423 "integer values at present.");
425 } else if (compiler_type
.IsFloatingPointType(count
, is_complex
)) {
427 error
= Status::FromErrorString(
428 "We don't support returning complex values at present");
430 std::optional
<uint64_t> bit_width
=
431 compiler_type
.GetBitSize(frame_sp
.get());
433 error
= Status::FromErrorString("can't get type size");
436 if (*bit_width
<= 64) {
437 const RegisterInfo
*f0_info
= reg_ctx
->GetRegisterInfoByName("f0", 0);
438 RegisterValue f0_value
;
441 size_t num_bytes
= new_value_sp
->GetData(data
, data_error
);
442 if (data_error
.Fail()) {
443 error
= Status::FromErrorStringWithFormat(
444 "Couldn't convert return value to raw data: %s",
445 data_error
.AsCString());
449 unsigned char buffer
[8];
450 ByteOrder byte_order
= data
.GetByteOrder();
452 data
.CopyByteOrderedData(0, num_bytes
, buffer
, 8, byte_order
);
453 f0_value
.SetBytes(buffer
, 8, byte_order
);
454 reg_ctx
->WriteRegister(f0_info
, f0_value
);
455 set_it_simple
= true;
457 // FIXME - don't know how to do long doubles yet.
458 error
= Status::FromErrorString(
459 "We don't support returning float values > 64 bits at present");
464 if (!set_it_simple
) {
465 // Okay we've got a structure or something that doesn't fit in a simple
466 // register. We should figure out where it really goes, but we don't
468 error
= Status::FromErrorString(
469 "We only support setting simple integer and float "
470 "return types at present.");
476 ValueObjectSP
ABISysV_s390x::GetReturnValueObjectSimple(
477 Thread
&thread
, CompilerType
&return_compiler_type
) const {
478 ValueObjectSP return_valobj_sp
;
481 if (!return_compiler_type
)
482 return return_valobj_sp
;
484 // value.SetContext (Value::eContextTypeClangType, return_value_type);
485 value
.SetCompilerType(return_compiler_type
);
487 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
489 return return_valobj_sp
;
491 const uint32_t type_flags
= return_compiler_type
.GetTypeInfo();
492 if (type_flags
& eTypeIsScalar
) {
493 value
.SetValueType(Value::ValueType::Scalar
);
495 bool success
= false;
496 if (type_flags
& eTypeIsInteger
) {
497 // Extract the register context so we can read arguments from registers.
498 std::optional
<uint64_t> byte_size
=
499 return_compiler_type
.GetByteSize(&thread
);
501 return return_valobj_sp
;
502 uint64_t raw_value
= thread
.GetRegisterContext()->ReadRegisterAsUnsigned(
503 reg_ctx
->GetRegisterInfoByName("r2", 0), 0);
504 const bool is_signed
= (type_flags
& eTypeIsSigned
) != 0;
505 switch (*byte_size
) {
509 case sizeof(uint64_t):
511 value
.GetScalar() = (int64_t)(raw_value
);
513 value
.GetScalar() = (uint64_t)(raw_value
);
517 case sizeof(uint32_t):
519 value
.GetScalar() = (int32_t)(raw_value
& UINT32_MAX
);
521 value
.GetScalar() = (uint32_t)(raw_value
& UINT32_MAX
);
525 case sizeof(uint16_t):
527 value
.GetScalar() = (int16_t)(raw_value
& UINT16_MAX
);
529 value
.GetScalar() = (uint16_t)(raw_value
& UINT16_MAX
);
533 case sizeof(uint8_t):
535 value
.GetScalar() = (int8_t)(raw_value
& UINT8_MAX
);
537 value
.GetScalar() = (uint8_t)(raw_value
& UINT8_MAX
);
541 } else if (type_flags
& eTypeIsFloat
) {
542 if (type_flags
& eTypeIsComplex
) {
543 // Don't handle complex yet.
545 std::optional
<uint64_t> byte_size
=
546 return_compiler_type
.GetByteSize(&thread
);
547 if (byte_size
&& *byte_size
<= sizeof(long double)) {
548 const RegisterInfo
*f0_info
= reg_ctx
->GetRegisterInfoByName("f0", 0);
549 RegisterValue f0_value
;
550 if (reg_ctx
->ReadRegister(f0_info
, f0_value
)) {
552 if (f0_value
.GetData(data
)) {
553 lldb::offset_t offset
= 0;
554 if (*byte_size
== sizeof(float)) {
555 value
.GetScalar() = (float)data
.GetFloat(&offset
);
557 } else if (*byte_size
== sizeof(double)) {
558 value
.GetScalar() = (double)data
.GetDouble(&offset
);
560 } else if (*byte_size
== sizeof(long double)) {
561 // Don't handle long double yet.
570 return_valobj_sp
= ValueObjectConstResult::Create(
571 thread
.GetStackFrameAtIndex(0).get(), value
, ConstString(""));
572 } else if (type_flags
& eTypeIsPointer
) {
574 reg_ctx
->GetRegisterInfoByName("r2", 0)->kinds
[eRegisterKindLLDB
];
576 (uint64_t)thread
.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id
, 0);
577 value
.SetValueType(Value::ValueType::Scalar
);
578 return_valobj_sp
= ValueObjectConstResult::Create(
579 thread
.GetStackFrameAtIndex(0).get(), value
, ConstString(""));
582 return return_valobj_sp
;
585 ValueObjectSP
ABISysV_s390x::GetReturnValueObjectImpl(
586 Thread
&thread
, CompilerType
&return_compiler_type
) const {
587 ValueObjectSP return_valobj_sp
;
589 if (!return_compiler_type
)
590 return return_valobj_sp
;
592 ExecutionContext
exe_ctx(thread
.shared_from_this());
593 return_valobj_sp
= GetReturnValueObjectSimple(thread
, return_compiler_type
);
594 if (return_valobj_sp
)
595 return return_valobj_sp
;
597 RegisterContextSP reg_ctx_sp
= thread
.GetRegisterContext();
599 return return_valobj_sp
;
601 if (return_compiler_type
.IsAggregateType()) {
602 // FIXME: This is just taking a guess, r2 may very well no longer hold the
603 // return storage location.
604 // If we are going to do this right, when we make a new frame we should
605 // check to see if it uses a memory return, and if we are at the first
606 // instruction and if so stash away the return location. Then we would
607 // only return the memory return value if we know it is valid.
610 reg_ctx_sp
->GetRegisterInfoByName("r2", 0)->kinds
[eRegisterKindLLDB
];
611 lldb::addr_t storage_addr
=
612 (uint64_t)thread
.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id
, 0);
613 return_valobj_sp
= ValueObjectMemory::Create(
614 &thread
, "", Address(storage_addr
, nullptr), return_compiler_type
);
617 return return_valobj_sp
;
620 bool ABISysV_s390x::CreateFunctionEntryUnwindPlan(UnwindPlan
&unwind_plan
) {
622 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
624 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
626 // Our Call Frame Address is the stack pointer value + 160
627 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r15_s390x
, 160);
629 // The previous PC is in r14
630 row
->SetRegisterLocationToRegister(dwarf_pswa_s390x
, dwarf_r14_s390x
, true);
632 // All other registers are the same.
633 unwind_plan
.AppendRow(row
);
634 unwind_plan
.SetSourceName("s390x at-func-entry default");
635 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
639 bool ABISysV_s390x::CreateDefaultUnwindPlan(UnwindPlan
&unwind_plan
) {
640 // There's really no default way to unwind on s390x. Trust the .eh_frame CFI,
641 // which should always be good.
645 bool ABISysV_s390x::GetFallbackRegisterLocation(
646 const RegisterInfo
*reg_info
,
647 UnwindPlan::Row::AbstractRegisterLocation
&unwind_regloc
) {
648 // If a volatile register is being requested, we don't want to forward the
649 // next frame's register contents up the stack -- the register is not
650 // retrievable at this frame.
651 if (RegisterIsVolatile(reg_info
)) {
652 unwind_regloc
.SetUndefined();
659 bool ABISysV_s390x::RegisterIsVolatile(const RegisterInfo
*reg_info
) {
660 return !RegisterIsCalleeSaved(reg_info
);
663 bool ABISysV_s390x::RegisterIsCalleeSaved(const RegisterInfo
*reg_info
) {
665 // Preserved registers are :
669 const char *name
= reg_info
->name
;
670 if (name
[0] == 'r') {
676 return name
[2] == '\0';
678 case '1': // r10, r11, r12, r13, r15
679 if ((name
[2] >= '0' && name
[2] <= '3') || name
[2] == '5')
680 return name
[3] == '\0';
687 if (name
[0] == 'f') {
691 return name
[2] == '\0';
693 case '1': // r10, r11, r12, r13, r14, r15
694 if (name
[2] >= '0' && name
[2] <= '5')
695 return name
[3] == '\0';
703 // Accept shorter-variant versions
704 if (name
[0] == 's' && name
[1] == 'p' && name
[2] == '\0') // sp
706 if (name
[0] == 'f' && name
[1] == 'p' && name
[2] == '\0') // fp
708 if (name
[0] == 'p' && name
[1] == 'c' && name
[2] == '\0') // pc
714 void ABISysV_s390x::Initialize() {
715 PluginManager::RegisterPlugin(
716 GetPluginNameStatic(), "System V ABI for s390x targets", CreateInstance
);
719 void ABISysV_s390x::Terminate() {
720 PluginManager::UnregisterPlugin(CreateInstance
);