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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code-or1k/] [support/] [support.c] - Diff between revs 93 and 233

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 93 Rev 233
/* support.c -- Support code for Or1ksim testing.
/* support.c -- Support code for Or1ksim testing.
 
 
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 2008, 2010 Embecosm Limited
   Copyright (C) 2008, 2010 Embecosm Limited
 
 
   Contributor Damjan Lampret <lampret@opencores.org>
   Contributor Damjan Lampret <lampret@opencores.org>
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
 
   This file is part of OpenRISC 1000 Architectural Simulator.
   This file is part of OpenRISC 1000 Architectural Simulator.
 
 
   This program is free software; you can redistribute it and/or modify it
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   under the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3 of the License, or (at your option)
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.
   any later version.
 
 
   This program is distributed in the hope that it will be useful, but WITHOUT
   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.
   more details.
 
 
   You should have received a copy of the GNU General Public License along
   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 
/* ----------------------------------------------------------------------------
/* ----------------------------------------------------------------------------
   This code is commented throughout for use with Doxygen.
   This code is commented throughout for use with Doxygen.
   --------------------------------------------------------------------------*/
   --------------------------------------------------------------------------*/
 
 
/* Support */
/* Support */
 
 
#include "spr-defs.h"
#include "spr-defs.h"
#include "support.h"
#include "support.h"
#include "int.h"
#include "int.h"
 
 
 
 
/* Forward declarations of interrupt handlers */
/* Forward declarations of interrupt handlers */
static void excpt_dummy();
static void excpt_dummy();
extern void int_main();
extern void int_main();
 
 
/* Exception handlers. All are dummy except the interrupt handler */
/* Exception handlers. All are dummy except the interrupt handler */
unsigned long excpt_buserr   = (unsigned long) excpt_dummy;
unsigned long excpt_buserr   = (unsigned long) excpt_dummy;
unsigned long excpt_dpfault  = (unsigned long) excpt_dummy;
unsigned long excpt_dpfault  = (unsigned long) excpt_dummy;
unsigned long excpt_ipfault  = (unsigned long) excpt_dummy;
unsigned long excpt_ipfault  = (unsigned long) excpt_dummy;
unsigned long excpt_tick     = (unsigned long) excpt_dummy;
unsigned long excpt_tick     = (unsigned long) excpt_dummy;
unsigned long excpt_align    = (unsigned long) excpt_dummy;
unsigned long excpt_align    = (unsigned long) excpt_dummy;
unsigned long excpt_illinsn  = (unsigned long) excpt_dummy;
unsigned long excpt_illinsn  = (unsigned long) excpt_dummy;
unsigned long excpt_int      = (unsigned long) int_main;
unsigned long excpt_int      = (unsigned long) int_main;
unsigned long excpt_dtlbmiss = (unsigned long) excpt_dummy;
unsigned long excpt_dtlbmiss = (unsigned long) excpt_dummy;
unsigned long excpt_itlbmiss = (unsigned long) excpt_dummy;
unsigned long excpt_itlbmiss = (unsigned long) excpt_dummy;
unsigned long excpt_range    = (unsigned long) excpt_dummy;
unsigned long excpt_range    = (unsigned long) excpt_dummy;
unsigned long excpt_syscall  = (unsigned long) excpt_dummy;
unsigned long excpt_syscall  = (unsigned long) excpt_dummy;
unsigned long excpt_break    = (unsigned long) excpt_dummy;
unsigned long excpt_break    = (unsigned long) excpt_dummy;
unsigned long excpt_trap     = (unsigned long) excpt_dummy;
unsigned long excpt_trap     = (unsigned long) excpt_dummy;
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Is a character a decimal digit?
/*!Is a character a decimal digit?
 
 
   @param[in] c  The character to test
   @param[in] c  The character to test
 
 
   @return  1 (TRUE) if the character is a decimal digit, 0 (FALSE)
   @return  1 (TRUE) if the character is a decimal digit, 0 (FALSE)
            otherwise                                                        */
            otherwise                                                        */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
is_digit (char  c)
is_digit (char  c)
{
{
  return ('0' <= c) && (c <= '9');
  return ('0' <= c) && (c <= '9');
 
 
}       /* is_digit () */
}       /* is_digit () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a char in a width
/*!Print a char in a width
 
 
   The char is always right justified.
   The char is always right justified.
 
 
   @param[in] c      The character to print
   @param[in] c      The character to print
   @param[in] width  The width to print in
   @param[in] width  The width to print in
 
 
   @return  The number of characters actually printed (always width)         */
   @return  The number of characters actually printed (always width)         */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
printf_char (char  c,
printf_char (char  c,
             int   width)
             int   width)
{
{
  int  i;
  int  i;
 
 
  /* Spacing */
  /* Spacing */
  for (i = 1; i < width; i++)
  for (i = 1; i < width; i++)
    {
    {
      putchar (' ');
      putchar (' ');
    }
    }
 
 
  /* The char */
  /* The char */
  putchar (c);
  putchar (c);
 
 
  return  width;
  return  width;
 
 
}       /* printf_char () */
}       /* printf_char () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Convert a digit to a char
/*!Convert a digit to a char
 
 
   We don't worry about the base. If the value supplied is over 10, we assume
   We don't worry about the base. If the value supplied is over 10, we assume
   its a letter.
   its a letter.
 
 
   @param[in] d  The digit to convert.
   @param[in] d  The digit to convert.
 
 
   @return  The character representation.                                    */
   @return  The character representation.                                    */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static char
