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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [gdb/] [gdbserver/] [i387-fp.c] - Blame information for rev 330

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* i387-specific utility functions, for the remote server for GDB.
2
   Copyright (C) 2000, 2001, 2002, 2005, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "server.h"
21
#include "i387-fp.h"
22
#include "i386-xstate.h"
23
 
24
int num_xmm_registers = 8;
25
 
26
/* Note: These functions preserve the reserved bits in control registers.
27
   However, gdbserver promptly throws away that information.  */
28
 
29
/* These structs should have the proper sizes and alignment on both
30
   i386 and x86-64 machines.  */
31
 
32
struct i387_fsave {
33
  /* All these are only sixteen bits, plus padding, except for fop (which
34
     is only eleven bits), and fooff / fioff (which are 32 bits each).  */
35
  unsigned short fctrl;
36
  unsigned short pad1;
37
  unsigned short fstat;
38
  unsigned short pad2;
39
  unsigned short ftag;
40
  unsigned short pad3;
41
  unsigned int fioff;
42
  unsigned short fiseg;
43
  unsigned short fop;
44
  unsigned int fooff;
45
  unsigned short foseg;
46
  unsigned short pad4;
47
 
48
  /* Space for eight 80-bit FP values.  */
49
  unsigned char st_space[80];
50
};
51
 
52
struct i387_fxsave {
53
  /* All these are only sixteen bits, plus padding, except for fop (which
54
     is only eleven bits), and fooff / fioff (which are 32 bits each).  */
55
  unsigned short fctrl;
56
  unsigned short fstat;
57
  unsigned short ftag;
58
  unsigned short fop;
59
  unsigned int fioff;
60
  unsigned short fiseg;
61
  unsigned short pad1;
62
  unsigned int fooff;
63
  unsigned short foseg;
64
  unsigned short pad12;
65
 
66
  unsigned int mxcsr;
67
  unsigned int pad3;
68
 
69
  /* Space for eight 80-bit FP values in 128-bit spaces.  */
70
  unsigned char st_space[128];
71
 
72
  /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
73
  unsigned char xmm_space[256];
74
};
75
 
76
struct i387_xsave {
77
  /* All these are only sixteen bits, plus padding, except for fop (which
78
     is only eleven bits), and fooff / fioff (which are 32 bits each).  */
79
  unsigned short fctrl;
80
  unsigned short fstat;
81
  unsigned short ftag;
82
  unsigned short fop;
83
  unsigned int fioff;
84
  unsigned short fiseg;
85
  unsigned short pad1;
86
  unsigned int fooff;
87
  unsigned short foseg;
88
  unsigned short pad12;
89
 
90
  unsigned int mxcsr;
91
  unsigned int mxcsr_mask;
92
 
93
  /* Space for eight 80-bit FP values in 128-bit spaces.  */
94
  unsigned char st_space[128];
95
 
96
  /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
97
  unsigned char xmm_space[256];
98
 
99
  unsigned char reserved1[48];
100
 
101
  /* The extended control register 0 (the XFEATURE_ENABLED_MASK
102
     register).  */
103
  unsigned long long xcr0;
104
 
105
  unsigned char reserved2[40];
106
 
107
  /* The XSTATE_BV bit vector.  */
108
  unsigned long long xstate_bv;
109
 
110
  unsigned char reserved3[56];
111
 
112
  /* Space for eight upper 128-bit YMM values, or 16 on x86-64.  */
113
  unsigned char ymmh_space[256];
114
};
115
 
