2008-02-11 Maxim Grigoriev <maxim2405@gmail.com>
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-xtensa-low.c
1 /* GNU/Linux/Xtensa specific low level interface, for the remote server for GDB.
2 Copyright 2007, 2008 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19
20 #include "server.h"
21 #include "linux-low.h"
22
23 #include <sys/ptrace.h>
24 #include <xtensa-config.h>
25
26 #include "xtensa-xtregs.c"
27
28 enum regnum {
29 R_PC=0, R_PS,
30 R_LBEG, R_LEND, R_LCOUNT,
31 R_SAR,
32 R_WS, R_WB,
33 R_A0 = 64
34 };
35
36 static void
37 xtensa_fill_gregset (void *buf)
38 {
39 elf_greg_t* rset = (elf_greg_t*)buf;
40 int ar0_regnum;
41 char *ptr;
42 int i;
43
44 /* Take care of AR registers. */
45
46 ar0_regnum = find_regno ("ar0");
47 ptr = (char*)&rset[R_A0];
48
49 for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
50 {
51 collect_register (i, ptr);
52 ptr += register_size(i);
53 }
54
55 /* Loop registers, if hardware has it. */
56
57 #if XCHAL_HAVE_LOOP
58 collect_register_by_name ("lbeg", (char*)&rset[R_LBEG]);
59 collect_register_by_name ("lend", (char*)&rset[R_LEND]);
60 collect_register_by_name ("lcount", (char*)&rset[R_LCOUNT]);
61 #endif
62
63 collect_register_by_name ("sar", (char*)&rset[R_SAR]);
64 collect_register_by_name ("pc", (char*)&rset[R_PC]);
65 collect_register_by_name ("ps", (char*)&rset[R_PS]);
66 collect_register_by_name ("windowbase", (char*)&rset[R_WB]);
67 collect_register_by_name ("windowstart", (char*)&rset[R_WS]);
68 }
69
70 static void
71 xtensa_store_gregset (const void *buf)
72 {
73 const elf_greg_t* rset = (const elf_greg_t*)buf;
74 int ar0_regnum;
75 char *ptr;
76 int i;
77
78 /* Take care of AR registers. */
79
80 ar0_regnum = find_regno ("ar0");
81 ptr = (char *)&rset[R_A0];
82
83 for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
84 {
85 supply_register (i, ptr);
86 ptr += register_size(i);
87 }
88
89 /* Loop registers, if hardware has it. */
90
91 #if XCHAL_HAVE_LOOP
92 supply_register_by_name ("lbeg", (char*)&rset[R_LBEG]);
93 supply_register_by_name ("lend", (char*)&rset[R_LEND]);
94 supply_register_by_name ("lcount", (char*)&rset[R_LCOUNT]);
95 #endif
96
97 supply_register_by_name ("sar", (char*)&rset[R_SAR]);
98 supply_register_by_name ("pc", (char*)&rset[R_PC]);
99 supply_register_by_name ("ps", (char*)&rset[R_PS]);
100 supply_register_by_name ("windowbase", (char*)&rset[R_WB]);
101 supply_register_by_name ("windowstart", (char*)&rset[R_WS]);
102 }
103
104 /* Xtensa GNU/Linux PTRACE interface includes extended register set. */
105
106 static void
107 xtensa_fill_xtregset (void *buf)
108 {
109 const xtensa_regtable_t *ptr;
110
111 for (ptr = xtensa_regmap_table; ptr->name; ptr++)
112 {
113 collect_register_by_name (ptr->name,
114 (char*)buf + ptr->ptrace_offset);
115 }
116 }
117
118 static void
119 xtensa_store_xtregset (const void *buf)
120 {
121 const xtensa_regtable_t *ptr;
122
123 for (ptr = xtensa_regmap_table; ptr->name; ptr++)
124 {
125 supply_register_by_name (ptr->name,
126 (char*)buf + ptr->ptrace_offset);
127 }
128 }
129
130 struct regset_info target_regsets[] = {
131 { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
132 GENERAL_REGS,
133 xtensa_fill_gregset, xtensa_store_gregset },
134 { PTRACE_GETXTREGS, PTRACE_SETXTREGS, XTENSA_ELF_XTREG_SIZE,
135 EXTENDED_REGS,
136 xtensa_fill_xtregset, xtensa_store_xtregset },
137 { 0, 0, -1, -1, NULL, NULL }
138 };
139
140 #if XCHAL_HAVE_BE
141 #define XTENSA_BREAKPOINT {0xd2,0x0f}
142 #else
143 #define XTENSA_BREAKPOINT {0x2d,0xf0}
144 #endif
145
146 static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT;
147 #define xtensa_breakpoint_len 2
148
149 static CORE_ADDR
150 xtensa_get_pc (void)
151 {
152 unsigned long pc;
153
154 collect_register_by_name ("pc", &pc);
155 return pc;
156 }
157
158 static void
159 xtensa_set_pc (CORE_ADDR pc)
160 {
161 unsigned long newpc = pc;
162 supply_register_by_name ("pc", &newpc);
163 }
164
165 static int
166 xtensa_breakpoint_at (CORE_ADDR where)
167 {
168 unsigned long insn;
169
170 (*the_target->read_memory) (where, (unsigned char *) &insn,
171 xtensa_breakpoint_len);
172 return memcmp((char *)&insn, xtensa_breakpoint, xtensa_breakpoint_len) == 0;
173 }
174
175 struct linux_target_ops the_low_target = {
176 0,
177 0,
178 0,
179 0,
180 xtensa_get_pc,
181 xtensa_set_pc,
182 xtensa_breakpoint,
183 xtensa_breakpoint_len,
184 NULL,
185 0,
186 xtensa_breakpoint_at,
187 };
This page took 0.046067 seconds and 4 git commands to generate.