static char
dig2char (int  d)
dig2char (int  d)
{
{
  return (d < 10) ? '0' + d : 'a' + d - 10;
  return (d < 10) ? '0' + d : 'a' + d - 10;
 
 
}       /* dit2char () */
}       /* dit2char () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a number to a base to a string
/*!Print a number to a base to a string
 
 
   The number is unsigned, left justified and null terminated
   The number is unsigned, left justified and null terminated
 
 
   @param[in] uval  The value to print
   @param[in] uval  The value to print
   @param[in] buf   The buffer to print in
   @param[in] buf   The buffer to print in
   @param[in] base  The base to use.
   @param[in] base  The base to use.
 
 
   @return  the length of the string created.                                */
   @return  the length of the string created.                                */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
print_base (long unsigned int  uval,
print_base (long unsigned int  uval,
            char               buf[],
            char               buf[],
            unsigned int       base)
            unsigned int       base)
{
{
  /* Initially print backwards. Always have at least a zero. */
  /* Initially print backwards. Always have at least a zero. */
  int  i = 0;
  int  i = 0;
 
 
  do
  do
    {
    {
      buf[i] = dig2char (uval % base);
      buf[i] = dig2char (uval % base);
      uval = uval / base;
      uval = uval / base;
      i++;
      i++;
    }
    }
  while (0 != uval);
  while (0 != uval);
 
 
  buf[i] = 0;                    /* End of string */
  buf[i] = 0;                    /* End of string */
 
 
  int  len = i;                 /* Length of the string */
  int  len = i;                 /* Length of the string */
 
 
  /* Reverse the string */
  /* Reverse the string */
  for (i = 0; i < (len / 2); i++)
  for (i = 0; i < (len / 2); i++)
    {
    {
      char  c          = buf[i];
      char  c          = buf[i];
      buf[i]           = buf[len - i - 1];
      buf[i]           = buf[len - i - 1];
      buf[len - i - 1] = c;
      buf[len - i - 1] = c;
    }
    }
 
 
  return  len;
  return  len;
 
 
}       /* print_base () */
}       /* print_base () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a character multiple times
/*!Print a character multiple times
 
 
   @param[in] c    The char to print
   @param[in] c    The char to print
   @param[in] num  Number of times to print                                 */
   @param[in] num  Number of times to print                                 */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
print_multichar (char  c,
print_multichar (char  c,
                 int   num)
                 int   num)
{
{
  for (; num > 0; num--)
  for (; num > 0; num--)
    {
    {
      putchar (c);
      putchar (c);
    }
    }
}       /* print_multichar () */
}       /* print_multichar () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a string
/*!Print a string
 
 
   @param[in] str  The string to print                                       */
   @param[in] str  The string to print                                       */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
print_str (char  str [])
print_str (char  str [])
{
{
  int  i;
  int  i;
 
 
  for (i = 0; 0 != str[i]; i++)
  for (i = 0; 0 != str[i]; i++)
    {
    {
      putchar (str[i]);
      putchar (str[i]);
    }
    }
}       /* print_str () */
}       /* print_str () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Return the length of a string
/*!Return the length of a string
 
 
   @param[in] str    The string whose length is wanted
   @param[in] str    The string whose length is wanted
 
 
   @return  The length of the string                                         */
   @return  The length of the string                                         */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
strlen (char  str [])
strlen (char  str [])
{
{
  int  i;
  int  i;
 
 
  for (i = 0; str[i] != 0; i++)
  for (i = 0; str[i] != 0; i++)
    {
    {
    }
    }
 
 
  return  i;
  return  i;
 
 
}       /* strlen () */
}       /* strlen () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a string in a width
/*!Print a string in a width
 
 
   @param[in] str    The string to print
   @param[in] str    The string to print
   @param[in] width  The width to print it in (at least)
   @param[in] width  The width to print it in (at least)
 
 
   @return  The number of chars printed                                      */
   @return  The number of chars printed                                      */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
printf_str (char  str [],
printf_str (char  str [],
            int   width)
            int   width)
{
{
  int len = strlen (str);
  int len = strlen (str);
 
 
  if (width > len)
  if (width > len)
    {
    {
      print_multichar (' ', width - len);
      print_multichar (' ', width - len);
    }
    }
 
 
  print_str (str);
  print_str (str);
 
 
  return  (width > len) ? width : len;
  return  (width > len) ? width : len;
 
 
}       /* printf_str () */
}       /* printf_str () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a decimal in a width
/*!Print a decimal in a width
 
 
   The number is always right justified and signed.
   The number is always right justified and signed.
 
 
   @param[in] val              The value to print
   @param[in] val              The value to print
   @param[in] width            The width to print in (at least)
   @param[in] width            The width to print in (at least)
   @param[in] leading_zeros_p  1 (TRUE) if we should print leading zeros,
   @param[in] leading_zeros_p  1 (TRUE) if we should print leading zeros,
                               0 (FALSE) otherwise
                               0 (FALSE) otherwise
 
 
   @return  The number of chars printed                                      */
   @return  The number of chars printed                                      */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
