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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [sim/] [ppc/] [psim.c] - Diff between revs 827 and 840

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

Rev 827 Rev 840
/*  This file is part of the program psim.
/*  This file is part of the program psim.
 
 
    Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
    Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
 
 
    This program is free software; you can redistribute it and/or modify
    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
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    (at your option) any later version.
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 
    */
    */
 
 
 
 
#ifndef _PSIM_C_
#ifndef _PSIM_C_
#define _PSIM_C_
#define _PSIM_C_
 
 
#include "cpu.h" /* includes psim.h */
#include "cpu.h" /* includes psim.h */
#include "idecode.h"
#include "idecode.h"
#include "options.h"
#include "options.h"
 
 
#include "tree.h"
#include "tree.h"
 
 
#include <signal.h>
#include <signal.h>
 
 
#include <stdio.h>
#include <stdio.h>
#include <ctype.h>
#include <ctype.h>
 
 
#ifdef HAVE_STDLIB_H
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#endif
 
 
#include <setjmp.h>
#include <setjmp.h>
 
 
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#else
#else
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRINGS_H
#include <strings.h>
#include <strings.h>
#endif
#endif
#endif
#endif
 
 
 
 
#include "bfd.h"
#include "bfd.h"
#include "libiberty.h"
#include "libiberty.h"
#include "gdb/signals.h"
#include "gdb/signals.h"
 
 
/* system structure, actual size of processor array determined at
/* system structure, actual size of processor array determined at
   runtime */
   runtime */
 
 