116
void
117
i387_cache_to_fsave (struct regcache *regcache, void *buf)
118
{
119
  struct i387_fsave *fp = (struct i387_fsave *) buf;
120
  int i;
121
  int st0_regnum = find_regno ("st0");
122
  unsigned long val, val2;
123
 
124
  for (i = 0; i < 8; i++)
125
    collect_register (regcache, i + st0_regnum,
126
                      ((char *) &fp->st_space[0]) + i * 10);
127
 
128
  collect_register_by_name (regcache, "fioff", &fp->fioff);
129
  collect_register_by_name (regcache, "fooff", &fp->fooff);
130
 
131
  /* This one's 11 bits... */
132
  collect_register_by_name (regcache, "fop", &val2);
133
  fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
134
 
135
  /* Some registers are 16-bit.  */
136
  collect_register_by_name (regcache, "fctrl", &val);
137
  fp->fctrl = val;
138
 
139
  collect_register_by_name (regcache, "fstat", &val);
140
  val &= 0xFFFF;
141
  fp->fstat = val;
142
 
143
  collect_register_by_name (regcache, "ftag", &val);
144
  val &= 0xFFFF;
145
  fp->ftag = val;
146
 
147
  collect_register_by_name (regcache, "fiseg", &val);
148
  val &= 0xFFFF;
149
  fp->fiseg = val;
150
 
151
  collect_register_by_name (regcache, "foseg", &val);
152
  val &= 0xFFFF;
153
  fp->foseg = val;
154
}
155
 
156
void
157
i387_fsave_to_cache (struct regcache *regcache, const void *buf)
158
{
159
  struct i387_fsave *fp = (struct i387_fsave *) buf;
160
  int i;
161
  int st0_regnum = find_regno ("st0");
162
  unsigned long val;
163
 
164
  for (i = 0; i < 8; i++)
165
    supply_register (regcache, i + st0_regnum,
166
                     ((char *) &fp->st_space[0]) + i * 10);
167
 
168
  supply_register_by_name (regcache, "fioff", &fp->fioff);
169
  supply_register_by_name (regcache, "fooff", &fp->fooff);
170
 
171
  /* Some registers are 16-bit.  */
172
  val = fp->fctrl & 0xFFFF;
173
  supply_register_by_name (regcache, "fctrl", &val);
174
 
175
  val = fp->fstat & 0xFFFF;
176
  supply_register_by_name (regcache, "fstat", &val);
177
 
178
  val = fp->ftag & 0xFFFF;
179
  supply_register_by_name (regcache, "ftag", &val);
180
 
181
  val = fp->fiseg & 0xFFFF;
182
  supply_register_by_name (regcache, "fiseg", &val);
183
 
184
  val = fp->foseg & 0xFFFF;
185
  supply_register_by_name (regcache, "foseg", &val);
186
 
187
  /* fop has only 11 valid bits.  */
188
  val = (fp->fop) & 0x7FF;
189
  supply_register_by_name (regcache, "fop", &val);
190
}
191
 
192
void
193
i387_cache_to_fxsave (struct regcache *regcache, void *buf)
194
{
195
  struct i387_fxsave *fp = (struct i387_fxsave *) buf;
196
  int i;
197
  int st0_regnum = find_regno ("st0");
198
  int xmm0_regnum = find_regno ("xmm0");
199
  unsigned long val, val2;
200
 
201
  for (i = 0; i < 8; i++)
202
    collect_register (regcache, i + st0_regnum,
203
                      ((char *) &fp->st_space[0]) + i * 16);
204
  for (i = 0; i < num_xmm_registers; i++)
205
    collect_register (regcache, i + xmm0_regnum,
206
                      ((char *) &fp->xmm_space[0]) + i * 16);
207
 
208
  collect_register_by_name (regcache, "fioff", &fp->fioff);
209
  collect_register_by_name (regcache, "fooff", &fp->fooff);
210
  collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
211
 
212
  /* This one's 11 bits... */
213
  collect_register_by_name (regcache, "fop", &val2);
214
  fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
215
 
216
  /* Some registers are 16-bit.  */
217
  collect_register_by_name (regcache, "fctrl", &val);
218
  fp->fctrl = val;
219
 
220
  collect_register_by_name (regcache, "fstat", &val);
221
  fp->fstat = val;
222
 
223
  /* Convert to the simplifed tag form stored in fxsave data.  */
224
  collect_register_by_name (regcache, "ftag", &val);
225
  val &= 0xFFFF;
226
  val2 = 0;
227
  for (i = 7; i >= 0; i--)
228
    {
229
      int tag = (val >> (i * 2)) & 3;
230
 
231
      if (tag != 3)
232
        val2 |= (1 << i);
233
    }
234
  fp->ftag = val2;
235
 
236
  collect_register_by_name (regcache, "fiseg", &val);
237
  fp->fiseg = val;
238
 
239
  collect_register_by_name (regcache, "foseg", &val);
240
  fp->foseg = val;
241
}
242
 