printf_decimal (long int  val,
printf_decimal (long int  val,
                int       width,
                int       width,
                int       leading_zeros_p)
                int       leading_zeros_p)
{
{
  int  is_signed_p = 0;
  int  is_signed_p = 0;
 
 
  /* Note if we need a sign */
  /* Note if we need a sign */
  if (val < 0)
  if (val < 0)
    {
    {
      val         = -val;
      val         = -val;
      is_signed_p = 1;
      is_signed_p = 1;
    }
    }
 
 
  /* Array to store the number in. We know the max for 32 bits is 10
  /* Array to store the number in. We know the max for 32 bits is 10
     digits. Allow for end of string marker */
     digits. Allow for end of string marker */
  char  num_array[11];
  char  num_array[11];
 
 
  int  num_width = print_base ((unsigned long int) val, num_array, 10);
  int  num_width = print_base ((unsigned long int) val, num_array, 10);
 
 
  /* Now print out the number. */
  /* Now print out the number. */
  num_width += is_signed_p ? 1 : 0;
  num_width += is_signed_p ? 1 : 0;
 
 
  if (num_width < width)
  if (num_width < width)
    {
    {
      if (leading_zeros_p)
      if (leading_zeros_p)
        {
        {
          if (is_signed_p)
          if (is_signed_p)
            {
            {
              putchar ('-');
              putchar ('-');
            }
            }
 
 
          print_multichar ('0', width - num_width);
          print_multichar ('0', width - num_width);
        }
        }
      else
      else
        {
        {
          print_multichar (' ', width - num_width);
          print_multichar (' ', width - num_width);
 
 
          if (is_signed_p)
          if (is_signed_p)
            {
            {
              putchar ('-');
              putchar ('-');
            }
            }
        }
        }
    }
    }
  else
  else
    {
    {
      if (is_signed_p)
      if (is_signed_p)
        {
        {
          putchar ('-');
          putchar ('-');
        }
        }
    }
    }
 
 
  print_str (num_array);
  print_str (num_array);
 
 
  return  width > num_width ? width : num_width;
  return  width > num_width ? width : num_width;
 
 
}       /* printf_decimal () */
}       /* printf_decimal () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a unsigned to a base in a width
/*!Print a unsigned to a base in a width
 
 
   The number is always right justified and unsigned.
   The number is always right justified and unsigned.
 
 
   @param[in] val              The value to print
   @param[in] val              The value to print
   @param[in] width            The width to print in (at least)
   @param[in] width            The width to print in (at least)
   @param[in] leading_zeros_p  1 (TRUE) if we should print leading zeros,
   @param[in] leading_zeros_p  1 (TRUE) if we should print leading zeros,
                               0 (FALSE) otherwise
                               0 (FALSE) otherwise
   @param[in] base             Base to use when printing
   @param[in] base             Base to use when printing
 
 
   @return  The number of chars printed                                      */
   @return  The number of chars printed                                      */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static int
static int
printf_unsigned_base (unsigned long int  val,
printf_unsigned_base (unsigned long int  val,
                      int                width,
                      int                width,
                      int                leading_zeros_p,
                      int                leading_zeros_p,
                      unsigned int       base)
                      unsigned int       base)
{
{
  int  is_signed_p = 0;
  int  is_signed_p = 0;
 
 
  /* Note if we need a sign */
  /* Note if we need a sign */
  if (val < 0)
  if (val < 0)
    {
    {
      val         = -val;
      val         = -val;
      is_signed_p = 1;
      is_signed_p = 1;
    }
    }
 
 
  /* Array to store the number in. We know the max for 32 bits of octal is 11
  /* Array to store the number in. We know the max for 32 bits of octal is 11
     digits. Allow for end of string marker */
     digits. Allow for end of string marker */
  char  num_array[12];
  char  num_array[12];
 
 
  int  num_width = print_base (val, num_array, base);
  int  num_width = print_base (val, num_array, base);
 
 
  /* Now print out the number. */
  /* Now print out the number. */
  num_width += is_signed_p ? 1 : 0;
  num_width += is_signed_p ? 1 : 0;
 
 
  if (num_width < width)
  if (num_width < width)
    {
    {
      print_multichar (leading_zeros_p ? '0' : ' ', width - num_width);
      print_multichar (leading_zeros_p ? '0' : ' ', width - num_width);
    }
    }
 
 
  print_str (num_array);
  print_str (num_array);
 
 
  return  width > num_width ? width : num_width;
  return  width > num_width ? width : num_width;
 
 
}       /* printf_unsigned_base () */
}       /* printf_unsigned_base () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Dummy exception handler
/*!Dummy exception handler
 
 
   Used for most exceptions as the default hander which does nothing.        */
   Used for most exceptions as the default hander which does nothing.        */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
