OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

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

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
          /* Are leading zeros requested? */
481
          if ('0' == fmt[i])
482
            {
483
              leading_zeros_p = 1;
484
              i++;
485
            }
486
          else
487
            {
488
              leading_zeros_p = 0;
489
            }
490
 
491
          /* Is there a width specification? */
492
          width = 0;
493
 
494
          while (is_digit (fmt[i]))
495
            {
496
              width = width * 10 + fmt[i] - '0';
497
              i++;
498
            }
499
 
500
          /* We just ignore any "l" specification. We do everything as
501
             32-bit. */
502
          i += ('l' == fmt[i]) ? 1 : 0;
503
 
504
          /* Deal with each field according to the type indicactor */
505
          char              ch;
506
          char             *str;
507
          long int          val;
508
          unsigned long int uval;
509
 
510
          /* There is a bug in GCC for OR1K, which can't handle two many
511
             cases. For now we split this into two disjoint case statements. */
512
          switch (fmt[i])
513
            {
514
            case 'c':
515
              ch = va_arg (args, int);
516
              num_chars += printf_char (ch, width);
517
              break;
518
 
519
            case 'o':
520
              uval = va_arg (args, unsigned long int);
521
              num_chars +=printf_unsigned_base (uval, width, leading_zeros_p,
522
                                               8);
523
              break;
524
 
525
            case 's':
526
              str = va_arg (args, char *);
527
              num_chars += printf_str (str, width);
528
              break;
529
 
530
            case 'x':
531
              uval = va_arg (args, unsigned long int);
532
              num_chars += printf_unsigned_base (uval, width, leading_zeros_p,
533
                                                16);
534
              break;
535
 
536
            default:
537
              /* Default is to do nothing silently */
538
              break;
539
            }
540
 
541
          switch (fmt[i])
542
            {
543
            case'd': case 'i':
544
              val = va_arg (args, long int);
545
              num_chars += printf_decimal (val, width, leading_zeros_p);
546
              break;
547
            }
548
        }
549
      else
550
        {
551
          putchar (fmt[i]);
552
          num_chars++;
553
        }
554
    }
555
 
556
  va_end (args);
557
 
558
  return  num_chars;
559
 
560
}       /* printf () */
561
 
562
 
563
/* --------------------------------------------------------------------------*/
564
/*!Report a 32-bit value
565
 
566
   Uses the built-in simulator functionality.
567
 
568
   @param[in] value  Value to report.                                        */
569
/* --------------------------------------------------------------------------*/
570
void
571
report (unsigned long int  value)
572
{
573
  __asm__ __volatile__ ("l.addi\tr3,%0,0\n\t"
574
                        "l.nop %1": : "r" (value), "K" (NOP_REPORT));
575
 
576
}       /* report () */
577
 
578
 
579
/* --------------------------------------------------------------------------*/
580
/*!Mutliply two 32-bit values to give a 64-bit result
581
 
582
   This is not supported by the OR1K GCC.
583
 
584
   Use the identity
585
 
586
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
587
 
588
   x = 2^16. None of this should overflow.
589
 
590
   @param[in] op1  First operand
591
   @param[in] op2  Second operand
592
 
593
   @return  The result                                                       */
594
/* --------------------------------------------------------------------------*/
595
static unsigned long long int
596
l_mulu (unsigned long int  op1,
597
        unsigned long int  op2)
598
{
599
  unsigned long int a, b, c, d;
600
 
601
  a = op1 >> 16;
602
  b = op1 & 0xffff;
603
  c = op2 >> 16;
604
  d = op2 & 0xffff;
605
 
606
  /* Add in the terms */
607
  unsigned long long int  res;
608
 
609
  /* printf ("a = 0x%08lx, b = 0x%08lx, c = 0x%08lx, d = 0x%08lx\n", a, b, c, d); */
610
  res  =  (unsigned long long int) (a * c) << 32;
611
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
612
  /*      (unsigned long int) res); */
613
  res += ((unsigned long long int) (a * d) << 16);
614
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
615
  /*      (unsigned long int) res); */
616
  res += ((unsigned long long int) (b * c) << 16);
617
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
618
  /*      (unsigned long int) res); */
619
  res +=  (unsigned long long int) (b * d);
620
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
621
  /*      (unsigned long int) res); */
622
 
623
  /* printf ("0x%08lx * 0x%08lx = 0x%08lx%08lx\n", op1, op2, */
624
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
625
 
626
  return  res;
627
 
628
}       /* l_mulu () */
629
 
