Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / gdb6 / gdb / shnbsd-tdep.c
blobc55c59135d1a5bcd43bdfff1319b02c0acfddc25
1 /* Target-dependent code for SuperH running NetBSD, for GDB.
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3 Contributed by Wasabi Systems, 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 2 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, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "inferior.h"
25 #include "regcache.h"
26 #include "regset.h"
27 #include "value.h"
28 #include "osabi.h"
30 #include "trad-frame.h"
31 #include "tramp-frame.h"
33 #include "gdb_assert.h"
34 #include "gdb_string.h"
36 #include "solib-svr4.h"
38 #include "sh-tdep.h"
39 #include "shnbsd-tdep.h"
40 #include "nbsd-tdep.h"
42 /* Convert an r0-r15 register number into an offset into a ptrace
43 register structure. */
44 static const int regmap[] =
46 (20 * 4), /* r0 */
47 (19 * 4), /* r1 */
48 (18 * 4), /* r2 */
49 (17 * 4), /* r3 */
50 (16 * 4), /* r4 */
51 (15 * 4), /* r5 */
52 (14 * 4), /* r6 */
53 (13 * 4), /* r7 */
54 (12 * 4), /* r8 */
55 (11 * 4), /* r9 */
56 (10 * 4), /* r10 */
57 ( 9 * 4), /* r11 */
58 ( 8 * 4), /* r12 */
59 ( 7 * 4), /* r13 */
60 ( 6 * 4), /* r14 */
61 ( 5 * 4), /* r15 */
64 /* Sizeof `struct reg' in <machine/reg.h>. */
65 #define SHNBSD_SIZEOF_GREGS (22 * 4)
67 /* From <machine/mcontext.h>. */
68 static const int shnbsd_mc_reg_offset[] =
70 (20 * 4), /* r0 */
71 (19 * 4), /* r1 */
72 (18 * 4), /* r2 */
73 (17 * 4), /* r3 */
74 (16 * 4), /* r4 */
75 (15 * 4), /* r5 */
76 (14 * 4), /* r6 */
77 (13 * 4), /* r7 */
78 (12 * 4), /* r8 */
79 (11 * 4), /* r9 */
80 (10 * 4), /* r10 */
81 ( 9 * 4), /* r11 */
82 ( 8 * 4), /* r12 */
83 ( 7 * 4), /* r13 */
84 ( 6 * 4), /* r14 */
85 (21 * 4), /* r15/sp */
86 ( 1 * 4), /* pc */
87 ( 5 * 4), /* pr */
88 ( 0 * 4), /* gbr */
89 -1,
90 ( 4 * 4), /* mach */
91 ( 3 * 4), /* macl */
92 ( 2 * 4), /* sr */
95 /* Supply register REGNUM from the buffer specified by GREGS and LEN
96 in the general-purpose register set REGSET to register cache
97 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
99 static void
100 shnbsd_supply_gregset (const struct regset *regset,
101 struct regcache *regcache,
102 int regnum, const void *gregs, size_t len)
104 struct gdbarch *gdbarch = get_regcache_arch (regcache);
105 const gdb_byte *regs = gregs;
106 int i;
108 gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
110 if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
111 regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch),
112 regs + (0 * 4));
114 if (regnum == SR_REGNUM || regnum == -1)
115 regcache_raw_supply (regcache, SR_REGNUM, regs + (1 * 4));
117 if (regnum == PR_REGNUM || regnum == -1)
118 regcache_raw_supply (regcache, PR_REGNUM, regs + (2 * 4));
120 if (regnum == MACH_REGNUM || regnum == -1)
121 regcache_raw_supply (regcache, MACH_REGNUM, regs + (3 * 4));
123 if (regnum == MACL_REGNUM || regnum == -1)
124 regcache_raw_supply (regcache, MACL_REGNUM, regs + (4 * 4));
126 for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
128 if (regnum == i || regnum == -1)
129 regcache_raw_supply (regcache, i, regs + regmap[i - R0_REGNUM]);
132 if (regnum == GBR_REGNUM || regnum == -1)
133 regcache_raw_supply (regcache, GBR_REGNUM, regs + (21 * 4));
136 /* Collect register REGNUM in the general-purpose register set
137 REGSET. from register cache REGCACHE into the buffer specified by
138 GREGS and LEN. If REGNUM is -1, do this for all registers in
139 REGSET. */
141 static void
142 shnbsd_collect_gregset (const struct regset *regset,
143 const struct regcache *regcache,
144 int regnum, void *gregs, size_t len)
146 struct gdbarch *gdbarch = get_regcache_arch (regcache);
147 gdb_byte *regs = gregs;
148 int i;
150 gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
152 if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
153 regcache_raw_collect (regcache, gdbarch_pc_regnum (gdbarch),
154 regs + (0 * 4));
156 if (regnum == SR_REGNUM || regnum == -1)
157 regcache_raw_collect (regcache, SR_REGNUM, regs + (1 * 4));
159 if (regnum == PR_REGNUM || regnum == -1)
160 regcache_raw_collect (regcache, PR_REGNUM, regs + (2 * 4));
162 if (regnum == MACH_REGNUM || regnum == -1)
163 regcache_raw_collect (regcache, MACH_REGNUM, regs + (3 * 4));
165 if (regnum == MACL_REGNUM || regnum == -1)
166 regcache_raw_collect (regcache, MACL_REGNUM, regs + (4 * 4));
168 for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
170 if (regnum == i || regnum == -1)
171 regcache_raw_collect (regcache, i, regs + regmap[i - R0_REGNUM]);
174 if (regnum == GBR_REGNUM || regnum == -1)
175 regcache_raw_collect (regcache, GBR_REGNUM, regs + (21 * 4));
178 /* Hitachi SH instruction encoding masks and opcodes */
181 * xxxx x--x ---- ---- 0xf900 mask
182 * 1001 1**1 ---- ---- 0x8900 match
183 * BT 1000 1001 dddd dddd
184 * BF 1000 1011 dddd dddd
185 * BT/S 1000 1101 dddd dddd
186 * BF/S 1000 1111 dddd dddd
187 * ---- --x- ---- ---- T or F?
188 * ---- -x-- ---- ---- has delay slot
190 #define CONDITIONAL_BRANCH_P(insn) (((insn) & 0xf900) == 0x8900)
191 #define CONDITIONAL_BRANCH_TAKEN_P(insn, sr) ((((insn) >> 9) ^ sr) & 0x1)
192 #define CONDITIONAL_BRANCH_SLOT_P(insn) (((insn) & 0x0400) != 0)
195 * xxx- ---- ---- ---- 0xe000 mask
196 * 101* ---- ---- ---- 0xa000 match
197 * BRA 1010 dddd dddd dddd
198 * BSR 1011 dddd dddd dddd
200 #define BRANCH_P(insn) (((insn) & 0xe000) == 0xa000)
203 * xxxx ---- xx-x xxxx 0xf0df mask
204 * 0000 ---- 00*0 0011 0x0003 match
205 * BSRF 0000 rrrr 0000 0011
206 * BRAF 0000 rrrr 0010 0011
208 #define BRANCH_FAR_P(insn) (((insn) & 0xf0df) == 0x0003)
209 #define BRANCH_FAR_REG(insn) (((insn) >> 8) & 0xf)
212 * xxxx ---- xx-x xxxx 0xf0df mask
213 * 0100 ---- 00*0 1011 0x400b match
214 * JSR 0100 rrrr 0000 1011
215 * JMP 0100 rrrr 0010 1011
217 #define JUMP_P(insn) (((insn) & 0xf0df) == 0x400b)
218 #define JUMP_REG(insn) (((insn) >> 8) & 0xf)
221 * RTS 0000 0000 0000 1011
222 * RTE 0000 0000 0010 1011
224 #define RTS_INSN 0x000b
225 #define RTE_INSN 0x002b
228 * xxxx xxxx ---- ---- 0xff00 mask
229 *TRAPA 1100 0011 tttt tttt 0xc300 match
231 #define TRAPA_P(insn) (((insn) & 0xff00) == 0xc300)
234 /* signed 8-bit displacement */
235 static int
236 shnbsd_displacement_8 (unsigned short insn)
238 int displacement;
240 if (insn & 0x80)
241 displacement = insn | 0xffffff00;
242 else
243 displacement = insn & 0x000000ff;
245 return displacement;
248 /* signed 12-bit displacement */
249 static int
250 shnbsd_displacement_12 (unsigned short insn)
252 int displacement;
254 if (insn & 0x800)
255 displacement = insn | 0xfffff000;
256 else
257 displacement = insn & 0x00000fff;
259 return displacement;
262 static CORE_ADDR
263 shnbsd_get_next_pc (CORE_ADDR pc)
265 unsigned short insn;
266 ULONGEST sr;
267 int displacement;
268 int reg;
269 CORE_ADDR next_pc;
270 int delay_slot;
272 insn = read_memory_integer (pc, sizeof (insn));
273 delay_slot = 0;
275 /* As we cannot step through the delay slot, we break at the target
276 address of the control transfer. One tricky case is when the
277 target of the jump is the delay slot of that same instruction
278 (e.g. PLT entries use such code). In that case we cannot set the
279 break to the target, as trapa is illegal in the delay slot. Set
280 break to the next instruction instead, we are guaranteed to
281 arrive there, as control transfers are illegal in the delay
282 slot. */
284 /* BT, BF, BT/S, BF/S */
285 if (CONDITIONAL_BRANCH_P(insn))
287 sr = read_register (SR_REGNUM);
289 if (!CONDITIONAL_BRANCH_TAKEN_P(insn, sr))
290 next_pc = pc + 2;
291 else
293 displacement = shnbsd_displacement_8 (insn);
295 next_pc = pc + 4 + (displacement << 1);
296 delay_slot = CONDITIONAL_BRANCH_SLOT_P(insn);
300 /* BRA, BSR */
301 else if (BRANCH_P(insn))
303 displacement = shnbsd_displacement_12 (insn);
305 next_pc = pc + 4 + (displacement << 1);
306 delay_slot = 1;
309 /* BRAF, BSRF */
310 else if (BRANCH_FAR_P(insn))
312 displacement = read_register (BRANCH_FAR_REG(insn));
314 next_pc = pc + 4 + displacement;
315 delay_slot = 1;
318 /* JMP, JSR */
319 else if (JUMP_P(insn))
321 next_pc = read_register (JUMP_REG(insn));
322 delay_slot = 1;
325 /* RTS */
326 else if (insn == RTS_INSN)
328 next_pc = read_register (PR_REGNUM);
329 delay_slot = 1;
332 /* RTE - XXX: privileged */
333 else if (insn == RTE_INSN)
335 next_pc = read_register (SPC_REGNUM);
336 delay_slot = 1;
339 /* TRAPA */
340 else if (TRAPA_P(insn))
341 next_pc = pc + 2; /* XXX: after return from syscall */
343 /* not a control transfer instruction */
344 else
345 next_pc = pc + 2;
347 /* jumping to our own delay slot? */
348 if (delay_slot && next_pc == pc + 2)
349 next_pc += 2;
351 return next_pc;
354 /* Single step (in a painstaking fashion) by inspecting the current
355 instruction and setting a breakpoint on the "next" instruction
356 which would be executed.
358 void
359 shnbsd_software_single_step (enum target_signal sig,
360 int insert_breakpoints_p)
362 static CORE_ADDR next_pc;
363 CORE_ADDR pc;
365 if (insert_breakpoints_p)
367 pc = read_pc ();
369 /* If inferior was signalled before it had a chance to execute
370 the single step breakpoint, keep the breakpoint where it
371 was */
372 if (sig == 0 || pc != next_pc)
373 next_pc = shnbsd_get_next_pc (pc);
375 insert_single_step_breakpoint (next_pc);
377 else
378 remove_single_step_breakpoints ();
381 /* SH register sets. */
383 static struct regset shnbsd_gregset =
385 NULL,
386 shnbsd_supply_gregset
389 /* Return the appropriate register set for the core section identified
390 by SECT_NAME and SECT_SIZE. */
392 const struct regset *
393 shnbsd_regset_from_core_section (struct gdbarch *gdbarch,
394 const char *sect_name, size_t sect_size)
396 if (strcmp (sect_name, ".reg") == 0 && sect_size >= SHNBSD_SIZEOF_GREGS)
397 return &shnbsd_gregset;
399 return NULL;
402 void
403 shnbsd_supply_reg (struct regcache *regcache, const char *regs, int regnum)
405 shnbsd_supply_gregset (&shnbsd_gregset, regcache, regnum,
406 regs, SHNBSD_SIZEOF_GREGS);
409 void
410 shnbsd_fill_reg (const struct regcache *regcache, char *regs, int regnum)
412 shnbsd_collect_gregset (&shnbsd_gregset, regcache, regnum,
413 regs, SHNBSD_SIZEOF_GREGS);
416 static void
417 shnbsd_sigtramp_cache_init (const struct tramp_frame *,
418 struct frame_info *,
419 struct trad_frame_cache *,
420 CORE_ADDR);
422 /* The siginfo signal trampoline for NetBSD/sh3 versions 2.0 and later */
423 static const struct tramp_frame shnbsd_sigtramp_si2 =
425 SIGTRAMP_FRAME,
428 { 0x64f3, -1 }, /* mov r15,r4 */
429 { 0xd002, -1 }, /* mov.l .LSYS_setcontext */
430 { 0xc380, -1 }, /* trapa #-128 */
431 { 0xa003, -1 }, /* bra .Lskip1 */
432 { 0x0009, -1 }, /* nop */
433 { 0x0009, -1 }, /* nop */
434 /* .LSYS_setcontext */
435 { 0x0134, -1 }, { 0x0000, -1 }, /* 0x134 */
436 /* .Lskip1 */
437 { 0x6403, -1 }, /* mov r0,r4 */
438 { 0xd002, -1 }, /* mov.l .LSYS_exit */
439 { 0xc380, -1 }, /* trapa #-128 */
440 { 0xa003, -1 }, /* bra .Lskip2 */
441 { 0x0009, -1 }, /* nop */
442 { 0x0009, -1 }, /* nop */
443 /* .LSYS_exit */
444 { 0x0001, -1 }, { 0x0000, -1 }, /* 0x1 */
445 /* .Lskip2 */
446 { TRAMP_SENTINEL_INSN, -1 }
448 shnbsd_sigtramp_cache_init
451 static void
452 shnbsd_sigtramp_cache_init (const struct tramp_frame *self,
453 struct frame_info *next_frame,
454 struct trad_frame_cache *this_cache,
455 CORE_ADDR func)
457 struct gdbarch *gdbarch = get_frame_arch (next_frame);
458 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
459 CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, SP_REGNUM);
460 CORE_ADDR base;
461 const int *reg_offset;
462 int num_regs;
463 int i;
465 reg_offset = shnbsd_mc_reg_offset;
466 num_regs = ARRAY_SIZE (shnbsd_mc_reg_offset);
467 /* SP already points at the ucontext. */
468 base = sp;
469 /* offsetof(ucontext_t, uc_mcontext) == 36 */
470 base += 36;
472 for (i = 0; i < num_regs; i++)
473 if (reg_offset[i] != -1)
474 trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]);
476 /* Construct the frame ID using the function start. */
477 trad_frame_set_id (this_cache, frame_id_build (sp, func));
480 static void
481 shnbsd_init_abi (struct gdbarch_info info,
482 struct gdbarch *gdbarch)
484 /* NetBSD SuperH ports do not provide single step support via ptrace(2);
485 we must use software single-stepping. */
486 set_gdbarch_software_single_step (gdbarch, shnbsd_software_single_step);
488 set_gdbarch_regset_from_core_section
489 (gdbarch, shnbsd_regset_from_core_section);
491 set_solib_svr4_fetch_link_map_offsets (gdbarch,
492 nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
493 tramp_frame_prepend_unwinder (gdbarch, &shnbsd_sigtramp_si2);
497 static enum gdb_osabi
498 shnbsd_core_osabi_sniffer (bfd *abfd)
500 if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
501 return GDB_OSABI_NETBSD_AOUT;
503 return GDB_OSABI_UNKNOWN;
506 void
507 _initialize_shnbsd_tdep (void)
509 /* BFD doesn't set a flavour for NetBSD style a.out core files. */
510 gdbarch_register_osabi_sniffer (bfd_arch_sh, bfd_target_unknown_flavour,
511 shnbsd_core_osabi_sniffer);
513 gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD_ELF,
514 shnbsd_init_abi);