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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [arm/] [maverick.c] - Blame information for rev 859

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

Line No. Rev Author Line
1 330 jeremybenn
/*  maverick.c -- Cirrus/DSP co-processor interface.
2
    Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3
    Contributed by Aldy Hernandez (aldyh@redhat.com).
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 3 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
17
 
18
#include <assert.h>
19
#include "armdefs.h"
20
#include "ansidecl.h"
21
#include "armemu.h"
22
 
23
/*#define CIRRUS_DEBUG 1        /**/
24
#if CIRRUS_DEBUG
25
#  define printfdbg printf
26
#else
27
#  define printfdbg printf_nothing
28
#endif
29
 
30
#define POS64(i) ( (~(i)) >> 63 )
31
#define NEG64(i) ( (i) >> 63 )
32
 
33
/* Define Co-Processor instruction handlers here.  */
34
 
35
/* Here's ARMulator's DSP definition.  A few things to note:
36
   1) it has 16 64-bit registers and 4 72-bit accumulators
37
   2) you can only access its registers with MCR and MRC.  */
38
 
39
/* We can't define these in here because this file might not be linked
40
   unless the target is arm9e-*.  They are defined in wrapper.c.
41
   Eventually the simulator should be made to handle any coprocessor
42
   at run time.  */
43
struct maverick_regs
44
{
45
  union
46
  {
47
    int i;
48
    float f;
49
  } upper;
50
 
51
  union
52
  {
53
    int i;
54
    float f;
55
  } lower;
56
};
57
 
58
union maverick_acc_regs
59
{
60
  long double ld;               /* Acc registers are 72-bits.  */
61
};
62
 
63
struct maverick_regs DSPregs[16];
64
union maverick_acc_regs DSPacc[4];
65
ARMword DSPsc;
66
 
67
#define DEST_REG        (BITS (12, 15))
68
#define SRC1_REG        (BITS (16, 19))
69
#define SRC2_REG        (BITS (0, 3))
70
 
71
static int lsw_int_index, msw_int_index;
72
static int lsw_float_index, msw_float_index;
73
 
74
static double mv_getRegDouble (int);
75
static long long mv_getReg64int (int);
76
static void mv_setRegDouble (int, double val);
77
static void mv_setReg64int (int, long long val);
78
 
79
static union
80
{
81
  double d;
82
  long long ll;
83
  int ints[2];
84
} reg_conv;
85
 
86
static void
87
printf_nothing (void * foo, ...)
88
{
89
}
90
 
91
static void
92
cirrus_not_implemented (char * insn)
93
{
94
  fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
95
  fprintf (stderr, "aborting!\n");
96
 
97
  exit (1);
98
}
99
 
100
static unsigned
101
DSPInit (ARMul_State * state)
102
{
103
  ARMul_ConsolePrint (state, ", DSP present");
104
  return TRUE;
105
}
106
 
107
unsigned
108
DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
109
         unsigned      type  ATTRIBUTE_UNUSED,
110
         ARMword       instr,
111
         ARMword *     value)