243
void
244
i387_cache_to_xsave (struct regcache *regcache, void *buf)
245
{
246
  struct i387_xsave *fp = (struct i387_xsave *) buf;
247
  int i;
248
  unsigned long val, val2;
249
  unsigned int clear_bv;
250
  unsigned long long xstate_bv = 0;
251
  char raw[16];
252
  char *p;
253
 
254
  /* The supported bits in `xstat_bv' are 1 byte.  Clear part in
255
     vector registers if its bit in xstat_bv is zero.  */
256
  clear_bv = (~fp->xstate_bv) & x86_xcr0;
257
 
258
  /* Clear part in x87 and vector registers if its bit in xstat_bv is
259
     zero.  */
260
  if (clear_bv)
261
    {
262
      if ((clear_bv & I386_XSTATE_X87))
263
        for (i = 0; i < 8; i++)
264
          memset (((char *) &fp->st_space[0]) + i * 16, 0, 10);
265
 
266
      if ((clear_bv & I386_XSTATE_SSE))
267
        for (i = 0; i < num_xmm_registers; i++)
268
          memset (((char *) &fp->xmm_space[0]) + i * 16, 0, 16);
269
 
270
      if ((clear_bv & I386_XSTATE_AVX))
271
        for (i = 0; i < num_xmm_registers; i++)
272
          memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
273
    }
274
 
275
  /* Check if any x87 registers are changed.  */
276
  if ((x86_xcr0 & I386_XSTATE_X87))
277
    {
278
      int st0_regnum = find_regno ("st0");
279
 
280
      for (i = 0; i < 8; i++)
281
        {
282
          collect_register (regcache, i + st0_regnum, raw);
283
          p = ((char *) &fp->st_space[0]) + i * 16;
284
          if (memcmp (raw, p, 10))
285
            {
286
              xstate_bv |= I386_XSTATE_X87;
287
              memcpy (p, raw, 10);
288
            }
289
        }
290
    }
291
 
292
  /* Check if any SSE registers are changed.  */
293
  if ((x86_xcr0 & I386_XSTATE_SSE))
294
    {
295
      int xmm0_regnum = find_regno ("xmm0");
296
 
297
      for (i = 0; i < num_xmm_registers; i++)
298
        {
299
          collect_register (regcache, i + xmm0_regnum, raw);
300
          p = ((char *) &fp->xmm_space[0]) + i * 16;
301
          if (memcmp (raw, p, 16))
302
            {
303
              xstate_bv |= I386_XSTATE_SSE;
304
              memcpy (p, raw, 16);
305
            }
306
        }
307
    }
308
 
309
  /* Check if any AVX registers are changed.  */
310
  if ((x86_xcr0 & I386_XSTATE_AVX))
311
    {
312
      int ymm0h_regnum = find_regno ("ymm0h");
313
 
314
      for (i = 0; i < num_xmm_registers; i++)
315
        {
316
          collect_register (regcache, i + ymm0h_regnum, raw);
317
          p = ((char *) &fp->ymmh_space[0]) + i * 16;
318
          if (memcmp (raw, p, 16))
319
            {
320
              xstate_bv |= I386_XSTATE_AVX;
321
              memcpy (p, raw, 16);
322
            }
323
        }
324
    }
325
 
326
  /* Update the corresponding bits in xstate_bv if any SSE/AVX
327
     registers are changed.  */
328
  fp->xstate_bv |= xstate_bv;
329
 
330
  collect_register_by_name (regcache, "fioff", &fp->fioff);
331
  collect_register_by_name (regcache, "fooff", &fp->fooff);
332
  collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
333
 
334
  /* This one's 11 bits... */
335
  collect_register_by_name (regcache, "fop", &val2);
336
  fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
337
 
338
  /* Some registers are 16-bit.  */
339
  collect_register_by_name (regcache, "fctrl", &val);
340
  fp->fctrl = val;
341
 
342
  collect_register_by_name (regcache, "fstat", &val);
343
  fp->fstat = val;
344
 
345
  /* Convert to the simplifed tag form stored in fxsave data.  */
346
  collect_register_by_name (regcache, "ftag", &val);
347
  val &= 0xFFFF;
348
  val2 = 0;
349
  for (i = 7; i >= 0; i--)
350
    {
351
      int tag = (val >> (i * 2)) & 3;
352
 
353
      if (tag != 3)
354
        val2 |= (1 << i);
355
    }
356
  fp->ftag = val2;
357
 
358
  collect_register_by_name (regcache, "fiseg", &val);
359
  fp->fiseg = val;
360
 
361
  collect_register_by_name (regcache, "foseg", &val);
362
  fp->foseg = val;
363
}
364
 