excpt_dummy()
excpt_dummy()
{
{
}       /* excpt_dummy ()*/
}       /* excpt_dummy ()*/
 
 
 
 
/*! Function to be called at entry point - not defined here. */
/*! Function to be called at entry point - not defined here. */
extern int main  ();
extern int main  ();
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Start function
/*!Start function
 
 
   Called by reset exception handler.                                        */
   Called by reset exception handler.                                        */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
void
void
reset ()
reset ()
{
{
  exit (main ());
  exit (main ());
 
 
}       /* reset () */
}       /* reset () */
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Exit function
/*!Exit function
 
 
   Return value by making a syscall
   Return value by making a syscall
 
 
   @param[in] rc  Return code                                                */
   @param[in] rc  Return code                                                */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
void
void
exit (int rc)
exit (int rc)
{
{
  __asm__ __volatile__ ("l.add r3,r0,%0\n\t"
  __asm__ __volatile__ ("l.add r3,r0,%0\n\t"
                        "l.nop %1": : "r" (rc), "K" (NOP_EXIT));
                        "l.nop %1": : "r" (rc), "K" (NOP_EXIT));
 
 
  /* Header declares function as __noreturn, so ensure that is so. */
  /* Header declares function as __noreturn, so ensure that is so. */
  while (1)
  while (1)
    {
    {
    }
    }
}       /* exit () */
}       /* exit () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Activate printing a character in the simulator
/*!Activate printing a character in the simulator
 
 
   @param[in] c  The character to print
   @param[in] c  The character to print
 
 
   @return  The char printed cast to an int                                  */
   @return  The char printed cast to an int                                  */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
int
int
putchar (int  c)
putchar (int  c)
{
{
  __asm__ __volatile__ ("l.addi\tr3,%0,0\n\t"
  __asm__ __volatile__ ("l.addi\tr3,%0,0\n\t"
                        "l.nop %1": : "r" (c), "K" (NOP_PUTC));
                        "l.nop %1": : "r" (c), "K" (NOP_PUTC));
 
 
  return  c;
  return  c;
 
 
}       /* putchar () */
}       /* putchar () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Print a string
/*!Print a string
 
 
   We need to define this, since the compiler will replace calls to printf
   We need to define this, since the compiler will replace calls to printf
   using just constant strings with trailing newlines with calls to puts
   using just constant strings with trailing newlines with calls to puts
   without the newline.
   without the newline.
 
 
   @param[in] str  The string to print (without a newline)
   @param[in] str  The string to print (without a newline)
 
 
   @return  The char printed cast to an int                                  */
   @return  The char printed cast to an int                                  */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
int
int
puts (const char *str)
puts (const char *str)
{
{
  return  printf ("%s\n", str);
  return  printf ("%s\n", str);
 
 
}       /* puts () */
}       /* puts () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Activate printf support in simulator
/*!Activate printf support in simulator
 
 
   @note This doesn't actually work, so we implement the basics of printf by
   @note This doesn't actually work, so we implement the basics of printf by
         steam, calling useful subsidiary functions based on putchar (), which
         steam, calling useful subsidiary functions based on putchar (), which
         does work.
         does work.
 
 
   @param[in] fmt  The format string
   @param[in] fmt  The format string
   @param[in] ...  The variable arguments if any
   @param[in] ...  The variable arguments if any
 
 
   @return  The number of characters printed                                 */
   @return  The number of characters printed                                 */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
