OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [i387-nat.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Native-dependent code for the i387.
2
   Copyright 2000, 2001 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
#include "defs.h"
22
#include "inferior.h"
23
#include "value.h"
24
#include "regcache.h"
25
 
26
#include "i387-nat.h"
27
 
28
/* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
29
   define their own routines to manage the floating-point registers in
30
   GDB's register array.  Most (if not all) of these targets use the
31
   format used by the "fsave" instruction in their communication with
32
   the OS.  They should all be converted to use the routines below.  */
33
 
34
/* At fsave_offset[REGNUM] you'll find the offset to the location in
35
   the data structure used by the "fsave" instruction where GDB
36
   register REGNUM is stored.  */
37
 
38
static int fsave_offset[] =
39
{
40
  28 + 0 * FPU_REG_RAW_SIZE,     /* FP0_REGNUM through ...  */
41
  28 + 1 * FPU_REG_RAW_SIZE,
42
  28 + 2 * FPU_REG_RAW_SIZE,
43
  28 + 3 * FPU_REG_RAW_SIZE,
44
  28 + 4 * FPU_REG_RAW_SIZE,
45
  28 + 5 * FPU_REG_RAW_SIZE,
46
  28 + 6 * FPU_REG_RAW_SIZE,
47
  28 + 7 * FPU_REG_RAW_SIZE,    /* ... FP7_REGNUM.  */
48
  0,                             /* FCTRL_REGNUM (16 bits).  */
49
  4,                            /* FSTAT_REGNUM (16 bits).  */
50
  8,                            /* FTAG_REGNUM (16 bits).  */
51
  16,                           /* FCS_REGNUM (16 bits).  */
52
  12,                           /* FCOFF_REGNUM.  */
53
  24,                           /* FDS_REGNUM.  */
54
  20,                           /* FDOFF_REGNUM.  */
55
  18                            /* FOP_REGNUM (bottom 11 bits).  */
56
};
57
 
58
#define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
59
 
60
 
61
/* Fill register REGNUM in GDB's register array with the appropriate
62
   value from *FSAVE.  This function masks off any of the reserved
63
   bits in *FSAVE.  */
64
 
65
void
66
i387_supply_register (int regnum, char *fsave)
67
{
68
  /* Most of the FPU control registers occupy only 16 bits in
69
     the fsave area.  Give those a special treatment.  */
70
  if (regnum >= FIRST_FPU_CTRL_REGNUM
71
      && regnum != FCOFF_REGNUM && regnum != FDOFF_REGNUM)
72
    {
73
      unsigned int val = *(unsigned short *) (FSAVE_ADDR (fsave, regnum));
74
 
75
      if (regnum == FOP_REGNUM)
76
        {
77
          val &= ((1 << 11) - 1);
78
          supply_register (regnum, (char *) &val);
79
        }
80
      else
81
        supply_register (regnum, (char *) &val);
82
    }
83
  else
84
    supply_register (regnum, FSAVE_ADDR (fsave, regnum));
85
}
86
 
87
/* Fill GDB's register array with the floating-point register values
88
   in *FSAVE.  This function masks off any of the reserved
89
   bits in *FSAVE.  */
90
 
91
void
92
i387_supply_fsave (char *fsave)
93
{
94
  int i;
95
 
96
  for (i = FP0_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
97
    i387_supply_register (i, fsave);
98
}
99
 
100
/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
101
   with the value in GDB's register array.  If REGNUM is -1, do this
102
   for all registers.  This function doesn't touch any of the reserved
103
   bits in *FSAVE.  */
104
 
105
void
106
i387_fill_fsave (char *fsave, int regnum)
107
{
108
  int i;
109
 
110
  for (i = FP0_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
111
    if (regnum == -1 || regnum == i)
112
      {
113
        /* Most of the FPU control registers occupy only 16 bits in
114
           the fsave area.  Give those a special treatment.  */
115
        if (i >= FIRST_FPU_CTRL_REGNUM
116
            && i != FCOFF_REGNUM && i != FDOFF_REGNUM)
117
          {
118
            if (i == FOP_REGNUM)
119
              {
120
                unsigned short oldval, newval;
121
 
122
                /* The opcode occupies only 11 bits.  */
123
                oldval = (*(unsigned short *) (FSAVE_ADDR (fsave, i)));
124
                newval = *(unsigned short *) &registers[REGISTER_BYTE (i)];
125
                newval &= ((1 << 11) - 1);
126
                newval |= oldval & ~((1 << 11) - 1);
127
                memcpy (FSAVE_ADDR (fsave, i), &newval, 2);
128
              }
129
            else
130
              memcpy (FSAVE_ADDR (fsave, i), &registers[REGISTER_BYTE (i)], 2);
131
          }
132
        else
133
          memcpy (FSAVE_ADDR (fsave, i), &registers[REGISTER_BYTE (i)],
134
                  REGISTER_RAW_SIZE (i));
135
      }
136
}
137
 
138
 
139
/* At fxsave_offset[REGNUM] you'll find the offset to the location in
140
   the data structure used by the "fxsave" instruction where GDB
141
   register REGNUM is stored.  */
142
 
143
static int fxsave_offset[] =
144
{
145
  32,                           /* FP0_REGNUM through ...  */
146
  48,
147
  64,
148
  80,
149
  96,
150
  112,
151
  128,
152
  144,                          /* ... FP7_REGNUM (80 bits each).  */
153
  0,                             /* FCTRL_REGNUM (16 bits).  */
154
  2,                            /* FSTAT_REGNUM (16 bits).  */
155
  4,                            /* FTAG_REGNUM (16 bits).  */
156
  12,                           /* FCS_REGNUM (16 bits).  */
157
  8,                            /* FCOFF_REGNUM.  */
158
  20,                           /* FDS_REGNUM (16 bits).  */
159
  16,                           /* FDOFF_REGNUM.  */
160
  6,                            /* FOP_REGNUM (bottom 11 bits).  */
161
  160,                          /* XMM0_REGNUM through ...  */
162
  176,
163
  192,
164
  208,
165
  224,
166
  240,
167
  256,
168
  272,                          /* ... XMM7_REGNUM (128 bits each).  */
169
  24,                           /* MXCSR_REGNUM.  */
170
};
171
 
172
#define FXSAVE_ADDR(fxsave, regnum) \
173
  (fxsave + fxsave_offset[regnum - FP0_REGNUM])
174
 
175
static int i387_tag (unsigned char *raw);
176
 
177
 
178
/* Fill GDB's register array with the floating-point and SSE register
179
   values in *FXSAVE.  This function masks off any of the reserved
180
   bits in *FXSAVE.  */
181
 
182
void
183
i387_supply_fxsave (char *fxsave)
184
{
185
  int i;
186
 
187
  for (i = FP0_REGNUM; i <= MXCSR_REGNUM; i++)
188
    {
189
      /* Most of the FPU control registers occupy only 16 bits in
190
         the fxsave area.  Give those a special treatment.  */
191
      if (i >= FIRST_FPU_CTRL_REGNUM && i < XMM0_REGNUM
192
          && i != FCOFF_REGNUM && i != FDOFF_REGNUM)
193
        {
194
          unsigned long val = *(unsigned short *) (FXSAVE_ADDR (fxsave, i));
195
 
196
          if (i == FOP_REGNUM)
197
            {
198
              val &= ((1 << 11) - 1);
199
              supply_register (i, (char *) &val);
200
            }
201
          else if (i== FTAG_REGNUM)
202
            {
203
              /* The fxsave area contains a simplified version of the
204
                 tag word.  We have to look at the actual 80-bit FP
205
                 data to recreate the traditional i387 tag word.  */
206
 
207
              unsigned long ftag = 0;
208
              unsigned long fstat;
209
              int fpreg;
210
              int top;
211
 
212
              fstat = *(unsigned short *) (FXSAVE_ADDR (fxsave, FSTAT_REGNUM));
213
              top = ((fstat >> 11) & 0x7);
214
 
215
              for (fpreg = 7; fpreg >= 0; fpreg--)
216
                {
217
                  int tag;
218
 
219
                  if (val & (1 << fpreg))
220
                    {
221
                      int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
222
                      tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
223
                    }
224
                  else
225
                    tag = 3;            /* Empty */
226
 
227
                  ftag |= tag << (2 * fpreg);
228
                }
229
              supply_register (i, (char *) &ftag);
230
            }
231
          else
232
            supply_register (i, (char *) &val);
233
        }
234
      else
235
        supply_register (i, FXSAVE_ADDR (fxsave, i));
236
    }
237
}
238
 
239
/* Fill register REGNUM (if it is a floating-point or SSE register) in
240
   *FXSAVE with the value in GDB's register array.  If REGNUM is -1, do
241
   this for all registers.  This function doesn't touch any of the
242
   reserved bits in *FXSAVE.  */
243
 
244
void
245
i387_fill_fxsave (char *fxsave, int regnum)
246
{
247
  int i;
248
 
249
  for (i = FP0_REGNUM; i <= MXCSR_REGNUM; i++)
250
    if (regnum == -1 || regnum == i)
251
      {
252
        /* Most of the FPU control registers occupy only 16 bits in
253
           the fxsave area.  Give those a special treatment.  */
254
        if (i >= FIRST_FPU_CTRL_REGNUM && i < XMM0_REGNUM
255
            && i != FCOFF_REGNUM && i != FDOFF_REGNUM)
256
          {
257
            if (i == FOP_REGNUM)
258
              {
259
                unsigned short oldval, newval;
260
 
261
                /* The opcode occupies only 11 bits.  */
262
                oldval = (*(unsigned short *) (FXSAVE_ADDR (fxsave, i)));
263
                newval = *(unsigned short *) &registers[REGISTER_BYTE (i)];
264
                newval &= ((1 << 11) - 1);
265
                newval |= oldval & ~((1 << 11) - 1);
266
                memcpy (FXSAVE_ADDR (fxsave, i), &newval, 2);
267
              }
268
            else if (i == FTAG_REGNUM)
269
              {
270
                /* Converting back is much easier.  */
271
 
272
                unsigned char val = 0;
273
                unsigned short ftag;
274
                int fpreg;
275
 
276
                ftag = *(unsigned short *) &registers[REGISTER_BYTE (i)];
277
 
278
                for (fpreg = 7; fpreg >= 0; fpreg--)
279
                  {
280
                    int tag = (ftag >> (fpreg * 2)) & 3;
281
 
282
                    if (tag != 3)
283
                      val |= (1 << (fpreg * 2));
284
                  }
285
 
286
                memcpy (FXSAVE_ADDR (fxsave, i), &val, 2);
287
              }
288
            else
289
              memcpy (FXSAVE_ADDR (fxsave, i),
290
                      &registers[REGISTER_BYTE (i)], 2);
291
          }
292
        else
293
          memcpy (FXSAVE_ADDR (fxsave, i), &registers[REGISTER_BYTE (i)],
294
                  REGISTER_RAW_SIZE (i));
295
      }
296
}
297
 
298
/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
299
   *RAW.  */
300
 
301
static int
302
i387_tag (unsigned char *raw)
303
{
304
  int integer;
305
  unsigned int exponent;
306
  unsigned long fraction[2];
307
 
308
  integer = raw[7] & 0x80;
309
  exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
310
  fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
311
  fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
312
                 | (raw[5] << 8) | raw[4]);
313
 
314
  if (exponent == 0x7fff)
315
    {
316
      /* Special.  */
317
      return (2);
318
    }
319
  else if (exponent == 0x0000)
320
    {
321
      if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
322
        {
323
          /* Zero.  */
324
          return (1);
325
        }
326
      else
327
        {
328
          /* Special.  */
329
          return (2);
330
        }
331
    }
332
  else
333
    {
334
      if (integer)
335
        {
336
          /* Valid.  */
337
          return (0);
338
        }
339
      else
340
        {
341
          /* Special.  */
342
          return (2);
343
        }
344
    }
345
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.