2008-02-11 Maxim Grigoriev <maxim2405@gmail.com>
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-xtensa-low.c
CommitLineData
1525d545
MG
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
28enum 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
36static void
37xtensa_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
70static void
71xtensa_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
106static void
107xtensa_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
118static void
119xtensa_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
130struct 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
146static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT;
147#define xtensa_breakpoint_len 2
148
149static CORE_ADDR
150xtensa_get_pc (void)
151{
152 unsigned long pc;
153
154 collect_register_by_name ("pc", &pc);
155 return pc;
156}
157
158static void
159xtensa_set_pc (CORE_ADDR pc)
160{
161 unsigned long newpc = pc;
162 supply_register_by_name ("pc", &newpc);
163}
164
165static int
166xtensa_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
175struct 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.106383 seconds and 4 git commands to generate.