xref: /openbsd-src/gnu/usr.bin/binutils/gdb/gdbserver/linux-sh-low.c (revision b725ae7711052a2233e31a66fefb8a752c388d7a)
1*b725ae77Skettenis /* GNU/Linux/SH specific low level interface, for the remote server for GDB.
2*b725ae77Skettenis    Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003
3*b725ae77Skettenis    Free Software Foundation, Inc.
4*b725ae77Skettenis 
5*b725ae77Skettenis    This file is part of GDB.
6*b725ae77Skettenis 
7*b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
8*b725ae77Skettenis    it under the terms of the GNU General Public License as published by
9*b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
10*b725ae77Skettenis    (at your option) any later version.
11*b725ae77Skettenis 
12*b725ae77Skettenis    This program is distributed in the hope that it will be useful,
13*b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*b725ae77Skettenis    GNU General Public License for more details.
16*b725ae77Skettenis 
17*b725ae77Skettenis    You should have received a copy of the GNU General Public License
18*b725ae77Skettenis    along with this program; if not, write to the Free Software
19*b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20*b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
21*b725ae77Skettenis 
22*b725ae77Skettenis #include "server.h"
23*b725ae77Skettenis #include "linux-low.h"
24*b725ae77Skettenis 
25*b725ae77Skettenis #ifdef HAVE_SYS_REG_H
26*b725ae77Skettenis #include <sys/reg.h>
27*b725ae77Skettenis #endif
28*b725ae77Skettenis 
29*b725ae77Skettenis #include <asm/ptrace.h>
30*b725ae77Skettenis 
31*b725ae77Skettenis #define sh_num_regs 41
32*b725ae77Skettenis 
33*b725ae77Skettenis /* Currently, don't check/send MQ.  */
34*b725ae77Skettenis static int sh_regmap[] = {
35*b725ae77Skettenis  0,	4,	8,	12,	16,	20,	24,	28,
36*b725ae77Skettenis  32,	36,	40,	44,	48,	52,	56,	60,
37*b725ae77Skettenis 
38*b725ae77Skettenis  REG_PC*4,   REG_PR*4,   REG_GBR*4,  -1,
39*b725ae77Skettenis  REG_MACH*4, REG_MACL*4, REG_SR*4,
40*b725ae77Skettenis  REG_FPUL*4, REG_FPSCR*4,
41*b725ae77Skettenis 
42*b725ae77Skettenis  REG_FPREG0*4+0,   REG_FPREG0*4+4,   REG_FPREG0*4+8,   REG_FPREG0*4+12,
43*b725ae77Skettenis  REG_FPREG0*4+16,  REG_FPREG0*4+20,  REG_FPREG0*4+24,  REG_FPREG0*4+28,
44*b725ae77Skettenis  REG_FPREG0*4+32,  REG_FPREG0*4+36,  REG_FPREG0*4+40,  REG_FPREG0*4+44,
45*b725ae77Skettenis  REG_FPREG0*4+48,  REG_FPREG0*4+52,  REG_FPREG0*4+56,  REG_FPREG0*4+60,
46*b725ae77Skettenis };
47*b725ae77Skettenis 
48*b725ae77Skettenis static int
sh_cannot_store_register(int regno)49*b725ae77Skettenis sh_cannot_store_register (int regno)
50*b725ae77Skettenis {
51*b725ae77Skettenis   return 0;
52*b725ae77Skettenis }
53*b725ae77Skettenis 
54*b725ae77Skettenis static int
sh_cannot_fetch_register(int regno)55*b725ae77Skettenis sh_cannot_fetch_register (int regno)
56*b725ae77Skettenis {
57*b725ae77Skettenis   return 0;
58*b725ae77Skettenis }
59*b725ae77Skettenis 
60*b725ae77Skettenis static CORE_ADDR
sh_get_pc()61*b725ae77Skettenis sh_get_pc ()
62*b725ae77Skettenis {
63*b725ae77Skettenis   unsigned long pc;
64*b725ae77Skettenis   collect_register_by_name ("pc", &pc);
65*b725ae77Skettenis   return pc;
66*b725ae77Skettenis }
67*b725ae77Skettenis 
68*b725ae77Skettenis static void
sh_set_pc(CORE_ADDR pc)69*b725ae77Skettenis sh_set_pc (CORE_ADDR pc)
70*b725ae77Skettenis {
71*b725ae77Skettenis   unsigned long newpc = pc;
72*b725ae77Skettenis   supply_register_by_name ("pc", &newpc);
73*b725ae77Skettenis }
74*b725ae77Skettenis 
75*b725ae77Skettenis /* Correct in either endianness, obviously.  */
76*b725ae77Skettenis static const unsigned short sh_breakpoint = 0xc3c3;
77*b725ae77Skettenis #define sh_breakpoint_len 2
78*b725ae77Skettenis 
79*b725ae77Skettenis static int
sh_breakpoint_at(CORE_ADDR where)80*b725ae77Skettenis sh_breakpoint_at (CORE_ADDR where)
81*b725ae77Skettenis {
82*b725ae77Skettenis   unsigned short insn;
83*b725ae77Skettenis 
84*b725ae77Skettenis   (*the_target->read_memory) (where, (char *) &insn, 2);
85*b725ae77Skettenis   if (insn == sh_breakpoint)
86*b725ae77Skettenis     return 1;
87*b725ae77Skettenis 
88*b725ae77Skettenis   /* If necessary, recognize more trap instructions here.  GDB only uses the
89*b725ae77Skettenis      one.  */
90*b725ae77Skettenis   return 0;
91*b725ae77Skettenis }
92*b725ae77Skettenis 
93*b725ae77Skettenis struct linux_target_ops the_low_target = {
94*b725ae77Skettenis   sh_num_regs,
95*b725ae77Skettenis   sh_regmap,
96*b725ae77Skettenis   sh_cannot_fetch_register,
97*b725ae77Skettenis   sh_cannot_store_register,
98*b725ae77Skettenis   sh_get_pc,
99*b725ae77Skettenis   sh_set_pc,
100*b725ae77Skettenis   (const char *) &sh_breakpoint,
101*b725ae77Skettenis   sh_breakpoint_len,
102*b725ae77Skettenis   NULL,
103*b725ae77Skettenis   0,
104*b725ae77Skettenis   sh_breakpoint_at,
105*b725ae77Skettenis };
106