OSDN Git Service

Move hardware bug out of 5.1
[pf3gnuchains/pf3gnuchains3x.git] / gdb / mipsm3-nat.c
1 /* Definitions to make GDB run on a mips box under Mach 3.0
2    Copyright (C) 1992 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 2 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, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 /* Mach specific routines for little endian mips (e.g. pmax)
22  * running Mach 3.0
23  *
24  * Author: Jukka Virtanen <jtv@hut.fi>
25  */
26
27 #include "defs.h"
28 #include "inferior.h"
29
30 #include <stdio.h>
31
32 #include <mach.h>
33 #include <mach/message.h>
34 #include <mach/exception.h>
35 #include <mach_error.h>
36
37 /* Find offsets to thread states at compile time.
38  * If your compiler does not grok this, check the hand coded
39  * offsets and use them.
40  */
41
42 #if 1
43
44 #define  REG_OFFSET(reg) (int)(&((struct mips_thread_state *)0)->reg)
45 #define CREG_OFFSET(reg) (int)(&((struct mips_float_state *)0)->reg)
46 #define EREG_OFFSET(reg) (int)(&((struct mips_exc_state *)0)->reg)
47
48 /* at reg_offset[i] is the offset to the mips_thread_state
49  * location where the gdb registers[i] is stored.
50  *
51  * -1 means mach does not save it anywhere.
52  */
53 static int reg_offset[] =
54 {
55   /*  zero              at                v0                v1       */
56   -1, REG_OFFSET (r1), REG_OFFSET (r2), REG_OFFSET (r3),
57
58   /*  a0                a1                a2                a3       */
59   REG_OFFSET (r4), REG_OFFSET (r5), REG_OFFSET (r6), REG_OFFSET (r7),
60
61   /*  t0                t1                t2                t3       */
62   REG_OFFSET (r8), REG_OFFSET (r9), REG_OFFSET (r10), REG_OFFSET (r11),
63
64   /*  t4                t5                t6                t7       */
65   REG_OFFSET (r12), REG_OFFSET (r13), REG_OFFSET (r14), REG_OFFSET (r15),
66
67   /*  s0                s1                s2                s3       */
68   REG_OFFSET (r16), REG_OFFSET (r17), REG_OFFSET (r18), REG_OFFSET (r19),
69
70   /*  s4                s5                s6                s7       */
71   REG_OFFSET (r20), REG_OFFSET (r21), REG_OFFSET (r22), REG_OFFSET (r23),
72
73   /*  t8                t9                k0                k1       */
74   REG_OFFSET (r24), REG_OFFSET (r25), REG_OFFSET (r26), REG_OFFSET (r27),
75
76   /*  gp                sp            s8(30) == fp(72)      ra       */
77   REG_OFFSET (r28), REG_OFFSET (r29), REG_OFFSET (r30), REG_OFFSET (r31),
78
79   /*  sr(32) PS_REGNUM   */
80   EREG_OFFSET (coproc_state),
81
82   /*  lo(33)            hi(34)    */
83   REG_OFFSET (mdlo), REG_OFFSET (mdhi),
84
85   /*  bad(35)                 cause(36)          pc(37)  */
86   EREG_OFFSET (address), EREG_OFFSET (cause), REG_OFFSET (pc),
87
88   /*  f0(38)             f1(39)             f2(40)             f3(41)   */
89   CREG_OFFSET (r0), CREG_OFFSET (r1), CREG_OFFSET (r2), CREG_OFFSET (r3),
90   CREG_OFFSET (r4), CREG_OFFSET (r5), CREG_OFFSET (r6), CREG_OFFSET (r7),
91   CREG_OFFSET (r8), CREG_OFFSET (r9), CREG_OFFSET (r10), CREG_OFFSET (r11),
92   CREG_OFFSET (r12), CREG_OFFSET (r13), CREG_OFFSET (r14), CREG_OFFSET (r15),
93   CREG_OFFSET (r16), CREG_OFFSET (r17), CREG_OFFSET (r18), CREG_OFFSET (r19),
94   CREG_OFFSET (r20), CREG_OFFSET (r21), CREG_OFFSET (r22), CREG_OFFSET (r23),
95   CREG_OFFSET (r24), CREG_OFFSET (r25), CREG_OFFSET (r26), CREG_OFFSET (r27),
96   CREG_OFFSET (r28), CREG_OFFSET (r29), CREG_OFFSET (r30), CREG_OFFSET (r31),
97
98   /*  fsr(70)           fir(71)         fp(72) == s8(30) */
99   CREG_OFFSET (csr), CREG_OFFSET (esr), REG_OFFSET (r30)
100 };
101 #else
102 /* If the compiler does not grok the above defines */
103 static int reg_offset[] =
104 {
105 /* mach_thread_state offsets: */
106   -1, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56,
107   60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120,
108 /*sr, lo, hi,addr,cause,pc   */
109   8, 124, 128, 4, 0, 132,
110 /* mach_float_state offsets: */
111   0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
112   64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
113 /*fsr,fir */
114   128, 132,
115 /* FP_REGNUM pseudo maps to s8==r30 in mach_thread_state */
116   116
117 };
118 #endif
119
120 /* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
121  * Caller knows that the regs handled in one transaction are of same size.
122  */
123 #define FETCH_REGS(state, regnum, count) \
124   memcpy (&registers[REGISTER_BYTE (regnum)], \
125           (char *)state+reg_offset[ regnum ], \
126           count*REGISTER_SIZE)
127
128 /* Store COUNT contiguous registers to thread STATE starting from REGNUM */
129 #define STORE_REGS(state, regnum, count) \
130   memcpy ((char *)state+reg_offset[ regnum ], \
131           &registers[REGISTER_BYTE (regnum)], \
132           count*REGISTER_SIZE)
133
134 #define REGS_ALL    -1
135 #define REGS_NORMAL  1
136 #define REGS_EXC     2
137 #define REGS_COP1    4
138
139 /* Hardware regs that matches FP_REGNUM */
140 #define MACH_FP_REGNUM 30
141
142 /* Fech thread's registers. if regno == -1, fetch all regs */
143 void
144 fetch_inferior_registers (int regno)
145 {
146   kern_return_t ret;
147
148   thread_state_data_t state;
149   struct mips_exc_state exc_state;
150
151   int stateCnt = MIPS_THREAD_STATE_COUNT;
152
153   int which_regs = 0;           /* A bit mask */
154
155   if (!MACH_PORT_VALID (current_thread))
156     error ("fetch inferior registers: Invalid thread");
157
158   if (regno < -1 || regno >= NUM_REGS)
159     error ("invalid register %d supplied to fetch_inferior_registers", regno);
160
161   if (regno == -1)
162     which_regs = REGS_ALL;
163   else if (regno == ZERO_REGNUM)
164     {
165       int zero = 0;
166       supply_register (ZERO_REGNUM, &zero);
167       return;
168     }
169   else if ((ZERO_REGNUM < regno && regno < PS_REGNUM)
170            || regno == FP_REGNUM
171            || regno == LO_REGNUM
172            || regno == HI_REGNUM
173            || regno == PC_REGNUM)
174     which_regs = REGS_NORMAL;
175   else if (FP0_REGNUM <= regno && regno <= FCRIR_REGNUM)
176     which_regs = REGS_COP1 | REGS_EXC;
177   else
178     which_regs = REGS_EXC;
179
180   /* fetch regs saved to mips_thread_state */
181   if (which_regs & REGS_NORMAL)
182     {
183       ret = thread_get_state (current_thread,
184                               MIPS_THREAD_STATE,
185                               state,
186                               &stateCnt);
187       CHK ("fetch inferior registers: thread_get_state", ret);
188
189       if (which_regs == REGS_NORMAL)
190         {
191           /* Fetch also FP_REGNUM if fetching MACH_FP_REGNUM and vice versa */
192           if (regno == MACH_FP_REGNUM || regno == FP_REGNUM)
193             {
194               supply_register (FP_REGNUM,
195                                (char *) state + reg_offset[MACH_FP_REGNUM]);
196               supply_register (MACH_FP_REGNUM,
197                                (char *) state + reg_offset[MACH_FP_REGNUM]);
198             }
199           else
200             supply_register (regno,
201                              (char *) state + reg_offset[regno]);
202           return;
203         }
204
205       /* ZERO_REGNUM is always zero */
206       *(int *) registers = 0;
207
208       /* Copy thread saved regs 1..31 to gdb's reg value array
209        * Luckily, they are contiquous
210        */
211       FETCH_REGS (state, 1, 31);
212
213       /* Copy mdlo and mdhi */
214       FETCH_REGS (state, LO_REGNUM, 2);
215
216       /* Copy PC */
217       FETCH_REGS (state, PC_REGNUM, 1);
218
219       /* Mach 3.0 saves FP to MACH_FP_REGNUM.
220        * For some reason gdb wants to assign a pseudo register for it.
221        */
222       FETCH_REGS (state, FP_REGNUM, 1);
223     }
224
225   /* Read exc state. Also read if need to fetch floats */
226   if (which_regs & REGS_EXC)
227     {
228       stateCnt = MIPS_EXC_STATE_COUNT;
229       ret = thread_get_state (current_thread,
230                               MIPS_EXC_STATE,
231                               (thread_state_t) & exc_state,
232                               &stateCnt);
233       CHK ("fetch inferior regs (exc): thread_get_state", ret);
234
235       /* We need to fetch exc_state to see if the floating
236        * state is valid for the thread.
237        */
238
239       /* cproc_state: Which coprocessors the thread uses */
240       supply_register (PS_REGNUM,
241                        (char *) &exc_state + reg_offset[PS_REGNUM]);
242
243       if (which_regs == REGS_EXC || which_regs == REGS_ALL)
244         {
245           supply_register (BADVADDR_REGNUM,
246                          (char *) &exc_state + reg_offset[BADVADDR_REGNUM]);
247
248           supply_register (CAUSE_REGNUM,
249                            (char *) &exc_state + reg_offset[CAUSE_REGNUM]);
250           if (which_regs == REGS_EXC)
251             return;
252         }
253     }
254
255
256   if (which_regs & REGS_COP1)
257     {
258       /* If the thread does not have saved COPROC1, set regs to zero */
259
260       if (!(exc_state.coproc_state & MIPS_STATUS_USE_COP1))
261         bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
262                sizeof (struct mips_float_state));
263       else
264         {
265           stateCnt = MIPS_FLOAT_STATE_COUNT;
266           ret = thread_get_state (current_thread,
267                                   MIPS_FLOAT_STATE,
268                                   state,
269                                   &stateCnt);
270           CHK ("fetch inferior regs (floats): thread_get_state", ret);
271
272           if (regno != -1)
273             {
274               supply_register (regno,
275                                (char *) state + reg_offset[regno]);
276               return;
277             }
278
279           FETCH_REGS (state, FP0_REGNUM, 34);
280         }
281     }
282
283   /* All registers are valid, if not returned yet */
284   registers_fetched ();
285 }
286
287 /* Store gdb's view of registers to the thread.
288  * All registers are always valid when entering here.
289  * @@ ahem, maybe that is too strict, we could validate the necessary ones
290  *    here.
291  *
292  * Hmm. It seems that gdb set $reg=value command first reads everything,
293  * then sets the reg and then stores everything. -> we must make sure
294  * that the immutable registers are not changed by reading them first.
295  */
296
297 void
298 store_inferior_registers (register int regno)
299 {
300   thread_state_data_t state;
301   kern_return_t ret;
302
303   if (!MACH_PORT_VALID (current_thread))
304     error ("store inferior registers: Invalid thread");
305
306   /* Check for read only regs.
307    * @@ If some of these is can be changed, fix this
308    */
309   if (regno == ZERO_REGNUM ||
310       regno == PS_REGNUM ||
311       regno == BADVADDR_REGNUM ||
312       regno == CAUSE_REGNUM ||
313       regno == FCRIR_REGNUM)
314     {
315       message ("You can not alter read-only register `%s'",
316                REGISTER_NAME (regno));
317       fetch_inferior_registers (regno);
318       return;
319     }
320
321   if (regno == -1)
322     {
323       /* Don't allow these to change */
324
325       /* ZERO_REGNUM */
326       *(int *) registers = 0;
327
328       fetch_inferior_registers (PS_REGNUM);
329       fetch_inferior_registers (BADVADDR_REGNUM);
330       fetch_inferior_registers (CAUSE_REGNUM);
331       fetch_inferior_registers (FCRIR_REGNUM);
332     }
333
334   if (regno == -1 || (ZERO_REGNUM < regno && regno <= PC_REGNUM))
335     {
336 #if 1
337       /* Mach 3.0 saves thread's FP to MACH_FP_REGNUM.
338        * GDB wants assigns a pseudo register FP_REGNUM for frame pointer.
339        *
340        * @@@ Here I assume (!) that gdb's FP has the value that
341        *     should go to threads frame pointer. If not true, this
342        *     fails badly!!!!!
343        */
344       memcpy (&registers[REGISTER_BYTE (MACH_FP_REGNUM)],
345               &registers[REGISTER_BYTE (FP_REGNUM)],
346               REGISTER_RAW_SIZE (FP_REGNUM));
347 #endif
348
349       /* Save gdb's regs 1..31 to thread saved regs 1..31
350        * Luckily, they are contiquous
351        */
352       STORE_REGS (state, 1, 31);
353
354       /* Save mdlo, mdhi */
355       STORE_REGS (state, LO_REGNUM, 2);
356
357       /* Save PC */
358       STORE_REGS (state, PC_REGNUM, 1);
359
360       ret = thread_set_state (current_thread,
361                               MIPS_THREAD_STATE,
362                               state,
363                               MIPS_FLOAT_STATE_COUNT);
364       CHK ("store inferior regs : thread_set_state", ret);
365     }
366
367   if (regno == -1 || regno >= FP0_REGNUM)
368     {
369       /* If thread has floating state, save it */
370       if (read_register (PS_REGNUM) & MIPS_STATUS_USE_COP1)
371         {
372           /* Do NOT save FCRIR_REGNUM */
373           STORE_REGS (state, FP0_REGNUM, 33);
374
375           ret = thread_set_state (current_thread,
376                                   MIPS_FLOAT_STATE,
377                                   state,
378                                   MIPS_FLOAT_STATE_COUNT);
379           CHK ("store inferior registers (floats): thread_set_state", ret);
380         }
381       else if (regno != -1)
382         message
383           ("Thread does not use floating point unit, floating regs not saved");
384     }
385 }