112
{
113
  switch (BITS (5, 7))
114
    {
115
    case 0: /* cfmvrdl */
116
      /* Move lower half of a DF stored in a DSP reg into an Arm reg.  */
117
      printfdbg ("cfmvrdl\n");
118
      printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
119
      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
120
 
121
      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
122
      break;
123
 
124
    case 1: /* cfmvrdh */
125
      /* Move upper half of a DF stored in a DSP reg into an Arm reg.  */
126
      printfdbg ("cfmvrdh\n");
127
      printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
128
      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
129
 
130
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
131
      break;
132
 
133
    case 2: /* cfmvrs */
134
      /* Move SF from upper half of a DSP register to an Arm register.  */
135
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
136
      printfdbg ("cfmvrs = mvf%d <-- %f\n",
137
                 SRC1_REG,
138
                 DSPregs[SRC1_REG].upper.f);
139
      break;
140
 
141
#ifdef doesnt_work
142
    case 4: /* cfcmps */
143
      {
144
        float a, b;
145
        int n, z, c, v;
146
 
147
        a = DSPregs[SRC1_REG].upper.f;
148
        b = DSPregs[SRC2_REG].upper.f;
149
 
150
        printfdbg ("cfcmps\n");
151
        printfdbg ("\tcomparing %f and %f\n", a, b);
152
 
153
        z = a == b;             /* zero */
154
        n = a != b;             /* negative */
155
        v = a > b;              /* overflow */
156
        c = 0;                   /* carry */
157
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
158
        break;
159
      }
160
 
161
    case 5: /* cfcmpd */
162
      {
163
        double a, b;
164
        int n, z, c, v;
165
 
166
        a = mv_getRegDouble (SRC1_REG);
167
        b = mv_getRegDouble (SRC2_REG);
168
 
169
        printfdbg ("cfcmpd\n");
170
        printfdbg ("\tcomparing %g and %g\n", a, b);
171
 
172
        z = a == b;             /* zero */
173
        n = a != b;             /* negative */
174
        v = a > b;              /* overflow */
175
        c = 0;                   /* carry */
176
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
177
        break;
178
      }
179
#else
180
      case 4: /* cfcmps */
181
        {
182
          float a, b;
183
          int n, z, c, v;
184
 
185
          a = DSPregs[SRC1_REG].upper.f;
186
          b = DSPregs[SRC2_REG].upper.f;
187
 
188
          printfdbg ("cfcmps\n");
189
          printfdbg ("\tcomparing %f and %f\n", a, b);
190
 
191
          z = a == b;           /* zero */
192
          n = a < b;            /* negative */
193
          c = a > b;            /* carry */
194
          v = 0;         /* fixme */
195
          printfdbg ("\tz = %d, n = %d\n", z, n);
196
          *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
197
          break;
198
        }
199
 
200
      case 5: /* cfcmpd */
201
        {
202
          double a, b;
203
          int n, z, c, v;
204
 
205
          a = mv_getRegDouble (SRC1_REG);
206
          b = mv_getRegDouble (SRC2_REG);
207
 
208
          printfdbg ("cfcmpd\n");
209
          printfdbg ("\tcomparing %g and %g\n", a, b);
210
 
211
          z = a == b;           /* zero */
212
          n = a < b;            /* negative */
213
          c = a > b;            /* carry */
214
          v = 0;         /* fixme */
215
          *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
216
          break;
217
        }
218
#endif
219
    default:
220
      fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
221
      cirrus_not_implemented ("unknown");
222
      break;
223
    }
224
 
225
  return ARMul_DONE;
226
}
227
 
228
unsigned
229
DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
230
         unsigned      type  ATTRIBUTE_UNUSED,
231
         ARMword       instr,
232
         ARMword *     value)
233
{
234
  switch (BITS (5, 7))
235
    {
236
    case 0: /* cfmvr64l */
237
      /* Move lower half of 64bit int from Cirrus to Arm.  */
238
      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
239
      printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
240
                 DEST_REG,
241
                 (int) *value);
242
      break;
243
 
244
    case 1: /* cfmvr64h */
245
      /* Move upper half of 64bit int from Cirrus to Arm.  */
246
      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
247
      printfdbg ("cfmvr64h <-- %d\n", (int) *value);
248
      break;
249
 
250
    case 4: /* cfcmp32 */
251
      {
252
        int res;
253
        int n, z, c, v;
254
        unsigned int a, b;
255
 
256
        printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
257
                   SRC1_REG,
258
                   SRC2_REG);
259
 
260
        /* FIXME: see comment for cfcmps.  */
261
        a = DSPregs[SRC1_REG].lower.i;
262
        b = DSPregs[SRC2_REG].lower.i;
263
 
264
        res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
265
        /* zero */
266
        z = res == 0;
267
        /* negative */
268
        n = res < 0;
269
        /* overflow */
270
        v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
271
                         res);
272
        /* carry */
273
        c = (NEG (a) && POS (b) ||
274
             (NEG (a) && POS (res)) || (POS (b) && POS (res)));
275
 
276
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
277
        break;
278
      }
279
 
280
    case 5: /* cfcmp64 */
281
      {
282
        long long res;
283
        int n, z, c, v;
284
        unsigned long long a, b;
285
 
286
        printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
287
                   SRC1_REG,
288
                   SRC2_REG);
289
 
290
        /* fixme: see comment for cfcmps.  */
291
 
292
        a = mv_getReg64int (SRC1_REG);
293
        b = mv_getReg64int (SRC2_REG);
294
 
295
        res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
296
        /* zero */
297
        z = res == 0;
298
        /* negative */
299
        n = res < 0;
300
        /* overflow */
301
        v = ((NEG64 (a) && POS64 (b) && POS64 (res))
302
             || (POS64 (a) && NEG64 (b) && NEG64 (res)));
303
        /* carry */
304
        c = (NEG64 (a) && POS64 (b) ||
305
             (NEG64 (a) && POS64 (res)) || (POS64 (b) && POS64 (res)));
306
 
307
        *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
308
        break;
309
      }
310
 
311
    default:
312
      fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
313
      cirrus_not_implemented ("unknown");
314
      break;
315
    }
