Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
39648 views
//===-- ABISysV_mips.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "ABISysV_mips.h"910#include "llvm/ADT/STLExtras.h"11#include "llvm/TargetParser/Triple.h"1213#include "lldb/Core/Module.h"14#include "lldb/Core/PluginManager.h"15#include "lldb/Core/Value.h"16#include "lldb/Core/ValueObjectConstResult.h"17#include "lldb/Core/ValueObjectMemory.h"18#include "lldb/Core/ValueObjectRegister.h"19#include "lldb/Symbol/UnwindPlan.h"20#include "lldb/Target/Process.h"21#include "lldb/Target/RegisterContext.h"22#include "lldb/Target/StackFrame.h"23#include "lldb/Target/Target.h"24#include "lldb/Target/Thread.h"25#include "lldb/Utility/ConstString.h"26#include "lldb/Utility/DataExtractor.h"27#include "lldb/Utility/LLDBLog.h"28#include "lldb/Utility/Log.h"29#include "lldb/Utility/RegisterValue.h"30#include "lldb/Utility/Status.h"31#include <optional>3233using namespace lldb;34using namespace lldb_private;3536LLDB_PLUGIN_DEFINE(ABISysV_mips)3738enum dwarf_regnums {39dwarf_r0 = 0,40dwarf_r1,41dwarf_r2,42dwarf_r3,43dwarf_r4,44dwarf_r5,45dwarf_r6,46dwarf_r7,47dwarf_r8,48dwarf_r9,49dwarf_r10,50dwarf_r11,51dwarf_r12,52dwarf_r13,53dwarf_r14,54dwarf_r15,55dwarf_r16,56dwarf_r17,57dwarf_r18,58dwarf_r19,59dwarf_r20,60dwarf_r21,61dwarf_r22,62dwarf_r23,63dwarf_r24,64dwarf_r25,65dwarf_r26,66dwarf_r27,67dwarf_r28,68dwarf_r29,69dwarf_r30,70dwarf_r31,71dwarf_sr,72dwarf_lo,73dwarf_hi,74dwarf_bad,75dwarf_cause,76dwarf_pc77};7879static const RegisterInfo g_register_infos[] = {80// NAME ALT SZ OFF ENCODING FORMAT EH_FRAME81// DWARF GENERIC PROCESS PLUGINS82// LLDB NATIVE VALUE REGS INVALIDATE REGS83// ======== ====== == === ============= =========== ============84// ============== ============ =================85// =================== ========== =================86{"r0",87"zero",884,890,90eEncodingUint,91eFormatHex,92{dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,93LLDB_INVALID_REGNUM},94nullptr,95nullptr,96nullptr,97},98{"r1",99"AT",1004,1010,102eEncodingUint,103eFormatHex,104{dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,105LLDB_INVALID_REGNUM},106nullptr,107nullptr,108nullptr,109},110{"r2",111"v0",1124,1130,114eEncodingUint,115eFormatHex,116{dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,117LLDB_INVALID_REGNUM},118nullptr,119nullptr,120nullptr,121},122{"r3",123"v1",1244,1250,126eEncodingUint,127eFormatHex,128{dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,129LLDB_INVALID_REGNUM},130nullptr,131nullptr,132nullptr,133},134{"r4",135nullptr,1364,1370,138eEncodingUint,139eFormatHex,140{dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,141LLDB_INVALID_REGNUM},142nullptr,143nullptr,144nullptr,145},146{"r5",147nullptr,1484,1490,150eEncodingUint,151eFormatHex,152{dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,153LLDB_INVALID_REGNUM},154nullptr,155nullptr,156nullptr,157},158{"r6",159nullptr,1604,1610,162eEncodingUint,163eFormatHex,164{dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,165LLDB_INVALID_REGNUM},166nullptr,167nullptr,168nullptr,169},170{"r7",171nullptr,1724,1730,174eEncodingUint,175eFormatHex,176{dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,177LLDB_INVALID_REGNUM},178nullptr,179nullptr,180nullptr,181},182{"r8",183"arg5",1844,1850,186eEncodingUint,187eFormatHex,188{dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,189LLDB_INVALID_REGNUM},190nullptr,191nullptr,192nullptr,193},194{"r9",195"arg6",1964,1970,198eEncodingUint,199eFormatHex,200{dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,201LLDB_INVALID_REGNUM},202nullptr,203nullptr,204nullptr,205},206{"r10",207"arg7",2084,2090,210eEncodingUint,211eFormatHex,212{dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,213LLDB_INVALID_REGNUM},214nullptr,215nullptr,216nullptr,217},218{"r11",219"arg8",2204,2210,222eEncodingUint,223eFormatHex,224{dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,225LLDB_INVALID_REGNUM},226nullptr,227nullptr,228nullptr,229},230{"r12",231nullptr,2324,2330,234eEncodingUint,235eFormatHex,236{dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,237LLDB_INVALID_REGNUM},238nullptr,239nullptr,240nullptr,241},242{"r13",243nullptr,2444,2450,246eEncodingUint,247eFormatHex,248{dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,249LLDB_INVALID_REGNUM},250nullptr,251nullptr,252nullptr,253},254{"r14",255nullptr,2564,2570,258eEncodingUint,259eFormatHex,260{dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,261LLDB_INVALID_REGNUM},262nullptr,263nullptr,264nullptr,265},266{"r15",267nullptr,2684,2690,270eEncodingUint,271eFormatHex,272{dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,273LLDB_INVALID_REGNUM},274nullptr,275nullptr,276nullptr,277},278{"r16",279nullptr,2804,2810,282eEncodingUint,283eFormatHex,284{dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,285LLDB_INVALID_REGNUM},286nullptr,287nullptr,288nullptr,289},290{"r17",291nullptr,2924,2930,294eEncodingUint,295eFormatHex,296{dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,297LLDB_INVALID_REGNUM},298nullptr,299nullptr,300nullptr,301},302{"r18",303nullptr,3044,3050,306eEncodingUint,307eFormatHex,308{dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,309LLDB_INVALID_REGNUM},310nullptr,311nullptr,312nullptr,313},314{"r19",315nullptr,3164,3170,318eEncodingUint,319eFormatHex,320{dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,321LLDB_INVALID_REGNUM},322nullptr,323nullptr,324nullptr,325},326{"r20",327nullptr,3284,3290,330eEncodingUint,331eFormatHex,332{dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,333LLDB_INVALID_REGNUM},334nullptr,335nullptr,336nullptr,337},338{"r21",339nullptr,3404,3410,342eEncodingUint,343eFormatHex,344{dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,345LLDB_INVALID_REGNUM},346nullptr,347nullptr,348nullptr,349},350{"r22",351nullptr,3524,3530,354eEncodingUint,355eFormatHex,356{dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,357LLDB_INVALID_REGNUM},358nullptr,359nullptr,360nullptr,361},362{"r23",363nullptr,3644,3650,366eEncodingUint,367eFormatHex,368{dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,369LLDB_INVALID_REGNUM},370nullptr,371nullptr,372nullptr,373},374{"r24",375nullptr,3764,3770,378eEncodingUint,379eFormatHex,380{dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,381LLDB_INVALID_REGNUM},382nullptr,383nullptr,384nullptr,385},386{"r25",387nullptr,3884,3890,390eEncodingUint,391eFormatHex,392{dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,393LLDB_INVALID_REGNUM},394nullptr,395nullptr,396nullptr,397},398{"r26",399nullptr,4004,4010,402eEncodingUint,403eFormatHex,404{dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,405LLDB_INVALID_REGNUM},406nullptr,407nullptr,408nullptr,409},410{"r27",411nullptr,4124,4130,414eEncodingUint,415eFormatHex,416{dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,417LLDB_INVALID_REGNUM},418nullptr,419nullptr,420nullptr,421},422{"r28",423"gp",4244,4250,426eEncodingUint,427eFormatHex,428{dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,429LLDB_INVALID_REGNUM},430nullptr,431nullptr,432nullptr,433},434{"r29",435nullptr,4364,4370,438eEncodingUint,439eFormatHex,440{dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,441LLDB_INVALID_REGNUM},442nullptr,443nullptr,444nullptr,445},446{"r30",447nullptr,4484,4490,450eEncodingUint,451eFormatHex,452{dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,453LLDB_INVALID_REGNUM},454nullptr,455nullptr,456nullptr,457},458{"r31",459nullptr,4604,4610,462eEncodingUint,463eFormatHex,464{dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,465LLDB_INVALID_REGNUM},466nullptr,467nullptr,468nullptr,469},470{"sr",471nullptr,4724,4730,474eEncodingUint,475eFormatHex,476{dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,477LLDB_INVALID_REGNUM},478nullptr,479nullptr,480nullptr,481},482{"lo",483nullptr,4844,4850,486eEncodingUint,487eFormatHex,488{dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,489LLDB_INVALID_REGNUM},490nullptr,491nullptr,492nullptr,493},494{"hi",495nullptr,4964,4970,498eEncodingUint,499eFormatHex,500{dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,501LLDB_INVALID_REGNUM},502nullptr,503nullptr,504nullptr,505},506{"bad",507nullptr,5084,5090,510eEncodingUint,511eFormatHex,512{dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,513LLDB_INVALID_REGNUM},514nullptr,515nullptr,516nullptr,517},518{"cause",519nullptr,5204,5210,522eEncodingUint,523eFormatHex,524{dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,525LLDB_INVALID_REGNUM},526nullptr,527nullptr,528nullptr,529},530{"pc",531nullptr,5324,5330,534eEncodingUint,535eFormatHex,536{dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,537LLDB_INVALID_REGNUM},538nullptr,539nullptr,540nullptr,541},542};543544static const uint32_t k_num_register_infos = std::size(g_register_infos);545546const lldb_private::RegisterInfo *547ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {548count = k_num_register_infos;549return g_register_infos;550}551552size_t ABISysV_mips::GetRedZoneSize() const { return 0; }553554// Static Functions555556ABISP557ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {558const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();559if ((arch_type == llvm::Triple::mips) ||560(arch_type == llvm::Triple::mipsel)) {561return ABISP(562new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));563}564return ABISP();565}566567bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,568addr_t func_addr, addr_t return_addr,569llvm::ArrayRef<addr_t> args) const {570Log *log = GetLog(LLDBLog::Expressions);571572if (log) {573StreamString s;574s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64575", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64576", return_addr = 0x%" PRIx64,577thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,578(uint64_t)return_addr);579580for (size_t i = 0; i < args.size(); ++i)581s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);582s.PutCString(")");583log->PutString(s.GetString());584}585586RegisterContext *reg_ctx = thread.GetRegisterContext().get();587if (!reg_ctx)588return false;589590const RegisterInfo *reg_info = nullptr;591592RegisterValue reg_value;593594// Argument registers595const char *reg_names[] = {"r4", "r5", "r6", "r7"};596597llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();598599// Write arguments to registers600for (size_t i = 0; i < std::size(reg_names); ++i) {601if (ai == ae)602break;603604reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,605LLDB_REGNUM_GENERIC_ARG1 + i);606LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,607args[i], reg_info->name);608609if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))610return false;611612++ai;613}614615// If we have more than 4 arguments --Spill onto the stack616if (ai != ae) {617// No of arguments to go on stack618size_t num_stack_regs = args.size();619620// Allocate needed space for args on the stack621sp -= (num_stack_regs * 4);622623// Keep the stack 8 byte aligned624sp &= ~(8ull - 1ull);625626// just using arg1 to get the right size627const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(628eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);629630addr_t arg_pos = sp + 16;631632size_t i = 4;633for (; ai != ae; ++ai) {634reg_value.SetUInt32(*ai);635LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",636i + 1, args[i], arg_pos);637638if (reg_ctx639->WriteRegisterValueToMemory(reg_info, arg_pos,640reg_info->byte_size, reg_value)641.Fail())642return false;643arg_pos += reg_info->byte_size;644i++;645}646}647648Status error;649const RegisterInfo *pc_reg_info =650reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);651const RegisterInfo *sp_reg_info =652reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);653const RegisterInfo *ra_reg_info =654reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);655const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);656const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);657658LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);659660/* Write r0 with 0, in case we are stopped in syscall,661* such setting prevents automatic decrement of the PC.662* This clears the bug 23659 for MIPS.663*/664if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))665return false;666667LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);668669// Set "sp" to the requested value670if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))671return false;672673LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);674675// Set "ra" to the return address676if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))677return false;678679LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);680681// Set pc to the address of the called function.682if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))683return false;684685LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);686687// All callers of position independent functions must place the address of688// the called function in t9 (r25)689if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))690return false;691692return true;693}694695bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {696return false;697}698699Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,700lldb::ValueObjectSP &new_value_sp) {701Status error;702if (!new_value_sp) {703error.SetErrorString("Empty value object for return value.");704return error;705}706707CompilerType compiler_type = new_value_sp->GetCompilerType();708if (!compiler_type) {709error.SetErrorString("Null clang type for return value.");710return error;711}712713Thread *thread = frame_sp->GetThread().get();714715bool is_signed;716uint32_t count;717bool is_complex;718719RegisterContext *reg_ctx = thread->GetRegisterContext().get();720721bool set_it_simple = false;722if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||723compiler_type.IsPointerType()) {724DataExtractor data;725Status data_error;726size_t num_bytes = new_value_sp->GetData(data, data_error);727if (data_error.Fail()) {728error.SetErrorStringWithFormat(729"Couldn't convert return value to raw data: %s",730data_error.AsCString());731return error;732}733734lldb::offset_t offset = 0;735if (num_bytes <= 8) {736const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);737if (num_bytes <= 4) {738uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);739740if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))741set_it_simple = true;742} else {743uint32_t raw_value = data.GetMaxU32(&offset, 4);744745if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {746const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);747uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);748749if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))750set_it_simple = true;751}752}753} else {754error.SetErrorString("We don't support returning longer than 64 bit "755"integer values at present.");756}757} else if (compiler_type.IsFloatingPointType(count, is_complex)) {758if (is_complex)759error.SetErrorString(760"We don't support returning complex values at present");761else762error.SetErrorString(763"We don't support returning float values at present");764}765766if (!set_it_simple)767error.SetErrorString(768"We only support setting simple integer return types at present.");769770return error;771}772773ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(774Thread &thread, CompilerType &return_compiler_type) const {775ValueObjectSP return_valobj_sp;776return return_valobj_sp;777}778779ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(780Thread &thread, CompilerType &return_compiler_type) const {781ValueObjectSP return_valobj_sp;782Value value;783784if (!return_compiler_type)785return return_valobj_sp;786787ExecutionContext exe_ctx(thread.shared_from_this());788if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)789return return_valobj_sp;790791Target *target = exe_ctx.GetTargetPtr();792const ArchSpec target_arch = target->GetArchitecture();793ByteOrder target_byte_order = target_arch.GetByteOrder();794value.SetCompilerType(return_compiler_type);795uint32_t fp_flag =796target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;797798RegisterContext *reg_ctx = thread.GetRegisterContext().get();799if (!reg_ctx)800return return_valobj_sp;801802bool is_signed = false;803bool is_complex = false;804uint32_t count = 0;805806// In MIPS register "r2" (v0) holds the integer function return values807const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);808std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);809if (!bit_width)810return return_valobj_sp;811if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {812switch (*bit_width) {813default:814return return_valobj_sp;815case 64: {816const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);817uint64_t raw_value;818raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;819raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &820UINT32_MAX))821<< 32;822if (is_signed)823value.GetScalar() = (int64_t)raw_value;824else825value.GetScalar() = (uint64_t)raw_value;826} break;827case 32:828if (is_signed)829value.GetScalar() = (int32_t)(830reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);831else832value.GetScalar() = (uint32_t)(833reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);834break;835case 16:836if (is_signed)837value.GetScalar() = (int16_t)(838reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);839else840value.GetScalar() = (uint16_t)(841reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);842break;843case 8:844if (is_signed)845value.GetScalar() = (int8_t)(846reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);847else848value.GetScalar() = (uint8_t)(849reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);850break;851}852} else if (return_compiler_type.IsPointerType()) {853uint32_t ptr =854thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &855UINT32_MAX;856value.GetScalar() = ptr;857} else if (return_compiler_type.IsAggregateType()) {858// Structure/Vector is always passed in memory and pointer to that memory859// is passed in r2.860uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(861reg_ctx->GetRegisterInfoByName("r2", 0), 0);862// We have got the address. Create a memory object out of it863return_valobj_sp = ValueObjectMemory::Create(864&thread, "", Address(mem_address, nullptr), return_compiler_type);865return return_valobj_sp;866} else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {867if (IsSoftFloat(fp_flag)) {868uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);869if (count != 1 && is_complex)870return return_valobj_sp;871switch (*bit_width) {872default:873return return_valobj_sp;874case 32:875static_assert(sizeof(float) == sizeof(uint32_t));876value.GetScalar() = *((float *)(&raw_value));877break;878case 64:879static_assert(sizeof(double) == sizeof(uint64_t));880const RegisterInfo *r3_reg_info =881reg_ctx->GetRegisterInfoByName("r3", 0);882if (target_byte_order == eByteOrderLittle)883raw_value =884((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |885raw_value;886else887raw_value = (raw_value << 32) |888reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);889value.GetScalar() = *((double *)(&raw_value));890break;891}892}893894else {895const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);896RegisterValue f0_value;897DataExtractor f0_data;898reg_ctx->ReadRegister(f0_info, f0_value);899f0_value.GetData(f0_data);900lldb::offset_t offset = 0;901902if (count == 1 && !is_complex) {903switch (*bit_width) {904default:905return return_valobj_sp;906case 64: {907static_assert(sizeof(double) == sizeof(uint64_t));908const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);909RegisterValue f1_value;910DataExtractor f1_data;911reg_ctx->ReadRegister(f1_info, f1_value);912DataExtractor *copy_from_extractor = nullptr;913WritableDataBufferSP data_sp(new DataBufferHeap(8, 0));914DataExtractor return_ext(915data_sp, target_byte_order,916target->GetArchitecture().GetAddressByteSize());917918if (target_byte_order == eByteOrderLittle) {919copy_from_extractor = &f0_data;920copy_from_extractor->CopyByteOrderedData(921offset, 4, data_sp->GetBytes(), 4, target_byte_order);922f1_value.GetData(f1_data);923copy_from_extractor = &f1_data;924copy_from_extractor->CopyByteOrderedData(925offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);926} else {927copy_from_extractor = &f0_data;928copy_from_extractor->CopyByteOrderedData(929offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);930f1_value.GetData(f1_data);931copy_from_extractor = &f1_data;932copy_from_extractor->CopyByteOrderedData(933offset, 4, data_sp->GetBytes(), 4, target_byte_order);934}935value.GetScalar() = (double)return_ext.GetDouble(&offset);936break;937}938case 32: {939static_assert(sizeof(float) == sizeof(uint32_t));940value.GetScalar() = (float)f0_data.GetFloat(&offset);941break;942}943}944} else {945// not handled yet946return return_valobj_sp;947}948}949} else {950// not handled yet951return return_valobj_sp;952}953954// If we get here, we have a valid Value, so make our ValueObject out of it:955956return_valobj_sp = ValueObjectConstResult::Create(957thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));958return return_valobj_sp;959}960961bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {962unwind_plan.Clear();963unwind_plan.SetRegisterKind(eRegisterKindDWARF);964965UnwindPlan::RowSP row(new UnwindPlan::Row);966967// Our Call Frame Address is the stack pointer value968row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);969970// The previous PC is in the RA971row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);972unwind_plan.AppendRow(row);973974// All other registers are the same.975976unwind_plan.SetSourceName("mips at-func-entry default");977unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);978unwind_plan.SetReturnAddressRegister(dwarf_r31);979return true;980}981982bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {983unwind_plan.Clear();984unwind_plan.SetRegisterKind(eRegisterKindDWARF);985986UnwindPlan::RowSP row(new UnwindPlan::Row);987988row->SetUnspecifiedRegistersAreUndefined(true);989row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);990991row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);992993unwind_plan.AppendRow(row);994unwind_plan.SetSourceName("mips default unwind plan");995unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);996unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);997unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);998return true;999}10001001bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {1002return !RegisterIsCalleeSaved(reg_info);1003}10041005bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {1006return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);1007}10081009bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {1010if (reg_info) {1011// Preserved registers are :1012// r16-r23, r28, r29, r30, r311013const char *name = reg_info->name;10141015if (name[0] == 'r') {1016switch (name[1]) {1017case '1':1018if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||1019name[2] == '9') // r16-r191020return name[3] == '\0';1021break;1022case '2':1023if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||1024name[2] == '3' // r20-r231025|| name[2] == '8' || name[2] == '9') // r28 and r291026return name[3] == '\0';1027break;1028case '3':1029if (name[2] == '0' || name[2] == '1') // r30 and r311030return name[3] == '\0';1031break;1032}10331034if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)1035return true;1036if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)1037return true;1038if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)1039return true;1040if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)1041return true;1042}1043}1044return false;1045}10461047void ABISysV_mips::Initialize() {1048PluginManager::RegisterPlugin(1049GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);1050}10511052void ABISysV_mips::Terminate() {1053PluginManager::UnregisterPlugin(CreateInstance);1054}105510561057