1 /* GNU/Linux/LoongArch specific low level interface, for the remote server
3 Copyright (C) 2022 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "linux-low.h"
23 #include "elf/common.h"
24 #include "arch/loongarch.h"
26 /* Linux target ops definitions for the LoongArch architecture. */
28 class loongarch_target
: public linux_process_target
32 const regs_info
*get_regs_info () override
;
34 int breakpoint_kind_from_pc (CORE_ADDR
*pcptr
) override
;
36 const gdb_byte
*sw_breakpoint_from_kind (int kind
, int *size
) override
;
40 void low_arch_setup () override
;
42 bool low_cannot_fetch_register (int regno
) override
;
44 bool low_cannot_store_register (int regno
) override
;
46 bool low_fetch_register (regcache
*regcache
, int regno
) override
;
48 bool low_supports_breakpoints () override
;
50 CORE_ADDR
low_get_pc (regcache
*regcache
) override
;
52 void low_set_pc (regcache
*regcache
, CORE_ADDR newpc
) override
;
54 bool low_breakpoint_at (CORE_ADDR pc
) override
;
57 /* The singleton target ops object. */
59 static loongarch_target the_loongarch_target
;
62 loongarch_target::low_cannot_fetch_register (int regno
)
64 gdb_assert_not_reached ("linux target op low_cannot_fetch_register "
65 "is not implemented by the target");
69 loongarch_target::low_cannot_store_register (int regno
)
71 gdb_assert_not_reached ("linux target op low_cannot_store_register "
72 "is not implemented by the target");
75 /* Implementation of linux target ops method "low_arch_setup". */
78 loongarch_target::low_arch_setup ()
80 static const char *expedite_regs
[] = { "r3", "pc", NULL
};
81 loongarch_gdbarch_features features
;
84 features
.xlen
= sizeof (elf_greg_t
);
85 tdesc
= loongarch_create_target_description (features
);
87 if (!tdesc
->expedite_regs
)
88 init_target_desc (tdesc
.get (), expedite_regs
);
89 current_process ()->tdesc
= tdesc
.release ();
92 /* Collect GPRs from REGCACHE into BUF. */
95 loongarch_fill_gregset (struct regcache
*regcache
, void *buf
)
97 elf_gregset_t
*regset
= (elf_gregset_t
*) buf
;
100 for (i
= 1; i
< 32; i
++)
101 collect_register (regcache
, i
, *regset
+ i
);
102 collect_register (regcache
, LOONGARCH_ORIG_A0_REGNUM
, *regset
+ LOONGARCH_ORIG_A0_REGNUM
);
103 collect_register (regcache
, LOONGARCH_PC_REGNUM
, *regset
+ LOONGARCH_PC_REGNUM
);
104 collect_register (regcache
, LOONGARCH_BADV_REGNUM
, *regset
+ LOONGARCH_BADV_REGNUM
);
107 /* Supply GPRs from BUF into REGCACHE. */
110 loongarch_store_gregset (struct regcache
*regcache
, const void *buf
)
112 const elf_gregset_t
*regset
= (const elf_gregset_t
*) buf
;
115 supply_register_zeroed (regcache
, 0);
116 for (i
= 1; i
< 32; i
++)
117 supply_register (regcache
, i
, *regset
+ i
);
118 supply_register (regcache
, LOONGARCH_ORIG_A0_REGNUM
, *regset
+ LOONGARCH_ORIG_A0_REGNUM
);
119 supply_register (regcache
, LOONGARCH_PC_REGNUM
, *regset
+ LOONGARCH_PC_REGNUM
);
120 supply_register (regcache
, LOONGARCH_BADV_REGNUM
, *regset
+ LOONGARCH_BADV_REGNUM
);
123 /* Collect FPRs from REGCACHE into BUF. */
126 loongarch_fill_fpregset (struct regcache
*regcache
, void *buf
)
128 gdb_byte
*regbuf
= nullptr;
129 int fprsize
= register_size (regcache
->tdesc
, LOONGARCH_FIRST_FP_REGNUM
);
130 int fccsize
= register_size (regcache
->tdesc
, LOONGARCH_FIRST_FCC_REGNUM
);
132 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FPREGSET
; i
++)
134 regbuf
= (gdb_byte
*)buf
+ fprsize
* i
;
135 collect_register (regcache
, LOONGARCH_FIRST_FP_REGNUM
+ i
, regbuf
);
138 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FCC
; i
++)
140 regbuf
= (gdb_byte
*)buf
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
142 collect_register (regcache
, LOONGARCH_FIRST_FCC_REGNUM
+ i
, regbuf
);
145 regbuf
= (gdb_byte
*)buf
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
146 fccsize
* LOONGARCH_LINUX_NUM_FCC
;
147 collect_register (regcache
, LOONGARCH_FCSR_REGNUM
, regbuf
);
150 /* Supply FPRs from BUF into REGCACHE. */
153 loongarch_store_fpregset (struct regcache
*regcache
, const void *buf
)
155 const gdb_byte
*regbuf
= nullptr;
156 int fprsize
= register_size (regcache
->tdesc
, LOONGARCH_FIRST_FP_REGNUM
);
157 int fccsize
= register_size (regcache
->tdesc
, LOONGARCH_FIRST_FCC_REGNUM
);
159 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FPREGSET
; i
++)
161 regbuf
= (const gdb_byte
*)buf
+ fprsize
* i
;
162 supply_register (regcache
, LOONGARCH_FIRST_FP_REGNUM
+ i
, regbuf
);
165 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FCC
; i
++)
167 regbuf
= (const gdb_byte
*)buf
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
169 supply_register (regcache
, LOONGARCH_FIRST_FCC_REGNUM
+ i
, regbuf
);
172 regbuf
= (const gdb_byte
*)buf
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
173 fccsize
* LOONGARCH_LINUX_NUM_FCC
;
174 supply_register (regcache
, LOONGARCH_FCSR_REGNUM
, regbuf
);
177 /* LoongArch/Linux regsets. */
178 static struct regset_info loongarch_regsets
[] = {
179 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_PRSTATUS
, sizeof (elf_gregset_t
),
180 GENERAL_REGS
, loongarch_fill_gregset
, loongarch_store_gregset
},
181 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_FPREGSET
, sizeof (elf_fpregset_t
),
182 FP_REGS
, loongarch_fill_fpregset
, loongarch_store_fpregset
},
186 /* LoongArch/Linux regset information. */
187 static struct regsets_info loongarch_regsets_info
=
189 loongarch_regsets
, /* regsets */
191 NULL
, /* disabled_regsets */
194 /* Definition of linux_target_ops data member "regs_info". */
195 static struct regs_info loongarch_regs
=
197 NULL
, /* regset_bitmap */
199 &loongarch_regsets_info
,
202 /* Implementation of linux target ops method "get_regs_info". */
205 loongarch_target::get_regs_info ()
207 return &loongarch_regs
;
210 /* Implementation of linux target ops method "low_fetch_register". */
213 loongarch_target::low_fetch_register (regcache
*regcache
, int regno
)
217 supply_register_zeroed (regcache
, 0);
222 loongarch_target::low_supports_breakpoints ()
227 /* Implementation of linux target ops method "low_get_pc". */
230 loongarch_target::low_get_pc (regcache
*regcache
)
232 if (register_size (regcache
->tdesc
, 0) == 8)
233 return linux_get_pc_64bit (regcache
);
235 return linux_get_pc_32bit (regcache
);
238 /* Implementation of linux target ops method "low_set_pc". */
241 loongarch_target::low_set_pc (regcache
*regcache
, CORE_ADDR newpc
)
243 if (register_size (regcache
->tdesc
, 0) == 8)
244 linux_set_pc_64bit (regcache
, newpc
);
246 linux_set_pc_32bit (regcache
, newpc
);
249 #define loongarch_breakpoint_len 4
251 /* LoongArch BRK software debug mode instruction.
252 This instruction needs to match gdb/loongarch-tdep.c
253 (loongarch_default_breakpoint). */
254 static const gdb_byte loongarch_breakpoint
[] = {0x05, 0x00, 0x2a, 0x00};
256 /* Implementation of target ops method "breakpoint_kind_from_pc". */
259 loongarch_target::breakpoint_kind_from_pc (CORE_ADDR
*pcptr
)
261 return loongarch_breakpoint_len
;
264 /* Implementation of target ops method "sw_breakpoint_from_kind". */
267 loongarch_target::sw_breakpoint_from_kind (int kind
, int *size
)
269 *size
= loongarch_breakpoint_len
;
270 return (const gdb_byte
*) &loongarch_breakpoint
;
273 /* Implementation of linux target ops method "low_breakpoint_at". */
276 loongarch_target::low_breakpoint_at (CORE_ADDR pc
)
278 gdb_byte insn
[loongarch_breakpoint_len
];
280 read_memory (pc
, (unsigned char *) &insn
, loongarch_breakpoint_len
);
281 if (memcmp (insn
, loongarch_breakpoint
, loongarch_breakpoint_len
) == 0)
287 /* The linux target ops object. */
289 linux_process_target
*the_linux_target
= &the_loongarch_target
;
291 /* Initialize the LoongArch/Linux target. */
294 initialize_low_arch ()
296 initialize_regsets_info (&loongarch_regsets_info
);