316
 
317
  return ARMul_DONE;
318
}
319
 
320
unsigned
321
DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
322
         unsigned      type  ATTRIBUTE_UNUSED,
323
         ARMword       instr,
324
         ARMword *     value)
325
{
326
  switch (BITS (5, 7))
327
    {
328
    case 0: /* cfmval32 */
329
      cirrus_not_implemented ("cfmval32");
330
      break;
331
 
332
    case 1: /* cfmvam32 */
333
      cirrus_not_implemented ("cfmvam32");
334
      break;
335
 
336
    case 2: /* cfmvah32 */
337
      cirrus_not_implemented ("cfmvah32");
338
      break;
339
 
340
    case 3: /* cfmva32 */
341
      cirrus_not_implemented ("cfmva32");
342
      break;
343
 
344
    case 4: /* cfmva64 */
345
      cirrus_not_implemented ("cfmva64");
346
      break;
347
 
348
    case 5: /* cfmvsc32 */
349
      cirrus_not_implemented ("cfmvsc32");
350
      break;
351
 
352
    default:
353
      fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
354
      cirrus_not_implemented ("unknown");
355
      break;
356
    }
357
 
358
  return ARMul_DONE;
359
}
360
 
361
unsigned
362
DSPMCR4 (ARMul_State * state,
363
         unsigned      type ATTRIBUTE_UNUSED,
364
         ARMword       instr,
365
         ARMword       value)
366
{
367
  switch (BITS (5, 7))
368
    {
369
    case 0: /* cfmvdlr */
370
      /* Move the lower half of a DF value from an Arm register into
371
         the lower half of a Cirrus register.  */
372
      printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
373
      DSPregs[SRC1_REG].lower.i = (int) value;
374
      break;
375
 
376
    case 1: /* cfmvdhr */
377
      /* Move the upper half of a DF value from an Arm register into
378
         the upper half of a Cirrus register.  */
379
      printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
380
      DSPregs[SRC1_REG].upper.i = (int) value;
381
      break;
382
 
383
    case 2: /* cfmvsr */
384
      /* Move SF from Arm register into upper half of Cirrus register.  */
385
      printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
386
      DSPregs[SRC1_REG].upper.i = (int) value;
387
      break;
388
 
389
    default:
390
      fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
391
      cirrus_not_implemented ("unknown");
392
      break;
393
    }
394
 
395
  return ARMul_DONE;
396
}
397
 
398
unsigned
399
DSPMCR5 (ARMul_State * state,
400
         unsigned      type   ATTRIBUTE_UNUSED,
401
         ARMword       instr,
402
         ARMword       value)
403
{
404
  union
405
  {
406
    int s;
407
    unsigned int us;
408
  } val;
409
 
410
  switch (BITS (5, 7))
411
    {
412
    case 0: /* cfmv64lr */
413
      /* Move lower half of a 64bit int from an ARM register into the
414
         lower half of a DSP register and sign extend it.  */
415
      printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value);
416
      DSPregs[SRC1_REG].lower.i = (int) value;
417
      break;
418
 
419
    case 1: /* cfmv64hr */
420
      /* Move upper half of a 64bit int from an ARM register into the
421
         upper half of a DSP register.  */
422
      printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
423
                 SRC1_REG,
424
                 (int) value);
425
      DSPregs[SRC1_REG].upper.i = (int) value;
426
      break;
427
 
428
    case 2: /* cfrshl32 */
429
      printfdbg ("cfrshl32\n");
430
      val.us = value;
431
      if (val.s > 0)
432
        DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
433
      else
434
        DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
435
      break;
436
 
437
    case 3: /* cfrshl64 */
438
      printfdbg ("cfrshl64\n");
439
      val.us = value;
440
      if (val.s > 0)
441
        mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
442
      else
443
        mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
444
      break;
445
 
446
    default:
447
      fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
448
      cirrus_not_implemented ("unknown");
449
      break;
450
    }
451
 
452
  return ARMul_DONE;
453
}
454
 
455
unsigned
456
DSPMCR6 (ARMul_State * state,
457
         unsigned      type   ATTRIBUTE_UNUSED,
458
         ARMword       instr,
459
         ARMword       value)
