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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code-or1k/] [support/] [support.c] - Blame information for rev 588

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

Line No. Rev Author Line
1 90 jeremybenn
/* support.c -- Support code for Or1ksim testing.
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2008, 2010 Embecosm Limited
5
 
6
   Contributor Damjan Lampret <lampret@opencores.org>
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
23
 
24
/* ----------------------------------------------------------------------------
25
   This code is commented throughout for use with Doxygen.
26
   --------------------------------------------------------------------------*/
27
 
28
/* Support */
29
 
30
#include "spr-defs.h"
31
#include "support.h"
32
#include "int.h"
33
 
34
 
35
/* Forward declarations of interrupt handlers */
36
static void excpt_dummy();
37
extern void int_main();
38
 
39
/* Exception handlers. All are dummy except the interrupt handler */
40
unsigned long excpt_buserr   = (unsigned long) excpt_dummy;
41
unsigned long excpt_dpfault  = (unsigned long) excpt_dummy;
42
unsigned long excpt_ipfault  = (unsigned long) excpt_dummy;
43
unsigned long excpt_tick     = (unsigned long) excpt_dummy;
44
unsigned long excpt_align    = (unsigned long) excpt_dummy;
45
unsigned long excpt_illinsn  = (unsigned long) excpt_dummy;
46
unsigned long excpt_int      = (unsigned long) int_main;
47
unsigned long excpt_dtlbmiss = (unsigned long) excpt_dummy;
48
unsigned long excpt_itlbmiss = (unsigned long) excpt_dummy;
49
unsigned long excpt_range    = (unsigned long) excpt_dummy;
50
unsigned long excpt_syscall  = (unsigned long) excpt_dummy;
51
unsigned long excpt_break    = (unsigned long) excpt_dummy;
52
unsigned long excpt_trap     = (unsigned long) excpt_dummy;
53
 
54
 
55
/* --------------------------------------------------------------------------*/
56
/*!Is a character a decimal digit?
57
 
58
   @param[in] c  The character to test
59
 
60
   @return  1 (TRUE) if the character is a decimal digit, 0 (FALSE)
61
            otherwise                                                        */
62
/* --------------------------------------------------------------------------*/
63
static int
64
is_digit (char  c)
65
{
66
  return ('0' <= c) && (c <= '9');
67
 
68
}       /* is_digit () */
69
 
70
 
71
/* --------------------------------------------------------------------------*/
72
/*!Print a char in a width
73
 
74
   The char is always right justified.
75
 
76
   @param[in] c      The character to print
77
   @param[in] width  The width to print in
78
 
79
   @return  The number of characters actually printed (always width)         */
80
/* --------------------------------------------------------------------------*/
81
static int
82
printf_char (char  c,
83
             int   width)
84
{
85
  int  i;
86
 
87
  /* Spacing */
88
  for (i = 1; i < width; i++)
89
    {
90
      putchar (' ');
91
    }
92
 
93
  /* The char */
94
  putchar (c);
95
 
96
  return  width;
97
 
98
}       /* printf_char () */
99
 
100
 
101
/* --------------------------------------------------------------------------*/
102
/*!Convert a digit to a char
103
 
104
   We don't worry about the base. If the value supplied is over 10, we assume
105
   its a letter.
106
 
107
   @param[in] d  The digit to convert.
108
 
109
   @return  The character representation.                                    */
110
/* --------------------------------------------------------------------------*/
111
static char
112
dig2char (int  d)
113
{
114
  return (d < 10) ? '0' + d : 'a' + d - 10;
115
 
116
}       /* dit2char () */
117
 
118
 
119
/* --------------------------------------------------------------------------*/
120
/*!Print a number to a base to a string
121
 
122
   The number is unsigned, left justified and null terminated
123
 
124
   @param[in] uval  The value to print
125
   @param[in] buf   The buffer to print in
126
   @param[in] base  The base to use.
127
 
128
   @return  the length of the string created.                                */