int
int
printf(const char *fmt,
printf(const char *fmt,
          ...)
          ...)
{
{
  int  num_chars = 0;                    /* How many chars printed */
  int  num_chars = 0;                    /* How many chars printed */
 
 
  va_list args;
  va_list args;
  va_start (args, fmt);
  va_start (args, fmt);
 
 
  int  i;                               /* Index into the string */
  int  i;                               /* Index into the string */
 
 
  for (i = 0; fmt[i] != 0; i++)
  for (i = 0; fmt[i] != 0; i++)
    {
    {
      if ('%' == fmt[i])
      if ('%' == fmt[i])
        {
        {
          int  width;
          int  width;
          int  leading_zeros_p;
          int  leading_zeros_p;
 
 
          /* Decode the field */
          /* Decode the field */
          i++;
          i++;
 
 
          /* Are leading zeros requested? */
          /* Are leading zeros requested? */
          if ('0' == fmt[i])
          if ('0' == fmt[i])
            {
            {
              leading_zeros_p = 1;
              leading_zeros_p = 1;
              i++;
              i++;
            }
            }
          else
          else
            {
            {
              leading_zeros_p = 0;
              leading_zeros_p = 0;
            }
            }
 
 
          /* Is there a width specification? */
          /* Is there a width specification? */
          width = 0;
          width = 0;
 
 
          while (is_digit (fmt[i]))
          while (is_digit (fmt[i]))
            {
            {
              width = width * 10 + fmt[i] - '0';
              width = width * 10 + fmt[i] - '0';
              i++;
              i++;
            }
            }
 
 
          /* We just ignore any "l" specification. We do everything as
          /* We just ignore any "l" specification. We do everything as
             32-bit. */
             32-bit. */
          i += ('l' == fmt[i]) ? 1 : 0;
          i += ('l' == fmt[i]) ? 1 : 0;
 
 
          /* Deal with each field according to the type indicactor */
          /* Deal with each field according to the type indicactor */
          char              ch;
          char              ch;
          char             *str;
          char             *str;
          long int          val;
          long int          val;
          unsigned long int uval;
          unsigned long int uval;
 
 
          /* There is a bug in GCC for OR1K, which can't handle two many
          /* There is a bug in GCC for OR1K, which can't handle two many
             cases. For now we split this into two disjoint case statements. */
             cases. For now we split this into two disjoint case statements. */
          switch (fmt[i])
          switch (fmt[i])
            {
            {
            case 'c':
            case 'c':
              ch = va_arg (args, int);
              ch = va_arg (args, int);
              num_chars += printf_char (ch, width);
              num_chars += printf_char (ch, width);
              break;
              break;
 
 
            case 'o':
            case 'o':
              uval = va_arg (args, unsigned long int);
              uval = va_arg (args, unsigned long int);
              num_chars +=printf_unsigned_base (uval, width, leading_zeros_p,
              num_chars +=printf_unsigned_base (uval, width, leading_zeros_p,
                                               8);
                                               8);
              break;
              break;
 
 
            case 's':
            case 's':
              str = va_arg (args, char *);
              str = va_arg (args, char *);
              num_chars += printf_str (str, width);
              num_chars += printf_str (str, width);
              break;
              break;
 
 
            case 'x':
            case 'x':
              uval = va_arg (args, unsigned long int);
              uval = va_arg (args, unsigned long int);
              num_chars += printf_unsigned_base (uval, width, leading_zeros_p,
              num_chars += printf_unsigned_base (uval, width, leading_zeros_p,
                                                16);
                                                16);
              break;
              break;
 
 
            default:
            default:
              /* Default is to do nothing silently */
              /* Default is to do nothing silently */
              break;
              break;
            }
            }
 
 
          switch (fmt[i])
          switch (fmt[i])
            {
            {
            case'd': case 'i':
            case'd': case 'i':
              val = va_arg (args, long int);
              val = va_arg (args, long int);
              num_chars += printf_decimal (val, width, leading_zeros_p);
              num_chars += printf_decimal (val, width, leading_zeros_p);
              break;
              break;
            }
            }
        }
        }
      else
      else
        {
        {
          putchar (fmt[i]);
          putchar (fmt[i]);
          num_chars++;
          num_chars++;
        }
        }
    }
    }
 
 
  va_end (args);
  va_end (args);
 
 
  return  num_chars;
  return  num_chars;
 
 
}       /* printf () */
}       /* printf () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Report a 32-bit value
/*!Report a 32-bit value
 
 
   Uses the built-in simulator functionality.
   Uses the built-in simulator functionality.
 
 
   @param[in] value  Value to report.                                        */
   @param[in] value  Value to report.                                        */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
void
void
report (unsigned long int  value)
report (unsigned long int  value)
{
{
  __asm__ __volatile__ ("l.addi\tr3,%0,0\n\t"
  __asm__ __volatile__ ("l.addi\tr3,%0,0\n\t"
                        "l.nop %1": : "r" (value), "K" (NOP_REPORT));
                        "l.nop %1": : "r" (value), "K" (NOP_REPORT));
 
 
}       /* report () */
}       /* report () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Mutliply two 32-bit values to give a 64-bit result
/*!Mutliply two 32-bit values to give a 64-bit result
 
 
   This is not supported by the OR1K GCC.
   This is not supported by the OR1K GCC.
 
 
   Use the identity
   Use the identity
 
 
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
 
 
   x = 2^16. None of this should overflow.
   x = 2^16. None of this should overflow.
 
 
   @param[in] op1  First operand
   @param[in] op1  First operand
   @param[in] op2  Second operand
   @param[in] op2  Second operand
 
 
   @return  The result                                                       */
   @return  The result                                                       */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long long int