460
{
461
  switch (BITS (5, 7))
462
    {
463
    case 0: /* cfmv32al */
464
      cirrus_not_implemented ("cfmv32al");
465
      break;
466
 
467
    case 1: /* cfmv32am */
468
      cirrus_not_implemented ("cfmv32am");
469
      break;
470
 
471
    case 2: /* cfmv32ah */
472
      cirrus_not_implemented ("cfmv32ah");
473
      break;
474
 
475
    case 3: /* cfmv32a */
476
      cirrus_not_implemented ("cfmv32a");
477
      break;
478
 
479
    case 4: /* cfmv64a */
480
      cirrus_not_implemented ("cfmv64a");
481
      break;
482
 
483
    case 5: /* cfmv32sc */
484
      cirrus_not_implemented ("cfmv32sc");
485
      break;
486
 
487
    default:
488
      fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
489
      cirrus_not_implemented ("unknown");
490
      break;
491
    }
492
 
493
  return ARMul_DONE;
494
}
495
 
496
unsigned
497
DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
498
         unsigned      type,
499
         ARMword       instr,
500
         ARMword       data)
501
{
502
  static unsigned words;
503
 
504
  if (type != ARMul_DATA)
505
    {
506
      words = 0;
507
      return ARMul_DONE;
508
    }
509
 
510
  if (BIT (22))
511
    {                           /* it's a long access, get two words */
512
      /* cfldrd */
513
 
514
      printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
515
                 data, words, state->bigendSig, DEST_REG);
516
 
517
      if (words == 0)
518
        {
519
          if (state->bigendSig)
520
            DSPregs[DEST_REG].upper.i = (int) data;
521
          else
522
            DSPregs[DEST_REG].lower.i = (int) data;
523
        }
524
      else
525
        {
526
          if (state->bigendSig)
527
            DSPregs[DEST_REG].lower.i = (int) data;
528
          else
529
            DSPregs[DEST_REG].upper.i = (int) data;
530
        }
531
 
532
      ++ words;
533
 
534
      if (words == 2)
535
        {
536
          printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
537
                     mv_getRegDouble (DEST_REG));
538
 
539
          return ARMul_DONE;
540
        }
541
      else
542
        return ARMul_INC;
543
    }
544
  else
545
    {
546
      /* Get just one word.  */
547
 
548
      /* cfldrs */
549
      printfdbg ("cfldrs\n");
550
 
551
      DSPregs[DEST_REG].upper.i = (int) data;
552
 
553
      printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
554
                 DSPregs[DEST_REG].upper.f);
555
 
556
      return ARMul_DONE;
557
    }
558
}
559
 
560
unsigned
561
DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
562
         unsigned      type,
563
         ARMword       instr,
564
         ARMword       data)
565
{
566
  static unsigned words;
567
 
568
  if (type != ARMul_DATA)
569
    {
570
      words = 0;
571
      return ARMul_DONE;
572
    }
573
 
574
  if (BIT (22))
575
    {
576
      /* It's a long access, get two words.  */
577
 
578
      /* cfldr64 */
579
      printfdbg ("cfldr64: %d\n", data);
580
 
581
      if (words == 0)
582
        {
583
          if (state->bigendSig)
584
            DSPregs[DEST_REG].upper.i = (int) data;
585
          else
586
            DSPregs[DEST_REG].lower.i = (int) data;
587
        }
588
      else
589
        {
590
          if (state->bigendSig)
591
            DSPregs[DEST_REG].lower.i = (int) data;
592
          else
593
            DSPregs[DEST_REG].upper.i = (int) data;
594
        }
595
 
596
      ++ words;
597
 
598
      if (words == 2)
599
        {
600
          printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
601
                     mv_getReg64int (DEST_REG));
602
 
603
          return ARMul_DONE;
604
        }
605
      else
606
        return ARMul_INC;
607
    }
608
  else
609
    {
610
      /* Get just one word.  */
611
 
612
      /* cfldr32 */
613
      printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
614
 
615
      /* 32bit ints should be sign extended to 64bits when loaded.  */
616
      mv_setReg64int (DEST_REG, (long long) data);
617
 
618
      return ARMul_DONE;
619
    }
620
}
621
 
622
unsigned
623
DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
624
         unsigned      type,
625
         ARMword       instr,
626
         ARMword *     data)
627
{
628
  static unsigned words;
629
 
630
  if (type != ARMul_DATA)
631
    {
632
      words = 0;
633
      return ARMul_DONE;
634
    }
635
 
636
  if (BIT (22))
637
    {
638
      /* It's a long access, get two words.  */
639
      /* cfstrd */
640
      printfdbg ("cfstrd\n");
641
 
642
      if (words == 0)
643
        {
644
          if (state->bigendSig)
645
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
646
          else
647
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
648
        }
649
      else
650
        {
651
          if (state->bigendSig)
652
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
653
          else
654
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
655
        }
656
 
657
      ++ words;
658
 
659
      if (words == 2)
660
        {
661
          printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
662
                     mv_getRegDouble (DEST_REG));
663
 
664
          return ARMul_DONE;
665
        }
666
      else
667
        return ARMul_INC;
668
    }
