blob: 627bb79e6785bb40193f6f02291b0bf12eea465d [file] [log] [blame]
/*
* Copyright (c) 2021 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <inttypes.h>
#ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_
#define ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_
#ifdef CONFIG_GDBSTUB
#define XTREG_GRP_MASK 0x0F00
#define XTREG_GRP_GENERAL 0x0000
#define XTREG_GRP_ADDR 0x0100
#define XTREG_GRP_SPECIAL 0x0200
#define XTREG_GRP_USER 0x0300
/*
* Register description fot GDB stub.
*
* Values are based on gdb/gdb/xtensa-config.c in the Xtensa overlay,
* where registers are defined using XTREG() macro:
* XTREG(index,ofs,bsz,sz,al,tnum,flg,cp,ty,gr,name,fet,sto,mas,ct,x,y)
*
* Translation:
* idx : index
* regno : tnum
* 0x00xx : General Registers (A0 - A15, PC)
* 0x01xx : Address Registers (AR0 - AR31/AR63)
* 0x02xx : Special Registers (access via RSR/WSR)
* 0x03xx : User Registers (access via RUR/WUR)
* byte_size : sz
* gpkt_offset : ofs
*/
struct xtensa_register {
/* Register value */
uint32_t val;
/* GDB register index (for p/P packets) */
uint8_t idx;
/* Size of register */
uint8_t byte_size;
/* Xtensa register number */
uint16_t regno;
/* Offset of this register in GDB G-packet.
* -1 if register is not in G-packet.
*/
int16_t gpkt_offset;
/* Offset of saved register in stack frame.
* 0 if not saved in stack frame.
*/
int8_t stack_offset;
/* Sequence number */
uint8_t seqno;
/* Set 1 to if register should not be written
* to during debugging.
*/
uint8_t is_read_only:1;
};
/* Due to Xtensa SoCs being highly configurable,
* the register files between SoCs are not identical.
*
* This means generic registers can, sometimes, have
* different offsets from start of register files
* needed to communicate with GDB.
*
* Therefore, it is better to defer to the SoC layer
* for proper support for GDB.
*/
#include <gdbstub/soc.h>
struct gdb_ctx {
/* Exception reason */
unsigned int exception;
/* Register descriptions */
struct xtensa_register *regs;
/* Number of registers */
uint8_t num_regs;
/* Sequence number */
uint8_t seqno;
/* Index in register descriptions of A0 register */
uint8_t a0_idx;
/* Index in register descriptions of AR0 register */
uint8_t ar_idx;
/* Index in register descriptions of WINDOWBASE register */
uint8_t wb_idx;
};
/**
* Test if the register is a logical address register (A0 - A15).
*
* @retval true if register is A0 - A15
* @retval false if register is not A0 - A15
*/
static inline bool gdb_xtensa_is_logical_addr_reg(struct xtensa_register *reg)
{
if (reg->regno < 16) {
return true;
} else {
return false;
}
}
/**
* Test if the register is a address register (AR0 - AR31/AR63).
*
* @retval true if register is AR0 - AR31/AR63
* @retval false if not
*/
static inline bool gdb_xtensa_is_address_reg(struct xtensa_register *reg)
{
if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_ADDR) {
return true;
} else {
return false;
}
}
/**
* Test if the register is a special register that needs to be
* accessed via RSR/WSR.
*
* @retval true if special register
* @retval false if not
*/
static inline bool gdb_xtensa_is_special_reg(struct xtensa_register *reg)
{
if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_SPECIAL) {
return true;
} else {
return false;
}
}
/**
* Test if the register is a user register that needs to be
* accessed via RUR/WUR.
*
* @retval true if user register
* @retval false if not
*/
static inline bool gdb_xtensa_is_user_reg(struct xtensa_register *reg)
{
if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_USER) {
return true;
} else {
return false;
}
}
#endif /* CONFIG_GDBSTUB */
#endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_ */