static unsigned long long int
l_mulu (unsigned long int  op1,
l_mulu (unsigned long int  op1,
        unsigned long int  op2)
        unsigned long int  op2)
{
{
  unsigned long int a, b, c, d;
  unsigned long int a, b, c, d;
 
 
  a = op1 >> 16;
  a = op1 >> 16;
  b = op1 & 0xffff;
  b = op1 & 0xffff;
  c = op2 >> 16;
  c = op2 >> 16;
  d = op2 & 0xffff;
  d = op2 & 0xffff;
 
 
  /* Add in the terms */
  /* Add in the terms */
  unsigned long long int  res;
  unsigned long long int  res;
 
 
  /* printf ("a = 0x%08lx, b = 0x%08lx, c = 0x%08lx, d = 0x%08lx\n", a, b, c, d); */
  /* printf ("a = 0x%08lx, b = 0x%08lx, c = 0x%08lx, d = 0x%08lx\n", a, b, c, d); */
  res  =  (unsigned long long int) (a * c) << 32;
  res  =  (unsigned long long int) (a * c) << 32;
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /*      (unsigned long int) res); */
  /*      (unsigned long int) res); */
  res += ((unsigned long long int) (a * d) << 16);
  res += ((unsigned long long int) (a * d) << 16);
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /*      (unsigned long int) res); */
  /*      (unsigned long int) res); */
  res += ((unsigned long long int) (b * c) << 16);
  res += ((unsigned long long int) (b * c) << 16);
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /*      (unsigned long int) res); */
  /*      (unsigned long int) res); */
  res +=  (unsigned long long int) (b * d);
  res +=  (unsigned long long int) (b * d);
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /* printf ("  interim res = 0x%08lx%08lx\n", (unsigned long int) (res >> 32), */
  /*      (unsigned long int) res); */
  /*      (unsigned long int) res); */
 
 
  /* printf ("0x%08lx * 0x%08lx = 0x%08lx%08lx\n", op1, op2, */
  /* printf ("0x%08lx * 0x%08lx = 0x%08lx%08lx\n", op1, op2, */
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
 
 
  return  res;
  return  res;
 
 
}       /* l_mulu () */
}       /* l_mulu () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Mutliply two 64-bit values
/*!Mutliply two 64-bit values
 
 
   This is not supported by the OR1K GCC.
   This is not supported by the OR1K GCC.
 
 
   Use the identity
   Use the identity
 
 
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
   (ax + b).(cx + d) = ac.x^2 + (ad + bc).x + bd
 
 
   x = 2^32. We can discard the first term (overflow), though since this is
   x = 2^32. We can discard the first term (overflow), though since this is
   for testing we'll print a message.
   for testing we'll print a message.
 
 
   The second term may overflow, so we compute the coefficient to 64-bit to
   The second term may overflow, so we compute the coefficient to 64-bit to
   see if we have overflowed.
   see if we have overflowed.
 
 
   The final term may overflow, so we also compute this to 64-bit, so we can
   The final term may overflow, so we also compute this to 64-bit, so we can
   add the top 64-bits in.
   add the top 64-bits in.
 
 
   @param[in] op1  First operand
   @param[in] op1  First operand
   @param[in] op2  Second operand
   @param[in] op2  Second operand
 
 
   @return  The result                                                       */
   @return  The result                                                       */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long long int
static unsigned long long int
ll_mulu (unsigned long long int  op1,
ll_mulu (unsigned long long int  op1,
         unsigned long long int  op2)
         unsigned long long int  op2)
{
{
  unsigned long int       a, b, c, d;
  unsigned long int       a, b, c, d;
  unsigned long long int  tmp, res;
  unsigned long long int  tmp, res;
 
 
  a = op1 >> 32;
  a = op1 >> 32;
  b = op1 & 0xffffffff;
  b = op1 & 0xffffffff;
  c = op2 >> 32;
  c = op2 >> 32;
  d = op2 & 0xffffffff;
  d = op2 & 0xffffffff;
 
 
  if ((a > 0) && (c > 0))
  if ((a > 0) && (c > 0))
    {
    {
      printf ("ll_mulu overflows\n");
      printf ("ll_mulu overflows\n");
    }
    }
 
 
  /* Compute and test the second term */
  /* Compute and test the second term */
  tmp = l_mulu (a, d);
  tmp = l_mulu (a, d);
 
 
  if (tmp >= 0x100000000ULL)
  if (tmp >= 0x100000000ULL)
    {
    {
      printf ("ll_mulu overflows\n");
      printf ("ll_mulu overflows\n");
    }
    }
 
 
  res = tmp << 32;
  res = tmp << 32;
 
 
  tmp = l_mulu (b, c);
  tmp = l_mulu (b, c);
 
 
  if (tmp >= 0x100000000ULL)
  if (tmp >= 0x100000000ULL)
    {
    {
      printf ("ll_mulu overflows\n");
      printf ("ll_mulu overflows\n");
    }
    }
 
 
  res += tmp << 32;
  res += tmp << 32;
 
 
  /* Compute the third term. Although the term can't overflow, it could
  /* Compute the third term. Although the term can't overflow, it could
     overflow the result. So just check our answer is larger when the final
     overflow the result. So just check our answer is larger when the final
     term is added in. */
     term is added in. */
  tmp = res;
  tmp = res;
 
 
  res += l_mulu (b, d);
  res += l_mulu (b, d);
 
 
  if (res < tmp)
  if (res < tmp)
    {
    {
      printf ("ll_mulu overflows\n");
      printf ("ll_mulu overflows\n");
    }
    }
 
 
  /* printf ("0x%08lx%08lx * 0x%08lx%08lx = 0x%08lx%08lx\n", a, b, c, d, */
  /* printf ("0x%08lx%08lx * 0x%08lx%08lx = 0x%08lx%08lx\n", a, b, c, d, */
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
  /*      (unsigned long int) (res >> 32), (unsigned long int) res); */
 
 
  return  res;
  return  res;
 
 
}       /* ll_mulu () */
}       /* ll_mulu () */
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Divide a 64-bit value by a 32 bit value
/*!Divide a 64-bit value by a 32 bit value
 
 
   Until I can get hold of a copy of Knuth volume 2 to check the algorithm,
   Until I can get hold of a copy of Knuth volume 2 to check the algorithm,
   this is a bitwise version.
   this is a bitwise version.
 
 
   @param[in] op1  First operand
   @param[in] op1  First operand
   @param[in] op2  Second operand
   @param[in] op2  Second operand
 
 
   @return  The result                                                       */
   @return  The result                                                       */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long long int