630
 
631
/* --------------------------------------------------------------------------*/
632
/*!Mutliply two 64-bit values
633
 
634
   This is not supported by the OR1K GCC.
635
 
636
   Use the identity
637
 
638
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
639
 
640
   x = 2^32. We can discard the first term (overflow), though since this is
641
   for testing we'll print a message.
642
 
643
   The second term may overflow, so we compute the coefficient to 64-bit to
644
   see if we have overflowed.
645
 
646
   The final term may overflow, so we also compute this to 64-bit, so we can
647
   add the top 64-bits in.
648
 
649
   @param[in] op1  First operand
650
   @param[in] op2  Second operand
651
 
652
   @return  The result                                                       */
653
/* --------------------------------------------------------------------------*/
654
static unsigned long long int
655
ll_mulu (unsigned long long int  op1,
656
         unsigned long long int  op2)
657
{
658
  unsigned long int       a, b, c, d;
659
  unsigned long long int  tmp, res;
660
 
661
  a = op1 >> 32;
662
  b = op1 & 0xffffffff;
663
  c = op2 >> 32;
664
  d = op2 & 0xffffffff;
665
 
666
  if ((a > 0) && (c > 0))
667
    {
668
      printf ("ll_mulu overflows\n");
669
    }
670
 
671
  /* Compute and test the second term */
672
  tmp = l_mulu (a, d);
673
 
674
  if (tmp >= 0x100000000ULL)
675
    {
676
      printf ("ll_mulu overflows\n");
677
    }
678
 
679
  res = tmp << 32;
680
 
681
  tmp = l_mulu (b, c);
682
 
683
  if (tmp >= 0x100000000ULL)
684
    {
685
      printf ("ll_mulu overflows\n");
686
    }
687
 
688
  res += tmp << 32;
689
 
690
  /* Compute the third term. Although the term can't overflow, it could
691
     overflow the result. So just check our answer is larger when the final
692
     term is added in. */
693
  tmp = res;
694
 
695
  res += l_mulu (b, d);
696
 
697
  if (res < tmp)
698
    {
699
      printf ("ll_mulu overflows\n");
700
    }
701
 
702
  /* printf ("0x%08lx%08lx * 0x%08lx%08lx = 0x%08lx%08lx\n", a, b, c, d, */
703
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
704
 
705
  return  res;
706
 
707
}       /* ll_mulu () */
708
 
709
/* --------------------------------------------------------------------------*/
710
/*!Divide a 64-bit value by a 32 bit value
711
 
712
   Until I can get hold of a copy of Knuth volume 2 to check the algorithm,
713
   this is a bitwise version.
714
 
715
   @param[in] op1  First operand
716
   @param[in] op2  Second operand
717
 
718
   @return  The result                                                       */
719
/* --------------------------------------------------------------------------*/
720
static unsigned long long int
721
ll_divu (unsigned long long int  dividend,
722
         unsigned long int       divisor)
723
{
724
  unsigned long long int  t, num_bits;
725
  unsigned long long int  q, bit, d;
726
  int            i;
727
 
728
  if (divisor == 0)
729
    {
730
      printf ("ERROR: Invalid division by zero\n");
731
      return  0;
732
    }
733
 
734
  if (divisor > dividend)
735
    {
736
      return  0;
737
    }
738
 
739
  if (divisor == dividend)
740
    {
741
      return  1ULL;
742
    }
743
 
744
  /* printf ("0x%08x%08x / 0x%08x = ", (unsigned int) (dividend >> 32), */
745
  /*      (unsigned int) (dividend & 0xffffffff), (unsigned int) divisor); */
746
 
747
  num_bits = 64;
748
 
749
  unsigned long long int  remainder = 0;
750
  unsigned long long int  quotient  = 0;
751
 
752
  while (remainder < divisor)
753
    {
754
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
755
      remainder = (remainder << 1) | bit;
756
      d              = dividend;
757
      dividend       = dividend << 1;
758
      num_bits--;
759
    }
760
 
761
  /* The loop, above, always goes one iteration too far.  To avoid inserting
762
     an "if" statement inside the loop the last iteration is simply
763
     reversed. */
764
  dividend  = d;
765
  remainder = remainder >> 1;
766
  num_bits++;
767
 
768
  for (i = 0; i < num_bits; i++)
769
    {
770
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
771
      remainder = (remainder << 1) | bit;
772
      t              = remainder - divisor;
773
      q              = !((t & 0x8000000000000000ULL) >> 63);
774
      dividend       = dividend << 1;
775
      quotient  = (quotient << 1) | q;
776
 
777
      if (q)
778
        {
779
          remainder = t;
780
        }
781
    }
782
 
783
  /* printf ("0x%08x%08x\n", (unsigned int) (quotient >> 32), */
784
  /*      (unsigned int) (quotient & 0xffffffff)); */
785
 
786
  return  quotient;
787
 
788
}       /* ll_divu () */
789
 
