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
);
131 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FPREGSET
; i
++)
133 regbuf
= (gdb_byte
*)buf
+ fprsize
* i
;
134 collect_register (regcache
, LOONGARCH_FIRST_FP_REGNUM
+ i
, regbuf
);
138 /* Supply FPRs from BUF into REGCACHE. */
141 loongarch_store_fpregset (struct regcache
*regcache
, const void *buf
)
143 const gdb_byte
*regbuf
= nullptr;
144 int fprsize
= register_size (regcache
->tdesc
, LOONGARCH_FIRST_FP_REGNUM
);
146 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FPREGSET
; i
++)
148 regbuf
= (const gdb_byte
*)buf
+ fprsize
* i
;
149 supply_register (regcache
, LOONGARCH_FIRST_FP_REGNUM
+ i
, regbuf
);
153 /* LoongArch/Linux regsets. */
154 static struct regset_info loongarch_regsets
[] = {
155 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_PRSTATUS
, sizeof (elf_gregset_t
),
156 GENERAL_REGS
, loongarch_fill_gregset
, loongarch_store_gregset
},
157 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_FPREGSET
, sizeof (elf_fpregset_t
),
158 FP_REGS
, loongarch_fill_fpregset
, loongarch_store_fpregset
},
162 /* LoongArch/Linux regset information. */
163 static struct regsets_info loongarch_regsets_info
=
165 loongarch_regsets
, /* regsets */
167 NULL
, /* disabled_regsets */
170 /* Definition of linux_target_ops data member "regs_info". */
171 static struct regs_info loongarch_regs
=
173 NULL
, /* regset_bitmap */
175 &loongarch_regsets_info
,
178 /* Implementation of linux target ops method "get_regs_info". */
181 loongarch_target::get_regs_info ()
183 return &loongarch_regs
;
186 /* Implementation of linux target ops method "low_fetch_register". */
189 loongarch_target::low_fetch_register (regcache
*regcache
, int regno
)
193 supply_register_zeroed (regcache
, 0);
198 loongarch_target::low_supports_breakpoints ()
203 /* Implementation of linux target ops method "low_get_pc". */
206 loongarch_target::low_get_pc (regcache
*regcache
)
208 if (register_size (regcache
->tdesc
, 0) == 8)
209 return linux_get_pc_64bit (regcache
);
211 return linux_get_pc_32bit (regcache
);
214 /* Implementation of linux target ops method "low_set_pc". */
217 loongarch_target::low_set_pc (regcache
*regcache
, CORE_ADDR newpc
)
219 if (register_size (regcache
->tdesc
, 0) == 8)
220 linux_set_pc_64bit (regcache
, newpc
);
222 linux_set_pc_32bit (regcache
, newpc
);
225 #define loongarch_breakpoint_len 4
227 /* LoongArch BRK software debug mode instruction.
228 This instruction needs to match gdb/loongarch-tdep.c
229 (loongarch_default_breakpoint). */
230 static const gdb_byte loongarch_breakpoint
[] = {0x05, 0x00, 0x2a, 0x00};
232 /* Implementation of target ops method "breakpoint_kind_from_pc". */
235 loongarch_target::breakpoint_kind_from_pc (CORE_ADDR
*pcptr
)
237 return loongarch_breakpoint_len
;
240 /* Implementation of target ops method "sw_breakpoint_from_kind". */
243 loongarch_target::sw_breakpoint_from_kind (int kind
, int *size
)
245 *size
= loongarch_breakpoint_len
;
246 return (const gdb_byte
*) &loongarch_breakpoint
;
249 /* Implementation of linux target ops method "low_breakpoint_at". */
252 loongarch_target::low_breakpoint_at (CORE_ADDR pc
)
254 gdb_byte insn
[loongarch_breakpoint_len
];
256 read_memory (pc
, (unsigned char *) &insn
, loongarch_breakpoint_len
);
257 if (memcmp (insn
, loongarch_breakpoint
, loongarch_breakpoint_len
) == 0)
263 /* The linux target ops object. */
265 linux_process_target
*the_linux_target
= &the_loongarch_target
;
267 /* Initialize the LoongArch/Linux target. */
270 initialize_low_arch ()
272 initialize_regsets_info (&loongarch_regsets_info
);