365
static int
366
i387_ftag (struct i387_fxsave *fp, int regno)
367
{
368
  unsigned char *raw = &fp->st_space[regno * 16];
369
  unsigned int exponent;
370
  unsigned long fraction[2];
371
  int integer;
372
 
373
  integer = raw[7] & 0x80;
374
  exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
375
  fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
376
  fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
377
                 | (raw[5] << 8) | raw[4]);
378
 
379
  if (exponent == 0x7fff)
380
    {
381
      /* Special.  */
382
      return (2);
383
    }
384
  else if (exponent == 0x0000)
385
    {
386
      if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
387
        {
388
          /* Zero.  */
389
          return (1);
390
        }
391
      else
392
        {
393
          /* Special.  */
394
          return (2);
395
        }
396
    }
397
  else
398
    {
399
      if (integer)
400
        {
401
          /* Valid.  */
402
          return (0);
403
        }
404
      else
405
        {
406
          /* Special.  */
407
          return (2);
408
        }
409
    }
410
}
411
 
412
void
413
i387_fxsave_to_cache (struct regcache *regcache, const void *buf)
414
{
415
  struct i387_fxsave *fp = (struct i387_fxsave *) buf;
416
  int i, top;
417
  int st0_regnum = find_regno ("st0");
418
  int xmm0_regnum = find_regno ("xmm0");
419
  unsigned long val;
420
 
421
  for (i = 0; i < 8; i++)
422
    supply_register (regcache, i + st0_regnum,
423
                     ((char *) &fp->st_space[0]) + i * 16);
424
  for (i = 0; i < num_xmm_registers; i++)
425
    supply_register (regcache, i + xmm0_regnum,
426
                     ((char *) &fp->xmm_space[0]) + i * 16);
427
 
428
  supply_register_by_name (regcache, "fioff", &fp->fioff);
429
  supply_register_by_name (regcache, "fooff", &fp->fooff);
430
  supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
431
 
432
  /* Some registers are 16-bit.  */
433
  val = fp->fctrl & 0xFFFF;
434
  supply_register_by_name (regcache, "fctrl", &val);
435
 
436
  val = fp->fstat & 0xFFFF;
437
  supply_register_by_name (regcache, "fstat", &val);
438
 
439
  /* Generate the form of ftag data that GDB expects.  */
440
  top = (fp->fstat >> 11) & 0x7;
441
  val = 0;
442
  for (i = 7; i >= 0; i--)
443
    {
444
      int tag;
445
      if (fp->ftag & (1 << i))
446
        tag = i387_ftag (fp, (i + 8 - top) % 8);
447
      else
448
        tag = 3;
449
      val |= tag << (2 * i);
450
    }
451
  supply_register_by_name (regcache, "ftag", &val);
452
 
453
  val = fp->fiseg & 0xFFFF;
454
  supply_register_by_name (regcache, "fiseg", &val);
455
 
456
  val = fp->foseg & 0xFFFF;
457
  supply_register_by_name (regcache, "foseg", &val);
458
 
459
  val = (fp->fop) & 0x7FF;
460
  supply_register_by_name (regcache, "fop", &val);
461
}
462
 
