Add support for the armv7k ABI which has some small

changes from the normal armv7 ABI used on darwin.

llvm-svn: 252225
This commit is contained in:
Jason Molenda 2015-11-05 22:51:29 +00:00
parent 13c30d2f7d
commit 9b6b069a38
2 changed files with 112 additions and 2 deletions

View File

@ -238,8 +238,8 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
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);
// Keep the stack 16 byte aligned
sp &= ~(16ull-1ull);
// just using arg1 to get the right size
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
@ -413,6 +413,26 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,
return true;
}
bool
ABIMacOSX_arm::IsArmv7kProcess (Thread *thread) const
{
bool is_armv7k = false;
if (thread)
{
ProcessSP process_sp (thread->GetProcess());
if (process_sp)
{
const ArchSpec &arch (process_sp->GetTarget().GetArchitecture());
const ArchSpec::Core system_core = arch.GetCore();
if (system_core == ArchSpec::eCore_arm_armv7k)
{
is_armv7k = true;
}
}
}
return is_armv7k;
}
ValueObjectSP
ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
lldb_private::CompilerType &compiler_type) const
@ -443,6 +463,60 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
{
default:
return return_valobj_sp;
case 128:
if (IsArmv7kProcess (&thread))
{
// "A composite type not larger than 16 bytes is returned in r0-r3. The format is
// as if the result had been stored in memory at a word-aligned address and then
// loaded into r0-r3 with an ldm instruction"
{
const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
if (r1_reg_info && r2_reg_info && r3_reg_info)
{
const size_t byte_size = compiler_type.GetByteSize(&thread);
ProcessSP process_sp (thread.GetProcess());
if (byte_size <= r0_reg_info->byte_size + r1_reg_info->byte_size + r2_reg_info->byte_size + r3_reg_info->byte_size
&& process_sp)
{
std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
const ByteOrder byte_order = process_sp->GetByteOrder();
RegisterValue r0_reg_value;
RegisterValue r1_reg_value;
RegisterValue r2_reg_value;
RegisterValue r3_reg_value;
if (reg_ctx->ReadRegister(r0_reg_info, r0_reg_value)
&& reg_ctx->ReadRegister(r1_reg_info, r1_reg_value)
&& reg_ctx->ReadRegister(r2_reg_info, r2_reg_value)
&& reg_ctx->ReadRegister(r3_reg_info, r3_reg_value))
{
Error error;
if (r0_reg_value.GetAsMemoryData (r0_reg_info, heap_data_ap->GetBytes()+0, 4, byte_order, error)
&& r1_reg_value.GetAsMemoryData (r1_reg_info, heap_data_ap->GetBytes()+4, 4, byte_order, error)
&& r2_reg_value.GetAsMemoryData (r2_reg_info, heap_data_ap->GetBytes()+8, 4, byte_order, error)
&& r3_reg_value.GetAsMemoryData (r3_reg_info, heap_data_ap->GetBytes()+12, 4, byte_order, error))
{
DataExtractor data (DataBufferSP (heap_data_ap.release()),
byte_order,
process_sp->GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
compiler_type,
ConstString(""),
data);
return return_valobj_sp;
}
}
}
}
}
}
else
{
return return_valobj_sp;
}
break;
case 64:
{
const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
@ -555,6 +629,39 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
}
}
}
else if (num_bytes <= 16 && IsArmv7kProcess (frame_sp->GetThread().get()))
{
// "A composite type not larger than 16 bytes is returned in r0-r3. The format is
// as if the result had been stored in memory at a word-aligned address and then
// loaded into r0-r3 with an ldm instruction"
const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0);
const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0);
const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
lldb::offset_t offset = 0;
uint32_t bytes_written = 4;
uint32_t raw_value = data.GetMaxU64(&offset, 4);
if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value) && bytes_written <= num_bytes)
{
bytes_written += 4;
raw_value = data.GetMaxU64(&offset, 4);
if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value))
{
bytes_written += 4;
raw_value = data.GetMaxU64(&offset, 4);
if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
{
bytes_written += 4;
raw_value = data.GetMaxU64(&offset, 4);
if (bytes_written <= num_bytes && 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.");

View File

@ -79,6 +79,9 @@ public:
const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t &count) override;
bool
IsArmv7kProcess (lldb_private::Thread *thread) const;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------