1*b725ae77Skettenis /* GNU/Linux/ARM specific low level interface, for the remote server for GDB.
2*b725ae77Skettenis Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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 #define arm_num_regs 26
30*b725ae77Skettenis
31*b725ae77Skettenis static int arm_regmap[] = {
32*b725ae77Skettenis 0, 4, 8, 12, 16, 20, 24, 28,
33*b725ae77Skettenis 32, 36, 40, 44, 48, 52, 56, 60,
34*b725ae77Skettenis -1, -1, -1, -1, -1, -1, -1, -1, -1,
35*b725ae77Skettenis 64
36*b725ae77Skettenis };
37*b725ae77Skettenis
38*b725ae77Skettenis static int
arm_cannot_store_register(int regno)39*b725ae77Skettenis arm_cannot_store_register (int regno)
40*b725ae77Skettenis {
41*b725ae77Skettenis return (regno >= arm_num_regs);
42*b725ae77Skettenis }
43*b725ae77Skettenis
44*b725ae77Skettenis static int
arm_cannot_fetch_register(int regno)45*b725ae77Skettenis arm_cannot_fetch_register (int regno)
46*b725ae77Skettenis {
47*b725ae77Skettenis return (regno >= arm_num_regs);
48*b725ae77Skettenis }
49*b725ae77Skettenis
50*b725ae77Skettenis extern int debug_threads;
51*b725ae77Skettenis
52*b725ae77Skettenis static CORE_ADDR
arm_get_pc()53*b725ae77Skettenis arm_get_pc ()
54*b725ae77Skettenis {
55*b725ae77Skettenis unsigned long pc;
56*b725ae77Skettenis collect_register_by_name ("pc", &pc);
57*b725ae77Skettenis if (debug_threads)
58*b725ae77Skettenis fprintf (stderr, "stop pc is %08lx\n", pc);
59*b725ae77Skettenis return pc;
60*b725ae77Skettenis }
61*b725ae77Skettenis
62*b725ae77Skettenis static void
arm_set_pc(CORE_ADDR pc)63*b725ae77Skettenis arm_set_pc (CORE_ADDR pc)
64*b725ae77Skettenis {
65*b725ae77Skettenis unsigned long newpc = pc;
66*b725ae77Skettenis supply_register_by_name ("pc", &newpc);
67*b725ae77Skettenis }
68*b725ae77Skettenis
69*b725ae77Skettenis /* Correct in either endianness. We do not support Thumb yet. */
70*b725ae77Skettenis static const unsigned long arm_breakpoint = 0xef9f0001;
71*b725ae77Skettenis #define arm_breakpoint_len 4
72*b725ae77Skettenis
73*b725ae77Skettenis static int
arm_breakpoint_at(CORE_ADDR where)74*b725ae77Skettenis arm_breakpoint_at (CORE_ADDR where)
75*b725ae77Skettenis {
76*b725ae77Skettenis unsigned long insn;
77*b725ae77Skettenis
78*b725ae77Skettenis (*the_target->read_memory) (where, (char *) &insn, 4);
79*b725ae77Skettenis if (insn == arm_breakpoint)
80*b725ae77Skettenis return 1;
81*b725ae77Skettenis
82*b725ae77Skettenis /* If necessary, recognize more trap instructions here. GDB only uses the
83*b725ae77Skettenis one. */
84*b725ae77Skettenis return 0;
85*b725ae77Skettenis }
86*b725ae77Skettenis
87*b725ae77Skettenis /* We only place breakpoints in empty marker functions, and thread locking
88*b725ae77Skettenis is outside of the function. So rather than importing software single-step,
89*b725ae77Skettenis we can just run until exit. */
90*b725ae77Skettenis static CORE_ADDR
arm_reinsert_addr()91*b725ae77Skettenis arm_reinsert_addr ()
92*b725ae77Skettenis {
93*b725ae77Skettenis unsigned long pc;
94*b725ae77Skettenis collect_register_by_name ("lr", &pc);
95*b725ae77Skettenis return pc;
96*b725ae77Skettenis }
97*b725ae77Skettenis
98*b725ae77Skettenis struct linux_target_ops the_low_target = {
99*b725ae77Skettenis arm_num_regs,
100*b725ae77Skettenis arm_regmap,
101*b725ae77Skettenis arm_cannot_fetch_register,
102*b725ae77Skettenis arm_cannot_store_register,
103*b725ae77Skettenis arm_get_pc,
104*b725ae77Skettenis arm_set_pc,
105*b725ae77Skettenis (const char *) &arm_breakpoint,
106*b725ae77Skettenis arm_breakpoint_len,
107*b725ae77Skettenis arm_reinsert_addr,
108*b725ae77Skettenis 0,
109*b725ae77Skettenis arm_breakpoint_at,
110*b725ae77Skettenis };
111