669
  else
670
    {
671
      /* Get just one word.  */
672
      /* cfstrs */
673
      printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
674
                 DSPregs[DEST_REG].upper.f);
675
 
676
      *data = (ARMword) DSPregs[DEST_REG].upper.i;
677
 
678
      return ARMul_DONE;
679
    }
680
}
681
 
682
unsigned
683
DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
684
         unsigned      type,
685
         ARMword       instr,
686
         ARMword *     data)
687
{
688
  static unsigned words;
689
 
690
  if (type != ARMul_DATA)
691
    {
692
      words = 0;
693
      return ARMul_DONE;
694
    }
695
 
696
  if (BIT (22))
697
    {
698
      /* It's a long access, store two words.  */
699
      /* cfstr64 */
700
      printfdbg ("cfstr64\n");
701
 
702
      if (words == 0)
703
        {
704
          if (state->bigendSig)
705
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
706
          else
707
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
708
        }
709
      else
710
        {
711
          if (state->bigendSig)
712
            *data = (ARMword) DSPregs[DEST_REG].lower.i;
713
          else
714
            *data = (ARMword) DSPregs[DEST_REG].upper.i;
715
        }
716
 
717
      ++ words;
718
 
719
      if (words == 2)
720
        {
721
          printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
722
                     mv_getReg64int (DEST_REG));
723
 
724
          return ARMul_DONE;
725
        }
726
      else
727
        return ARMul_INC;
728
    }
729
  else
730
    {
731
      /* Store just one word.  */
732
      /* cfstr32 */
733
      *data = (ARMword) DSPregs[DEST_REG].lower.i;
734
 
735
      printfdbg ("cfstr32 MEM = %d\n", (int) *data);
736
 
737
      return ARMul_DONE;
738
    }
739
}
740
 
741
unsigned
742
DSPCDP4 (ARMul_State * state,
743
         unsigned      type,
744
         ARMword       instr)
745
{
746
  int opcode2;
747
 
748
  opcode2 = BITS (5,7);
749
 
750
  switch (BITS (20,21))
751
    {
752
    case 0:
753
      switch (opcode2)
754
        {
755
        case 0: /* cfcpys */
756
          printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
757
                     DEST_REG,
758
                     SRC1_REG,
759
                     DSPregs[SRC1_REG].upper.f);
760
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
761
          break;
762
 
763
        case 1: /* cfcpyd */
764
          printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
765
                     DEST_REG,
766
                     SRC1_REG,
767
                     mv_getRegDouble (SRC1_REG));
768
          mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
769
          break;
770
 
771
        case 2: /* cfcvtds */
772
          printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
773
                     DEST_REG,
774
                     SRC1_REG,
775
                     (float) mv_getRegDouble (SRC1_REG));
776
          DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
777
          break;
778
 
779
        case 3: /* cfcvtsd */
780
          printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
781
                     DEST_REG,
782
                     SRC1_REG,
783
                     (double) DSPregs[SRC1_REG].upper.f);
784
          mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
785
          break;
786
 
787
        case 4: /* cfcvt32s */
788
          printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
789
                     DEST_REG,
790
                     SRC1_REG,
791
                     (float) DSPregs[SRC1_REG].lower.i);
792
          DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
793
          break;
794
 
795
        case 5: /* cfcvt32d */
796
          printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
797
                     DEST_REG,
798
                     SRC1_REG,
799
                     (double) DSPregs[SRC1_REG].lower.i);
800
          mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
801
          break;
802
 
803
        case 6: /* cfcvt64s */
804
          printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
805
                     DEST_REG,
806
                     SRC1_REG,
807
                     (float) mv_getReg64int (SRC1_REG));
808
          DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
809
          break;
810
 
811
        case 7: /* cfcvt64d */
812
          printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
813
                     DEST_REG,
814
                     SRC1_REG,
815
                     (double) mv_getReg64int (SRC1_REG));
816
          mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
817
          break;
818
        }
819
      break;
820
 
821
    case 1:
822
      switch (opcode2)
823
        {
824
        case 0: /* cfmuls */
825
          printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
826
                     DEST_REG,
827
                     SRC1_REG,
828
                     DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
829
 
830
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
831
            * DSPregs[SRC2_REG].upper.f;
832
          break;
833
 
834
        case 1: /* cfmuld */
835
          printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
836
                     DEST_REG,
837
                     SRC1_REG,
838
                     mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
839
 
840
          mv_setRegDouble (DEST_REG,
841
                           mv_getRegDouble (SRC1_REG)
842
                           * mv_getRegDouble (SRC2_REG));
843
          break;
844
 
845
        default:
846
          fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
847
          cirrus_not_implemented ("unknown");
848
          break;
849
        }