463
void
464
i387_xsave_to_cache (struct regcache *regcache, const void *buf)
465
{
466
  struct i387_xsave *fp = (struct i387_xsave *) buf;
467
  struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
468
  int i, top;
469
  unsigned long val;
470
  unsigned int clear_bv;
471
  char *p;
472
 
473
  /* The supported bits in `xstat_bv' are 1 byte.  Clear part in
474
     vector registers if its bit in xstat_bv is zero.  */
475
  clear_bv = (~fp->xstate_bv) & x86_xcr0;
476
 
477
  /* Check if any x87 registers are changed.  */
478
  if ((x86_xcr0 & I386_XSTATE_X87))
479
    {
480
      int st0_regnum = find_regno ("st0");
481
 
482
      if ((clear_bv & I386_XSTATE_X87))
483
        p = NULL;
484
      else
485
        p = (char *) buf;
486
 
487
      for (i = 0; i < 8; i++)
488
        {
489
          if (p)
490
            p = ((char *) &fp->st_space[0]) + i * 16;
491
          supply_register (regcache, i + st0_regnum, p);
492
        }
493
    }
494
 
495
  if ((x86_xcr0 & I386_XSTATE_SSE))
496
    {
497
      int xmm0_regnum = find_regno ("xmm0");
498
 
499
      if ((clear_bv & I386_XSTATE_SSE))
500
        p = NULL;
501
      else
502
        p = (char *) buf;
503
 
504
      for (i = 0; i < num_xmm_registers; i++)
505
        {
506
          if (p)
507
            p = ((char *) &fp->xmm_space[0]) + i * 16;
508
          supply_register (regcache, i + xmm0_regnum, p);
509
        }
510
    }
511
 
512
  if ((x86_xcr0 & I386_XSTATE_AVX))
513
    {
514
      int ymm0h_regnum = find_regno ("ymm0h");
515
 
516
      if ((clear_bv & I386_XSTATE_AVX))
517
        p = NULL;
518
      else
519
        p = (char *) buf;
520
 
521
      for (i = 0; i < num_xmm_registers; i++)
522
        {
523
          if (p)
524
            p = ((char *) &fp->ymmh_space[0]) + i * 16;
525
          supply_register (regcache, i + ymm0h_regnum, p);
526
        }
527
    }
528
 
529
  supply_register_by_name (regcache, "fioff", &fp->fioff);
530
  supply_register_by_name (regcache, "fooff", &fp->fooff);
531
  supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
532
 
533
  /* Some registers are 16-bit.  */
534
  val = fp->fctrl & 0xFFFF;
535
  supply_register_by_name (regcache, "fctrl", &val);
536
 
537
  val = fp->fstat & 0xFFFF;
538
  supply_register_by_name (regcache, "fstat", &val);
539
 
540
  /* Generate the form of ftag data that GDB expects.  */
541
  top = (fp->fstat >> 11) & 0x7;
542
  val = 0;
543
  for (i = 7; i >= 0; i--)
544
    {
545
      int tag;
546
      if (fp->ftag & (1 << i))
547
        tag = i387_ftag (fxp, (i + 8 - top) % 8);
548
      else
549
        tag = 3;
550
      val |= tag << (2 * i);
551
    }
552
  supply_register_by_name (regcache, "ftag", &val);
553
 
554
  val = fp->fiseg & 0xFFFF;
555
  supply_register_by_name (regcache, "fiseg", &val);
556
 
557
  val = fp->foseg & 0xFFFF;
558
  supply_register_by_name (regcache, "foseg", &val);
559
 
560
  val = (fp->fop) & 0x7FF;
561
  supply_register_by_name (regcache, "fop", &val);
562
}
563
 
564
/* Default to SSE.  */
565
unsigned long long x86_xcr0 = I386_XSTATE_SSE_MASK;

powered by: WebSVN 2.1.0

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