blob: 14f5bc3ea8c49ad5fc8e0cf93f15c5ed8ed4c903 [file] [log] [blame] [edit]
//===-- RegisterContextDarwin_riscv32.cpp
//------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Scalar.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <cstddef>
#include <memory>
#include "RegisterContextDarwin_riscv32.h"
#include "Utility/RISCV_DWARF_Registers.h"
using namespace lldb;
using namespace lldb_private;
enum {
gpr_x0 = 0,
gpr_x1,
gpr_x2,
gpr_x3,
gpr_x4,
gpr_x5,
gpr_x6,
gpr_x7,
gpr_x8,
gpr_x9,
gpr_x10,
gpr_x11,
gpr_x12,
gpr_x13,
gpr_x14,
gpr_x15,
gpr_x16,
gpr_x17,
gpr_x18,
gpr_x19,
gpr_x20,
gpr_x21,
gpr_x22,
gpr_x23,
gpr_x24,
gpr_x25,
gpr_x26,
gpr_x27,
gpr_x28,
gpr_x29,
gpr_x30,
gpr_x31,
gpr_pc,
fpr_f0,
fpr_f1,
fpr_f2,
fpr_f3,
fpr_f4,
fpr_f5,
fpr_f6,
fpr_f7,
fpr_f8,
fpr_f9,
fpr_f10,
fpr_f11,
fpr_f12,
fpr_f13,
fpr_f14,
fpr_f15,
fpr_f16,
fpr_f17,
fpr_f18,
fpr_f19,
fpr_f20,
fpr_f21,
fpr_f22,
fpr_f23,
fpr_f24,
fpr_f25,
fpr_f26,
fpr_f27,
fpr_f28,
fpr_f29,
fpr_f30,
fpr_f31,
fpr_fcsr,
exc_exception,
exc_fsr,
exc_far,
csr_bank,
k_num_registers
};
/* clang-format off */
#define GPR_OFFSET(reg) \
(LLVM_EXTENSION offsetof(RegisterContextDarwin_riscv32::GPR, reg))
#define FPU_OFFSET(reg) \
(LLVM_EXTENSION offsetof(RegisterContextDarwin_riscv32::FPU, reg) + \
sizeof(RegisterContextDarwin_riscv32::GPR))
#define EXC_OFFSET(reg) \
(LLVM_EXTENSION offsetof(RegisterContextDarwin_riscv32::EXC, reg) + \
sizeof(RegisterContextDarwin_riscv32::GPR) + \
sizeof(RegisterContextDarwin_riscv32::FPU))
// These macros will auto define the register name, alt name, register size,
// register offset, encoding, format and native register. This ensures that the
// register state structures are defined correctly and have the correct sizes
// and offsets.
#define DEFINE_GPR_ABI(reg, canon) \
#reg, #canon, \
sizeof(((RegisterContextDarwin_riscv32::GPR *)nullptr)->canon), \
GPR_OFFSET(canon), eEncodingUint, eFormatHex
#define DEFINE_GPR(reg) \
#reg, nullptr, \
sizeof(((RegisterContextDarwin_riscv32::GPR *)nullptr)->reg), \
GPR_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_FPU_ABI(reg, canon) \
#reg, #canon, \
sizeof(((RegisterContextDarwin_riscv32::FPU *)nullptr)->canon), \
FPU_OFFSET(canon), eEncodingUint, eFormatHex
#define DEFINE_FPU(reg) \
#reg, nullptr, \
sizeof(((RegisterContextDarwin_riscv32::FPU *)nullptr)->reg), \
FPU_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_EXC(reg) \
#reg, nullptr, \
sizeof(((RegisterContextDarwin_riscv32::EXC *)nullptr)->reg), \
EXC_OFFSET(reg), eEncodingUint, eFormatHex
#define REG_CONTEXT_SIZE \
(sizeof(RegisterContextDarwin_riscv32::GPR) + \
sizeof(RegisterContextDarwin_riscv32::FPU) + \
sizeof(RegisterContextDarwin_riscv32::EXC) + \
sizeof(RegisterContextDarwin_riscv32::CSR))
/* clang-format on */
static RegisterInfo g_register_infos[] = {
{
DEFINE_GPR_ABI(zero, x0),
{riscv_dwarf::dwarf_gpr_x0, riscv_dwarf::dwarf_gpr_x0,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x0},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(ra, x1),
{riscv_dwarf::dwarf_gpr_x1, riscv_dwarf::dwarf_gpr_x1,
LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_x1},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(sp, x2),
{riscv_dwarf::dwarf_gpr_x2, riscv_dwarf::dwarf_gpr_x2,
LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_x2},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(gp, x3),
{riscv_dwarf::dwarf_gpr_x3, riscv_dwarf::dwarf_gpr_x3,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x3},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(tp, x4),
{riscv_dwarf::dwarf_gpr_x4, riscv_dwarf::dwarf_gpr_x4,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x4},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(t0, x5),
{riscv_dwarf::dwarf_gpr_x5, riscv_dwarf::dwarf_gpr_x5,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x5},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(t1, x6),
{riscv_dwarf::dwarf_gpr_x6, riscv_dwarf::dwarf_gpr_x6,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x6},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(t2, x7),
{riscv_dwarf::dwarf_gpr_x7, riscv_dwarf::dwarf_gpr_x7,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x7},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(fp, x8),
{riscv_dwarf::dwarf_gpr_x8, riscv_dwarf::dwarf_gpr_x8,
LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_x8},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s1, x9),
{riscv_dwarf::dwarf_gpr_x9, riscv_dwarf::dwarf_gpr_x9,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x9},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a0, x10),
{riscv_dwarf::dwarf_gpr_x10, riscv_dwarf::dwarf_gpr_x10,
LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_x10},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a1, x11),
{riscv_dwarf::dwarf_gpr_x11, riscv_dwarf::dwarf_gpr_x11,
LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_x11},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a2, x12),
{riscv_dwarf::dwarf_gpr_x12, riscv_dwarf::dwarf_gpr_x12,
LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_x12},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a3, x13),
{riscv_dwarf::dwarf_gpr_x13, riscv_dwarf::dwarf_gpr_x13,
LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_x13},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a4, x14),
{riscv_dwarf::dwarf_gpr_x14, riscv_dwarf::dwarf_gpr_x14,
LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, gpr_x14},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a5, x15),
{riscv_dwarf::dwarf_gpr_x15, riscv_dwarf::dwarf_gpr_x15,
LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, gpr_x15},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a6, x16),
{riscv_dwarf::dwarf_gpr_x16, riscv_dwarf::dwarf_gpr_x16,
LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, gpr_x16},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(a7, x17),
{riscv_dwarf::dwarf_gpr_x17, riscv_dwarf::dwarf_gpr_x17,
LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, gpr_x17},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s2, x18),
{riscv_dwarf::dwarf_gpr_x18, riscv_dwarf::dwarf_gpr_x18,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x18},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s3, x19),
{riscv_dwarf::dwarf_gpr_x19, riscv_dwarf::dwarf_gpr_x19,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x19},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s4, x20),
{riscv_dwarf::dwarf_gpr_x20, riscv_dwarf::dwarf_gpr_x20,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x20},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s5, x21),
{riscv_dwarf::dwarf_gpr_x21, riscv_dwarf::dwarf_gpr_x21,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x21},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s6, x22),
{riscv_dwarf::dwarf_gpr_x22, riscv_dwarf::dwarf_gpr_x22,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x22},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s7, x23),
{riscv_dwarf::dwarf_gpr_x23, riscv_dwarf::dwarf_gpr_x23,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x23},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s8, x24),
{riscv_dwarf::dwarf_gpr_x24, riscv_dwarf::dwarf_gpr_x24,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x24},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s9, x25),
{riscv_dwarf::dwarf_gpr_x25, riscv_dwarf::dwarf_gpr_x25,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x25},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s10, x26),
{riscv_dwarf::dwarf_gpr_x26, riscv_dwarf::dwarf_gpr_x26,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x26},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(s11, x27),
{riscv_dwarf::dwarf_gpr_x27, riscv_dwarf::dwarf_gpr_x27,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x27},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(t3, x28),
{riscv_dwarf::dwarf_gpr_x28, riscv_dwarf::dwarf_gpr_x28,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x28},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(t4, x29),
{riscv_dwarf::dwarf_gpr_x29, riscv_dwarf::dwarf_gpr_x29,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x29},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(t5, x30),
{riscv_dwarf::dwarf_gpr_x30, riscv_dwarf::dwarf_gpr_x30,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x30},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR_ABI(t6, x31),
{riscv_dwarf::dwarf_gpr_x31, riscv_dwarf::dwarf_gpr_x31,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x31},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_GPR(pc),
{riscv_dwarf::dwarf_gpr_pc, riscv_dwarf::dwarf_gpr_pc,
LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft0, f0),
{riscv_dwarf::dwarf_fpr_f0, riscv_dwarf::dwarf_fpr_f0,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f0},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft1, f1),
{riscv_dwarf::dwarf_fpr_f1, riscv_dwarf::dwarf_fpr_f1,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f1},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft2, f2),
{riscv_dwarf::dwarf_fpr_f2, riscv_dwarf::dwarf_fpr_f2,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f2},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft3, f3),
{riscv_dwarf::dwarf_fpr_f3, riscv_dwarf::dwarf_fpr_f3,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f3},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft4, f4),
{riscv_dwarf::dwarf_fpr_f4, riscv_dwarf::dwarf_fpr_f4,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f4},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft5, f5),
{riscv_dwarf::dwarf_fpr_f5, riscv_dwarf::dwarf_fpr_f5,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f5},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft6, f6),
{riscv_dwarf::dwarf_fpr_f6, riscv_dwarf::dwarf_fpr_f6,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f6},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft7, f7),
{riscv_dwarf::dwarf_fpr_f7, riscv_dwarf::dwarf_fpr_f7,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f7},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs0, f8),
{riscv_dwarf::dwarf_fpr_f8, riscv_dwarf::dwarf_fpr_f8,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f8},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs1, f9),
{riscv_dwarf::dwarf_fpr_f9, riscv_dwarf::dwarf_fpr_f9,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f9},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa0, f10),
{riscv_dwarf::dwarf_fpr_f10, riscv_dwarf::dwarf_fpr_f10,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f10},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa1, f11),
{riscv_dwarf::dwarf_fpr_f11, riscv_dwarf::dwarf_fpr_f11,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f11},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa2, f12),
{riscv_dwarf::dwarf_fpr_f12, riscv_dwarf::dwarf_fpr_f12,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f12},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa3, f13),
{riscv_dwarf::dwarf_fpr_f13, riscv_dwarf::dwarf_fpr_f13,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f13},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa4, f14),
{riscv_dwarf::dwarf_fpr_f14, riscv_dwarf::dwarf_fpr_f14,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f14},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa5, f15),
{riscv_dwarf::dwarf_fpr_f15, riscv_dwarf::dwarf_fpr_f15,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f15},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa6, f16),
{riscv_dwarf::dwarf_fpr_f16, riscv_dwarf::dwarf_fpr_f16,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f16},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fa7, f17),
{riscv_dwarf::dwarf_fpr_f17, riscv_dwarf::dwarf_fpr_f17,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f17},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs2, f18),
{riscv_dwarf::dwarf_fpr_f18, riscv_dwarf::dwarf_fpr_f18,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f18},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs3, f19),
{riscv_dwarf::dwarf_fpr_f19, riscv_dwarf::dwarf_fpr_f19,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f19},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs4, f20),
{riscv_dwarf::dwarf_fpr_f20, riscv_dwarf::dwarf_fpr_f20,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f20},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs5, f21),
{riscv_dwarf::dwarf_fpr_f21, riscv_dwarf::dwarf_fpr_f21,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f21},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs6, f22),
{riscv_dwarf::dwarf_fpr_f22, riscv_dwarf::dwarf_fpr_f22,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f22},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs7, f23),
{riscv_dwarf::dwarf_fpr_f23, riscv_dwarf::dwarf_fpr_f23,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f23},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs8, f24),
{riscv_dwarf::dwarf_fpr_f24, riscv_dwarf::dwarf_fpr_f24,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f24},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs9, f25),
{riscv_dwarf::dwarf_fpr_f25, riscv_dwarf::dwarf_fpr_f25,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f25},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs10, f26),
{riscv_dwarf::dwarf_fpr_f26, riscv_dwarf::dwarf_fpr_f26,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f26},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(fs11, f27),
{riscv_dwarf::dwarf_fpr_f27, riscv_dwarf::dwarf_fpr_f27,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f27},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft8, f28),
{riscv_dwarf::dwarf_fpr_f28, riscv_dwarf::dwarf_fpr_f28,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f28},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft9, f29),
{riscv_dwarf::dwarf_fpr_f29, riscv_dwarf::dwarf_fpr_f29,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f29},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft10, f30),
{riscv_dwarf::dwarf_fpr_f30, riscv_dwarf::dwarf_fpr_f30,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f30},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU_ABI(ft11, f31),
{riscv_dwarf::dwarf_fpr_f31, riscv_dwarf::dwarf_fpr_f31,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f31},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_FPU(fcsr),
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, fpr_fcsr},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_EXC(exception),
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, exc_exception},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_EXC(fsr),
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, exc_fsr},
nullptr,
nullptr,
nullptr,
},
{
DEFINE_EXC(far),
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, exc_far},
nullptr,
nullptr,
nullptr,
},
{"csr",
nullptr,
1024 * sizeof(uint32_t),
0,
eEncodingVector,
eFormatVectorOfUInt32,
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, csr_bank},
nullptr,
nullptr,
nullptr}};
static size_t k_num_register_infos = std::size(g_register_infos);
RegisterContextDarwin_riscv32::RegisterContextDarwin_riscv32(
Thread &thread, uint32_t concrete_frame_idx)
: RegisterContext(thread, concrete_frame_idx), gpr(), fpr(), exc() {
uint32_t i;
for (i = 0; i < kNumErrors; i++) {
gpr_errs[i] = -1;
fpr_errs[i] = -1;
exc_errs[i] = -1;
csr_errs[i] = -1;
}
}
RegisterContextDarwin_riscv32::~RegisterContextDarwin_riscv32() = default;
void RegisterContextDarwin_riscv32::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
}
size_t RegisterContextDarwin_riscv32::GetRegisterCount() {
assert(k_num_register_infos == k_num_registers);
return k_num_registers;
}
const RegisterInfo *
RegisterContextDarwin_riscv32::GetRegisterInfoAtIndex(size_t reg) {
assert(k_num_register_infos == k_num_registers);
if (reg < k_num_registers)
return &g_register_infos[reg];
return nullptr;
}
size_t RegisterContextDarwin_riscv32::GetRegisterInfosCount() {
return k_num_register_infos;
}
const RegisterInfo *RegisterContextDarwin_riscv32::GetRegisterInfos() {
return g_register_infos;
}
// General purpose registers
static uint32_t g_gpr_regnums[] = {
gpr_x0, gpr_x1, gpr_x2, gpr_x3, gpr_x4, gpr_x5, gpr_x6,
gpr_x7, gpr_x8, gpr_x9, gpr_x10, gpr_x11, gpr_x12, gpr_x13,
gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,
gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,
gpr_x28, gpr_x29, gpr_x30, gpr_x31, gpr_pc};
// Floating point registers
static uint32_t g_fpr_regnums[] = {
fpr_f0, fpr_f1, fpr_f2, fpr_f3, fpr_f4, fpr_f5, fpr_f6,
fpr_f7, fpr_f8, fpr_f9, fpr_f10, fpr_f11, fpr_f12, fpr_f13,
fpr_f14, fpr_f15, fpr_f16, fpr_f17, fpr_f18, fpr_f19, fpr_f20,
fpr_f21, fpr_f22, fpr_f23, fpr_f24, fpr_f25, fpr_f26, fpr_f27,
fpr_f28, fpr_f29, fpr_f30, fpr_f31, fpr_fcsr};
// Exception registers
static uint32_t g_exc_regnums[] = {exc_exception, exc_fsr, exc_far};
// CSR bank registers
static uint32_t g_csr_regnums[] = {csr_bank};
// Number of registers in each register set
const size_t k_num_gpr_registers = std::size(g_gpr_regnums);
const size_t k_num_fpr_registers = std::size(g_fpr_regnums);
const size_t k_num_exc_registers = std::size(g_exc_regnums);
const size_t k_num_csr_registers = std::size(g_csr_regnums);
// Register set definitions. The first definitions at register set index of
// zero is for all registers, followed by other registers sets. The register
// information for the all register set need not be filled in.
static const RegisterSet g_reg_sets[] = {
{
"General Purpose Registers",
"gpr",
k_num_gpr_registers,
g_gpr_regnums,
},
{"Floating Point Registers", "fpr", k_num_fpr_registers, g_fpr_regnums},
{"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums},
{"CSR register bank", "csr", k_num_csr_registers, g_csr_regnums}};
const size_t k_num_regsets = std::size(g_reg_sets);
size_t RegisterContextDarwin_riscv32::GetRegisterSetCount() {
return k_num_regsets;
}
const RegisterSet *
RegisterContextDarwin_riscv32::GetRegisterSet(size_t reg_set) {
if (reg_set < k_num_regsets)
return &g_reg_sets[reg_set];
return nullptr;
}
// Register information definitions for 32 bit riscv32.
int RegisterContextDarwin_riscv32::GetSetForNativeRegNum(int reg_num) {
if (reg_num < fpr_f0)
return GPRRegSet;
else if (reg_num < exc_exception)
return FPURegSet;
else if (reg_num < csr_bank)
return EXCRegSet;
else if (reg_num < k_num_registers)
return CSRRegSet;
return -1;
}
void RegisterContextDarwin_riscv32::LogGPR(Log *log, const char *title) {
if (log) {
if (title)
LLDB_LOGF(log, "%s", title);
for (uint32_t i = 0; i < k_num_gpr_registers; i++) {
uint32_t reg = gpr_x0 + i;
LLDB_LOGF(log, "%12s = 0x%4.4x", g_register_infos[reg].name,
(&gpr.x0)[reg]);
}
}
}
int RegisterContextDarwin_riscv32::ReadGPR(bool force) {
int set = GPRRegSet;
if (force || !RegisterSetIsCached(set)) {
SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
}
return GetError(set, Read);
}
int RegisterContextDarwin_riscv32::ReadFPU(bool force) {
int set = FPURegSet;
if (force || !RegisterSetIsCached(set)) {
SetError(set, Read, DoReadFPU(GetThreadID(), set, fpr));
}
return GetError(set, Read);
}
int RegisterContextDarwin_riscv32::ReadEXC(bool force) {
int set = EXCRegSet;
if (force || !RegisterSetIsCached(set)) {
SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
}
return GetError(set, Read);
}
int RegisterContextDarwin_riscv32::ReadCSR(bool force) {
int set = CSRRegSet;
if (force || !RegisterSetIsCached(set)) {
SetError(set, Read, DoReadCSR(GetThreadID(), set, csr));
}
return GetError(set, Read);
}
int RegisterContextDarwin_riscv32::WriteGPR() {
int set = GPRRegSet;
if (!RegisterSetIsCached(set)) {
SetError(set, Write, -1);
return -1;
}
SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
SetError(set, Read, -1);
return GetError(set, Write);
}
int RegisterContextDarwin_riscv32::WriteFPU() {
int set = FPURegSet;
if (!RegisterSetIsCached(set)) {
SetError(set, Write, -1);
return -1;
}
SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpr));
SetError(set, Read, -1);
return GetError(set, Write);
}
int RegisterContextDarwin_riscv32::WriteEXC() {
int set = EXCRegSet;
if (!RegisterSetIsCached(set)) {
SetError(set, Write, -1);
return -1;
}
SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
SetError(set, Read, -1);
return GetError(set, Write);
}
int RegisterContextDarwin_riscv32::WriteCSR() {
int set = CSRRegSet;
if (!RegisterSetIsCached(set)) {
SetError(set, Write, -1);
return -1;
}
SetError(set, Write, DoWriteCSR(GetThreadID(), set, csr));
SetError(set, Read, -1);
return GetError(set, Write);
}
int RegisterContextDarwin_riscv32::ReadRegisterSet(uint32_t set, bool force) {
switch (set) {
case GPRRegSet:
return ReadGPR(force);
case FPURegSet:
return ReadFPU(force);
case EXCRegSet:
return ReadEXC(force);
case CSRRegSet:
return ReadCSR(force);
default:
break;
}
return -1;
}
int RegisterContextDarwin_riscv32::WriteRegisterSet(uint32_t set) {
// Make sure we have a valid context to set.
if (RegisterSetIsCached(set)) {
switch (set) {
case GPRRegSet:
return WriteGPR();
case FPURegSet:
return WriteFPU();
case EXCRegSet:
return WriteEXC();
case CSRRegSet:
return WriteCSR();
default:
break;
}
}
return -1;
}
bool RegisterContextDarwin_riscv32::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &value) {
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
int set = RegisterContextDarwin_riscv32::GetSetForNativeRegNum(reg);
if (set == -1)
return false;
if (ReadRegisterSet(set, false) != 0)
return false;
switch (reg) {
case gpr_x0:
case gpr_x1:
case gpr_x2:
case gpr_x3:
case gpr_x4:
case gpr_x5:
case gpr_x6:
case gpr_x7:
case gpr_x8:
case gpr_x9:
case gpr_x10:
case gpr_x11:
case gpr_x12:
case gpr_x13:
case gpr_x14:
case gpr_x15:
case gpr_x16:
case gpr_x17:
case gpr_x18:
case gpr_x19:
case gpr_x20:
case gpr_x21:
case gpr_x22:
case gpr_x23:
case gpr_x24:
case gpr_x25:
case gpr_x26:
case gpr_x27:
case gpr_x28:
case gpr_x29:
case gpr_x30:
case gpr_x31:
case gpr_pc:
value = (&gpr.x0)[reg - gpr_x0];
break;
case fpr_f0:
case fpr_f1:
case fpr_f2:
case fpr_f3:
case fpr_f4:
case fpr_f5:
case fpr_f6:
case fpr_f7:
case fpr_f8:
case fpr_f9:
case fpr_f10:
case fpr_f11:
case fpr_f12:
case fpr_f13:
case fpr_f14:
case fpr_f15:
case fpr_f16:
case fpr_f17:
case fpr_f18:
case fpr_f19:
case fpr_f20:
case fpr_f21:
case fpr_f22:
case fpr_f23:
case fpr_f24:
case fpr_f25:
case fpr_f26:
case fpr_f27:
case fpr_f28:
case fpr_f29:
case fpr_f30:
case fpr_f31:
case fpr_fcsr:
value = (&fpr.f0)[reg - fpr_f0];
break;
case exc_exception:
value = exc.exception;
break;
case exc_fsr:
value = exc.fsr;
break;
case exc_far:
value = exc.far;
break;
case csr_bank:
// These values don't fit into scalar types,
// RegisterContext::ReadRegisterBytes() must be used for these registers
//::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes,
// 10);
// AArch64 copies NEON registers with
// value.SetBytes(csr.bytes, reg_info->byte_size,
// endian::InlHostByteOrder());
return false;
default:
return false;
}
return true;
}
bool RegisterContextDarwin_riscv32::WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &value) {
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
int set = GetSetForNativeRegNum(reg);
if (set == -1)
return false;
if (ReadRegisterSet(set, false) != 0)
return false;
switch (reg) {
case gpr_x0:
case gpr_x1:
case gpr_x2:
case gpr_x3:
case gpr_x4:
case gpr_x5:
case gpr_x6:
case gpr_x7:
case gpr_x8:
case gpr_x9:
case gpr_x10:
case gpr_x11:
case gpr_x12:
case gpr_x13:
case gpr_x14:
case gpr_x15:
case gpr_x16:
case gpr_x17:
case gpr_x18:
case gpr_x19:
case gpr_x20:
case gpr_x21:
case gpr_x22:
case gpr_x23:
case gpr_x24:
case gpr_x25:
case gpr_x26:
case gpr_x27:
case gpr_x28:
case gpr_x29:
case gpr_x30:
case gpr_x31:
case gpr_pc:
(&gpr.x0)[reg - gpr_x0] = value.GetAsUInt32();
break;
case fpr_f0:
case fpr_f1:
case fpr_f2:
case fpr_f3:
case fpr_f4:
case fpr_f5:
case fpr_f6:
case fpr_f7:
case fpr_f8:
case fpr_f9:
case fpr_f10:
case fpr_f11:
case fpr_f12:
case fpr_f13:
case fpr_f14:
case fpr_f15:
case fpr_f16:
case fpr_f17:
case fpr_f18:
case fpr_f19:
case fpr_f20:
case fpr_f21:
case fpr_f22:
case fpr_f23:
case fpr_f24:
case fpr_f25:
case fpr_f26:
case fpr_f27:
case fpr_f28:
case fpr_f29:
case fpr_f30:
case fpr_f31:
case fpr_fcsr:
(&fpr.f0)[reg - fpr_f0] = value.GetAsUInt32();
break;
case exc_exception:
exc.exception = value.GetAsUInt32();
break;
case exc_fsr:
exc.fsr = value.GetAsUInt32();
break;
case exc_far:
exc.far = value.GetAsUInt32();
break;
case csr_bank:
// These values don't fit into scalar types,
// RegisterContext::ReadRegisterBytes() must be used for these registers
//::memcpy(csr.bytes, value.GetBytes(),
// value.GetByteSize());
return false;
default:
return false;
}
return WriteRegisterSet(set) == 0;
}
bool RegisterContextDarwin_riscv32::ReadAllRegisterValues(
lldb::WritableDataBufferSP &data_sp) {
data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0 &&
ReadCSR(false) == 0) {
uint8_t *dst = data_sp->GetBytes();
::memcpy(dst, &gpr, sizeof(gpr));
dst += sizeof(gpr);
::memcpy(dst, &fpr, sizeof(fpr));
dst += sizeof(gpr);
::memcpy(dst, &exc, sizeof(exc));
return true;
::memcpy(dst, &csr, sizeof(csr));
return true;
}
return false;
}
bool RegisterContextDarwin_riscv32::WriteAllRegisterValues(
const lldb::DataBufferSP &data_sp) {
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
const uint8_t *src = data_sp->GetBytes();
::memcpy(&gpr, src, sizeof(gpr));
src += sizeof(gpr);
::memcpy(&fpr, src, sizeof(fpr));
src += sizeof(fpr);
::memcpy(&exc, src, sizeof(exc));
src += sizeof(exc);
::memcpy(&csr, src, sizeof(csr));
uint32_t success_count = 0;
if (WriteGPR() == 0)
++success_count;
if (WriteFPU() == 0)
++success_count;
if (WriteEXC() == 0)
++success_count;
if (WriteCSR() == 0)
++success_count;
return success_count == 3;
}
return false;
}
uint32_t RegisterContextDarwin_riscv32::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t reg) {
if (kind == eRegisterKindGeneric) {
switch (reg) {
case LLDB_REGNUM_GENERIC_PC:
return gpr_pc;
case LLDB_REGNUM_GENERIC_SP:
return gpr_x2;
case LLDB_REGNUM_GENERIC_FP:
return gpr_x8;
case LLDB_REGNUM_GENERIC_RA:
return gpr_x1;
default:
break;
}
} else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) {
switch (reg) {
case riscv_dwarf::dwarf_gpr_x0:
case riscv_dwarf::dwarf_gpr_x1:
case riscv_dwarf::dwarf_gpr_x2:
case riscv_dwarf::dwarf_gpr_x3:
case riscv_dwarf::dwarf_gpr_x4:
case riscv_dwarf::dwarf_gpr_x5:
case riscv_dwarf::dwarf_gpr_x6:
case riscv_dwarf::dwarf_gpr_x7:
case riscv_dwarf::dwarf_gpr_x8:
case riscv_dwarf::dwarf_gpr_x9:
case riscv_dwarf::dwarf_gpr_x10:
case riscv_dwarf::dwarf_gpr_x11:
case riscv_dwarf::dwarf_gpr_x12:
case riscv_dwarf::dwarf_gpr_x13:
case riscv_dwarf::dwarf_gpr_x14:
case riscv_dwarf::dwarf_gpr_x15:
case riscv_dwarf::dwarf_gpr_x16:
case riscv_dwarf::dwarf_gpr_x17:
case riscv_dwarf::dwarf_gpr_x18:
case riscv_dwarf::dwarf_gpr_x19:
case riscv_dwarf::dwarf_gpr_x20:
case riscv_dwarf::dwarf_gpr_x21:
case riscv_dwarf::dwarf_gpr_x22:
case riscv_dwarf::dwarf_gpr_x23:
case riscv_dwarf::dwarf_gpr_x24:
case riscv_dwarf::dwarf_gpr_x25:
case riscv_dwarf::dwarf_gpr_x26:
case riscv_dwarf::dwarf_gpr_x27:
case riscv_dwarf::dwarf_gpr_x28:
case riscv_dwarf::dwarf_gpr_x29:
case riscv_dwarf::dwarf_gpr_x30:
case riscv_dwarf::dwarf_gpr_x31:
return gpr_x0 + (reg - riscv_dwarf::dwarf_gpr_x0);
case riscv_dwarf::dwarf_fpr_f0:
case riscv_dwarf::dwarf_fpr_f1:
case riscv_dwarf::dwarf_fpr_f2:
case riscv_dwarf::dwarf_fpr_f3:
case riscv_dwarf::dwarf_fpr_f4:
case riscv_dwarf::dwarf_fpr_f5:
case riscv_dwarf::dwarf_fpr_f6:
case riscv_dwarf::dwarf_fpr_f7:
case riscv_dwarf::dwarf_fpr_f8:
case riscv_dwarf::dwarf_fpr_f9:
case riscv_dwarf::dwarf_fpr_f10:
case riscv_dwarf::dwarf_fpr_f11:
case riscv_dwarf::dwarf_fpr_f12:
case riscv_dwarf::dwarf_fpr_f13:
case riscv_dwarf::dwarf_fpr_f14:
case riscv_dwarf::dwarf_fpr_f15:
case riscv_dwarf::dwarf_fpr_f16:
case riscv_dwarf::dwarf_fpr_f17:
case riscv_dwarf::dwarf_fpr_f18:
case riscv_dwarf::dwarf_fpr_f19:
case riscv_dwarf::dwarf_fpr_f20:
case riscv_dwarf::dwarf_fpr_f21:
case riscv_dwarf::dwarf_fpr_f22:
case riscv_dwarf::dwarf_fpr_f23:
case riscv_dwarf::dwarf_fpr_f24:
case riscv_dwarf::dwarf_fpr_f25:
case riscv_dwarf::dwarf_fpr_f26:
case riscv_dwarf::dwarf_fpr_f27:
case riscv_dwarf::dwarf_fpr_f28:
case riscv_dwarf::dwarf_fpr_f29:
case riscv_dwarf::dwarf_fpr_f30:
case riscv_dwarf::dwarf_fpr_f31:
return fpr_f0 + (reg - riscv_dwarf::dwarf_fpr_f0);
default:
break;
}
} else if (kind == eRegisterKindLLDB) {
return reg;
}
return LLDB_INVALID_REGNUM;
}