850
      break;
851
 
852
    case 3:
853
      switch (opcode2)
854
        {
855
        case 0: /* cfabss */
856
          DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ?
857
                                       -DSPregs[SRC1_REG].upper.f
858
                                       : DSPregs[SRC1_REG].upper.f);
859
          printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
860
                     DEST_REG,
861
                     SRC1_REG,
862
                     DSPregs[DEST_REG].upper.f);
863
          break;
864
 
865
        case 1: /* cfabsd */
866
          mv_setRegDouble (DEST_REG,
867
                           (mv_getRegDouble (SRC1_REG) < 0.0 ?
868
                            -mv_getRegDouble (SRC1_REG)
869
                            : mv_getRegDouble (SRC1_REG)));
870
          printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
871
                     DEST_REG,
872
                     SRC1_REG,
873
                     mv_getRegDouble (DEST_REG));
874
          break;
875
 
876
        case 2: /* cfnegs */
877
          DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
878
          printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
879
                     DEST_REG,
880
                     SRC1_REG,
881
                     DSPregs[DEST_REG].upper.f);
882
          break;
883
 
884
        case 3: /* cfnegd */
885
          mv_setRegDouble (DEST_REG,
886
                           -mv_getRegDouble (SRC1_REG));
887
          printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
888
                     DEST_REG,
889
                     mv_getRegDouble (DEST_REG));
890
          break;
891
 
892
        case 4: /* cfadds */
893
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
894
            + DSPregs[SRC2_REG].upper.f;
895
          printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
896
                     DEST_REG,
897
                     SRC1_REG,
898
                     SRC2_REG,
899
                     DSPregs[DEST_REG].upper.f);
900
          break;
901
 
902
        case 5: /* cfaddd */
903
          mv_setRegDouble (DEST_REG,
904
                           mv_getRegDouble (SRC1_REG)
905
                           + mv_getRegDouble (SRC2_REG));
906
          printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
907
                     DEST_REG,
908
                     SRC1_REG,
909
                     SRC2_REG,
910
                     mv_getRegDouble (DEST_REG));
911
          break;
912
 
913
        case 6: /* cfsubs */
914
          DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
915
            - DSPregs[SRC2_REG].upper.f;
916
          printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
917
                     DEST_REG,
918
                     SRC1_REG,
919
                     SRC2_REG,
920
                     DSPregs[DEST_REG].upper.f);
921
          break;
922
 
923
        case 7: /* cfsubd */
924
          mv_setRegDouble (DEST_REG,
925
                           mv_getRegDouble (SRC1_REG)
926
                           - mv_getRegDouble (SRC2_REG));
927
          printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
928
                     DEST_REG,
929
                     SRC1_REG,
930
                     SRC2_REG,
931
                     mv_getRegDouble (DEST_REG));
932
          break;
933
        }
934
      break;
935
 
936
    default:
937
      fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
938
      cirrus_not_implemented ("unknown");
939
      break;
940
    }
941
 
942
  return ARMul_DONE;
943
}
944
 
945
unsigned
946
DSPCDP5 (ARMul_State * state,
947
         unsigned      type,
948
         ARMword       instr)
949
{
950
   int opcode2;
951
   char shift;
952
 
953
   opcode2 = BITS (5,7);
954
 
955
   /* Shift constants are 7bit signed numbers in bits 0..3|5..7.  */
956
   shift = BITS (0, 3) | (BITS (5, 7)) << 4;
957
   if (shift & 0x40)
958
     shift |= 0xc0;
959
 
960
   switch (BITS (20,21))
961
     {
962
     case 0:
963
       /* cfsh32 */
964
       printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
965
                  shift);
966
       if (shift < 0)
967
         /* Negative shift is a right shift.  */
968
         DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
969
       else
970
         /* Positive shift is a left shift.  */
971
         DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
972
       break;
973
 
974
     case 1:
975
       switch (opcode2)
976
         {
977
         case 0: /* cfmul32 */
978
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
979
             * DSPregs[SRC2_REG].lower.i;
980
           printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
981
                      DEST_REG,
982
                      SRC1_REG,
983
                      SRC2_REG,
984
                      DSPregs[DEST_REG].lower.i);
985
           break;
986
 
987
         case 1: /* cfmul64 */
988
           mv_setReg64int (DEST_REG,
989
                           mv_getReg64int (SRC1_REG)
990
                           * mv_getReg64int (SRC2_REG));
991
           printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
992
                      DEST_REG,
993
                      SRC1_REG,
994
                      SRC2_REG,
995
                      mv_getReg64int (DEST_REG));