static unsigned long long int
ll_divu (unsigned long long int  dividend,
ll_divu (unsigned long long int  dividend,
         unsigned long int       divisor)
         unsigned long int       divisor)
{
{
  unsigned long long int  t, num_bits;
  unsigned long long int  t, num_bits;
  unsigned long long int  q, bit, d;
  unsigned long long int  q, bit, d;
  int            i;
  int            i;
 
 
  if (divisor == 0)
  if (divisor == 0)
    {
    {
      printf ("ERROR: Invalid division by zero\n");
      printf ("ERROR: Invalid division by zero\n");
      return  0;
      return  0;
    }
    }
 
 
  if (divisor > dividend)
  if (divisor > dividend)
    {
    {
      return  0;
      return  0;
    }
    }
 
 
  if (divisor == dividend)
  if (divisor == dividend)
    {
    {
      return  1ULL;
      return  1ULL;
    }
    }
 
 
  /* printf ("0x%08x%08x / 0x%08x = ", (unsigned int) (dividend >> 32), */
  /* printf ("0x%08x%08x / 0x%08x = ", (unsigned int) (dividend >> 32), */
  /*      (unsigned int) (dividend & 0xffffffff), (unsigned int) divisor); */
  /*      (unsigned int) (dividend & 0xffffffff), (unsigned int) divisor); */
 
 
  num_bits = 64;
  num_bits = 64;
 
 
  unsigned long long int  remainder = 0;
  unsigned long long int  remainder = 0;
  unsigned long long int  quotient  = 0;
  unsigned long long int  quotient  = 0;
 
 
  while (remainder < divisor)
  while (remainder < divisor)
    {
    {
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
      remainder = (remainder << 1) | bit;
      remainder = (remainder << 1) | bit;
      d              = dividend;
      d              = dividend;
      dividend       = dividend << 1;
      dividend       = dividend << 1;
      num_bits--;
      num_bits--;
    }
    }
 
 
  /* The loop, above, always goes one iteration too far.  To avoid inserting
  /* The loop, above, always goes one iteration too far.  To avoid inserting
     an "if" statement inside the loop the last iteration is simply
     an "if" statement inside the loop the last iteration is simply
     reversed. */
     reversed. */
  dividend  = d;
  dividend  = d;
  remainder = remainder >> 1;
  remainder = remainder >> 1;
  num_bits++;
  num_bits++;
 
 
  for (i = 0; i < num_bits; i++)
  for (i = 0; i < num_bits; i++)
    {
    {
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
      bit            = (dividend & 0x8000000000000000ULL) >> 63;
      remainder = (remainder << 1) | bit;
      remainder = (remainder << 1) | bit;
      t              = remainder - divisor;
      t              = remainder - divisor;
      q              = !((t & 0x8000000000000000ULL) >> 63);
      q              = !((t & 0x8000000000000000ULL) >> 63);
      dividend       = dividend << 1;
      dividend       = dividend << 1;
      quotient  = (quotient << 1) | q;
      quotient  = (quotient << 1) | q;
 
 
      if (q)
      if (q)
        {
        {
          remainder = t;
          remainder = t;
        }
        }
    }
    }
 
 
  /* printf ("0x%08x%08x\n", (unsigned int) (quotient >> 32), */
  /* printf ("0x%08x%08x\n", (unsigned int) (quotient >> 32), */
  /*      (unsigned int) (quotient & 0xffffffff)); */
  /*      (unsigned int) (quotient & 0xffffffff)); */
 
 
  return  quotient;
  return  quotient;
 
 
}       /* ll_divu () */
}       /* ll_divu () */
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Read the simulator timer
/*!Read the simulator timer
 
 
   Uses the built-in simulator functionality to return the time in
   Uses the built-in simulator functionality to return the time in
   microseconds.
   microseconds.
 
 
   @note  Beware that this timer can wrap around.
   @note  Beware that this timer can wrap around.
 
 
   @return  The time used since the simulator started.                       */
   @return  The time used since the simulator started.                       */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