129
/* --------------------------------------------------------------------------*/
130
static int
131 93 jeremybenn
print_base (long unsigned int  uval,
132
            char               buf[],
133
            unsigned int       base)
134 90 jeremybenn
{
135
  /* Initially print backwards. Always have at least a zero. */
136
  int  i = 0;
137
 
138
  do
139
    {
140
      buf[i] = dig2char (uval % base);
141
      uval = uval / base;
142
      i++;
143
    }
144
  while (0 != uval);
145
 
146
  buf[i] = 0;                    /* End of string */
147
 
148
  int  len = i;                 /* Length of the string */
149
 
150
  /* Reverse the string */
151
  for (i = 0; i < (len / 2); i++)
152
    {
153
      char  c          = buf[i];
154
      buf[i]           = buf[len - i - 1];
155
      buf[len - i - 1] = c;
156
    }
157
 
158
  return  len;
159
 
160
}       /* print_base () */
161
 
162
 
163
/* --------------------------------------------------------------------------*/
164
/*!Print a character multiple times
165
 
166
   @param[in] c    The char to print
167
   @param[in] num  Number of times to print                                 */
168
/* --------------------------------------------------------------------------*/
169
static void
170
print_multichar (char  c,
171
                 int   num)
172
{
173
  for (; num > 0; num--)
174
    {
175
      putchar (c);
176
    }
177
}       /* print_multichar () */
178
 
179
 
180
/* --------------------------------------------------------------------------*/
181
/*!Print a string
182
 
183
   @param[in] str  The string to print                                       */
184
/* --------------------------------------------------------------------------*/
185
static void
186
print_str (char  str [])
187
{
188
  int  i;
189
 
190
  for (i = 0; 0 != str[i]; i++)
191
    {
192
      putchar (str[i]);
193
    }
194
}       /* print_str () */
195
 
196
 
197
/* --------------------------------------------------------------------------*/
198
/*!Return the length of a string
199
 
200
   @param[in] str    The string whose length is wanted
201
 
202
   @return  The length of the string                                         */
203
/* --------------------------------------------------------------------------*/
204
static int
205
strlen (char  str [])
206
{
207
  int  i;
208
 
209
  for (i = 0; str[i] != 0; i++)
210
    {
211
    }
212
 
213
  return  i;
214
 
215
}       /* strlen () */
216
 
217
 
218
/* --------------------------------------------------------------------------*/
219
/*!Print a string in a width
220
 
221
   @param[in] str    The string to print
222
   @param[in] width  The width to print it in (at least)
223
 
224
   @return  The number of chars printed                                      */
225
/* --------------------------------------------------------------------------*/
226
static int
227
printf_str (char  str [],
228
            int   width)
229
{
230
  int len = strlen (str);
231
 
232
  if (width > len)
233
    {
234
      print_multichar (' ', width - len);
235
    }
236
 
237
  print_str (str);
238
 
239
  return  (width > len) ? width : len;
240
 
241
}       /* printf_str () */
242
 
243
 
244
/* --------------------------------------------------------------------------*/
245
/*!Print a decimal in a width
246
 
247
   The number is always right justified and signed.
248
 
249
   @param[in] val              The value to print
250
   @param[in] width            The width to print in (at least)
251
   @param[in] leading_zeros_p  1 (TRUE) if we should print leading zeros,
252
 
253
 
254
   @return  The number of chars printed                                      */
255
/* --------------------------------------------------------------------------*/
256
static int
257
printf_decimal (long int  val,
258
                int       width,
259
                int       leading_zeros_p)
