]> Git Repo - binutils.git/blob - gdb/csky-linux-tdep.c
Automatic date update in version.in
[binutils.git] / gdb / csky-linux-tdep.c
1 /* Target-dependent code for GNU/Linux on CSKY.
2
3    Copyright (C) 2012-2022 Free Software Foundation, Inc.
4
5    Contributed by C-SKY Microsystems and Mentor Graphics.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "defs.h"
23 #include "osabi.h"
24 #include "glibc-tdep.h"
25 #include "linux-tdep.h"
26 #include "gdbarch.h"
27 #include "solib-svr4.h"
28 #include "regset.h"
29 #include "trad-frame.h"
30 #include "tramp-frame.h"
31 #include "csky-tdep.h"
32
33 /* Functions, definitions, and data structures for C-Sky core file debug.  */
34
35 /* General regset pc, r1, r0, psr, r2-r31 for CK810.  */
36 #define SIZEOF_CSKY_GREGSET 34*4
37 /* Float regset fesr fsr fr0-fr31 for CK810.  */
38 #define SIZEOF_CSKY_FREGSET 34*4
39 /* Float regset vr0~vr15 fr15~fr31, reserved for CK810 when kernel 4.x.  */
40 #define SIZEOF_CSKY_FREGSET_K4X  400
41
42 /* Offset mapping table from core_section to regcache of general
43    registers for ck810.  */
44 static const int csky_gregset_offset[] =
45 {
46   72,  1,  0, 89,  2,  /* pc, r1, r0, psr, r2.  */
47    3,  4,  5,  6,  7,  /* r3 ~ r32.  */
48    8,  9, 10, 11, 12,
49   13, 14, 15, 16, 17,
50   18, 19, 20, 21, 22,
51   23, 24, 25, 26, 27,
52   28, 29, 30, 31
53 };
54
55 /* Offset mapping table from core_section to regcache of float
56    registers for ck810.  */
57
58 static const int csky_fregset_offset[] =
59 {
60   122, 123, 40, 41, 42,     /* fcr, fesr, fr0 ~ fr2.  */
61    43,  44, 45, 46, 47,     /* fr3 ~ fr15.  */
62    48,  49, 50, 51, 52,
63    53,  54, 55
64 };
65
66 /* Implement the supply_regset hook for GP registers in core files.  */
67
68 static void
69 csky_supply_gregset (const struct regset *regset,
70                      struct regcache *regcache, int regnum,
71                      const void *regs, size_t len)
72 {
73   int i, gregset_num;
74   const gdb_byte *gregs = (const gdb_byte *) regs ;
75
76   gdb_assert (len >= SIZEOF_CSKY_GREGSET);
77   gregset_num = ARRAY_SIZE (csky_gregset_offset);
78
79   for (i = 0; i < gregset_num; i++)
80     {
81       if ((regnum == csky_gregset_offset[i] || regnum == -1)
82           && csky_gregset_offset[i] != -1)
83         regcache->raw_supply (csky_gregset_offset[i], gregs + 4 * i);
84     }
85 }
86
87 /* Implement the collect_regset hook for GP registers in core files.  */
88
89 static void
90 csky_collect_gregset (const struct regset *regset,
91                       const struct regcache *regcache,
92                       int regnum, void *gregs_buf, size_t len)
93 {
94   int regno, gregset_num;
95   gdb_byte *gregs = (gdb_byte *) gregs_buf ;
96
97   gdb_assert (len >= SIZEOF_CSKY_GREGSET);
98   gregset_num = ARRAY_SIZE (csky_gregset_offset);
99
100   for (regno = 0; regno < gregset_num; regno++)
101     {
102       if ((regnum == csky_gregset_offset[regno] || regnum == -1)
103           && csky_gregset_offset[regno] != -1)
104         regcache->raw_collect (regno,
105                                gregs + 4 + csky_gregset_offset[regno]);
106     }
107 }
108
109 /* Implement the supply_regset hook for FP registers in core files.  */
110
111 static void
112 csky_supply_fregset (const struct regset *regset,
113                      struct regcache *regcache, int regnum,
114                      const void *regs, size_t len)
115 {
116   int i;
117   int offset = 0;
118   struct gdbarch *gdbarch = regcache->arch ();
119   const gdb_byte *fregs = (const gdb_byte *) regs;
120   int fregset_num = ARRAY_SIZE (csky_fregset_offset);
121
122   gdb_assert (len >= SIZEOF_CSKY_FREGSET);
123   if (len == SIZEOF_CSKY_FREGSET)
124     {
125       for (i = 0; i < fregset_num; i++)
126         {
127           if ((regnum == csky_fregset_offset[i] || regnum == -1)
128               && csky_fregset_offset[i] != -1)
129             {
130               int num = csky_fregset_offset[i];
131               offset += register_size (gdbarch, num);
132               regcache->raw_supply (csky_fregset_offset[i], fregs + offset);
133             }
134         }
135     }
136   else if (len == SIZEOF_CSKY_FREGSET_K4X)
137     {
138       /* When kernel version >= 4.x, .reg2 size will be 400.
139          Contents is {
140           unsigned long vr[96];
141           unsigned long fcr;
142           unsigned long fesr;
143           unsigned long fid;
144           unsigned long reserved;
145          }
146          VR[96] means: (vr0~vr15) + (fr16~fr31), each Vector register is
147          128-bits, each Float register is 64 bits, the total size is
148          (4*96).
149
150          In addition, for fr0~fr15, each FRx is the lower 64 bits of the
151          corresponding VRx. So fr0~fr15 and vr0~vr15 regisetrs use the same
152          offset.  */
153       int fcr_regno[] = {122, 123, 121}; /* fcr, fesr, fid.  */
154
155       /* Supply vr0~vr15.  */
156       for (i = 0; i < 16; i ++)
157         {
158           if (*gdbarch_register_name (gdbarch, (CSKY_VR0_REGNUM + i)) != '\0')
159             {
160               offset = 16 * i;
161               regcache->raw_supply (CSKY_VR0_REGNUM + i, fregs + offset);
162             }
163         }
164       /* Supply fr0~fr15.  */
165       for (i = 0; i < 16; i ++)
166         {
167           if (*gdbarch_register_name (gdbarch, (CSKY_FR0_REGNUM + i)) != '\0')
168             {
169               offset = 16 * i;
170               regcache->raw_supply (CSKY_FR0_REGNUM + i, fregs + offset);
171             }
172         }
173       /* Supply fr16~fr31.  */
174       for (i = 0; i < 16; i ++)
175         {
176           if (*gdbarch_register_name (gdbarch, (CSKY_FR16_REGNUM + i)) != '\0')
177             {
178               offset = (16 * 16) + (8 * i);
179               regcache->raw_supply (CSKY_FR16_REGNUM + i, fregs + offset);
180             }
181         }
182      /* Supply fcr, fesr, fid.  */
183       for (i = 0; i < 3; i ++)
184         {
185           if (*gdbarch_register_name (gdbarch, fcr_regno[i]) != '\0')
186             {
187               offset = (16 * 16) + (16 * 8) + (4 * i);
188               regcache->raw_supply (fcr_regno[i], fregs + offset);
189             }
190         }
191     }
192   else
193     {
194       warning (_("Unknow size %s of section .reg2, can not get value"
195                  " of float registers."), pulongest (len));
196     }
197 }
198
199 /* Implement the collect_regset hook for FP registers in core files.  */
200
201 static void
202 csky_collect_fregset (const struct regset *regset,
203                       const struct regcache *regcache,
204                       int regnum, void *fregs_buf, size_t len)
205 {
206   int regno;
207   struct gdbarch *gdbarch = regcache->arch ();
208   gdb_byte *fregs = (gdb_byte *) fregs_buf ;
209   int fregset_num = ARRAY_SIZE (csky_fregset_offset);
210   int offset = 0;
211
212   gdb_assert (len >= SIZEOF_CSKY_FREGSET);
213   if (len == SIZEOF_CSKY_FREGSET)
214     {
215       for (regno = 0; regno < fregset_num; regno++)
216         {
217           if ((regnum == csky_fregset_offset[regno] || regnum == -1)
218                && csky_fregset_offset[regno] != -1)
219             {
220               offset += register_size (gdbarch, csky_fregset_offset[regno]);
221               regcache->raw_collect (regno, fregs + offset);
222             }
223         }
224     }
225   else if (len == SIZEOF_CSKY_FREGSET_K4X)
226     {
227       /* When kernel version >= 4.x, .reg2 size will be 400.
228          Contents is {
229            unsigned long vr[96];
230            unsigned long fcr;
231            unsigned long fesr;
232            unsigned long fid;
233            unsigned long reserved;
234          }
235          VR[96] means: (vr0~vr15) + (fr16~fr31), each Vector register is$
236          128-bits, each Float register is 64 bits, the total size is$
237          (4*96).$
238
239          In addition, for fr0~fr15, each FRx is the lower 64 bits of the$
240          corresponding VRx. So fr0~fr15 and vr0~vr15 regisetrs use the same$
241          offset.  */
242       int i = 0;
243       int fcr_regno[] = {122, 123, 121}; /* fcr, fesr, fid.  */
244
245       /* Supply vr0~vr15.  */
246       for (i = 0; i < 16; i ++)
247         {
248           if (*gdbarch_register_name (gdbarch, (CSKY_VR0_REGNUM + i)) != '\0')
249             {
250               offset = 16 * i;
251               regcache ->raw_collect (CSKY_VR0_REGNUM + i, fregs + offset);
252             }
253         }
254       /* Supply fr16~fr31.  */
255       for (i = 0; i < 16; i ++)
256         {
257           if (*gdbarch_register_name (gdbarch, (CSKY_FR16_REGNUM + i)) != '\0')
258             {
259               offset = (16 * 16) + (8 * i);
260               regcache ->raw_collect (CSKY_FR16_REGNUM + i, fregs + offset);
261             }
262         }
263       /* Supply fcr, fesr, fid.  */
264       for (i = 0; i < 3; i ++)
265         {
266           if (*gdbarch_register_name (gdbarch, fcr_regno[i]) != '\0')
267             {
268               offset = (16 * 16) + (16 * 8) + (4 * i);
269               regcache ->raw_collect (fcr_regno[i], fregs + offset);
270             }
271         }
272     }
273   else
274     {
275       warning (_("Unknow size %s of section .reg2, will not set value"
276                  " of float registers."), pulongest (len));
277     }
278 }
279
280 static const struct regset csky_regset_general =
281 {
282   NULL,
283   csky_supply_gregset,
284   csky_collect_gregset
285 };
286
287 static const struct regset csky_regset_float =
288 {
289   NULL,
290   csky_supply_fregset,
291   csky_collect_fregset,
292   /* Allow .reg2 to have a different size, and the size of .reg2 should
293      always be bigger than SIZEOF_CSKY_FREGSET.  */
294   1
295 };
296
297 /* Iterate over core file register note sections.  */
298
299 static void
300 csky_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
301                                          iterate_over_regset_sections_cb *cb,
302                                          void *cb_data,
303                                          const struct regcache *regcache)
304 {
305   cb (".reg", sizeof (csky_gregset_offset), sizeof (csky_gregset_offset),
306       &csky_regset_general, NULL, cb_data);
307   cb (".reg2", sizeof (csky_fregset_offset), sizeof (csky_fregset_offset),
308       &csky_regset_float, NULL, cb_data);
309 }
310
311 static void
312 csky_linux_rt_sigreturn_init (const struct tramp_frame *self,
313                               frame_info_ptr this_frame,
314                               struct trad_frame_cache *this_cache,
315                               CORE_ADDR func)
316 {
317   int i;
318   CORE_ADDR sp = get_frame_register_unsigned (this_frame, 14);
319
320   CORE_ADDR base = sp + CSKY_SIGINFO_OFFSET + CSKY_SIGINFO_SIZE
321                    + CSKY_UCONTEXT_SIGCONTEXT
322                    + CSKY_SIGCONTEXT_SC_USP
323                    + CSKY_SIGCONTEXT_SC_A0;
324
325   /* Set addrs of R0 ~ R13.  */
326   for (i = 0; i < 14; i++)
327    trad_frame_set_reg_addr (this_cache, i, base + i * 4);
328
329   /* Set addrs of SP(R14) and R15.  */
330   trad_frame_set_reg_addr (this_cache, 14, base - 4);
331   trad_frame_set_reg_addr (this_cache, 15, base + 4 * 14);
332
333   /* Set addrs of R16 ~ R31.  */
334   for (i = 15; i < 31; i++)
335    trad_frame_set_reg_addr (this_cache, i, base + i * 4);
336
337   /* Set addrs of PSR and PC.  */
338   trad_frame_set_reg_addr (this_cache, 89, base + 4 * 33);
339   trad_frame_set_reg_addr (this_cache, 72, base + 4 * 34);
340
341   trad_frame_set_id (this_cache, frame_id_build (sp, func));
342 }
343
344 static struct tramp_frame
345 csky_linux_rt_sigreturn_tramp_frame = {
346   SIGTRAMP_FRAME,
347   4,
348   {
349     { CSKY_MOVI_R7_173, ULONGEST_MAX },
350     { CSKY_TRAP_0, ULONGEST_MAX },
351     { TRAMP_SENTINEL_INSN }
352   },
353   csky_linux_rt_sigreturn_init
354 };
355
356 static void
357 csky_linux_rt_sigreturn_init_pt_regs (const struct tramp_frame *self,
358                                       frame_info_ptr this_frame,
359                                       struct trad_frame_cache *this_cache,
360                                       CORE_ADDR func)
361 {
362   int i;
363   CORE_ADDR sp = get_frame_register_unsigned (this_frame, CSKY_SP_REGNUM);
364
365   CORE_ADDR base = sp + CSKY_SIGINFO_OFFSET + CSKY_SIGINFO_SIZE
366                    + CSKY_UCONTEXT_SIGCONTEXT
367                    + CSKY_SIGCONTEXT_PT_REGS_TLS;
368
369   /* LR */
370   trad_frame_set_reg_addr (this_cache, CSKY_R15_REGNUM, base);
371
372   /* PC */
373   trad_frame_set_reg_addr (this_cache, CSKY_PC_REGNUM, base + 4);
374
375   /* PSR */
376   trad_frame_set_reg_addr (this_cache, CSKY_CR0_REGNUM, base + 8);
377
378   /* SP */
379   trad_frame_set_reg_addr (this_cache, CSKY_SP_REGNUM, base + 12);
380
381   /* Set addrs of R0 ~ R13.  */
382   for (i = 0; i < 14; i++)
383     trad_frame_set_reg_addr (this_cache, i, base + i * 4 + 20);
384
385   trad_frame_set_id (this_cache, frame_id_build (sp, func));
386 }
387
388
389 static struct tramp_frame
390 csky_linux_rt_sigreturn_tramp_frame_kernel_4x = {
391   SIGTRAMP_FRAME,
392   4,
393   {
394     { CSKY_MOVI_R7_139, ULONGEST_MAX },
395     { CSKY_TRAP_0, ULONGEST_MAX },
396     { TRAMP_SENTINEL_INSN }
397   },
398   csky_linux_rt_sigreturn_init_pt_regs
399 };
400
401 /* Hook function for gdbarch_register_osabi.  */
402
403 static void
404 csky_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
405 {
406   linux_init_abi (info, gdbarch, 0);
407
408   /* Shared library handling.  */
409   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
410   set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
411   set_solib_svr4_fetch_link_map_offsets (gdbarch,
412                                          linux_ilp32_fetch_link_map_offsets);
413
414   /* Enable TLS support.  */
415   set_gdbarch_fetch_tls_load_module_address (gdbarch,
416                                              svr4_fetch_objfile_link_map);
417
418   /* Core file support.  */
419   set_gdbarch_iterate_over_regset_sections (
420     gdbarch, csky_linux_iterate_over_regset_sections);
421
422   /* Append tramp frame unwinder for SIGNAL.  */
423
424   tramp_frame_prepend_unwinder (gdbarch,
425                                 &csky_linux_rt_sigreturn_tramp_frame);
426   tramp_frame_prepend_unwinder (gdbarch,
427                                 &csky_linux_rt_sigreturn_tramp_frame_kernel_4x);
428 }
429
430 void _initialize_csky_linux_tdep ();
431 void
432 _initialize_csky_linux_tdep ()
433 {
434   gdbarch_register_osabi (bfd_arch_csky, 0, GDB_OSABI_LINUX,
435                           csky_linux_init_abi);
436 }
This page took 0.050499 seconds and 4 git commands to generate.