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_PC_REGNUM
, *regset
+ LOONGARCH_PC_REGNUM
);
103 collect_register (regcache
, LOONGARCH_BADV_REGNUM
, *regset
+ LOONGARCH_BADV_REGNUM
);
106 /* Supply GPRs from BUF into REGCACHE. */
109 loongarch_store_gregset (struct regcache
*regcache
, const void *buf
)
111 const elf_gregset_t
*regset
= (const elf_gregset_t
*) buf
;
114 supply_register_zeroed (regcache
, 0);
115 for (i
= 1; i
< 32; i
++)
116 supply_register (regcache
, i
, *regset
+ i
);
117 supply_register (regcache
, LOONGARCH_PC_REGNUM
, *regset
+ LOONGARCH_PC_REGNUM
);
118 supply_register (regcache
, LOONGARCH_BADV_REGNUM
, *regset
+ LOONGARCH_BADV_REGNUM
);
121 /* LoongArch/Linux regsets. */
122 static struct regset_info loongarch_regsets
[] = {
123 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_PRSTATUS
, sizeof (elf_gregset_t
),
124 GENERAL_REGS
, loongarch_fill_gregset
, loongarch_store_gregset
},
128 /* LoongArch/Linux regset information. */
129 static struct regsets_info loongarch_regsets_info
=
131 loongarch_regsets
, /* regsets */
133 NULL
, /* disabled_regsets */
136 /* Definition of linux_target_ops data member "regs_info". */
137 static struct regs_info loongarch_regs
=
139 NULL
, /* regset_bitmap */
141 &loongarch_regsets_info
,
144 /* Implementation of linux target ops method "get_regs_info". */
147 loongarch_target::get_regs_info ()
149 return &loongarch_regs
;
152 /* Implementation of linux target ops method "low_fetch_register". */
155 loongarch_target::low_fetch_register (regcache
*regcache
, int regno
)
159 supply_register_zeroed (regcache
, 0);
164 loongarch_target::low_supports_breakpoints ()
169 /* Implementation of linux target ops method "low_get_pc". */
172 loongarch_target::low_get_pc (regcache
*regcache
)
174 if (register_size (regcache
->tdesc
, 0) == 8)
175 return linux_get_pc_64bit (regcache
);
177 return linux_get_pc_32bit (regcache
);
180 /* Implementation of linux target ops method "low_set_pc". */
183 loongarch_target::low_set_pc (regcache
*regcache
, CORE_ADDR newpc
)
185 if (register_size (regcache
->tdesc
, 0) == 8)
186 linux_set_pc_64bit (regcache
, newpc
);
188 linux_set_pc_32bit (regcache
, newpc
);
191 #define loongarch_breakpoint_len 4
193 /* LoongArch BRK software debug mode instruction.
194 This instruction needs to match gdb/loongarch-tdep.c
195 (loongarch_default_breakpoint). */
196 static const gdb_byte loongarch_breakpoint
[] = {0x05, 0x00, 0x2a, 0x00};
198 /* Implementation of target ops method "breakpoint_kind_from_pc". */
201 loongarch_target::breakpoint_kind_from_pc (CORE_ADDR
*pcptr
)
203 return loongarch_breakpoint_len
;
206 /* Implementation of target ops method "sw_breakpoint_from_kind". */
209 loongarch_target::sw_breakpoint_from_kind (int kind
, int *size
)
211 *size
= loongarch_breakpoint_len
;
212 return (const gdb_byte
*) &loongarch_breakpoint
;
215 /* Implementation of linux target ops method "low_breakpoint_at". */
218 loongarch_target::low_breakpoint_at (CORE_ADDR pc
)
220 gdb_byte insn
[loongarch_breakpoint_len
];
222 read_memory (pc
, (unsigned char *) &insn
, loongarch_breakpoint_len
);
223 if (memcmp (insn
, loongarch_breakpoint
, loongarch_breakpoint_len
) == 0)
229 /* The linux target ops object. */
231 linux_process_target
*the_linux_target
= &the_loongarch_target
;
233 /* Initialize the LoongArch/Linux target. */
236 initialize_low_arch ()
238 initialize_regsets_info (&loongarch_regsets_info
);