260
{
261
  int  is_signed_p = 0;
262
 
263
  /* Note if we need a sign */
264
  if (val < 0)
265
    {
266
      val         = -val;
267
      is_signed_p = 1;
268
    }
269
 
270
  /* Array to store the number in. We know the max for 32 bits is 10
271
     digits. Allow for end of string marker */
272
  char  num_array[11];
273
 
274 93 jeremybenn
  int  num_width = print_base ((unsigned long int) val, num_array, 10);
275 90 jeremybenn
 
276
  /* Now print out the number. */
277
  num_width += is_signed_p ? 1 : 0;
278
 
279
  if (num_width < width)
280
    {
281
      if (leading_zeros_p)
282
        {
283
          if (is_signed_p)
284
            {
285
              putchar ('-');
286
            }
287
 
288
          print_multichar ('0', width - num_width);
289
        }
290
      else
291
        {
292
          print_multichar (' ', width - num_width);
293
 
294
          if (is_signed_p)
295
            {
296
              putchar ('-');
297
            }
298
        }
299
    }
300
  else
301
    {
302
      if (is_signed_p)
303
        {
304
          putchar ('-');
305
        }
306
    }
307
 
308
  print_str (num_array);
309
 
310
  return  width > num_width ? width : num_width;
311
 
312
}       /* printf_decimal () */
313
 
314
 
315
/* --------------------------------------------------------------------------*/
316
/*!Print a unsigned to a base in a width
317
 
318
   The number is always right justified and unsigned.
319
 
320
   @param[in] val              The value to print
321
   @param[in] width            The width to print in (at least)
322
   @param[in] leading_zeros_p  1 (TRUE) if we should print leading zeros,
323
 
324
   @param[in] base             Base to use when printing
325
 
326
   @return  The number of chars printed                                      */
327
/* --------------------------------------------------------------------------*/
328
static int
329 93 jeremybenn
printf_unsigned_base (unsigned long int  val,
330
                      int                width,
331
                      int                leading_zeros_p,
332
                      unsigned int       base)
333 90 jeremybenn
{
334
  int  is_signed_p = 0;
335
 
336
  /* Note if we need a sign */
337
  if (val < 0)
338
    {
339
      val         = -val;
340
      is_signed_p = 1;
341
    }
342
 
343
  /* Array to store the number in. We know the max for 32 bits of octal is 11
344
     digits. Allow for end of string marker */
345
  char  num_array[12];
346
 
347
  int  num_width = print_base (val, num_array, base);
348
 
349
  /* Now print out the number. */
350
  num_width += is_signed_p ? 1 : 0;
351
 
352
  if (num_width < width)
353
    {
354
      print_multichar (leading_zeros_p ? '0' : ' ', width - num_width);
355
    }
356
 
357
  print_str (num_array);
358
 
359
  return  width > num_width ? width : num_width;
360
 
361
}       /* printf_unsigned_base () */
362
 
363
 
364
/* --------------------------------------------------------------------------*/
365
/*!Dummy exception handler
366
 
367
   Used for most exceptions as the default hander which does nothing.        */
368
/* --------------------------------------------------------------------------*/
369
static void
370
excpt_dummy()
371
{
372
}       /* excpt_dummy ()*/
373
 
374
 
375
/*! Function to be called at entry point - not defined here. */
376
extern int main  ();
377
 
378
/* --------------------------------------------------------------------------*/
379
/*!Start function
380
 
381
   Called by reset exception handler.                                        */
382
/* --------------------------------------------------------------------------*/
383
void
384
reset ()
385
{
386
  exit (main ());
387
 
388
}       /* reset () */
389
 
390
/* --------------------------------------------------------------------------*/
391
/*!Exit function
392
 
393
   Return value by making a syscall
394
 
395
   @param[in] rc  Return code                                                */
396
/* --------------------------------------------------------------------------*/
397
void
398
exit (int rc)
399
{
400
  __asm__ __volatile__ ("l.add r3,r0,%0\n\t"
401
                        "l.nop %1": : "r" (rc), "K" (NOP_EXIT));
402
 
403
  /* Header declares function as __noreturn, so ensure that is so. */
404
  while (1)
405
    {
406
    }
407
}       /* exit () */
408
 
409
 