struct _psim {
struct _psim {
  event_queue *events;
  event_queue *events;
  device *devices;
  device *devices;
  mon *monitor;
  mon *monitor;
  os_emul *os_emulation;
  os_emul *os_emulation;
  core *memory;
  core *memory;
 
 
  /* escape routine for inner functions */
  /* escape routine for inner functions */
  void *path_to_halt;
  void *path_to_halt;
  void *path_to_restart;
  void *path_to_restart;
 
 
  /* status from last halt */
  /* status from last halt */
  psim_status halt_status;
  psim_status halt_status;
 
 
  /* the processors proper */
  /* the processors proper */
  int nr_cpus;
  int nr_cpus;
  int last_cpu; /* CPU that last (tried to) execute an instruction */
  int last_cpu; /* CPU that last (tried to) execute an instruction */
  cpu *processors[MAX_NR_PROCESSORS];
  cpu *processors[MAX_NR_PROCESSORS];
};
};
 
 
 
 
int current_target_byte_order;
int current_target_byte_order;
int current_host_byte_order;
int current_host_byte_order;
int current_environment;
int current_environment;
int current_alignment;
int current_alignment;
int current_floating_point;
int current_floating_point;
int current_model_issue = MODEL_ISSUE_IGNORE;
int current_model_issue = MODEL_ISSUE_IGNORE;
int current_stdio = DO_USE_STDIO;
int current_stdio = DO_USE_STDIO;
model_enum current_model = WITH_DEFAULT_MODEL;
model_enum current_model = WITH_DEFAULT_MODEL;
 
 
 
 
/* create the device tree */
/* create the device tree */
 
 
INLINE_PSIM\
INLINE_PSIM\
(device *)
(device *)
psim_tree(void)
psim_tree(void)
{
{
  device *root = tree_parse(NULL, "core");
  device *root = tree_parse(NULL, "core");
  tree_parse(root, "/aliases");
  tree_parse(root, "/aliases");
  tree_parse(root, "/options");
  tree_parse(root, "/options");
  tree_parse(root, "/chosen");
  tree_parse(root, "/chosen");
  tree_parse(root, "/packages");
  tree_parse(root, "/packages");
  tree_parse(root, "/cpus");
  tree_parse(root, "/cpus");
  tree_parse(root, "/openprom");
  tree_parse(root, "/openprom");
  tree_parse(root, "/openprom/init");
  tree_parse(root, "/openprom/init");
  tree_parse(root, "/openprom/trace");
  tree_parse(root, "/openprom/trace");
  tree_parse(root, "/openprom/options");
  tree_parse(root, "/openprom/options");
  return root;
  return root;
}
}
 
 
STATIC_INLINE_PSIM\
STATIC_INLINE_PSIM\
(char *)
(char *)
find_arg(char *err_msg,
find_arg(char *err_msg,
         int *ptr_to_argp,
         int *ptr_to_argp,
         char **argv)
         char **argv)
{
{
  *ptr_to_argp += 1;
  *ptr_to_argp += 1;
  if (argv[*ptr_to_argp] == NULL)
  if (argv[*ptr_to_argp] == NULL)
    error(err_msg);
    error(err_msg);
  return argv[*ptr_to_argp];
  return argv[*ptr_to_argp];
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_usage(int verbose)
psim_usage(int verbose)
{
{
  printf_filtered("Usage:\n");
  printf_filtered("Usage:\n");
  printf_filtered("\n");
  printf_filtered("\n");
  printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
  printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
  printf_filtered("\n");
  printf_filtered("\n");
  printf_filtered("Where\n");
  printf_filtered("Where\n");
  printf_filtered("\n");
  printf_filtered("\n");
  printf_filtered("\t<image>         Name of the PowerPC program to run.\n");
  printf_filtered("\t<image>         Name of the PowerPC program to run.\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\t                This can either be a PowerPC binary or\n");
  printf_filtered("\t                This can either be a PowerPC binary or\n");
  printf_filtered("\t                a text file containing a device tree\n");
  printf_filtered("\t                a text file containing a device tree\n");
  printf_filtered("\t                specification.\n");
  printf_filtered("\t                specification.\n");
  printf_filtered("\t                PSIM will attempt to determine from the\n");
  printf_filtered("\t                PSIM will attempt to determine from the\n");
  printf_filtered("\t                specified <image> the intended emulation\n");
  printf_filtered("\t                specified <image> the intended emulation\n");
  printf_filtered("\t                environment.\n");
  printf_filtered("\t                environment.\n");
  printf_filtered("\t                If PSIM gets it wrong, the emulation\n");
  printf_filtered("\t                If PSIM gets it wrong, the emulation\n");
  printf_filtered("\t                environment can be specified using the\n");
  printf_filtered("\t                environment can be specified using the\n");
  printf_filtered("\t                `-e' option (described below).\n");
  printf_filtered("\t                `-e' option (described below).\n");
  printf_filtered("\n"); }
  printf_filtered("\n"); }
  printf_filtered("\t<image-arg>     Argument to be passed to <image>\n");
  printf_filtered("\t<image-arg>     Argument to be passed to <image>\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\t                These arguments will be passed to\n");
  printf_filtered("\t                These arguments will be passed to\n");
  printf_filtered("\t                <image> (as standard C argv, argc)\n");
  printf_filtered("\t                <image> (as standard C argv, argc)\n");
  printf_filtered("\t                when <image> is started.\n");
  printf_filtered("\t                when <image> is started.\n");
  printf_filtered("\n"); }
  printf_filtered("\n"); }
  printf_filtered("\t<psim-option>   See below\n");
  printf_filtered("\t<psim-option>   See below\n");
  printf_filtered("\n");
  printf_filtered("\n");
  printf_filtered("The following are valid <psim-option>s:\n");
  printf_filtered("The following are valid <psim-option>s:\n");
  printf_filtered("\n");
  printf_filtered("\n");
 
 
  printf_filtered("\t-c <count>      Limit the simulation to <count> iterations\n");
  printf_filtered("\t-c <count>      Limit the simulation to <count> iterations\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\n");
  printf_filtered("\n");
  }
  }
 
 
  printf_filtered("\t-i or -i2       Print instruction counting statistics\n");
  printf_filtered("\t-i or -i2       Print instruction counting statistics\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\t                Specify -i2 for a more detailed display\n");
  printf_filtered("\t                Specify -i2 for a more detailed display\n");
  printf_filtered("\n");
  printf_filtered("\n");
  }
  }
 
 
  printf_filtered("\t-I              Print execution unit statistics\n");
  printf_filtered("\t-I              Print execution unit statistics\n");
  if (verbose) { printf_filtered("\n"); }
  if (verbose) { printf_filtered("\n"); }
 
 
  printf_filtered("\t-e <os-emul>    specify an OS or platform to model\n");
  printf_filtered("\t-e <os-emul>    specify an OS or platform to model\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\t                Can be any of the following:\n");
  printf_filtered("\t                Can be any of the following:\n");
  printf_filtered("\t                bug - OEA + MOTO BUG ROM calls\n");
  printf_filtered("\t                bug - OEA + MOTO BUG ROM calls\n");
  printf_filtered("\t                netbsd - UEA + NetBSD system calls\n");
  printf_filtered("\t                netbsd - UEA + NetBSD system calls\n");
  printf_filtered("\t                solaris - UEA + Solaris system calls\n");
  printf_filtered("\t                solaris - UEA + Solaris system calls\n");
  printf_filtered("\t                linux - UEA + Linux system calls\n");
  printf_filtered("\t                linux - UEA + Linux system calls\n");
  printf_filtered("\t                chirp - OEA + a few OpenBoot calls\n");
  printf_filtered("\t                chirp - OEA + a few OpenBoot calls\n");
  printf_filtered("\n"); }
  printf_filtered("\n"); }
 
 
  printf_filtered("\t-E <endian>     Specify the endianness of the target\n");
  printf_filtered("\t-E <endian>     Specify the endianness of the target\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\t                Can be any of the following:\n");
  printf_filtered("\t                Can be any of the following:\n");
  printf_filtered("\t                big - big endian target\n");
  printf_filtered("\t                big - big endian target\n");
  printf_filtered("\t                little - little endian target\n");
  printf_filtered("\t                little - little endian target\n");
  printf_filtered("\n"); }
  printf_filtered("\n"); }
 
 
  printf_filtered("\t-f <file>       Merge <file> into the device tree\n");
  printf_filtered("\t-f <file>       Merge <file> into the device tree\n");
  if (verbose) { printf_filtered("\n"); }
  if (verbose) { printf_filtered("\n"); }
 
 
  printf_filtered("\t-h -? -H        give more detailed usage\n");
  printf_filtered("\t-h -? -H        give more detailed usage\n");
  if (verbose) { printf_filtered("\n"); }
  if (verbose) { printf_filtered("\n"); }
 
 
  printf_filtered("\t-m <model>      Specify the processor to model (604)\n");
  printf_filtered("\t-m <model>      Specify the processor to model (604)\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\t                Selects the processor to use when\n");
  printf_filtered("\t                Selects the processor to use when\n");
  printf_filtered("\t                modeling execution units.  Includes:\n");
  printf_filtered("\t                modeling execution units.  Includes:\n");
  printf_filtered("\t                604, 603 and 603e\n");
  printf_filtered("\t                604, 603 and 603e\n");
  printf_filtered("\n"); }
  printf_filtered("\n"); }
 
 
  printf_filtered("\t-n <nr-smp>     Specify the number of processors in SMP simulations\n");
  printf_filtered("\t-n <nr-smp>     Specify the number of processors in SMP simulations\n");
  if (verbose) {
  if (verbose) {
  printf_filtered("\t                Specifies the number of processors that are\n");
  printf_filtered("\t                Specifies the number of processors that are\n");
  printf_filtered("\t                to be modeled in a symetric multi-processor (SMP)\n");
  printf_filtered("\t                to be modeled in a symetric multi-processor (SMP)\n");
  printf_filtered("\t                simulation\n");
  printf_filtered("\t                simulation\n");
  printf_filtered("\n"); }
  printf_filtered("\n"); }
 
 
  printf_filtered("\t-o <dev-spec>   Add device <dev-spec> to the device tree\n");
  printf_filtered("\t-o <dev-spec>   Add device <dev-spec> to the device tree\n");
  if (verbose) { printf_filtered("\n"); }
  if (verbose) { printf_filtered("\n"); }
 
 
  printf_filtered("\t-r <ram-size>   Set RAM size in bytes (OEA environments)\n");
  printf_filtered("\t-r <ram-size>   Set RAM size in bytes (OEA environments)\n");
  if (verbose) { printf_filtered("\n"); }
  if (verbose) { printf_filtered("\n"); }
 
 
  printf_filtered("\t-t [!]<trace>   Enable (disable) <trace> option\n");
  printf_filtered("\t-t [!]<trace>   Enable (disable) <trace> option\n");
  if (verbose) { printf_filtered("\n"); }
  if (verbose) { printf_filtered("\n"); }
 
 
  printf_filtered("\n");
  printf_filtered("\n");
  trace_usage(verbose);
  trace_usage(verbose);
  device_usage(verbose);
  device_usage(verbose);
  if (verbose > 1) {
  if (verbose > 1) {
    printf_filtered("\n");
    printf_filtered("\n");
    print_options();
    print_options();
  }
  }
  error("");
  error("");
}
}
 
 
/* Test "string" for containing a string of digits that form a number
/* Test "string" for containing a string of digits that form a number
between "min" and "max".  The return value is the number or "err". */
between "min" and "max".  The return value is the number or "err". */
static
static
int is_num( char *string, int min, int max, int err)
int is_num( char *string, int min, int max, int err)
{
{
  int result = 0;
  int result = 0;
 
 
  for ( ; *string; ++string)
  for ( ; *string; ++string)
  {
  {
    if (!isdigit(*string))
    if (!isdigit(*string))
    {
    {
      result = err;
      result = err;
      break;
      break;
    }
    }
    result = result * 10 + (*string - '0');
    result = result * 10 + (*string - '0');
  }
  }
  if (result < min || result > max)
  if (result < min || result > max)
    result = err;
    result = err;
 
 
  return result;
  return result;
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(char **)
(char **)
psim_options(device *root,
psim_options(device *root,
             char **argv)
             char **argv)
{
{
  device *current = root;
  device *current = root;
  int argp;
  int argp;
  if (argv == NULL)
  if (argv == NULL)
    return NULL;
    return NULL;
  argp = 0;
  argp = 0;
  while (argv[argp] != NULL && argv[argp][0] == '-') {
  while (argv[argp] != NULL && argv[argp][0] == '-') {
    char *p = argv[argp] + 1;
    char *p = argv[argp] + 1;
    char *param;
    char *param;
    while (*p != '\0') {
    while (*p != '\0') {
      switch (*p) {
      switch (*p) {
      default:
      default:
        psim_usage(0);
        psim_usage(0);
        error ("");
        error ("");
        break;
        break;
      case 'c':
      case 'c':
        param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
        param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
        tree_parse(root, "/openprom/options/max-iterations %s", param);
        tree_parse(root, "/openprom/options/max-iterations %s", param);
        break;
        break;
      case 'e':
      case 'e':
        param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
        param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
        tree_parse(root, "/openprom/options/os-emul %s", param);
        tree_parse(root, "/openprom/options/os-emul %s", param);
        break;
        break;
      case 'E':
      case 'E':
        /* endian spec, ignored for now */
        /* endian spec, ignored for now */
        param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
        param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
        if (strcmp (param, "big") == 0)
        if (strcmp (param, "big") == 0)
          tree_parse (root, "/options/little-endian? false");
          tree_parse (root, "/options/little-endian? false");
        else if (strcmp (param, "little") == 0)
        else if (strcmp (param, "little") == 0)
          tree_parse (root, "/options/little-endian? true");
          tree_parse (root, "/options/little-endian? true");
        else
        else
          {
          {
            printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
            printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
            psim_usage (0);
            psim_usage (0);
          }
          }
        break;
        break;
      case 'f':
      case 'f':
        param = find_arg("Missing <file> option for -f\n", &argp, argv);
        param = find_arg("Missing <file> option for -f\n", &argp, argv);
        psim_merge_device_file(root, param);
        psim_merge_device_file(root, param);
        break;
        break;
      case 'h':
      case 'h':
      case '?':
      case '?':
        psim_usage(1);
        psim_usage(1);
        break;
        break;
      case 'H':
      case 'H':
        psim_usage(2);
        psim_usage(2);
        break;
        break;
      case 'i':
      case 'i':
        if (isdigit(p[1])) {
        if (isdigit(p[1])) {
          tree_parse(root, "/openprom/trace/print-info %c", p[1]);
          tree_parse(root, "/openprom/trace/print-info %c", p[1]);
          p++;
          p++;
        }
        }
        else {
        else {
          tree_parse(root, "/openprom/trace/print-info 1");
          tree_parse(root, "/openprom/trace/print-info 1");
        }
        }
        break;
        break;
      case 'I':
      case 'I':
        tree_parse(root, "/openprom/trace/print-info 2");
        tree_parse(root, "/openprom/trace/print-info 2");
        tree_parse(root, "/openprom/options/model-issue %d",
        tree_parse(root, "/openprom/options/model-issue %d",
                   MODEL_ISSUE_PROCESS);
                   MODEL_ISSUE_PROCESS);
        break;
        break;
      case 'm':
      case 'm':
        param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
        param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
        tree_parse(root, "/openprom/options/model \"%s", param);
        tree_parse(root, "/openprom/options/model \"%s", param);
        break;
        break;
      case 'n':
      case 'n':
        param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
        param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
        tree_parse(root, "/openprom/options/smp %s", param);
        tree_parse(root, "/openprom/options/smp %s", param);
        break;
        break;
      case 'o':
      case 'o':
        param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
        param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
        if (memcmp(param, "mpc860c0", 8) == 0)
        if (memcmp(param, "mpc860c0", 8) == 0)
        {
        {
          if (param[8] == '\0')
          if (param[8] == '\0')
            tree_parse(root, "/options/mpc860c0 5");
            tree_parse(root, "/options/mpc860c0 5");
          else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
          else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
          {
          {
            tree_parse(root, "/options/mpc860c0 %s", param+9);
            tree_parse(root, "/options/mpc860c0 %s", param+9);
          }
          }
          else error("Invalid mpc860c0 option for -o\n");
          else error("Invalid mpc860c0 option for -o\n");
        }
        }
        else
        else
          current = tree_parse(current, "%s", param);
          current = tree_parse(current, "%s", param);
        break;
        break;
      case 'r':
      case 'r':
        param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
        param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
        tree_parse(root, "/openprom/options/oea-memory-size %s",
        tree_parse(root, "/openprom/options/oea-memory-size %s",
                               param);
                               param);
        break;
        break;
      case 't':
      case 't':
        param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
        param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
        if (param[0] == '!')
        if (param[0] == '!')
          tree_parse(root, "/openprom/trace/%s 0", param+1);
          tree_parse(root, "/openprom/trace/%s 0", param+1);
        else
        else
          tree_parse(root, "/openprom/trace/%s 1", param);
          tree_parse(root, "/openprom/trace/%s 1", param);
        break;
        break;
      case '-':
      case '-':
        /* it's a long option of the form --optionname=optionvalue.
        /* it's a long option of the form --optionname=optionvalue.
           Such options can be passed through if we are invoked by
           Such options can be passed through if we are invoked by
           gdb.  */
           gdb.  */
        if (strstr(argv[argp], "architecture") != NULL) {
        if (strstr(argv[argp], "architecture") != NULL) {
          /* we must consume the argument here, so that we get out
          /* we must consume the argument here, so that we get out
             of the loop.  */
             of the loop.  */
          p = argv[argp] + strlen(argv[argp]) - 1;
          p = argv[argp] + strlen(argv[argp]) - 1;
          printf_filtered("Warning - architecture parameter ignored\n");
          printf_filtered("Warning - architecture parameter ignored\n");
        }
        }
        else
        else
          error("Unrecognized option");
          error("Unrecognized option");
        break;
        break;
      }
      }
      p += 1;
      p += 1;
    }
    }
    argp += 1;
    argp += 1;
  }
  }
  /* force the trace node to process its options now *before* the tree
  /* force the trace node to process its options now *before* the tree
     initialization occures */
     initialization occures */
  device_ioctl(tree_find_device(root, "/openprom/trace"),
  device_ioctl(tree_find_device(root, "/openprom/trace"),
               NULL, 0,
               NULL, 0,
               device_ioctl_set_trace);
               device_ioctl_set_trace);
 
 
  {
  {
    void semantic_init(device* root);
    void semantic_init(device* root);
    semantic_init(root);
    semantic_init(root);
  }
  }
 
 
  /* return where the options end */
  /* return where the options end */
  return argv + argp;
  return argv + argp;
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_command(device *root,
psim_command(device *root,
             char **argv)
             char **argv)
{
{
  int argp = 0;
  int argp = 0;
  if (argv[argp] == NULL) {
  if (argv[argp] == NULL) {
    return;
    return;
  }
  }
  else if (strcmp(argv[argp], "trace") == 0) {
  else if (strcmp(argv[argp], "trace") == 0) {
    const char *opt = find_arg("Missing <trace> option", &argp, argv);
    const char *opt = find_arg("Missing <trace> option", &argp, argv);
    if (opt[0] == '!')
    if (opt[0] == '!')
      trace_option(opt + 1, 0);
      trace_option(opt + 1, 0);
    else
    else
      trace_option(opt, 1);
      trace_option(opt, 1);
  }
  }
  else if (strcmp(*argv, "change-media") == 0) {
  else if (strcmp(*argv, "change-media") == 0) {
    char *device = find_arg("Missing device name", &argp, argv);
    char *device = find_arg("Missing device name", &argp, argv);
    char *media = argv[++argp];
    char *media = argv[++argp];
    device_ioctl(tree_find_device(root, device), NULL, 0,
    device_ioctl(tree_find_device(root, device), NULL, 0,
                 device_ioctl_change_media, media);
                 device_ioctl_change_media, media);
  }
  }
  else {
  else {
    printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
    printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
    printf_filtered("    trace <trace-option>\n");
    printf_filtered("    trace <trace-option>\n");
    printf_filtered("    change-media <device> [ <new-image> ]\n");
    printf_filtered("    change-media <device> [ <new-image> ]\n");
  }
  }
}
}
 
 
 
 
/* create the simulator proper from the device tree and executable */
/* create the simulator proper from the device tree and executable */
 
 
INLINE_PSIM\
INLINE_PSIM\
(psim *)
(psim *)
psim_create(const char *file_name,
psim_create(const char *file_name,
            device *root)
            device *root)
{
{
  int cpu_nr;
  int cpu_nr;
  const char *env;
  const char *env;
  psim *system;
  psim *system;
  os_emul *os_emulation;
  os_emul *os_emulation;
  int nr_cpus;
  int nr_cpus;
 
 
  /* given this partially populated device tree, os_emul_create() uses
  /* given this partially populated device tree, os_emul_create() uses
     it and file_name to determine the selected emulation and hence
     it and file_name to determine the selected emulation and hence
     further populate the tree with any other required nodes. */
     further populate the tree with any other required nodes. */
 
 
  os_emulation = os_emul_create(file_name, root);
  os_emulation = os_emul_create(file_name, root);
  if (os_emulation == NULL)
  if (os_emulation == NULL)
    error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
    error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
 
 
  /* fill in the missing real number of CPU's */
  /* fill in the missing real number of CPU's */
  nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
  nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
  if (MAX_NR_PROCESSORS < nr_cpus)
  if (MAX_NR_PROCESSORS < nr_cpus)
    error("target and configured number of cpus conflict\n");
    error("target and configured number of cpus conflict\n");
 
 
  /* fill in the missing TARGET BYTE ORDER information */
  /* fill in the missing TARGET BYTE ORDER information */
  current_target_byte_order
  current_target_byte_order
    = (tree_find_boolean_property(root, "/options/little-endian?")
    = (tree_find_boolean_property(root, "/options/little-endian?")
       ? LITTLE_ENDIAN
       ? LITTLE_ENDIAN
       : BIG_ENDIAN);
       : BIG_ENDIAN);
  if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
  if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
    error("target and configured byte order conflict\n");
    error("target and configured byte order conflict\n");
 
 
  /* fill in the missing HOST BYTE ORDER information */
  /* fill in the missing HOST BYTE ORDER information */
  current_host_byte_order = (current_host_byte_order = 1,
  current_host_byte_order = (current_host_byte_order = 1,
                             (*(char*)(&current_host_byte_order)
                             (*(char*)(&current_host_byte_order)
                              ? LITTLE_ENDIAN
                              ? LITTLE_ENDIAN
                              : BIG_ENDIAN));
                              : BIG_ENDIAN));
  if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
  if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
    error("host and configured byte order conflict\n");
    error("host and configured byte order conflict\n");
 
 
  /* fill in the missing OEA/VEA information */
  /* fill in the missing OEA/VEA information */
  env = tree_find_string_property(root, "/openprom/options/env");
  env = tree_find_string_property(root, "/openprom/options/env");
  current_environment = ((strcmp(env, "user") == 0
  current_environment = ((strcmp(env, "user") == 0
                          || strcmp(env, "uea") == 0)
                          || strcmp(env, "uea") == 0)
                         ? USER_ENVIRONMENT
                         ? USER_ENVIRONMENT
                         : (strcmp(env, "virtual") == 0
                         : (strcmp(env, "virtual") == 0
                            || strcmp(env, "vea") == 0)
                            || strcmp(env, "vea") == 0)
                         ? VIRTUAL_ENVIRONMENT
                         ? VIRTUAL_ENVIRONMENT
                         : (strcmp(env, "operating") == 0
                         : (strcmp(env, "operating") == 0
                            || strcmp(env, "oea") == 0)
                            || strcmp(env, "oea") == 0)
                         ? OPERATING_ENVIRONMENT
                         ? OPERATING_ENVIRONMENT
                         : 0);
                         : 0);
  if (current_environment == 0)
  if (current_environment == 0)
    error("unreconized /options env property\n");
    error("unreconized /options env property\n");
  if (CURRENT_ENVIRONMENT != current_environment)
  if (CURRENT_ENVIRONMENT != current_environment)
    error("target and configured environment conflict\n");
    error("target and configured environment conflict\n");
 
 
  /* fill in the missing ALLIGNMENT information */
  /* fill in the missing ALLIGNMENT information */
  current_alignment
  current_alignment
    = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
    = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
       ? STRICT_ALIGNMENT
       ? STRICT_ALIGNMENT
       : NONSTRICT_ALIGNMENT);
       : NONSTRICT_ALIGNMENT);
  if (CURRENT_ALIGNMENT != current_alignment)
  if (CURRENT_ALIGNMENT != current_alignment)
    error("target and configured alignment conflict\n");
    error("target and configured alignment conflict\n");
 
 
  /* fill in the missing FLOATING POINT information */
  /* fill in the missing FLOATING POINT information */
  current_floating_point
  current_floating_point
    = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
    = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
       ? HARD_FLOATING_POINT
       ? HARD_FLOATING_POINT
       : SOFT_FLOATING_POINT);
       : SOFT_FLOATING_POINT);
  if (CURRENT_FLOATING_POINT != current_floating_point)
  if (CURRENT_FLOATING_POINT != current_floating_point)
    error("target and configured floating-point conflict\n");
    error("target and configured floating-point conflict\n");
 
 
  /* fill in the missing STDIO information */
  /* fill in the missing STDIO information */
  current_stdio
  current_stdio
    = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
    = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
       ? DO_USE_STDIO
       ? DO_USE_STDIO
       : DONT_USE_STDIO);
       : DONT_USE_STDIO);
  if (CURRENT_STDIO != current_stdio)
  if (CURRENT_STDIO != current_stdio)
    error("target and configured stdio interface conflict\n");
    error("target and configured stdio interface conflict\n");
 
 
  /* sort out the level of detail for issue modeling */
  /* sort out the level of detail for issue modeling */
  current_model_issue
  current_model_issue
    = tree_find_integer_property(root, "/openprom/options/model-issue");
    = tree_find_integer_property(root, "/openprom/options/model-issue");
  if (CURRENT_MODEL_ISSUE != current_model_issue)
  if (CURRENT_MODEL_ISSUE != current_model_issue)
    error("target and configured model-issue conflict\n");
    error("target and configured model-issue conflict\n");
 
 
  /* sort out our model architecture - wrong.
  /* sort out our model architecture - wrong.
 
 
     FIXME: this should be obtaining the required information from the
     FIXME: this should be obtaining the required information from the
     device tree via the "/chosen" property "cpu" which is an instance
     device tree via the "/chosen" property "cpu" which is an instance
     (ihandle) for the only executing processor. By converting that
     (ihandle) for the only executing processor. By converting that
     ihandle into the corresponding cpu's phandle and then querying
     ihandle into the corresponding cpu's phandle and then querying
     the "name" property, the cpu type can be determined. Ok? */
     the "name" property, the cpu type can be determined. Ok? */
 
 
  model_set(tree_find_string_property(root, "/openprom/options/model"));
  model_set(tree_find_string_property(root, "/openprom/options/model"));
 
 
  /* create things */
  /* create things */
  system = ZALLOC(psim);
  system = ZALLOC(psim);
  system->events = event_queue_create();
  system->events = event_queue_create();
  system->memory = core_from_device(root);
  system->memory = core_from_device(root);
  system->monitor = mon_create();
  system->monitor = mon_create();
  system->nr_cpus = nr_cpus;
  system->nr_cpus = nr_cpus;
  system->os_emulation = os_emulation;
  system->os_emulation = os_emulation;
  system->devices = root;
  system->devices = root;
 
 
  /* now all the processors attaching to each their per-cpu information */
  /* now all the processors attaching to each their per-cpu information */
  for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
  for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
    system->processors[cpu_nr] = cpu_create(system,
    system->processors[cpu_nr] = cpu_create(system,
                                            system->memory,
                                            system->memory,
                                            mon_cpu(system->monitor,
                                            mon_cpu(system->monitor,
                                                    cpu_nr),
                                                    cpu_nr),
                                            system->os_emulation,
                                            system->os_emulation,
                                            cpu_nr);
                                            cpu_nr);
  }
  }
 
 
  /* dump out the contents of the device tree */
  /* dump out the contents of the device tree */
  if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
  if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
    tree_print(root);
    tree_print(root);
  if (ppc_trace[trace_dump_device_tree])
  if (ppc_trace[trace_dump_device_tree])
    error("");
    error("");
 
 
  return system;
  return system;
}
}
 
 
 
 
/* allow the simulation to stop/restart abnormaly */
/* allow the simulation to stop/restart abnormaly */
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_set_halt_and_restart(psim *system,
psim_set_halt_and_restart(psim *system,
                          void *halt_jmp_buf,
                          void *halt_jmp_buf,
                          void *restart_jmp_buf)
                          void *restart_jmp_buf)
{
{
  system->path_to_halt = halt_jmp_buf;
  system->path_to_halt = halt_jmp_buf;
  system->path_to_restart = restart_jmp_buf;
  system->path_to_restart = restart_jmp_buf;
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_clear_halt_and_restart(psim *system)
psim_clear_halt_and_restart(psim *system)
{
{
  system->path_to_halt = NULL;
  system->path_to_halt = NULL;
  system->path_to_restart = NULL;
  system->path_to_restart = NULL;
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_restart(psim *system,
psim_restart(psim *system,
             int current_cpu)
             int current_cpu)
{
{
  ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
  ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
  ASSERT(system->path_to_restart != NULL);
  ASSERT(system->path_to_restart != NULL);
  system->last_cpu = current_cpu;
  system->last_cpu = current_cpu;
  longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
  longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
}
}
 
 
 
 
static void
static void
cntrl_c_simulation(void *data)
cntrl_c_simulation(void *data)
{
{
  psim *system = data;
  psim *system = data;
  psim_halt(system,
  psim_halt(system,
            psim_nr_cpus(system),
            psim_nr_cpus(system),
            was_continuing,
            was_continuing,
            TARGET_SIGNAL_INT);
            TARGET_SIGNAL_INT);
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_stop(psim *system)
psim_stop(psim *system)
{
{
  event_queue_schedule_after_signal(psim_event_queue(system),
  event_queue_schedule_after_signal(psim_event_queue(system),
                                    0 /*NOW*/,
                                    0 /*NOW*/,
                                    cntrl_c_simulation,
                                    cntrl_c_simulation,
                                    system);
                                    system);
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_halt(psim *system,
psim_halt(psim *system,
          int current_cpu,
          int current_cpu,
          stop_reason reason,
          stop_reason reason,
          int signal)
          int signal)
{
{
  ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
  ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
  ASSERT(system->path_to_halt != NULL);
  ASSERT(system->path_to_halt != NULL);
  system->last_cpu = current_cpu;
  system->last_cpu = current_cpu;
  system->halt_status.reason = reason;
  system->halt_status.reason = reason;
  system->halt_status.signal = signal;
  system->halt_status.signal = signal;
  if (current_cpu == system->nr_cpus) {
  if (current_cpu == system->nr_cpus) {
    system->halt_status.cpu_nr = 0;
    system->halt_status.cpu_nr = 0;
    system->halt_status.program_counter =
    system->halt_status.program_counter =
      cpu_get_program_counter(system->processors[0]);
      cpu_get_program_counter(system->processors[0]);
  }
  }
  else {
  else {
    system->halt_status.cpu_nr = current_cpu;
    system->halt_status.cpu_nr = current_cpu;
    system->halt_status.program_counter =
    system->halt_status.program_counter =
      cpu_get_program_counter(system->processors[current_cpu]);
      cpu_get_program_counter(system->processors[current_cpu]);
  }
  }
  longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
  longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
}
}
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(int)
(int)
psim_last_cpu(psim *system)
psim_last_cpu(psim *system)
{
{
  return system->last_cpu;
  return system->last_cpu;
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(int)
(int)
psim_nr_cpus(psim *system)
psim_nr_cpus(psim *system)
{
{
  return system->nr_cpus;
  return system->nr_cpus;
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(psim_status)
(psim_status)
psim_get_status(psim *system)
psim_get_status(psim *system)
{
{
  return system->halt_status;
  return system->halt_status;
}
}
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(cpu *)
(cpu *)
psim_cpu(psim *system,
psim_cpu(psim *system,
         int cpu_nr)
         int cpu_nr)
{
{
  if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
  if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
    return NULL;
    return NULL;
  else
  else
    return system->processors[cpu_nr];
    return system->processors[cpu_nr];
}
}
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(device *)
(device *)
psim_device(psim *system,
psim_device(psim *system,
            const char *path)
            const char *path)
{
{
  return tree_find_device(system->devices, path);
  return tree_find_device(system->devices, path);
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(event_queue *)
(event_queue *)
psim_event_queue(psim *system)
psim_event_queue(psim *system)
{
{
  return system->events;
  return system->events;
}
}
 
 
 
 
 
 
STATIC_INLINE_PSIM\
STATIC_INLINE_PSIM\
(void)
(void)
psim_max_iterations_exceeded(void *data)
psim_max_iterations_exceeded(void *data)
{
{
  psim *system = data;
  psim *system = data;
  psim_halt(system,
  psim_halt(system,
            system->nr_cpus, /* halted during an event */
            system->nr_cpus, /* halted during an event */
            was_signalled,
            was_signalled,
            -1);
            -1);
}
}
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_init(psim *system)
psim_init(psim *system)
{
{
  int cpu_nr;
  int cpu_nr;
 
 
  /* scrub the monitor */
  /* scrub the monitor */
  mon_init(system->monitor, system->nr_cpus);
  mon_init(system->monitor, system->nr_cpus);
 
 
  /* trash any pending events */
  /* trash any pending events */
  event_queue_init(system->events);
  event_queue_init(system->events);
 
 
  /* if needed, schedule a halt event.  FIXME - In the future this
  /* if needed, schedule a halt event.  FIXME - In the future this
     will be replaced by a more generic change to psim_command().  A
     will be replaced by a more generic change to psim_command().  A
     new command `schedule NNN halt' being added. */
     new command `schedule NNN halt' being added. */
  if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
  if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
    event_queue_schedule(system->events,
    event_queue_schedule(system->events,
                         tree_find_integer_property(system->devices,
                         tree_find_integer_property(system->devices,
                                                    "/openprom/options/max-iterations") - 2,
                                                    "/openprom/options/max-iterations") - 2,
                         psim_max_iterations_exceeded,
                         psim_max_iterations_exceeded,
                         system);
                         system);
  }
  }
 
 
  /* scrub all the cpus */
  /* scrub all the cpus */
  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
    cpu_init(system->processors[cpu_nr]);
    cpu_init(system->processors[cpu_nr]);
 
 
  /* init all the devices (which updates the cpus) */
  /* init all the devices (which updates the cpus) */
  tree_init(system->devices, system);
  tree_init(system->devices, system);
 
 
  /* and the emulation (which needs an initialized device tree) */
  /* and the emulation (which needs an initialized device tree) */
  os_emul_init(system->os_emulation, system->nr_cpus);
  os_emul_init(system->os_emulation, system->nr_cpus);
 
 
  /* now sync each cpu against the initialized state of its registers */
  /* now sync each cpu against the initialized state of its registers */
  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
  for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
    cpu *processor = system->processors[cpu_nr];
    cpu *processor = system->processors[cpu_nr];
    cpu_synchronize_context(processor, cpu_get_program_counter(processor));
    cpu_synchronize_context(processor, cpu_get_program_counter(processor));
    cpu_page_tlb_invalidate_all(processor);
    cpu_page_tlb_invalidate_all(processor);
  }
  }
 
 
  /* force loop to start with first cpu */
  /* force loop to start with first cpu */
  system->last_cpu = -1;
  system->last_cpu = -1;
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_stack(psim *system,
psim_stack(psim *system,
           char **argv,
           char **argv,
           char **envp)
           char **envp)
{
{
  /* pass the stack device the argv/envp and let it work out what to
  /* pass the stack device the argv/envp and let it work out what to
     do with it */
     do with it */
  device *stack_device = tree_find_device(system->devices,
  device *stack_device = tree_find_device(system->devices,
                                          "/openprom/init/stack");
                                          "/openprom/init/stack");
  if (stack_device != (device*)0) {
  if (stack_device != (device*)0) {
    unsigned_word stack_pointer;
    unsigned_word stack_pointer;
    ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
    ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
                               cooked_transfer) > 0);
                               cooked_transfer) > 0);
    device_ioctl(stack_device,
    device_ioctl(stack_device,
                 NULL, /*cpu*/
                 NULL, /*cpu*/
                 0, /*cia*/
                 0, /*cia*/
                 device_ioctl_create_stack,
                 device_ioctl_create_stack,
                 stack_pointer,
                 stack_pointer,
                 argv,
                 argv,
                 envp);
                 envp);
  }
  }
}
}
 
 
 
 
 
 
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
   thing */
   thing */
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_step(psim *system)
psim_step(psim *system)
{
{
  volatile int keep_running = 0;
  volatile int keep_running = 0;
  idecode_run_until_stop(system, &keep_running,
  idecode_run_until_stop(system, &keep_running,
                         system->events, system->processors, system->nr_cpus);
                         system->events, system->processors, system->nr_cpus);
}
}
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_run(psim *system)
psim_run(psim *system)
{
{
  idecode_run(system,
  idecode_run(system,
              system->events, system->processors, system->nr_cpus);
              system->events, system->processors, system->nr_cpus);
}
}
 
 
 
 
/* storage manipulation functions */
/* storage manipulation functions */
 
 
INLINE_PSIM\
INLINE_PSIM\
(int)
(int)
psim_read_register(psim *system,
psim_read_register(psim *system,
                   int which_cpu,
                   int which_cpu,
                   void *buf,
                   void *buf,
                   const char reg[],
                   const char reg[],
                   transfer_mode mode)
                   transfer_mode mode)
{
{
  register_descriptions description;
  register_descriptions description;
  char *cooked_buf;
  char *cooked_buf;
  cpu *processor;
  cpu *processor;
 
 
  /* find our processor */
  /* find our processor */
  if (which_cpu == MAX_NR_PROCESSORS) {
  if (which_cpu == MAX_NR_PROCESSORS) {
    if (system->last_cpu == system->nr_cpus
    if (system->last_cpu == system->nr_cpus
        || system->last_cpu == -1)
        || system->last_cpu == -1)
      which_cpu = 0;
      which_cpu = 0;
    else
    else
      which_cpu = system->last_cpu;
      which_cpu = system->last_cpu;
  }
  }
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
 
 
  processor = system->processors[which_cpu];
  processor = system->processors[which_cpu];
 
 
  /* find the register description */
  /* find the register description */
  description = register_description(reg);
  description = register_description(reg);
  if (description.type == reg_invalid)
  if (description.type == reg_invalid)
    return 0;
    return 0;
  cooked_buf = alloca (description.size);
  cooked_buf = alloca (description.size);
 
 
  /* get the cooked value */
  /* get the cooked value */
  switch (description.type) {
  switch (description.type) {
 
 
  case reg_gpr:
  case reg_gpr:
    *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
    *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
    break;
    break;
 
 
  case reg_spr:
  case reg_spr:
    *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
    *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
    break;
    break;
 
 
  case reg_sr:
  case reg_sr:
    *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
    *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
    break;
    break;
 
 
  case reg_fpr:
  case reg_fpr:
    *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
    *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
    break;
    break;
 
 
  case reg_pc:
  case reg_pc:
    *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
    *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
    break;
    break;
 
 
  case reg_cr:
  case reg_cr:
    *(creg*)cooked_buf = cpu_registers(processor)->cr;
    *(creg*)cooked_buf = cpu_registers(processor)->cr;
    break;
    break;
 
 
  case reg_msr:
  case reg_msr:
    *(msreg*)cooked_buf = cpu_registers(processor)->msr;
    *(msreg*)cooked_buf = cpu_registers(processor)->msr;
    break;
    break;
 
 
  case reg_fpscr:
  case reg_fpscr:
    *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
    *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
    break;
    break;
 
 
  case reg_insns:
  case reg_insns:
    *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
    *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
                                                          which_cpu);
                                                          which_cpu);
    break;
    break;
 
 
  case reg_stalls:
  case reg_stalls:
    if (cpu_model(processor) == NULL)
    if (cpu_model(processor) == NULL)
      error("$stalls only valid if processor unit model enabled (-I)\n");
      error("$stalls only valid if processor unit model enabled (-I)\n");
    *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
    *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
    break;
    break;
 
 
  case reg_cycles:
  case reg_cycles:
    if (cpu_model(processor) == NULL)
    if (cpu_model(processor) == NULL)
      error("$cycles only valid if processor unit model enabled (-I)\n");
      error("$cycles only valid if processor unit model enabled (-I)\n");
    *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
    *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
    break;
    break;
 
 
#ifdef WITH_ALTIVEC
#ifdef WITH_ALTIVEC
  case reg_vr:
  case reg_vr:
    *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
    *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
    break;
    break;
 
 
  case reg_vscr:
  case reg_vscr:
    *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
    *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
    break;
    break;
#endif
#endif
 
 
#ifdef WITH_E500
#ifdef WITH_E500
  case reg_gprh:
  case reg_gprh:
    *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
    *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
    break;
    break;
 
 
  case reg_evr:
  case reg_evr:
    *(unsigned64*)cooked_buf = EVR(description.index);
    *(unsigned64*)cooked_buf = EVR(description.index);
    break;
    break;
 
 
  case reg_acc:
  case reg_acc:
    *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
    *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
    break;
    break;
#endif
#endif
 
 
  default:
  default:
    printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
    printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
                    (unsigned long)processor, (unsigned long)buf, reg,
                    (unsigned long)processor, (unsigned long)buf, reg,
                    "read of this register unimplemented");
                    "read of this register unimplemented");
    break;
    break;
 
 
  }
  }
 
 
  /* the PSIM internal values are in host order.  To fetch raw data,
  /* the PSIM internal values are in host order.  To fetch raw data,
     they need to be converted into target order and then returned */
     they need to be converted into target order and then returned */
  if (mode == raw_transfer) {
  if (mode == raw_transfer) {
    /* FIXME - assumes that all registers are simple integers */
    /* FIXME - assumes that all registers are simple integers */
    switch (description.size) {
    switch (description.size) {
    case 1:
    case 1:
      *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
      *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
      break;
      break;
    case 2:
    case 2:
      *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
      *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
      break;
      break;
    case 4:
    case 4:
      *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
      *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
      break;
      break;
    case 8:
    case 8:
      *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
      *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
      break;
      break;
#ifdef WITH_ALTIVEC
#ifdef WITH_ALTIVEC
    case 16:
    case 16:
      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
        {
        {
          union { vreg v; unsigned_8 d[2]; } h, t;
          union { vreg v; unsigned_8 d[2]; } h, t;
          memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
          memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
          { _SWAP_8(t.d[0] =, h.d[1]); }
          { _SWAP_8(t.d[0] =, h.d[1]); }
          { _SWAP_8(t.d[1] =, h.d[0]); }
          { _SWAP_8(t.d[1] =, h.d[0]); }
          memcpy(buf/*dest*/, &t/*src*/, description.size);
          memcpy(buf/*dest*/, &t/*src*/, description.size);
          break;
          break;
        }
        }
      else
      else
        memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
        memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
      break;
      break;
#endif
#endif
    }
    }
  }
  }
  else {
  else {
    memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
    memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
  }
  }
 
 
  return description.size;
  return description.size;
}
}
 
 
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(int)
(int)
psim_write_register(psim *system,
psim_write_register(psim *system,
                    int which_cpu,
                    int which_cpu,
                    const void *buf,
                    const void *buf,
                    const char reg[],
                    const char reg[],
                    transfer_mode mode)
                    transfer_mode mode)
{
{
  cpu *processor;
  cpu *processor;
  register_descriptions description;
  register_descriptions description;
  char *cooked_buf;
  char *cooked_buf;
 
 
  /* find our processor */
  /* find our processor */
  if (which_cpu == MAX_NR_PROCESSORS) {
  if (which_cpu == MAX_NR_PROCESSORS) {
    if (system->last_cpu == system->nr_cpus
    if (system->last_cpu == system->nr_cpus
        || system->last_cpu == -1)
        || system->last_cpu == -1)
      which_cpu = 0;
      which_cpu = 0;
    else
    else
      which_cpu = system->last_cpu;
      which_cpu = system->last_cpu;
  }
  }
 
 
  /* find the description of the register */
  /* find the description of the register */
  description = register_description(reg);
  description = register_description(reg);
  if (description.type == reg_invalid)
  if (description.type == reg_invalid)
    return 0;
    return 0;
  cooked_buf = alloca (description.size);
  cooked_buf = alloca (description.size);
 
 
  if (which_cpu == -1) {
  if (which_cpu == -1) {
    int i;
    int i;
    for (i = 0; i < system->nr_cpus; i++)
    for (i = 0; i < system->nr_cpus; i++)
      psim_write_register(system, i, buf, reg, mode);
      psim_write_register(system, i, buf, reg, mode);
    return description.size;
    return description.size;
  }
  }
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
 
 
  processor = system->processors[which_cpu];
  processor = system->processors[which_cpu];
 
 
  /* If the data is comming in raw (target order), need to cook it
  /* If the data is comming in raw (target order), need to cook it
     into host order before putting it into PSIM's internal structures */
     into host order before putting it into PSIM's internal structures */
  if (mode == raw_transfer) {
  if (mode == raw_transfer) {
    switch (description.size) {
    switch (description.size) {
    case 1:
    case 1:
      *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
      *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
      break;
      break;
    case 2:
    case 2:
      *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
      *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
      break;
      break;
    case 4:
    case 4:
      *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
      *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
      break;
      break;
    case 8:
    case 8:
      *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
      *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
      break;
      break;
#ifdef WITH_ALTIVEC
#ifdef WITH_ALTIVEC
    case 16:
    case 16:
      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
      if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
        {
        {
          union { vreg v; unsigned_8 d[2]; } h, t;
          union { vreg v; unsigned_8 d[2]; } h, t;
          memcpy(&t.v/*dest*/, buf/*src*/, description.size);
          memcpy(&t.v/*dest*/, buf/*src*/, description.size);
          { _SWAP_8(h.d[0] =, t.d[1]); }
          { _SWAP_8(h.d[0] =, t.d[1]); }
          { _SWAP_8(h.d[1] =, t.d[0]); }
          { _SWAP_8(h.d[1] =, t.d[0]); }
          memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
          memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
          break;
          break;
        }
        }
      else
      else
        memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
        memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
#endif
#endif
    }
    }
  }
  }
  else {
  else {
    memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
    memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
  }
  }
 
 
  /* put the cooked value into the register */
  /* put the cooked value into the register */
  switch (description.type) {
  switch (description.type) {
 
 
  case reg_gpr:
  case reg_gpr:
    cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
    cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
    break;
    break;
 
 
  case reg_fpr:
  case reg_fpr:
    cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
    cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
    break;
    break;
 
 
  case reg_pc:
  case reg_pc:
    cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
    cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
    break;
    break;
 
 
  case reg_spr:
  case reg_spr:
    cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
    cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
    break;
    break;
 
 
  case reg_sr:
  case reg_sr:
    cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
    cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
    break;
    break;
 
 
  case reg_cr:
  case reg_cr:
    cpu_registers(processor)->cr = *(creg*)cooked_buf;
    cpu_registers(processor)->cr = *(creg*)cooked_buf;
    break;
    break;
 
 
  case reg_msr:
  case reg_msr:
    cpu_registers(processor)->msr = *(msreg*)cooked_buf;
    cpu_registers(processor)->msr = *(msreg*)cooked_buf;
    break;
    break;
 
 
  case reg_fpscr:
  case reg_fpscr:
    cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
    cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
    break;
    break;
 
 
#ifdef WITH_E500
#ifdef WITH_E500
  case reg_gprh:
  case reg_gprh:
    cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
    cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
    break;
    break;
 
 
  case reg_evr:
  case reg_evr:
    {
    {
      unsigned64 v;
      unsigned64 v;
      v = *(unsigned64*)cooked_buf;
      v = *(unsigned64*)cooked_buf;
      cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
      cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
      cpu_registers(processor)->gpr[description.index] = v;
      cpu_registers(processor)->gpr[description.index] = v;
      break;
      break;
    }
    }
 
 
  case reg_acc:
  case reg_acc:
    cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
    cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
    break;
    break;
#endif
#endif
 
 
#ifdef WITH_ALTIVEC
#ifdef WITH_ALTIVEC
  case reg_vr:
  case reg_vr:
    cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
    cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
    break;
    break;
 
 
  case reg_vscr:
  case reg_vscr:
    cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
    cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
    break;
    break;
#endif
#endif
 
 
  default:
  default:
    printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
    printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
                    (unsigned long)processor, (unsigned long)cooked_buf, reg,
                    (unsigned long)processor, (unsigned long)cooked_buf, reg,
                    "read of this register unimplemented");
                    "read of this register unimplemented");
    break;
    break;
 
 
  }
  }
 
 
  return description.size;
  return description.size;
}
}
 
 
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(unsigned)
(unsigned)
psim_read_memory(psim *system,
psim_read_memory(psim *system,
                 int which_cpu,
                 int which_cpu,
                 void *buffer,
                 void *buffer,
                 unsigned_word vaddr,
                 unsigned_word vaddr,
                 unsigned nr_bytes)
                 unsigned nr_bytes)
{
{
  cpu *processor;
  cpu *processor;
  if (which_cpu == MAX_NR_PROCESSORS) {
  if (which_cpu == MAX_NR_PROCESSORS) {
    if (system->last_cpu == system->nr_cpus
    if (system->last_cpu == system->nr_cpus
        || system->last_cpu == -1)
        || system->last_cpu == -1)
      which_cpu = 0;
      which_cpu = 0;
    else
    else
      which_cpu = system->last_cpu;
      which_cpu = system->last_cpu;
  }
  }
  processor = system->processors[which_cpu];
  processor = system->processors[which_cpu];
  return vm_data_map_read_buffer(cpu_data_map(processor),
  return vm_data_map_read_buffer(cpu_data_map(processor),
                                 buffer, vaddr, nr_bytes,
                                 buffer, vaddr, nr_bytes,
                                 NULL, -1);
                                 NULL, -1);
}
}
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(unsigned)
(unsigned)
psim_write_memory(psim *system,
psim_write_memory(psim *system,
                  int which_cpu,
                  int which_cpu,
                  const void *buffer,
                  const void *buffer,
                  unsigned_word vaddr,
                  unsigned_word vaddr,
                  unsigned nr_bytes,
                  unsigned nr_bytes,
                  int violate_read_only_section)
                  int violate_read_only_section)
{
{
  cpu *processor;
  cpu *processor;
  if (which_cpu == MAX_NR_PROCESSORS) {
  if (which_cpu == MAX_NR_PROCESSORS) {
    if (system->last_cpu == system->nr_cpus
    if (system->last_cpu == system->nr_cpus
        || system->last_cpu == -1)
        || system->last_cpu == -1)
      which_cpu = 0;
      which_cpu = 0;
    else
    else
      which_cpu = system->last_cpu;
      which_cpu = system->last_cpu;
  }
  }
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
  ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
  processor = system->processors[which_cpu];
  processor = system->processors[which_cpu];
  return vm_data_map_write_buffer(cpu_data_map(processor),
  return vm_data_map_write_buffer(cpu_data_map(processor),
                                  buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
                                  buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
                                  NULL, -1);
                                  NULL, -1);
}
}
 
 
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_print_info(psim *system,
psim_print_info(psim *system,
                int verbose)
                int verbose)
{
{
  mon_print_info(system, system->monitor, verbose);
  mon_print_info(system, system->monitor, verbose);
}
}
 
 
 
 
/* Merge a device tree and a device file. */
/* Merge a device tree and a device file. */
 
 
INLINE_PSIM\
INLINE_PSIM\
(void)
(void)
psim_merge_device_file(device *root,
psim_merge_device_file(device *root,
                       const char *file_name)
                       const char *file_name)
{
{
  FILE *description;
  FILE *description;
  int line_nr;
  int line_nr;
  char device_path[1000];
  char device_path[1000];
  device *current;
  device *current;
 
 
  /* try opening the file */
  /* try opening the file */
  description = fopen(file_name, "r");
  description = fopen(file_name, "r");
  if (description == NULL) {
  if (description == NULL) {
    perror(file_name);
    perror(file_name);
    error("Invalid file %s specified", file_name);
    error("Invalid file %s specified", file_name);
  }
  }
 
 
  line_nr = 0;
  line_nr = 0;
  current = root;
  current = root;
  while (fgets(device_path, sizeof(device_path), description)) {
  while (fgets(device_path, sizeof(device_path), description)) {
    char *device;
    char *device;
    /* check that the full line was read */
    /* check that the full line was read */
    if (strchr(device_path, '\n') == NULL) {
    if (strchr(device_path, '\n') == NULL) {
      fclose(description);
      fclose(description);
      error("%s:%d: line to long - %s",
      error("%s:%d: line to long - %s",
            file_name, line_nr, device_path);
            file_name, line_nr, device_path);
    }
    }
    else
    else
      *strchr(device_path, '\n') = '\0';
      *strchr(device_path, '\n') = '\0';
    line_nr++;
    line_nr++;
    /* skip comments ("#" or ";") and blank lines lines */
    /* skip comments ("#" or ";") and blank lines lines */
    for (device = device_path;
    for (device = device_path;
         *device != '\0' && isspace(*device);
         *device != '\0' && isspace(*device);
         device++);
         device++);
    if (device[0] == '#'
    if (device[0] == '#'
        || device[0] == ';'
        || device[0] == ';'
        || device[0] == '\0')
        || device[0] == '\0')
      continue;
      continue;
    /* merge any appended lines */
    /* merge any appended lines */
    while (device_path[strlen(device_path) - 1] == '\\') {
    while (device_path[strlen(device_path) - 1] == '\\') {
      int curlen = strlen(device_path) - 1;
      int curlen = strlen(device_path) - 1;
      /* zap \ */
      /* zap \ */
      device_path[curlen] = '\0';
      device_path[curlen] = '\0';
      /* append the next line */
      /* append the next line */
      if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
      if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
        fclose(description);
        fclose(description);
        error("%s:%s: unexpected eof in line continuation - %s",
        error("%s:%s: unexpected eof in line continuation - %s",
              file_name, line_nr, device_path);
              file_name, line_nr, device_path);
      }
      }
      if (strchr(device_path, '\n') == NULL) {
      if (strchr(device_path, '\n') == NULL) {
        fclose(description);
        fclose(description);
        error("%s:%d: line to long - %s",
        error("%s:%d: line to long - %s",
            file_name, line_nr, device_path);
            file_name, line_nr, device_path);
      }
      }
      else
      else
        *strchr(device_path, '\n') = '\0';
        *strchr(device_path, '\n') = '\0';
      line_nr++;
      line_nr++;
    }
    }
    /* parse this line */
    /* parse this line */
    current = tree_parse(current, "%s", device);
    current = tree_parse(current, "%s", device);
  }
  }
  fclose(description);
  fclose(description);
}
}
 
 
 
 
#endif /* _PSIM_C_ */
#endif /* _PSIM_C_ */
 
 

powered by: WebSVN 2.1.0

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