1*ef5ccd6cSJohn Marino /* Ravenscar SPARC target support.
2*ef5ccd6cSJohn Marino
3*ef5ccd6cSJohn Marino Copyright (C) 2004-2013 Free Software Foundation, Inc.
4*ef5ccd6cSJohn Marino
5*ef5ccd6cSJohn Marino This file is part of GDB.
6*ef5ccd6cSJohn Marino
7*ef5ccd6cSJohn Marino This program is free software; you can redistribute it and/or modify
8*ef5ccd6cSJohn Marino it under the terms of the GNU General Public License as published by
9*ef5ccd6cSJohn Marino the Free Software Foundation; either version 3 of the License, or
10*ef5ccd6cSJohn Marino (at your option) any later version.
11*ef5ccd6cSJohn Marino
12*ef5ccd6cSJohn Marino This program is distributed in the hope that it will be useful,
13*ef5ccd6cSJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
14*ef5ccd6cSJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*ef5ccd6cSJohn Marino GNU General Public License for more details.
16*ef5ccd6cSJohn Marino
17*ef5ccd6cSJohn Marino You should have received a copy of the GNU General Public License
18*ef5ccd6cSJohn Marino along with this program. If not, see <http://www.gnu.org/licenses/>. */
19*ef5ccd6cSJohn Marino
20*ef5ccd6cSJohn Marino #include "defs.h"
21*ef5ccd6cSJohn Marino #include "gdbcore.h"
22*ef5ccd6cSJohn Marino #include "regcache.h"
23*ef5ccd6cSJohn Marino #include "sparc-tdep.h"
24*ef5ccd6cSJohn Marino #include "inferior.h"
25*ef5ccd6cSJohn Marino #include "ravenscar-thread.h"
26*ef5ccd6cSJohn Marino #include "sparc-ravenscar-thread.h"
27*ef5ccd6cSJohn Marino
28*ef5ccd6cSJohn Marino static void sparc_ravenscar_fetch_registers (struct regcache *regcache,
29*ef5ccd6cSJohn Marino int regnum);
30*ef5ccd6cSJohn Marino static void sparc_ravenscar_store_registers (struct regcache *regcache,
31*ef5ccd6cSJohn Marino int regnum);
32*ef5ccd6cSJohn Marino static void sparc_ravenscar_prepare_to_store (struct regcache *regcache);
33*ef5ccd6cSJohn Marino
34*ef5ccd6cSJohn Marino /* Register offsets from a referenced address (exempli gratia the
35*ef5ccd6cSJohn Marino Thread_Descriptor). The referenced address depends on the register
36*ef5ccd6cSJohn Marino number. The Thread_Descriptor layout and the stack layout are documented
37*ef5ccd6cSJohn Marino in the GNAT sources, in sparc-bb.h. */
38*ef5ccd6cSJohn Marino
39*ef5ccd6cSJohn Marino static const int sparc_register_offsets[] =
40*ef5ccd6cSJohn Marino {
41*ef5ccd6cSJohn Marino /* G0 - G7 */
42*ef5ccd6cSJohn Marino -1, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
43*ef5ccd6cSJohn Marino /* O0 - O7 */
44*ef5ccd6cSJohn Marino 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
45*ef5ccd6cSJohn Marino /* L0 - L7 */
46*ef5ccd6cSJohn Marino 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
47*ef5ccd6cSJohn Marino /* I0 - I7 */
48*ef5ccd6cSJohn Marino 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
49*ef5ccd6cSJohn Marino /* F0 - F31 */
50*ef5ccd6cSJohn Marino 0x50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C,
51*ef5ccd6cSJohn Marino 0x70, 0x74, 0x78, 0x7C, 0x80, 0x84, 0x88, 0x8C,
52*ef5ccd6cSJohn Marino 0x90, 0x94, 0x99, 0x9C, 0xA0, 0xA4, 0xA8, 0xAC,
53*ef5ccd6cSJohn Marino 0xB0, 0xB4, 0xBB, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC,
54*ef5ccd6cSJohn Marino /* Y PSR WIM TBR PC NPC FPSR CPSR */
55*ef5ccd6cSJohn Marino 0x40, 0x20, 0x44, -1, 0x1C, -1, 0x4C, -1
56*ef5ccd6cSJohn Marino };
57*ef5ccd6cSJohn Marino
58*ef5ccd6cSJohn Marino /* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
59*ef5ccd6cSJohn Marino regcache. */
60*ef5ccd6cSJohn Marino
61*ef5ccd6cSJohn Marino static void
supply_register_at_address(struct regcache * regcache,int regnum,CORE_ADDR register_addr)62*ef5ccd6cSJohn Marino supply_register_at_address (struct regcache *regcache, int regnum,
63*ef5ccd6cSJohn Marino CORE_ADDR register_addr)
64*ef5ccd6cSJohn Marino {
65*ef5ccd6cSJohn Marino struct gdbarch *gdbarch = get_regcache_arch (regcache);
66*ef5ccd6cSJohn Marino int buf_size = register_size (gdbarch, regnum);
67*ef5ccd6cSJohn Marino char *buf;
68*ef5ccd6cSJohn Marino
69*ef5ccd6cSJohn Marino buf = (char *) alloca (buf_size);
70*ef5ccd6cSJohn Marino read_memory (register_addr, buf, buf_size);
71*ef5ccd6cSJohn Marino regcache_raw_supply (regcache, regnum, buf);
72*ef5ccd6cSJohn Marino }
73*ef5ccd6cSJohn Marino
74*ef5ccd6cSJohn Marino /* Return true if, for a non-running thread, REGNUM has been saved on the
75*ef5ccd6cSJohn Marino stack. */
76*ef5ccd6cSJohn Marino
77*ef5ccd6cSJohn Marino static int
register_on_stack_p(int regnum)78*ef5ccd6cSJohn Marino register_on_stack_p (int regnum)
79*ef5ccd6cSJohn Marino {
80*ef5ccd6cSJohn Marino return (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
81*ef5ccd6cSJohn Marino || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM);
82*ef5ccd6cSJohn Marino }
83*ef5ccd6cSJohn Marino
84*ef5ccd6cSJohn Marino /* Return true if, for a non-running thread, REGNUM has been saved on the
85*ef5ccd6cSJohn Marino Thread_Descriptor. */
86*ef5ccd6cSJohn Marino
87*ef5ccd6cSJohn Marino static int
register_in_thread_descriptor_p(int regnum)88*ef5ccd6cSJohn Marino register_in_thread_descriptor_p (int regnum)
89*ef5ccd6cSJohn Marino {
90*ef5ccd6cSJohn Marino return (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
91*ef5ccd6cSJohn Marino || (regnum == SPARC32_PSR_REGNUM)
92*ef5ccd6cSJohn Marino || (regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
93*ef5ccd6cSJohn Marino || (regnum == SPARC32_Y_REGNUM)
94*ef5ccd6cSJohn Marino || (regnum == SPARC32_WIM_REGNUM)
95*ef5ccd6cSJohn Marino || (regnum == SPARC32_FSR_REGNUM)
96*ef5ccd6cSJohn Marino || (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F0_REGNUM + 31)
97*ef5ccd6cSJohn Marino || (regnum == SPARC32_PC_REGNUM);
98*ef5ccd6cSJohn Marino }
99*ef5ccd6cSJohn Marino
100*ef5ccd6cSJohn Marino /* to_fetch_registers when inferior_ptid is different from the running
101*ef5ccd6cSJohn Marino thread. */
102*ef5ccd6cSJohn Marino
103*ef5ccd6cSJohn Marino static void
sparc_ravenscar_fetch_registers(struct regcache * regcache,int regnum)104*ef5ccd6cSJohn Marino sparc_ravenscar_fetch_registers (struct regcache *regcache, int regnum)
105*ef5ccd6cSJohn Marino {
106*ef5ccd6cSJohn Marino struct gdbarch *gdbarch = get_regcache_arch (regcache);
107*ef5ccd6cSJohn Marino const int sp_regnum = gdbarch_sp_regnum (gdbarch);
108*ef5ccd6cSJohn Marino const int num_regs = gdbarch_num_regs (gdbarch);
109*ef5ccd6cSJohn Marino int current_regnum;
110*ef5ccd6cSJohn Marino CORE_ADDR current_address;
111*ef5ccd6cSJohn Marino CORE_ADDR thread_descriptor_address;
112*ef5ccd6cSJohn Marino ULONGEST stack_address;
113*ef5ccd6cSJohn Marino
114*ef5ccd6cSJohn Marino /* The tid is the thread_id field, which is a pointer to the thread. */
115*ef5ccd6cSJohn Marino thread_descriptor_address = (CORE_ADDR) ptid_get_tid (inferior_ptid);
116*ef5ccd6cSJohn Marino
117*ef5ccd6cSJohn Marino /* Read the saved SP in the context buffer. */
118*ef5ccd6cSJohn Marino current_address = thread_descriptor_address
119*ef5ccd6cSJohn Marino + sparc_register_offsets [sp_regnum];
120*ef5ccd6cSJohn Marino supply_register_at_address (regcache, sp_regnum, current_address);
121*ef5ccd6cSJohn Marino regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address);
122*ef5ccd6cSJohn Marino
123*ef5ccd6cSJohn Marino /* Read registers. */
124*ef5ccd6cSJohn Marino for (current_regnum = 0; current_regnum < num_regs; current_regnum ++)
125*ef5ccd6cSJohn Marino {
126*ef5ccd6cSJohn Marino if (register_in_thread_descriptor_p (current_regnum))
127*ef5ccd6cSJohn Marino {
128*ef5ccd6cSJohn Marino current_address = thread_descriptor_address
129*ef5ccd6cSJohn Marino + sparc_register_offsets [current_regnum];
130*ef5ccd6cSJohn Marino supply_register_at_address (regcache, current_regnum,
131*ef5ccd6cSJohn Marino current_address);
132*ef5ccd6cSJohn Marino }
133*ef5ccd6cSJohn Marino else if (register_on_stack_p (current_regnum))
134*ef5ccd6cSJohn Marino {
135*ef5ccd6cSJohn Marino current_address = stack_address
136*ef5ccd6cSJohn Marino + sparc_register_offsets [current_regnum];
137*ef5ccd6cSJohn Marino supply_register_at_address (regcache, current_regnum,
138*ef5ccd6cSJohn Marino current_address);
139*ef5ccd6cSJohn Marino }
140*ef5ccd6cSJohn Marino }
141*ef5ccd6cSJohn Marino }
142*ef5ccd6cSJohn Marino
143*ef5ccd6cSJohn Marino /* to_prepare_to_store when inferior_ptid is different from the running
144*ef5ccd6cSJohn Marino thread. */
145*ef5ccd6cSJohn Marino
146*ef5ccd6cSJohn Marino static void
sparc_ravenscar_prepare_to_store(struct regcache * regcache)147*ef5ccd6cSJohn Marino sparc_ravenscar_prepare_to_store (struct regcache *regcache)
148*ef5ccd6cSJohn Marino {
149*ef5ccd6cSJohn Marino /* Nothing to do. */
150*ef5ccd6cSJohn Marino }
151*ef5ccd6cSJohn Marino
152*ef5ccd6cSJohn Marino /* to_store_registers when inferior_ptid is different from the running
153*ef5ccd6cSJohn Marino thread. */
154*ef5ccd6cSJohn Marino
155*ef5ccd6cSJohn Marino static void
sparc_ravenscar_store_registers(struct regcache * regcache,int regnum)156*ef5ccd6cSJohn Marino sparc_ravenscar_store_registers (struct regcache *regcache, int regnum)
157*ef5ccd6cSJohn Marino {
158*ef5ccd6cSJohn Marino struct gdbarch *gdbarch = get_regcache_arch (regcache);
159*ef5ccd6cSJohn Marino int buf_size = register_size (gdbarch, regnum);
160*ef5ccd6cSJohn Marino char buf [buf_size];
161*ef5ccd6cSJohn Marino ULONGEST register_address;
162*ef5ccd6cSJohn Marino
163*ef5ccd6cSJohn Marino if (register_in_thread_descriptor_p (regnum))
164*ef5ccd6cSJohn Marino register_address =
165*ef5ccd6cSJohn Marino ptid_get_tid (inferior_ptid) + sparc_register_offsets [regnum];
166*ef5ccd6cSJohn Marino else if (register_on_stack_p (regnum))
167*ef5ccd6cSJohn Marino {
168*ef5ccd6cSJohn Marino regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM,
169*ef5ccd6cSJohn Marino ®ister_address);
170*ef5ccd6cSJohn Marino register_address += sparc_register_offsets [regnum];
171*ef5ccd6cSJohn Marino }
172*ef5ccd6cSJohn Marino else
173*ef5ccd6cSJohn Marino return;
174*ef5ccd6cSJohn Marino
175*ef5ccd6cSJohn Marino regcache_raw_collect (regcache, regnum, buf);
176*ef5ccd6cSJohn Marino write_memory (register_address,
177*ef5ccd6cSJohn Marino buf,
178*ef5ccd6cSJohn Marino buf_size);
179*ef5ccd6cSJohn Marino }
180*ef5ccd6cSJohn Marino
181*ef5ccd6cSJohn Marino static struct ravenscar_arch_ops sparc_ravenscar_ops =
182*ef5ccd6cSJohn Marino {
183*ef5ccd6cSJohn Marino sparc_ravenscar_fetch_registers,
184*ef5ccd6cSJohn Marino sparc_ravenscar_store_registers,
185*ef5ccd6cSJohn Marino sparc_ravenscar_prepare_to_store
186*ef5ccd6cSJohn Marino };
187*ef5ccd6cSJohn Marino
188*ef5ccd6cSJohn Marino /* Register ravenscar_arch_ops in GDBARCH. */
189*ef5ccd6cSJohn Marino
190*ef5ccd6cSJohn Marino void
register_sparc_ravenscar_ops(struct gdbarch * gdbarch)191*ef5ccd6cSJohn Marino register_sparc_ravenscar_ops (struct gdbarch *gdbarch)
192*ef5ccd6cSJohn Marino {
193*ef5ccd6cSJohn Marino set_gdbarch_ravenscar_ops (gdbarch, &sparc_ravenscar_ops);
194*ef5ccd6cSJohn Marino }
195