410
/* --------------------------------------------------------------------------*/
411
/*!Activate printing a character in the simulator
412
 
413
   @param[in] c  The character to print
414
 
415
   @return  The char printed cast to an int                                  */
416
/* --------------------------------------------------------------------------*/
417
int
418
putchar (int  c)
419
{
420
  __asm__ __volatile__ ("l.addi\tr3,%0,0\n\t"
421
                        "l.nop %1": : "r" (c), "K" (NOP_PUTC));
422
 
423
  return  c;
424
 
425
}       /* putchar () */
426
 
427
 
428
/* --------------------------------------------------------------------------*/
429
/*!Print a string
430
 
431
   We need to define this, since the compiler will replace calls to printf
432
   using just constant strings with trailing newlines with calls to puts
433
   without the newline.
434
 
435
   @param[in] str  The string to print (without a newline)
436
 
437
   @return  The char printed cast to an int                                  */
438
/* --------------------------------------------------------------------------*/
439
int
440
puts (const char *str)
441
{
442
  return  printf ("%s\n", str);
443
 
444
}       /* puts () */
445
 
446
 
447
/* --------------------------------------------------------------------------*/
448
/*!Activate printf support in simulator
449
 
450
   @note This doesn't actually work, so we implement the basics of printf by
451
         steam, calling useful subsidiary functions based on putchar (), which
452
         does work.
453
 
454
   @param[in] fmt  The format string
455
   @param[in] ...  The variable arguments if any
456
 
457
   @return  The number of characters printed                                 */
458
/* --------------------------------------------------------------------------*/
459
int
460
printf(const char *fmt,
461
          ...)
462
{
463
  int  num_chars = 0;                    /* How many chars printed */
464
 
465
  va_list args;
466
  va_start (args, fmt);
467
 
468
  int  i;                               /* Index into the string */
469
 
470
  for (i = 0; fmt[i] != 0; i++)
471
    {
472
      if ('%' == fmt[i])
473
        {
474
          int  width;
475
          int  leading_zeros_p;
476
 
477
          /* Decode the field */
478
          i++;
479
 
480 458 julius
          /* Ignore periods */
481
          if ('.' == fmt[i])
482
                  i++;
483
 
484 90 jeremybenn
          /* Are leading zeros requested? */
485
          if ('0' == fmt[i])
486
            {
487
              leading_zeros_p = 1;
488
              i++;
489
            }
490
          else
491
            {
492
              leading_zeros_p = 0;
493
            }
494
 
495
          /* Is there a width specification? */
496
          width = 0;
497
 
498
          while (is_digit (fmt[i]))
499
            {
500
              width = width * 10 + fmt[i] - '0';
501
              i++;
502
            }
503
 
504
          /* We just ignore any "l" specification. We do everything as
505
             32-bit. */
506
          i += ('l' == fmt[i]) ? 1 : 0;
507
 
508
          /* Deal with each field according to the type indicactor */
509
          char              ch;
510
          char             *str;
511
          long int          val;
512
          unsigned long int uval;
513
 
514
          /* There is a bug in GCC for OR1K, which can't handle two many
515
             cases. For now we split this into two disjoint case statements. */
516
          switch (fmt[i])
517
            {
518
            case 'c':
519
              ch = va_arg (args, int);
520
              num_chars += printf_char (ch, width);
521
              break;
522
 
523
            case 'o':
524
              uval = va_arg (args, unsigned long int);
525
              num_chars +=printf_unsigned_base (uval, width, leading_zeros_p,
526
                                               8);
527
              break;
528
 
529
            case 's':
530
              str = va_arg (args, char *);
531
              num_chars += printf_str (str, width);
532
              break;
533
 
534
            case 'x':
535
              uval = va_arg (args, unsigned long int);
536
              num_chars += printf_unsigned_base (uval, width, leading_zeros_p,
537
                                                16);
538
              break;
539
 
540
            default:
541
              /* Default is to do nothing silently */
542
              break;
543
            }
544
 
545
          switch (fmt[i])
546
            {
547
            case'd': case 'i':
548
              val = va_arg (args, long int);
549
              num_chars += printf_decimal (val, width, leading_zeros_p);
550
              break;
551
            }
552
        }
553
      else
554
        {
555
          putchar (fmt[i]);
556
          num_chars++;
557
        }
558
    }
559
 
560
  va_end (args);
561
 
562
  return  num_chars;
563
 
564
}       /* printf () */
565
 
