1/* Common target dependent code for GDB on ARM systems.
2   Copyright (C) 2002-2023 Free Software Foundation, Inc.
3
4   This file is part of GDB.
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19#ifndef ARM_TDEP_H
20#define ARM_TDEP_H
21
22/* Forward declarations.  */
23struct regset;
24struct address_space;
25struct get_next_pcs;
26struct arm_get_next_pcs;
27struct gdb_get_next_pcs;
28
29/* Set to true if the 32-bit mode is in use.  */
30
31extern bool arm_apcs_32;
32
33#include "gdbarch.h"
34#include "arch/arm.h"
35#include "infrun.h"
36
37#include <vector>
38
39/* Number of machine registers.  The only define actually required
40   is gdbarch_num_regs.  The other definitions are used for documentation
41   purposes and code readability.  */
42/* For 26 bit ARM code, a fake copy of the PC is placed in register 25 (PS)
43   (and called PS for processor status) so the status bits can be cleared
44   from the PC (register 15).  For 32 bit ARM code, a copy of CPSR is placed
45   in PS.  */
46#define NUM_FREGS	8	/* Number of floating point registers.  */
47#define NUM_SREGS	2	/* Number of status registers.  */
48#define NUM_GREGS	16	/* Number of general purpose registers.  */
49
50
51
52/* Type of floating-point code in use by inferior.  There are really 3 models
53   that are traditionally supported (plus the endianness issue), but gcc can
54   only generate 2 of those.  The third is APCS_FLOAT, where arguments to
55   functions are passed in floating-point registers.
56
57   In addition to the traditional models, VFP adds two more.
58
59   If you update this enum, don't forget to update fp_model_strings in
60   arm-tdep.c.  */
61
62enum arm_float_model
63{
64  ARM_FLOAT_AUTO,	/* Automatic detection.  Do not set in tdep.  */
65  ARM_FLOAT_SOFT_FPA,	/* Traditional soft-float (mixed-endian on LE ARM).  */
66  ARM_FLOAT_FPA,	/* FPA co-processor.  GCC calling convention.  */
67  ARM_FLOAT_SOFT_VFP,	/* Soft-float with pure-endian doubles.  */
68  ARM_FLOAT_VFP,	/* Full VFP calling convention.  */
69  ARM_FLOAT_LAST	/* Keep at end.  */
70};
71
72/* ABI used by the inferior.  */
73enum arm_abi_kind
74{
75  ARM_ABI_AUTO,
76  ARM_ABI_APCS,
77  ARM_ABI_AAPCS,
78  ARM_ABI_LAST
79};
80
81/* Convention for returning structures.  */
82
83enum struct_return
84{
85  pcc_struct_return,		/* Return "short" structures in memory.  */
86  reg_struct_return		/* Return "short" structures in registers.  */
87};
88
89/* Target-dependent structure in gdbarch.  */
90struct arm_gdbarch_tdep : gdbarch_tdep_base
91{
92  /* The ABI for this architecture.  It should never be set to
93     ARM_ABI_AUTO.  */
94  enum arm_abi_kind arm_abi {};
95
96  enum arm_float_model fp_model {}; /* Floating point calling conventions.  */
97
98  bool have_fpa_registers = false;	/* Does the target report the FPA registers?  */
99  bool have_wmmx_registers = false;	/* Does the target report the WMMX registers?  */
100  /* The number of VFP registers reported by the target.  It is zero
101     if VFP registers are not supported.  */
102  int vfp_register_count = 0;
103  bool have_s_pseudos = false;	/* Are we synthesizing the single precision
104				   VFP registers?  */
105  int s_pseudo_base = 0;	/* Register number for the first S pseudo
106				   register.  */
107  int s_pseudo_count = 0;	/* Number of S pseudo registers.  */
108  bool have_q_pseudos = false;	/* Are we synthesizing the quad precision
109				   Q (NEON or MVE) registers?  Requires
110				   have_s_pseudos.  */
111  int q_pseudo_base = 0;	/* Register number for the first quad
112				   precision pseudo register.  */
113  int q_pseudo_count = 0;	/* Number of quad precision pseudo
114				   registers.  */
115  bool have_neon = false;	/* Do we have a NEON unit?  */
116
117  bool have_mve = false;	/* Do we have a MVE extension?  */
118  int mve_vpr_regnum = 0;	/* MVE VPR register number.  */
119  int mve_pseudo_base = 0;	/* Number of the first MVE pseudo register.  */
120  int mve_pseudo_count = 0;	/* Total number of MVE pseudo registers.  */
121
122  bool have_pacbti = false;	/* True if we have the ARMv8.1-m PACBTI
123				   extensions.  */
124  int pacbti_pseudo_base = 0;	/* Number of the first PACBTI pseudo
125				   register.  */
126  int pacbti_pseudo_count = 0;	/* Total number of PACBTI pseudo registers.  */
127
128  int m_profile_msp_regnum = ARM_SP_REGNUM;	/* M-profile MSP register number.  */
129  int m_profile_psp_regnum = ARM_SP_REGNUM;	/* M-profile PSP register number.  */
130
131  /* Secure and Non-secure stack pointers with security extension.  */
132  int m_profile_msp_ns_regnum = ARM_SP_REGNUM;	/* M-profile MSP_NS register number.  */
133  int m_profile_psp_ns_regnum = ARM_SP_REGNUM;	/* M-profile PSP_NS register number.  */
134  int m_profile_msp_s_regnum = ARM_SP_REGNUM;	/* M-profile MSP_S register number.  */
135  int m_profile_psp_s_regnum = ARM_SP_REGNUM;	/* M-profile PSP_S register number.  */
136
137  int tls_regnum = 0;		/* Number of the tpidruro register.  */
138
139  bool is_m = false;		/* Does the target follow the "M" profile.  */
140  bool have_sec_ext = false;	/* Do we have security extensions?  */
141  CORE_ADDR lowest_pc = 0;	/* Lowest address at which instructions
142				   will appear.  */
143
144  const gdb_byte *arm_breakpoint = nullptr;	/* Breakpoint pattern for an ARM insn.  */
145  int arm_breakpoint_size = 0;	/* And its size.  */
146  const gdb_byte *thumb_breakpoint = nullptr;	/* Breakpoint pattern for a Thumb insn.  */
147  int thumb_breakpoint_size = 0;	/* And its size.  */
148
149  /* If the Thumb breakpoint is an undefined instruction (which is
150     affected by IT blocks) rather than a BKPT instruction (which is
151     not), then we need a 32-bit Thumb breakpoint to preserve the
152     instruction count in IT blocks.  */
153  const gdb_byte *thumb2_breakpoint = nullptr;
154  int thumb2_breakpoint_size = 0;
155
156  int jb_pc = 0;			/* Offset to PC value in jump buffer.
157				   If this is negative, longjmp support
158				   will be disabled.  */
159  size_t jb_elt_size = 0;		/* And the size of each entry in the buf.  */
160
161  /* Convention for returning structures.  */
162  enum struct_return struct_return {};
163
164  /* ISA-specific data types.  */
165  struct type *arm_ext_type = nullptr;
166  struct type *neon_double_type = nullptr;
167  struct type *neon_quad_type = nullptr;
168
169   /* syscall record.  */
170  int (*arm_syscall_record) (struct regcache *regcache,
171			     unsigned long svc_number) = nullptr;
172};
173
174/* Structures used for displaced stepping.  */
175
176/* The maximum number of temporaries available for displaced instructions.  */
177#define DISPLACED_TEMPS			16
178/* The maximum number of modified instructions generated for one single-stepped
179   instruction, including the breakpoint (usually at the end of the instruction
180   sequence) and any scratch words, etc.  */
181#define ARM_DISPLACED_MODIFIED_INSNS	8
182
183struct arm_displaced_step_copy_insn_closure
184  : public displaced_step_copy_insn_closure
185{
186  ULONGEST tmp[DISPLACED_TEMPS];
187  int rd;
188  int wrote_to_pc;
189  union
190  {
191    struct
192    {
193      int xfersize;
194      int rn;			   /* Writeback register.  */
195      unsigned int immed : 1;      /* Offset is immediate.  */
196      unsigned int writeback : 1;  /* Perform base-register writeback.  */
197      unsigned int restore_r4 : 1; /* Used r4 as scratch.  */
198    } ldst;
199
200    struct
201    {
202      unsigned long dest;
203      unsigned int link : 1;
204      unsigned int exchange : 1;
205      unsigned int cond : 4;
206    } branch;
207
208    struct
209    {
210      unsigned int regmask;
211      int rn;
212      CORE_ADDR xfer_addr;
213      unsigned int load : 1;
214      unsigned int user : 1;
215      unsigned int increment : 1;
216      unsigned int before : 1;
217      unsigned int writeback : 1;
218      unsigned int cond : 4;
219    } block;
220
221    struct
222    {
223      unsigned int immed : 1;
224    } preload;
225
226    struct
227    {
228      /* If non-NULL, override generic SVC handling (e.g. for a particular
229	 OS).  */
230      int (*copy_svc_os) (struct gdbarch *gdbarch, struct regcache *regs,
231			  arm_displaced_step_copy_insn_closure *dsc);
232    } svc;
233  } u;
234
235  /* The size of original instruction, 2 or 4.  */
236  unsigned int insn_size;
237  /* True if the original insn (and thus all replacement insns) are Thumb
238     instead of ARM.   */
239  unsigned int is_thumb;
240
241  /* The slots in the array is used in this way below,
242     - ARM instruction occupies one slot,
243     - Thumb 16 bit instruction occupies one slot,
244     - Thumb 32-bit instruction occupies *two* slots, one part for each.  */
245  unsigned long modinsn[ARM_DISPLACED_MODIFIED_INSNS];
246  int numinsns;
247  CORE_ADDR insn_addr;
248  CORE_ADDR scratch_base;
249  void (*cleanup) (struct gdbarch *, struct regcache *,
250		   arm_displaced_step_copy_insn_closure *);
251};
252
253/* Values for the WRITE_PC argument to displaced_write_reg.  If the register
254   write may write to the PC, specifies the way the CPSR T bit, etc. is
255   modified by the instruction.  */
256
257enum pc_write_style
258{
259  BRANCH_WRITE_PC,
260  BX_WRITE_PC,
261  LOAD_WRITE_PC,
262  ALU_WRITE_PC,
263  CANNOT_WRITE_PC
264};
265
266extern void
267  arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
268			      CORE_ADDR to, struct regcache *regs,
269			      arm_displaced_step_copy_insn_closure *dsc);
270extern void
271  arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
272			      CORE_ADDR to,
273			      arm_displaced_step_copy_insn_closure *dsc);
274extern ULONGEST
275  displaced_read_reg (regcache *regs, arm_displaced_step_copy_insn_closure *dsc,
276		      int regno);
277extern void
278  displaced_write_reg (struct regcache *regs,
279		       arm_displaced_step_copy_insn_closure *dsc, int regno,
280		       ULONGEST val, enum pc_write_style write_pc);
281
282CORE_ADDR arm_skip_stub (frame_info_ptr, CORE_ADDR);
283
284ULONGEST arm_get_next_pcs_read_memory_unsigned_integer (CORE_ADDR memaddr,
285							int len,
286							int byte_order);
287
288CORE_ADDR arm_get_next_pcs_addr_bits_remove (struct arm_get_next_pcs *self,
289					     CORE_ADDR val);
290
291int arm_get_next_pcs_is_thumb (struct arm_get_next_pcs *self);
292
293std::vector<CORE_ADDR> arm_software_single_step (struct regcache *);
294int arm_is_thumb (struct regcache *regcache);
295int arm_frame_is_thumb (frame_info_ptr frame);
296
297extern void arm_displaced_step_fixup (struct gdbarch *,
298				      displaced_step_copy_insn_closure *,
299				      CORE_ADDR, CORE_ADDR, struct regcache *);
300
301/* Return the bit mask in ARM_PS_REGNUM that indicates Thumb mode.  */
302extern int arm_psr_thumb_bit (struct gdbarch *);
303
304/* Is the instruction at the given memory address a Thumb or ARM
305   instruction?  */
306extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
307
308extern int arm_process_record (struct gdbarch *gdbarch,
309			       struct regcache *regcache, CORE_ADDR addr);
310/* Functions exported from arm-bsd-tdep.h.  */
311
312/* Return the appropriate register set for the core section identified
313   by SECT_NAME and SECT_SIZE.  */
314
315extern void
316  armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
317				       iterate_over_regset_sections_cb *cb,
318				       void *cb_data,
319				       const struct regcache *regcache);
320
321/* Get the correct Arm target description with given FP hardware type.  */
322const target_desc *arm_read_description (arm_fp_type fp_type, bool tls);
323
324/* Get the correct Arm M-Profile target description with given hardware
325   type.  */
326const target_desc *arm_read_mprofile_description (arm_m_profile_type m_type);
327
328#endif /* arm-tdep.h */
329