This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gdb / gdbserver / linux-m68k-low.c
1 /* GNU/Linux/m68k specific low level interface, for the remote server for GDB.
2    Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3    Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
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.
11
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.
16
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.  */
21
22 #include "server.h"
23 #include "linux-low.h"
24
25 #ifdef HAVE_SYS_REG_H
26 #include <sys/reg.h>
27 #endif
28
29 #define m68k_num_regs 29
30 #define m68k_num_gregs 18
31
32 /* This table must line up with REGISTER_NAMES in tm-m68k.h */
33 static int m68k_regmap[] =
34 {
35 #ifdef PT_D0
36   PT_D0 * 4, PT_D1 * 4, PT_D2 * 4, PT_D3 * 4,
37   PT_D4 * 4, PT_D5 * 4, PT_D6 * 4, PT_D7 * 4,
38   PT_A0 * 4, PT_A1 * 4, PT_A2 * 4, PT_A3 * 4,
39   PT_A4 * 4, PT_A5 * 4, PT_A6 * 4, PT_USP * 4,
40   PT_SR * 4, PT_PC * 4,
41 #else
42   14 * 4, 0 * 4, 1 * 4, 2 * 4, 3 * 4, 4 * 4, 5 * 4, 6 * 4,
43   7 * 4, 8 * 4, 9 * 4, 10 * 4, 11 * 4, 12 * 4, 13 * 4, 15 * 4,
44   17 * 4, 18 * 4,
45 #endif
46 #ifdef PT_FP0
47   PT_FP0 * 4, PT_FP1 * 4, PT_FP2 * 4, PT_FP3 * 4,
48   PT_FP4 * 4, PT_FP5 * 4, PT_FP6 * 4, PT_FP7 * 4,
49   PT_FPCR * 4, PT_FPSR * 4, PT_FPIAR * 4
50 #else
51   21 * 4, 24 * 4, 27 * 4, 30 * 4, 33 * 4, 36 * 4,
52   39 * 4, 42 * 4, 45 * 4, 46 * 4, 47 * 4
53 #endif
54 };
55
56 static int
57 m68k_cannot_store_register (int regno)
58 {
59   return (regno >= m68k_num_regs);
60 }
61
62 static int
63 m68k_cannot_fetch_register (int regno)
64 {
65   return (regno >= m68k_num_regs);
66 }
67
68 #ifdef HAVE_PTRACE_GETREGS
69 #include <sys/procfs.h>
70 #include <sys/ptrace.h>
71
72 static void
73 m68k_fill_gregset (void *buf)
74 {
75   int i;
76
77   for (i = 0; i < m68k_num_gregs; i++)
78     collect_register (i, (char *) buf + m68k_regmap[i]);
79 }
80
81 static void
82 m68k_store_gregset (const void *buf)
83 {
84   int i;
85
86   for (i = 0; i < m68k_num_gregs; i++)
87     supply_register (i, (const char *) buf + m68k_regmap[i]);
88 }
89
90 static void
91 m68k_fill_fpregset (void *buf)
92 {
93   int i;
94
95   for (i = m68k_num_gregs; i < m68k_num_regs; i++)
96     collect_register (i, ((char *) buf
97                           + (m68k_regmap[i] - m68k_regmap[m68k_num_gregs])));
98 }
99
100 static void
101 m68k_store_fpregset (const void *buf)
102 {
103   int i;
104
105   for (i = m68k_num_gregs; i < m68k_num_regs; i++)
106     supply_register (i, ((const char *) buf
107                          + (m68k_regmap[i] - m68k_regmap[m68k_num_gregs])));
108 }
109
110 #endif /* HAVE_PTRACE_GETREGS */
111
112 struct regset_info target_regsets[] = {
113 #ifdef HAVE_PTRACE_GETREGS
114   { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
115     GENERAL_REGS,
116     m68k_fill_gregset, m68k_store_gregset },
117   { PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
118     FP_REGS,
119     m68k_fill_fpregset, m68k_store_fpregset },
120 #endif /* HAVE_PTRACE_GETREGS */
121   { 0, 0, -1, -1, NULL, NULL }
122 };
123
124 static const unsigned char m68k_breakpoint[] = { 0x4E, 0x4F };
125 #define m68k_breakpoint_len 2
126
127 static CORE_ADDR
128 m68k_get_pc ()
129 {
130   unsigned long pc;
131
132   collect_register_by_name ("pc", &pc);
133   return pc;
134 }
135
136 static void
137 m68k_set_pc (CORE_ADDR value)
138 {
139   unsigned long newpc = value;
140
141   supply_register_by_name ("pc", &newpc);
142 }
143
144 static int
145 m68k_breakpoint_at (CORE_ADDR pc)
146 {
147   unsigned char c[2];
148
149   read_inferior_memory (pc, c, 2);
150   if (c[0] == 0x4E && c[1] == 0x4F)
151     return 1;
152
153   return 0;
154 }
155
156 struct linux_target_ops the_low_target = {
157   m68k_num_regs,
158   m68k_regmap,
159   m68k_cannot_fetch_register,
160   m68k_cannot_store_register,
161   m68k_get_pc,
162   m68k_set_pc,
163   m68k_breakpoint,
164   m68k_breakpoint_len,
165   NULL,
166   2,
167   m68k_breakpoint_at,
168 };