566
 
567
/* --------------------------------------------------------------------------*/
568
/*!Report a 32-bit value
569
 
570
   Uses the built-in simulator functionality.
571
 
572
   @param[in] value  Value to report.                                        */
573
/* --------------------------------------------------------------------------*/
574
void
575
report (unsigned long int  value)
576
{
577
  __asm__ __volatile__ ("l.addi\tr3,%0,0\n\t"
578
                        "l.nop %1": : "r" (value), "K" (NOP_REPORT));
579
 
580
}       /* report () */
581
 
582
 
583
/* --------------------------------------------------------------------------*/
584
/*!Mutliply two 32-bit values to give a 64-bit result
585
 
586
   This is not supported by the OR1K GCC.
587
 
588
   Use the identity
589
 
590
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
591
 
592
   x = 2^16. None of this should overflow.
593
 
594
   @param[in] op1  First operand
595
   @param[in] op2  Second operand
596
 
597
   @return  The result                                                       */
598
/* --------------------------------------------------------------------------*/
599
static unsigned long long int
600
l_mulu (unsigned long int  op1,
601
        unsigned long int  op2)
602
{
603
  unsigned long int a, b, c, d;
604
 
605
  a = op1 >> 16;
606
  b = op1 & 0xffff;
607
  c = op2 >> 16;
608
  d = op2 & 0xffff;
609
 
610
  /* Add in the terms */
611
  unsigned long long int  res;
612
 
613
  /* printf ("a = 0x%08lx, b = 0x%08lx, c = 0x%08lx, d = 0x%08lx\n", a, b, c, d); */
614
  res  =  (unsigned long long int) (a * c) << 32;
615
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
616
  /*      (unsigned long int) res); */
617
  res += ((unsigned long long int) (a * d) << 16);
618
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
619
  /*      (unsigned long int) res); */
620
  res += ((unsigned long long int) (b * c) << 16);
621
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
622
  /*      (unsigned long int) res); */
623
  res +=  (unsigned long long int) (b * d);
624
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
625
  /*      (unsigned long int) res); */
626
 
627
  /* printf ("0x%08lx * 0x%08lx = 0x%08lx%08lx\n", op1, op2, */
628
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
629
 
630
  return  res;
631
 
632
}       /* l_mulu () */
633
 
634
 
635
/* --------------------------------------------------------------------------*/
636
/*!Mutliply two 64-bit values
637
 
638
   This is not supported by the OR1K GCC.
639
 
640
   Use the identity
641
 
642
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
643
 
644
   x = 2^32. We can discard the first term (overflow), though since this is
645
   for testing we'll print a message.
646
 
647
   The second term may overflow, so we compute the coefficient to 64-bit to
648
   see if we have overflowed.
649
 
650
   The final term may overflow, so we also compute this to 64-bit, so we can
651
   add the top 64-bits in.
652
 
653
   @param[in] op1  First operand
654
   @param[in] op2  Second operand
655
 
656
   @return  The result                                                       */
657
/* --------------------------------------------------------------------------*/
658
static unsigned long long int
659
ll_mulu (unsigned long long int  op1,
660
         unsigned long long int  op2)