996
           break;
997
 
998
         case 2: /* cfmac32 */
999
           DSPregs[DEST_REG].lower.i
1000
             += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
1001
           printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
1002
                      DEST_REG,
1003
                      SRC1_REG,
1004
                      SRC2_REG,
1005
                      DSPregs[DEST_REG].lower.i);
1006
           break;
1007
 
1008
         case 3: /* cfmsc32 */
1009
           DSPregs[DEST_REG].lower.i
1010
             -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
1011
           printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
1012
                      DEST_REG,
1013
                      SRC1_REG,
1014
                      SRC2_REG,
1015
                      DSPregs[DEST_REG].lower.i);
1016
           break;
1017
 
1018
         case 4: /* cfcvts32 */
1019
           /* fixme: this should round */
1020
           DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
1021
           printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
1022
                      DEST_REG,
1023
                      SRC1_REG,
1024
                      DSPregs[DEST_REG].lower.i);
1025
           break;
1026
 
1027
         case 5: /* cfcvtd32 */
1028
           /* fixme: this should round */
1029
           DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
1030
           printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
1031
                      DEST_REG,
1032
                      SRC1_REG,
1033
                      DSPregs[DEST_REG].lower.i);
1034
           break;
1035
 
1036
         case 6: /* cftruncs32 */
1037
           DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
1038
           printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
1039
                      DEST_REG,
1040
                      SRC1_REG,
1041
                      DSPregs[DEST_REG].lower.i);
1042
           break;
1043
 
1044
         case 7: /* cftruncd32 */
1045
           DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
1046
           printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
1047
                      DEST_REG,
1048
                      SRC1_REG,
1049
                      DSPregs[DEST_REG].lower.i);
1050
           break;
1051
         }
1052
       break;
1053
 
1054
     case 2:
1055
       /* cfsh64 */
1056
       printfdbg ("cfsh64\n");
1057
 
1058
       if (shift < 0)
1059
         /* Negative shift is a right shift.  */
1060
         mv_setReg64int (DEST_REG,
1061
                         mv_getReg64int (SRC1_REG) >> -shift);
1062
       else
1063
         /* Positive shift is a left shift.  */
1064
         mv_setReg64int (DEST_REG,
1065
                         mv_getReg64int (SRC1_REG) << shift);
1066
       printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG));
1067
       break;
1068
 
1069
     case 3:
1070
       switch (opcode2)
1071
         {
1072
         case 0: /* cfabs32 */
1073
           DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0
1074
             ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i);
1075
           printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
1076
                      DEST_REG,
1077
                      SRC1_REG,
1078
                      SRC2_REG,
1079
                      DSPregs[DEST_REG].lower.i);
1080
           break;
1081
 
1082
         case 1: /* cfabs64 */
1083
           mv_setReg64int (DEST_REG,
1084
                           (mv_getReg64int (SRC1_REG) < 0
1085
                            ? -mv_getReg64int (SRC1_REG)
1086
                            : mv_getReg64int (SRC1_REG)));
1087
           printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
1088
                      DEST_REG,
1089
                      SRC1_REG,
1090
                      SRC2_REG,
1091
                      mv_getReg64int (DEST_REG));
1092
           break;
1093
 
1094
         case 2: /* cfneg32 */
1095
           DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
1096
           printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
1097
                      DEST_REG,
1098
                      SRC1_REG,
1099
                      SRC2_REG,
1100
                      DSPregs[DEST_REG].lower.i);
1101
           break;
1102
 
1103
         case 3: /* cfneg64 */
1104
           mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
1105
           printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
1106
                      DEST_REG,
1107
                      SRC1_REG,
1108
                      SRC2_REG,
1109
                      mv_getReg64int (DEST_REG));
1110
           break;
1111
 
1112
         case 4: /* cfadd32 */
1113
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1114
             + DSPregs[SRC2_REG].lower.i;
1115
           printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
1116
                      DEST_REG,
1117
                      SRC1_REG,
1118
                      SRC2_REG,
1119
                      DSPregs[DEST_REG].lower.i);
1120
           break;
1121
 
1122
         case 5: /* cfadd64 */
1123
           mv_setReg64int (DEST_REG,
1124
                           mv_getReg64int (SRC1_REG)
1125
                           + mv_getReg64int (SRC2_REG));
1126
           printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
1127
                      DEST_REG,
1128
                      SRC1_REG,