unsigned long int
unsigned long int
read_timer()
read_timer()
{
{
  unsigned long int       cycles_lo;
  unsigned long int       cycles_lo;
  unsigned long int       cycles_hi;
  unsigned long int       cycles_hi;
  unsigned long int       cycle_ps;
  unsigned long int       cycle_ps;
  unsigned long long int  time_us;
  unsigned long long int  time_us;
 
 
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_TICKS));
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_TICKS));
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycles_lo) : );
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycles_lo) : );
  __asm__ __volatile__ ("l.add\t\t%0,r0,r12": "=r" (cycles_hi) : );
  __asm__ __volatile__ ("l.add\t\t%0,r0,r12": "=r" (cycles_hi) : );
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_PS));
  __asm__ __volatile__ ("l.nop\t\t%0"       : : "K" (NOP_GET_PS));
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycle_ps) : );
  __asm__ __volatile__ ("l.add\t\t%0,r0,r11": "=r" (cycle_ps) : );
 
 
  unsigned long long int  cycles = ((unsigned long long int) cycles_hi << 32) |
  unsigned long long int  cycles = ((unsigned long long int) cycles_hi << 32) |
                                   ((unsigned long long int) cycles_lo);
                                   ((unsigned long long int) cycles_lo);
 
 
  /* This could overflow 64 bits, but if so then the result would overflow 32
  /* This could overflow 64 bits, but if so then the result would overflow 32
     bits. */
     bits. */
  time_us = ll_mulu (cycles, (unsigned long long int) cycle_ps);
  time_us = ll_mulu (cycles, (unsigned long long int) cycle_ps);
  time_us = ll_divu (time_us, 1000000UL);
  time_us = ll_divu (time_us, 1000000UL);
  return  (unsigned long int) time_us;
  return  (unsigned long int) time_us;
 
 
}       /* read_timer () */
}       /* read_timer () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Write a SPR
/*!Write a SPR
 
 
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
         as is for now due to large amount of user code that might need
         as is for now due to large amount of user code that might need
         changing.
         changing.
 
 
   @param[in] spr    The SPR to write
   @param[in] spr    The SPR to write
   @param[in] value  The value to write to the SPR                           */
   @param[in] value  The value to write to the SPR                           */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
void
void
mtspr (unsigned long int  spr,
mtspr (unsigned long int  spr,
       unsigned long int  value)
       unsigned long int  value)
{
{
  __asm__ __volatile__ ("l.mtspr\t\t%0,%1,0": : "r" (spr), "r" (value));
  __asm__ __volatile__ ("l.mtspr\t\t%0,%1,0": : "r" (spr), "r" (value));
 
 
}       /* mtspr () */
}       /* mtspr () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Read a SPR
/*!Read a SPR
 
 
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
   @todo Surely the SPR should be a short int, since it is only 16-bits. Left
         as is for now due to large amount of user code that might need
         as is for now due to large amount of user code that might need
         changing.
         changing.
 
 
   @param[in] spr    The SPR to write
   @param[in] spr    The SPR to write
 
 
   @return  The value read from the SPR                                      */
   @return  The value read from the SPR                                      */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
unsigned long int
unsigned long int
mfspr (unsigned long spr)
mfspr (unsigned long spr)
{
{
  unsigned long value;
  unsigned long value;
 
 
  __asm__ __volatile__ ("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr));
  __asm__ __volatile__ ("l.mfspr\t\t%0,%1,0" : "=r" (value) : "r" (spr));
 
 
  return value;
  return value;
 
 
}       /* mfspr () */
}       /* mfspr () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Copy between regions of memory
/*!Copy between regions of memory
 
 
   This should match the library version of memcpy
   This should match the library version of memcpy
 
 
   @param[out] dstvoid  Pointer to the destination memory area
   @param[out] dstvoid  Pointer to the destination memory area
   @param[in]  srcvoid  Pointer to the source memory area
   @param[in]  srcvoid  Pointer to the source memory area
   @param[in]  length   Number of bytes to copy.                             */
   @param[in]  length   Number of bytes to copy.                             */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
void *
void *
memcpy (void *__restrict          dstvoid,
memcpy (void *__restrict          dstvoid,
        __const void *__restrict  srcvoid,
        __const void *__restrict  srcvoid,
        size_t                    length)
        size_t                    length)
{
{
  char *dst = dstvoid;
  char *dst = dstvoid;
  const char *src = (const char *) srcvoid;
  const char *src = (const char *) srcvoid;
 
 
  while (length--)
  while (length--)
    {
    {
      *dst++ = *src++;
      *dst++ = *src++;
    }
    }
 
 
  return dst;
  return dst;
 
 
}       /* memcpy () */
}       /* memcpy () */
 
 
 No newline at end of file
 No newline at end of file
 
/* --------------------------------------------------------------------------*/
 
/*!Pseudo-random number generator
 
 
 
   This should return pseudo-random numbers, based on a Galois LFSR
 
 
 
   @return The next pseudo-random number                                     */
 
/* --------------------------------------------------------------------------*/
 
unsigned long int
 
rand ()
 
{
 
  static unsigned long int lfsr = 1;
 
  static int period = 0;
 
  /* taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
 
  lfsr = (lfsr >> 1) ^ (unsigned long int)((0 - (lfsr & 1u)) & 0xd0000001u);
 
  ++period;
 
  return lfsr;
 
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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