661
{
662
  unsigned long int       a, b, c, d;
663
  unsigned long long int  tmp, res;
664
 
665
  a = op1 >> 32;
666
  b = op1 & 0xffffffff;
667
  c = op2 >> 32;
668
  d = op2 & 0xffffffff;
669
 
670
  if ((a > 0) && (c > 0))
671
    {
672
      printf ("ll_mulu overflows\n");
673
    }
674
 
675
  /* Compute and test the second term */
676
  tmp = l_mulu (a, d);
677
 
678
  if (tmp >= 0x100000000ULL)
679
    {
680
      printf ("ll_mulu overflows\n");
681
    }
682
 
683
  res = tmp << 32;
684
 
685
  tmp = l_mulu (b, c);
686
 
687
  if (tmp >= 0x100000000ULL)
688
    {
689
      printf ("ll_mulu overflows\n");
690
    }
691
 
692
  res += tmp << 32;
693
 
694
  /* Compute the third term. Although the term can't overflow, it could
695
     overflow the result. So just check our answer is larger when the final
696
     term is added in. */
697
  tmp = res;
698
 
699
  res += l_mulu (b, d);
700
 
701
  if (res < tmp)
702
    {
703
      printf ("ll_mulu overflows\n");
704
    }
705
 
706
  /* printf ("0x%08lx%08lx * 0x%08lx%08lx = 0x%08lx%08lx\n", a, b, c, d, */
707
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
708
 
709
  return  res;
710
 
711
}       /* ll_mulu () */
712
 
713
/* --------------------------------------------------------------------------*/
714
/*!Divide a 64-bit value by a 32 bit value
715
 
716
   Until I can get hold of a copy of Knuth volume 2 to check the algorithm,
717
   this is a bitwise version.
718
 
719
   @param[in] op1  First operand
720
   @param[in] op2  Second operand
721
 
722
   @return  The result                                                       */
723
/* --------------------------------------------------------------------------*/
724
static unsigned long long int
725
ll_divu (unsigned long long int  dividend,
726
         unsigned long int       divisor)
727
{
728
  unsigned long long int  t, num_bits;
729
  unsigned long long int  q, bit, d;
730
  int            i;
731
 
732
  if (divisor == 0)
733
    {
734
      printf ("ERROR: Invalid division by zero\n");
735
      return  0;
736
    }
737
 
738
  if (divisor > dividend)
739
    {
740
      return  0;
741
    }
742
 
743
  if (divisor == dividend)
744
    {
745
      return  1ULL;
746
    }
747
 
748
  /* printf ("0x%08x%08x / 0x%08x = ", (unsigned int) (dividend >> 32), */
749
  /*      (unsigned int) (dividend & 0xffffffff), (unsigned int) divisor); */
750
 
751
  num_bits = 64;
752
 
753
  unsigned long long int  remainder = 0;
754
  unsigned long long int  quotient  = 0;
755
 
756
  while (remainder < divisor)
757
    {
758
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
759
      remainder = (remainder << 1) | bit;
760
      d              = dividend;
761
      dividend       = dividend << 1;
762
      num_bits--;
763
    }
764
 
765
  /* The loop, above, always goes one iteration too far.  To avoid inserting
766
     an "if" statement inside the loop the last iteration is simply
767
     reversed. */
768
  dividend  = d;
769
  remainder = remainder >> 1;
770
  num_bits++;
771
 
772
  for (i = 0; i < num_bits; i++)
773
    {
774
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
775
      remainder = (remainder << 1) | bit;
776
      t              = remainder - divisor;
777
      q              = !((t & 0x8000000000000000ULL) >> 63);
778
      dividend       = dividend << 1;
779
      quotient  = (quotient << 1) | q;
780
 
781
      if (q)
782
        {
783
          remainder = t;
784
        }
785
    }
786
 
787
  /* printf ("0x%08x%08x\n", (unsigned int) (quotient >> 32), */
788
  /*      (unsigned int) (quotient & 0xffffffff)); */
789
 
790
  return  quotient;
791
 
792
}       /* ll_divu () */
793
 
