xref: /openbsd-src/gnu/usr.bin/binutils/gdb/m32r-linux-nat.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1*11efff7fSkettenis /* Native-dependent code for GNU/Linux m32r.
2*11efff7fSkettenis 
3*11efff7fSkettenis    Copyright 2004 Free Software Foundation, Inc.
4*11efff7fSkettenis 
5*11efff7fSkettenis    This file is part of GDB.
6*11efff7fSkettenis 
7*11efff7fSkettenis    This program is free software; you can redistribute it and/or modify
8*11efff7fSkettenis    it under the terms of the GNU General Public License as published by
9*11efff7fSkettenis    the Free Software Foundation; either version 2 of the License, or
10*11efff7fSkettenis    (at your option) any later version.
11*11efff7fSkettenis 
12*11efff7fSkettenis    This program is distributed in the hope that it will be useful,
13*11efff7fSkettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*11efff7fSkettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*11efff7fSkettenis    GNU General Public License for more details.
16*11efff7fSkettenis 
17*11efff7fSkettenis    You should have received a copy of the GNU General Public License
18*11efff7fSkettenis    along with this program; if not, write to the Free Software
19*11efff7fSkettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20*11efff7fSkettenis    Boston, MA 02111-1307, USA.  */
21*11efff7fSkettenis 
22*11efff7fSkettenis #include "defs.h"
23*11efff7fSkettenis #include "inferior.h"
24*11efff7fSkettenis #include "gdbcore.h"
25*11efff7fSkettenis #include "regcache.h"
26*11efff7fSkettenis #include "linux-nat.h"
27*11efff7fSkettenis 
28*11efff7fSkettenis #include "gdb_assert.h"
29*11efff7fSkettenis #include "gdb_string.h"
30*11efff7fSkettenis #include <sys/ptrace.h>
31*11efff7fSkettenis #include <sys/user.h>
32*11efff7fSkettenis #include <sys/procfs.h>
33*11efff7fSkettenis 
34*11efff7fSkettenis /* Prototypes for supply_gregset etc.  */
35*11efff7fSkettenis #include "gregset.h"
36*11efff7fSkettenis 
37*11efff7fSkettenis #include "m32r-tdep.h"
38*11efff7fSkettenis 
39*11efff7fSkettenis 
40*11efff7fSkettenis 
41*11efff7fSkettenis 
42*11efff7fSkettenis /* Since EVB register is not available for native debug, we reduce
43*11efff7fSkettenis    the number of registers.  */
44*11efff7fSkettenis #define M32R_LINUX_NUM_REGS (M32R_NUM_REGS - 1)
45*11efff7fSkettenis 
46*11efff7fSkettenis /* Mapping between the general-purpose registers in `struct user'
47*11efff7fSkettenis    format and GDB's register array layout.  */
48*11efff7fSkettenis static int regmap[] = {
49*11efff7fSkettenis   4, 5, 6, 7, 0, 1, 2, 8,
50*11efff7fSkettenis   9, 10, 11, 12, 13, 24, 25, 23,
51*11efff7fSkettenis   19, 19, 26, 23, 22, 20, 16, 15
52*11efff7fSkettenis };
53*11efff7fSkettenis 
54*11efff7fSkettenis #define PSW_REGMAP 19
55*11efff7fSkettenis #define BBPSW_REGMAP 21
56*11efff7fSkettenis #define SPU_REGMAP 23
57*11efff7fSkettenis #define SPI_REGMAP 26
58*11efff7fSkettenis 
59*11efff7fSkettenis /* Doee apply to the corresponding SET requests as well.  */
60*11efff7fSkettenis #define GETREGS_SUPPLIES(regno) (0 <= (regno) && (regno) <= M32R_LINUX_NUM_REGS)
61*11efff7fSkettenis 
62*11efff7fSkettenis 
63*11efff7fSkettenis 
64*11efff7fSkettenis /* Transfering the general-purpose registers between GDB, inferiors
65*11efff7fSkettenis    and core files.  */
66*11efff7fSkettenis 
67*11efff7fSkettenis /* Fill GDB's register array with the general-purpose register values
68*11efff7fSkettenis    in *GREGSETP.  */
69*11efff7fSkettenis 
70*11efff7fSkettenis void
supply_gregset(elf_gregset_t * gregsetp)71*11efff7fSkettenis supply_gregset (elf_gregset_t * gregsetp)
72*11efff7fSkettenis {
73*11efff7fSkettenis   elf_greg_t *regp = (elf_greg_t *) gregsetp;
74*11efff7fSkettenis   int i;
75*11efff7fSkettenis   unsigned long psw, bbpsw;
76*11efff7fSkettenis 
77*11efff7fSkettenis   psw = *(regp + PSW_REGMAP);
78*11efff7fSkettenis   bbpsw = *(regp + BBPSW_REGMAP);
79*11efff7fSkettenis 
80*11efff7fSkettenis   for (i = 0; i < M32R_LINUX_NUM_REGS; i++)
81*11efff7fSkettenis     {
82*11efff7fSkettenis       switch (i)
83*11efff7fSkettenis 	{
84*11efff7fSkettenis 	case PSW_REGNUM:
85*11efff7fSkettenis 	  *(regp + regmap[i]) =
86*11efff7fSkettenis 	    ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8);
87*11efff7fSkettenis 	  break;
88*11efff7fSkettenis 	case CBR_REGNUM:
89*11efff7fSkettenis 	  *(regp + regmap[i]) = ((psw >> 8) & 1);
90*11efff7fSkettenis 	  break;
91*11efff7fSkettenis 	}
92*11efff7fSkettenis 
93*11efff7fSkettenis       if (i != M32R_SP_REGNUM)
94*11efff7fSkettenis 	regcache_raw_supply (current_regcache, i, regp + regmap[i]);
95*11efff7fSkettenis       else if (psw & 0x8000)
96*11efff7fSkettenis 	regcache_raw_supply (current_regcache, i, regp + SPU_REGMAP);
97*11efff7fSkettenis       else
98*11efff7fSkettenis 	regcache_raw_supply (current_regcache, i, regp + SPI_REGMAP);
99*11efff7fSkettenis     }
100*11efff7fSkettenis }
101*11efff7fSkettenis 
102*11efff7fSkettenis /* Fetch all general-purpose registers from process/thread TID and
103*11efff7fSkettenis    store their values in GDB's register array.  */
104*11efff7fSkettenis 
105*11efff7fSkettenis static void
fetch_regs(int tid)106*11efff7fSkettenis fetch_regs (int tid)
107*11efff7fSkettenis {
108*11efff7fSkettenis   elf_gregset_t regs;
109*11efff7fSkettenis 
110*11efff7fSkettenis   if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
111*11efff7fSkettenis     perror_with_name ("Couldn't get registers");
112*11efff7fSkettenis 
113*11efff7fSkettenis   supply_gregset (&regs);
114*11efff7fSkettenis }
115*11efff7fSkettenis 
116*11efff7fSkettenis /* Fill register REGNO (if it is a general-purpose register) in
117*11efff7fSkettenis    *GREGSETPS with the value in GDB's register array.  If REGNO is -1,
118*11efff7fSkettenis    do this for all registers.  */
119*11efff7fSkettenis 
120*11efff7fSkettenis void
fill_gregset(elf_gregset_t * gregsetp,int regno)121*11efff7fSkettenis fill_gregset (elf_gregset_t * gregsetp, int regno)
122*11efff7fSkettenis {
123*11efff7fSkettenis   elf_greg_t *regp = (elf_greg_t *) gregsetp;
124*11efff7fSkettenis   int i;
125*11efff7fSkettenis   unsigned long psw, bbpsw, tmp;
126*11efff7fSkettenis 
127*11efff7fSkettenis   psw = *(regp + PSW_REGMAP);
128*11efff7fSkettenis   bbpsw = *(regp + BBPSW_REGMAP);
129*11efff7fSkettenis 
130*11efff7fSkettenis   for (i = 0; i < M32R_LINUX_NUM_REGS; i++)
131*11efff7fSkettenis     {
132*11efff7fSkettenis       if (regno != -1 && regno != i)
133*11efff7fSkettenis 	continue;
134*11efff7fSkettenis 
135*11efff7fSkettenis       if (i == CBR_REGNUM || i == PSW_REGNUM)
136*11efff7fSkettenis 	continue;
137*11efff7fSkettenis 
138*11efff7fSkettenis       if (i == SPU_REGNUM || i == SPI_REGNUM)
139*11efff7fSkettenis 	continue;
140*11efff7fSkettenis 
141*11efff7fSkettenis       if (i != M32R_SP_REGNUM)
142*11efff7fSkettenis 	regcache_raw_collect (current_regcache, i, regp + regmap[i]);
143*11efff7fSkettenis       else if (psw & 0x8000)
144*11efff7fSkettenis 	regcache_raw_collect (current_regcache, i, regp + SPU_REGMAP);
145*11efff7fSkettenis       else
146*11efff7fSkettenis 	regcache_raw_collect (current_regcache, i, regp + SPI_REGMAP);
147*11efff7fSkettenis     }
148*11efff7fSkettenis }
149*11efff7fSkettenis 
150*11efff7fSkettenis /* Store all valid general-purpose registers in GDB's register array
151*11efff7fSkettenis    into the process/thread specified by TID.  */
152*11efff7fSkettenis 
153*11efff7fSkettenis static void
store_regs(int tid,int regno)154*11efff7fSkettenis store_regs (int tid, int regno)
155*11efff7fSkettenis {
156*11efff7fSkettenis   elf_gregset_t regs;
157*11efff7fSkettenis 
158*11efff7fSkettenis   if (ptrace (PTRACE_GETREGS, tid, 0, (int) &regs) < 0)
159*11efff7fSkettenis     perror_with_name ("Couldn't get registers");
160*11efff7fSkettenis 
161*11efff7fSkettenis   fill_gregset (&regs, regno);
162*11efff7fSkettenis 
163*11efff7fSkettenis   if (ptrace (PTRACE_SETREGS, tid, 0, (int) &regs) < 0)
164*11efff7fSkettenis     perror_with_name ("Couldn't write registers");
165*11efff7fSkettenis }
166*11efff7fSkettenis 
167*11efff7fSkettenis 
168*11efff7fSkettenis 
169*11efff7fSkettenis /* Transfering floating-point registers between GDB, inferiors and cores.
170*11efff7fSkettenis    Since M32R has no floating-point registers, these functions do nothing.  */
171*11efff7fSkettenis 
172*11efff7fSkettenis void
supply_fpregset(gdb_fpregset_t * fpregs)173*11efff7fSkettenis supply_fpregset (gdb_fpregset_t *fpregs)
174*11efff7fSkettenis {
175*11efff7fSkettenis }
176*11efff7fSkettenis 
177*11efff7fSkettenis void
fill_fpregset(gdb_fpregset_t * fpregs,int regno)178*11efff7fSkettenis fill_fpregset (gdb_fpregset_t *fpregs, int regno)
179*11efff7fSkettenis {
180*11efff7fSkettenis }
181*11efff7fSkettenis 
182*11efff7fSkettenis 
183*11efff7fSkettenis 
184*11efff7fSkettenis /* Transferring arbitrary registers between GDB and inferior.  */
185*11efff7fSkettenis 
186*11efff7fSkettenis /* Fetch register REGNO from the child process.  If REGNO is -1, do
187*11efff7fSkettenis    this for all registers (including the floating point and SSE
188*11efff7fSkettenis    registers).  */
189*11efff7fSkettenis 
190*11efff7fSkettenis void
fetch_inferior_registers(int regno)191*11efff7fSkettenis fetch_inferior_registers (int regno)
192*11efff7fSkettenis {
193*11efff7fSkettenis   int tid;
194*11efff7fSkettenis 
195*11efff7fSkettenis   /* GNU/Linux LWP ID's are process ID's.  */
196*11efff7fSkettenis   tid = TIDGET (inferior_ptid);
197*11efff7fSkettenis   if (tid == 0)
198*11efff7fSkettenis     tid = PIDGET (inferior_ptid);	/* Not a threaded program.  */
199*11efff7fSkettenis 
200*11efff7fSkettenis   /* Use the PTRACE_GETREGS request whenever possible, since it
201*11efff7fSkettenis      transfers more registers in one system call, and we'll cache the
202*11efff7fSkettenis      results.  */
203*11efff7fSkettenis   if (regno == -1 || GETREGS_SUPPLIES (regno))
204*11efff7fSkettenis     {
205*11efff7fSkettenis       fetch_regs (tid);
206*11efff7fSkettenis       return;
207*11efff7fSkettenis     }
208*11efff7fSkettenis 
209*11efff7fSkettenis   internal_error (__FILE__, __LINE__,
210*11efff7fSkettenis 		  "Got request for bad register number %d.", regno);
211*11efff7fSkettenis }
212*11efff7fSkettenis 
213*11efff7fSkettenis /* Store register REGNO back into the child process.  If REGNO is -1,
214*11efff7fSkettenis    do this for all registers (including the floating point and SSE
215*11efff7fSkettenis    registers).  */
216*11efff7fSkettenis void
store_inferior_registers(int regno)217*11efff7fSkettenis store_inferior_registers (int regno)
218*11efff7fSkettenis {
219*11efff7fSkettenis   int tid;
220*11efff7fSkettenis 
221*11efff7fSkettenis   /* GNU/Linux LWP ID's are process ID's.  */
222*11efff7fSkettenis   if ((tid = TIDGET (inferior_ptid)) == 0)
223*11efff7fSkettenis     tid = PIDGET (inferior_ptid);	/* Not a threaded program.  */
224*11efff7fSkettenis 
225*11efff7fSkettenis   /* Use the PTRACE_SETREGS request whenever possible, since it
226*11efff7fSkettenis      transfers more registers in one system call.  */
227*11efff7fSkettenis   if (regno == -1 || GETREGS_SUPPLIES (regno))
228*11efff7fSkettenis     {
229*11efff7fSkettenis       store_regs (tid, regno);
230*11efff7fSkettenis       return;
231*11efff7fSkettenis     }
232*11efff7fSkettenis 
233*11efff7fSkettenis   internal_error (__FILE__, __LINE__,
234*11efff7fSkettenis 		  "Got request to store bad register number %d.", regno);
235*11efff7fSkettenis }
236