790
/* --------------------------------------------------------------------------*/
791
/*!Read the simulator timer
792
 
793
   Uses the built-in simulator functionality to return the time in
794
   microseconds.
795
 
796
   @note  Beware that this timer can wrap around.
797
 
798
   @return  The time used since the simulator started.                       */
799
/* --------------------------------------------------------------------------*/
800
unsigned long int
801
read_timer()
802
{
803
  unsigned long int       cycles_lo;
804
  unsigned long int       cycles_hi;
805
  unsigned long int       cycle_ps;
806
  unsigned long long int  time_us;
807
 
808
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_TICKS));
809
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycles_lo) : );
810
  __asm__ __volatile__ ("l.add\t\t%0,r0,r12": "=r" (cycles_hi) : );
811
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_PS));
812
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycle_ps) : );
813
 
814
  unsigned long long int  cycles = ((unsigned long long int) cycles_hi << 32) |
815
                                   ((unsigned long long int) cycles_lo);
816
 
817
  /* This could overflow 64 bits, but if so then the result would overflow 32
818
     bits. */
819
  time_us = ll_mulu (cycles, (unsigned long long int) cycle_ps);
820
  time_us = ll_divu (time_us, 1000000UL);
821
  return  (unsigned long int) time_us;
822
 
823
}       /* read_timer () */
824
 
825
 
826
/* --------------------------------------------------------------------------*/
827
/*!Write a SPR
828
 
829
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
830
         as is for now due to large amount of user code that might need
831
         changing.
832
 
833
   @param[in] spr    The SPR to write
834
   @param[in] value  The value to write to the SPR                           */
835
/* --------------------------------------------------------------------------*/
836
void
837
mtspr (unsigned long int  spr,
838
       unsigned long int  value)
839
{
840
  __asm__ __volatile__ ("l.mtspr\t\t%0,%1,0": : "r" (spr), "r" (value));
841
 
842
}       /* mtspr () */
843
 
844
 
845
/* --------------------------------------------------------------------------*/
846
/*!Read a SPR
847
 
848
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
849
         as is for now due to large amount of user code that might need
850
         changing.
851
 
852
   @param[in] spr    The SPR to write
853
 
854
   @return  The value read from the SPR                                      */
855
/* --------------------------------------------------------------------------*/
856
unsigned long int
857
mfspr (unsigned long spr)
858
{
859
  unsigned long value;
860
 
861
  __asm__ __volatile__ ("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr));
862
 
863
  return value;
864
 
865
}       /* mfspr () */
866
 
867
 
868
/* --------------------------------------------------------------------------*/
869
/*!Copy between regions of memory
870
 
871
   This should match the library version of memcpy
872
 
873
   @param[out] dstvoid  Pointer to the destination memory area
874
   @param[in]  srcvoid  Pointer to the source memory area
875
   @param[in]  length   Number of bytes to copy.                             */
876
/* --------------------------------------------------------------------------*/
877
void *
878
memcpy (void *__restrict          dstvoid,
879
        __const void *__restrict  srcvoid,
880
        size_t                    length)
881
{
882
  char *dst = dstvoid;
883
  const char *src = (const char *) srcvoid;
884
 
885
  while (length--)
886
    {
887
      *dst++ = *src++;
888
    }
889
 
890
  return dst;
891
 
892
}       /* memcpy () */

powered by: WebSVN 2.1.0

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