794
/* --------------------------------------------------------------------------*/
795
/*!Read the simulator timer
796
 
797
   Uses the built-in simulator functionality to return the time in
798
   microseconds.
799
 
800
   @note  Beware that this timer can wrap around.
801
 
802
   @return  The time used since the simulator started.                       */
803
/* --------------------------------------------------------------------------*/
804
unsigned long int
805
read_timer()
806
{
807
  unsigned long int       cycles_lo;
808
  unsigned long int       cycles_hi;
809
  unsigned long int       cycle_ps;
810
  unsigned long long int  time_us;
811
 
812
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_TICKS));
813
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycles_lo) : );
814
  __asm__ __volatile__ ("l.add\t\t%0,r0,r12": "=r" (cycles_hi) : );
815
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_PS));
816
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycle_ps) : );
817
 
818
  unsigned long long int  cycles = ((unsigned long long int) cycles_hi << 32) |
819
                                   ((unsigned long long int) cycles_lo);
820
 
821
  /* This could overflow 64 bits, but if so then the result would overflow 32
822
     bits. */
823
  time_us = ll_mulu (cycles, (unsigned long long int) cycle_ps);
824
  time_us = ll_divu (time_us, 1000000UL);
825
  return  (unsigned long int) time_us;
826
 
827
}       /* read_timer () */
828
 
829
 
830
/* --------------------------------------------------------------------------*/
831
/*!Write a SPR
832
 
833
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
834
         as is for now due to large amount of user code that might need
835
         changing.
836
 
837
   @param[in] spr    The SPR to write
838
   @param[in] value  The value to write to the SPR                           */
839
/* --------------------------------------------------------------------------*/
840
void
841
mtspr (unsigned long int  spr,
842
       unsigned long int  value)
843
{
844
  __asm__ __volatile__ ("l.mtspr\t\t%0,%1,0": : "r" (spr), "r" (value));
845
 
846
}       /* mtspr () */
847
 
848
 
849
/* --------------------------------------------------------------------------*/
850
/*!Read a SPR
851
 
852
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
853
         as is for now due to large amount of user code that might need
854
         changing.
855
 
856
   @param[in] spr    The SPR to write
857
 
858
   @return  The value read from the SPR                                      */
859
/* --------------------------------------------------------------------------*/
860
unsigned long int
861
mfspr (unsigned long spr)
862
{
863
  unsigned long value;
864
 
865
  __asm__ __volatile__ ("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr));
866
 
867
  return value;
868
 
869
}       /* mfspr () */
870
 
871
 
872
/* --------------------------------------------------------------------------*/
873
/*!Copy between regions of memory
874
 
875
   This should match the library version of memcpy
876
 
877
   @param[out] dstvoid  Pointer to the destination memory area
878
   @param[in]  srcvoid  Pointer to the source memory area
879
   @param[in]  length   Number of bytes to copy.                             */
880
/* --------------------------------------------------------------------------*/
881
void *
882
memcpy (void *__restrict          dstvoid,
883
        __const void *__restrict  srcvoid,
884
        size_t                    length)
885
{
886
  char *dst = dstvoid;
887
  const char *src = (const char *) srcvoid;
888
 
889
  while (length--)
890
    {
891
      *dst++ = *src++;
892
    }
893
 
894
  return dst;
895
 
896
}       /* memcpy () */
897 233 julius
 
898
/* --------------------------------------------------------------------------*/
899
/*!Pseudo-random number generator
900
 
901
   This should return pseudo-random numbers, based on a Galois LFSR
902
 
903
   @return The next pseudo-random number                                     */
904
/* --------------------------------------------------------------------------*/
905
unsigned long int
906
rand ()
907
{
908
  static unsigned long int lfsr = 1;
909
  static int period = 0;
910
  /* taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
911
  lfsr = (lfsr >> 1) ^ (unsigned long int)((0 - (lfsr & 1u)) & 0xd0000001u);
912
  ++period;
913
  return lfsr;
914
}

powered by: WebSVN 2.1.0

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