1129
                      SRC2_REG,
1130
                      mv_getReg64int (DEST_REG));
1131
           break;
1132
 
1133
         case 6: /* cfsub32 */
1134
           DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
1135
             - DSPregs[SRC2_REG].lower.i;
1136
           printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
1137
                      DEST_REG,
1138
                      SRC1_REG,
1139
                      SRC2_REG,
1140
                      DSPregs[DEST_REG].lower.i);
1141
           break;
1142
 
1143
         case 7: /* cfsub64 */
1144
           mv_setReg64int (DEST_REG,
1145
                           mv_getReg64int (SRC1_REG)
1146
                           - mv_getReg64int (SRC2_REG));
1147
           printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
1148
                      DEST_REG,
1149
                      SRC1_REG,
1150
                      SRC2_REG,
1151
                      mv_getReg64int (DEST_REG));
1152
           break;
1153
         }
1154
       break;
1155
 
1156
     default:
1157
       fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
1158
       cirrus_not_implemented ("unknown");
1159
       break;
1160
     }
1161
 
1162
  return ARMul_DONE;
1163
}
1164
 
1165
unsigned
1166
DSPCDP6 (ARMul_State * state,
1167
         unsigned      type,
1168
         ARMword       instr)
1169
{
1170
   int opcode2;
1171
 
1172
   opcode2 = BITS (5,7);
1173
 
1174
   switch (BITS (20,21))
1175
     {
1176
     case 0:
1177
       /* cfmadd32 */
1178
       cirrus_not_implemented ("cfmadd32");
1179
       break;
1180
 
1181
     case 1:
1182
       /* cfmsub32 */
1183
       cirrus_not_implemented ("cfmsub32");
1184
       break;
1185
 
1186
     case 2:
1187
       /* cfmadda32 */
1188
       cirrus_not_implemented ("cfmadda32");
1189
       break;
1190
 
1191
     case 3:
1192
       /* cfmsuba32 */
1193
       cirrus_not_implemented ("cfmsuba32");
1194
       break;
1195
 
1196
     default:
1197
       fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
1198
     }
1199
 
1200
   return ARMul_DONE;
1201
}
1202
 
1203
/* Conversion functions.
1204
 
1205
   32-bit integers are stored in the LOWER half of a 64-bit physical
1206
   register.
1207
 
1208
   Single precision floats are stored in the UPPER half of a 64-bit
1209
   physical register.  */
1210
 
1211
static double
1212
mv_getRegDouble (int regnum)
1213
{
1214
  reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
1215
  reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
1216
  return reg_conv.d;
1217
}
1218
 
1219
static void
1220
mv_setRegDouble (int regnum, double val)
1221
{
1222
  reg_conv.d = val;
1223
  DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
1224
  DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
1225
}
1226
 
1227
static long long
1228
mv_getReg64int (int regnum)
1229
{
1230
  reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
1231
  reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
1232
  return reg_conv.ll;
1233
}
1234
 
1235
static void
1236
mv_setReg64int (int regnum, long long val)
1237
{
1238
  reg_conv.ll = val;
1239
  DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
1240
  DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
1241
}
1242
 
1243
/* Compute LSW in a double and a long long.  */
1244
 
1245
void
1246
mv_compute_host_endianness (ARMul_State * state)
1247
{
1248
  static union
1249
  {
1250
    long long ll;
1251
    long ints[2];
1252
    long i;
1253
    double d;
1254
    float floats[2];
1255
    float f;
1256
  } conv;
1257
 
1258
  /* Calculate where's the LSW in a 64bit int.  */
1259
  conv.ll = 45;
1260
 
1261
  if (conv.ints[0] == 0)
1262
    {
1263
      msw_int_index = 0;
1264
      lsw_int_index = 1;
1265
    }
1266
  else
1267
    {
1268
      assert (conv.ints[1] == 0);
1269
      msw_int_index = 1;
1270
      lsw_int_index = 0;
1271
    }
1272
 
1273
  /* Calculate where's the LSW in a double.  */
1274
  conv.d = 3.0;
1275
 
1276
  if (conv.ints[0] == 0)
1277
    {
1278
      msw_float_index = 0;
1279
      lsw_float_index = 1;
1280
    }
1281
  else
1282
    {
1283
      assert (conv.ints[1] == 0);
1284
      msw_float_index = 1;
1285
      lsw_float_index = 0;
1286
    }
1287
 
1288
  printfdbg ("lsw_int_index   %d\n", lsw_int_index);
1289
  printfdbg ("lsw_float_index %d\n", lsw_float_index);
1290
}

powered by: WebSVN 2.1.0

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