1 /*
2 * Copyright (c) 2021 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <inttypes.h>
8
9 #ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_
10 #define ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_
11
12 #ifdef CONFIG_GDBSTUB
13
14 #define XTREG_GRP_MASK 0x0F00
15 #define XTREG_GRP_GENERAL 0x0000
16 #define XTREG_GRP_ADDR 0x0100
17 #define XTREG_GRP_SPECIAL 0x0200
18 #define XTREG_GRP_USER 0x0300
19
20 /*
21 * Register description fot GDB stub.
22 *
23 * Values are based on gdb/gdb/xtensa-config.c in the Xtensa overlay,
24 * where registers are defined using XTREG() macro:
25 * XTREG(index,ofs,bsz,sz,al,tnum,flg,cp,ty,gr,name,fet,sto,mas,ct,x,y)
26 *
27 * Translation:
28 * idx : index
29 * regno : tnum
30 * 0x00xx : General Registers (A0 - A15, PC)
31 * 0x01xx : Address Registers (AR0 - AR31/AR63)
32 * 0x02xx : Special Registers (access via RSR/WSR)
33 * 0x03xx : User Registers (access via RUR/WUR)
34 * byte_size : sz
35 * gpkt_offset : ofs
36 */
37 struct xtensa_register {
38 /* Register value */
39 uint32_t val;
40
41 /* GDB register index (for p/P packets) */
42 uint8_t idx;
43
44 /* Size of register */
45 uint8_t byte_size;
46
47 /* Xtensa register number */
48 uint16_t regno;
49
50 /* Offset of this register in GDB G-packet.
51 * -1 if register is not in G-packet.
52 */
53 int16_t gpkt_offset;
54
55 /* Offset of saved register in stack frame.
56 * 0 if not saved in stack frame.
57 */
58 int8_t stack_offset;
59
60 /* Sequence number */
61 uint8_t seqno;
62
63 /* Set 1 to if register should not be written
64 * to during debugging.
65 */
66 uint8_t is_read_only:1;
67 };
68
69 /* Due to Xtensa SoCs being highly configurable,
70 * the register files between SoCs are not identical.
71 *
72 * This means generic registers can, sometimes, have
73 * different offsets from start of register files
74 * needed to communicate with GDB.
75 *
76 * Therefore, it is better to defer to the SoC layer
77 * for proper support for GDB.
78 */
79 #include <gdbstub/soc.h>
80
81 struct gdb_ctx {
82 /* Exception reason */
83 unsigned int exception;
84
85 /* Register descriptions */
86 struct xtensa_register *regs;
87
88 /* Number of registers */
89 uint8_t num_regs;
90
91 /* Sequence number */
92 uint8_t seqno;
93
94 /* Index in register descriptions of A0 register */
95 uint8_t a0_idx;
96
97 /* Index in register descriptions of AR0 register */
98 uint8_t ar_idx;
99
100 /* Index in register descriptions of WINDOWBASE register */
101 uint8_t wb_idx;
102 };
103
104 /**
105 * Test if the register is a logical address register (A0 - A15).
106 *
107 * @retval true if register is A0 - A15
108 * @retval false if register is not A0 - A15
109 */
gdb_xtensa_is_logical_addr_reg(struct xtensa_register * reg)110 static inline bool gdb_xtensa_is_logical_addr_reg(struct xtensa_register *reg)
111 {
112 if (reg->regno < 16) {
113 return true;
114 } else {
115 return false;
116 }
117 }
118
119 /**
120 * Test if the register is a address register (AR0 - AR31/AR63).
121 *
122 * @retval true if register is AR0 - AR31/AR63
123 * @retval false if not
124 */
gdb_xtensa_is_address_reg(struct xtensa_register * reg)125 static inline bool gdb_xtensa_is_address_reg(struct xtensa_register *reg)
126 {
127 if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_ADDR) {
128 return true;
129 } else {
130 return false;
131 }
132 }
133
134 /**
135 * Test if the register is a special register that needs to be
136 * accessed via RSR/WSR.
137 *
138 * @retval true if special register
139 * @retval false if not
140 */
gdb_xtensa_is_special_reg(struct xtensa_register * reg)141 static inline bool gdb_xtensa_is_special_reg(struct xtensa_register *reg)
142 {
143 if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_SPECIAL) {
144 return true;
145 } else {
146 return false;
147 }
148 }
149
150 /**
151 * Test if the register is a user register that needs to be
152 * accessed via RUR/WUR.
153 *
154 * @retval true if user register
155 * @retval false if not
156 */
gdb_xtensa_is_user_reg(struct xtensa_register * reg)157 static inline bool gdb_xtensa_is_user_reg(struct xtensa_register *reg)
158 {
159 if ((reg->regno & XTREG_GRP_MASK) == XTREG_GRP_USER) {
160 return true;
161 } else {
162 return false;
163 }
164 }
165
166 #endif /* CONFIG_GDBSTUB */
167
168 #endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_GDBSTUB_SYS_H_ */
169