home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / sim / ppc / psim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-24  |  27.6 KB  |  1,007 lines

  1. /*  This file is part of the program psim.
  2.  
  3.     Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19.     */
  20.  
  21.  
  22. #ifndef _PSIM_C_
  23. #define _PSIM_C_
  24.  
  25. #include "inline.c"
  26.  
  27. #include <stdio.h>
  28. #include <ctype.h>
  29.  
  30. #ifdef HAVE_STDLIB_H
  31. #include <stdlib.h>
  32. #endif
  33.  
  34. #include <setjmp.h>
  35.  
  36. #include "cpu.h" /* includes psim.h */
  37. #include "idecode.h"
  38. #include "options.h"
  39.  
  40. #ifdef HAVE_STRING_H
  41. #include <string.h>
  42. #else
  43. #ifdef HAVE_STRINGS_H
  44. #include <strings.h>
  45. #endif
  46. #endif
  47.  
  48. #include "bfd.h"
  49.  
  50.  
  51. /* system structure, actual size of processor array determined at
  52.    runtime */
  53.  
  54. struct _psim {
  55.   event_queue *events;
  56.   device *devices;
  57.   mon *monitor;
  58.   os_emul *os_emulation;
  59.   core *memory;
  60.  
  61.   /* escape routine for inner functions */
  62.   void *path_to_halt;
  63.   void *path_to_restart;
  64.  
  65.   /* status from last halt */
  66.   psim_status halt_status;
  67.  
  68.   /* the processors proper */
  69.   int nr_cpus;
  70.   int last_cpu; /* CPU that last (tried to) execute an instruction */
  71.   cpu *processors[MAX_NR_PROCESSORS];
  72. };
  73.  
  74.  
  75. int current_target_byte_order;
  76. int current_host_byte_order;
  77. int current_environment;
  78. int current_alignment;
  79. int current_floating_point;
  80. int current_model_issue = MODEL_ISSUE_IGNORE;
  81. model_enum current_model = WITH_DEFAULT_MODEL;
  82.  
  83.  
  84. /* create the device tree */
  85.  
  86. INLINE_PSIM\
  87. (device *)
  88. psim_tree(void)
  89. {
  90.   device *root = core_device_create();
  91.   device_tree_add_parsed(root, "/aliases");
  92.   device_tree_add_parsed(root, "/options");
  93.   device_tree_add_parsed(root, "/chosen");
  94.   device_tree_add_parsed(root, "/packages");
  95.   device_tree_add_parsed(root, "/cpus");
  96.   device_tree_add_parsed(root, "/openprom");
  97.   device_tree_add_parsed(root, "/openprom/init");
  98.   device_tree_add_parsed(root, "/openprom/trace");
  99.   device_tree_add_parsed(root, "/openprom/options");
  100.   return root;
  101. }
  102.  
  103. STATIC_INLINE_PSIM\
  104. (char *)
  105. find_arg(char *err_msg,
  106.      int *ptr_to_argp,
  107.      char **argv)
  108. {
  109.   *ptr_to_argp += 1;
  110.   if (argv[*ptr_to_argp] == NULL)
  111.     error(err_msg);
  112.   return argv[*ptr_to_argp];
  113. }
  114.  
  115. INLINE_PSIM\
  116. (void)
  117. psim_usage(int verbose)
  118. {
  119.   printf_filtered("Usage:\n");
  120.   printf_filtered("\n");
  121.   printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
  122.   printf_filtered("\n");
  123.   printf_filtered("Where\n");
  124.   printf_filtered("\n");
  125.   printf_filtered("\t<image>       Name of the PowerPC program to run.\n");
  126.   if (verbose) {
  127.   printf_filtered("\t              This can either be a PowerPC binary or\n");
  128.   printf_filtered("\t              a text file containing a device tree\n");
  129.   printf_filtered("\t              specification.\n");
  130.   printf_filtered("\t              PSIM will attempt to determine from the\n");
  131.   printf_filtered("\t              specified <image> the intended emulation\n");
  132.   printf_filtered("\t              environment.\n");
  133.   printf_filtered("\t              If PSIM gets it wrong, the emulation\n");
  134.   printf_filtered("\t              environment can be specified using the\n");
  135.   printf_filtered("\t              `-e' option (described below).\n");
  136.   printf_filtered("\n"); }
  137.   printf_filtered("\t<image-arg>   Argument to be passed to <image>\n");
  138.   if (verbose) {
  139.   printf_filtered("\t              These arguments will be passed to\n");
  140.   printf_filtered("\t              <image> (as standard C argv, argc)\n");
  141.   printf_filtered("\t              when <image> is started.\n");
  142.   printf_filtered("\n"); }
  143.   printf_filtered("\t<psim-option> See below\n");
  144.   printf_filtered("\n");
  145.   printf_filtered("The following are valid <psim-option>s:\n");
  146.   printf_filtered("\n");
  147.   printf_filtered("\t-m <model>    Specify the processor to model (604)\n");
  148.   if (verbose) {
  149.   printf_filtered("\t              Selects the processor to use when\n");
  150.   printf_filtered("\t              modeling execution units.  Includes:\n");
  151.   printf_filtered("\t              604, 603 and 603e\n");
  152.   printf_filtered("\n"); }
  153.   printf_filtered("\t-e <os-emul>  specify an OS or platform to model\n");
  154.   if (verbose) {
  155.   printf_filtered("\t              Can be any of the following:\n");
  156.   printf_filtered("\t              bug - OEA + MOTO BUG ROM calls\n");
  157.   printf_filtered("\t              netbsd - UEA + NetBSD system calls\n");
  158.   printf_filtered("\t              chirp - OEA + a few OpenBoot calls\n");
  159.   printf_filtered("\n"); }
  160.   printf_filtered("\t-i            Print instruction counting statistics\n");
  161.   if (verbose) { printf_filtered("\n"); }
  162.   printf_filtered("\t-I            Print execution unit statistics\n");
  163.   if (verbose) { printf_filtered("\n"); }
  164.   printf_filtered("\t-r <size>     Set RAM size in bytes (OEA environments)\n");
  165.   if (verbose) { printf_filtered("\n"); }
  166.   printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
  167.   if (verbose) { printf_filtered("\n"); }
  168.   printf_filtered("\t-o <spec>     add device <spec> to the device tree\n");
  169.   if (verbose) { printf_filtered("\n"); }
  170.   printf_filtered("\t-h -? -H      give more detailed usage\n");
  171.   if (verbose) { printf_filtered("\n"); }
  172.   printf_filtered("\n");
  173.   trace_usage(verbose);
  174.   device_usage(verbose);
  175.   if (verbose > 1) {
  176.     printf_filtered("\n");
  177.     print_options();
  178.   }
  179.   error("");
  180. }
  181.  
  182. INLINE_PSIM\
  183. (char **)
  184. psim_options(device *root,
  185.          char **argv)
  186. {
  187.   device *current = root;
  188.   int argp;
  189.   if (argv == NULL)
  190.     return NULL;
  191.   argp = 0;
  192.   while (argv[argp] != NULL && argv[argp][0] == '-') {
  193.     char *p = argv[argp] + 1;
  194.     char *param;
  195.     while (*p != '\0') {
  196.       switch (*p) {
  197.       default:
  198.     psim_usage(0);
  199.     error ("");
  200.     break;
  201.       case 'e':
  202.     param = find_arg("Missing <emul> option for -e\n", &argp, argv);
  203.     device_tree_add_parsed(root, "/openprom/options/os-emul %s", param);
  204.     break;
  205.       case 'h':
  206.       case '?':
  207.     psim_usage(1);
  208.     break;
  209.       case 'H':
  210.     psim_usage(2);
  211.     break;
  212.       case 'i':
  213.     device_tree_add_parsed(root, "/openprom/trace/print-info 1");
  214.     break;
  215.       case 'I':
  216.     device_tree_add_parsed(root, "/openprom/trace/print-info 2");
  217.     device_tree_add_parsed(root, "/openprom/options/model-issue %d",
  218.                    MODEL_ISSUE_PROCESS);
  219.     break;
  220.       case 'm':
  221.     param = find_arg("Missing <model> option for -m\n", &argp, argv);
  222.     device_tree_add_parsed(root, "/openprom/options/model \"%s", param);
  223.     break;
  224.       case 'o':
  225.     param = find_arg("Missing <device> option for -o\n", &argp, argv);
  226.     current = device_tree_add_parsed(current, "%s", param);
  227.     break;
  228.       case 'r':
  229.     param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
  230.     device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx",
  231.                    atol(param));
  232.     break;
  233.       case 't':
  234.     param = find_arg("Missing <trace> option for -t\n", &argp, argv);
  235.     if (param[0] == '!')
  236.       device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1);
  237.     else
  238.       device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
  239.     break;
  240.       }
  241.       p += 1;
  242.     }
  243.     argp += 1;
  244.   }
  245.   /* force the trace node to (re)process its options */
  246.   device_init_data(device_tree_find_device(root, "/openprom/trace"), NULL);
  247.   /* return where the options end */
  248.   return argv + argp;
  249. }
  250.  
  251.  
  252. /* create the simulator proper from the device tree and executable */
  253.  
  254. INLINE_PSIM\
  255. (psim *)
  256. psim_create(const char *file_name,
  257.         device *root)
  258. {
  259.   int cpu_nr;
  260.   const char *env;
  261.   psim *system;
  262.   os_emul *os_emulation;
  263.   int nr_cpus;
  264.  
  265.   /* given this partially populated device tree, os_emul_create() uses
  266.      it and file_name to determine the selected emulation and hence
  267.      further populate the tree with any other required nodes. */
  268.  
  269.   os_emulation = os_emul_create(file_name, root);
  270.   if (os_emulation == NULL)
  271.     error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
  272.  
  273.   /* fill in the missing real number of CPU's */
  274.   nr_cpus = device_find_integer_property(root, "/openprom/options/smp");
  275.   if (MAX_NR_PROCESSORS < nr_cpus)
  276.     error("target and configured number of cpus conflict\n");
  277.  
  278.   /* fill in the missing TARGET BYTE ORDER information */
  279.   current_target_byte_order
  280.     = (device_find_boolean_property(root, "/options/little-endian?")
  281.        ? LITTLE_ENDIAN
  282.        : BIG_ENDIAN);
  283.   if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
  284.     error("target and configured byte order conflict\n");
  285.  
  286.   /* fill in the missing HOST BYTE ORDER information */
  287.   current_host_byte_order = (current_host_byte_order = 1,
  288.                  (*(char*)(¤t_host_byte_order)
  289.                   ? LITTLE_ENDIAN
  290.                   : BIG_ENDIAN));
  291.   if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
  292.     error("host and configured byte order conflict\n");
  293.  
  294.   /* fill in the missing OEA/VEA information */
  295.   env = device_find_string_property(root, "/openprom/options/env");
  296.   current_environment = ((strcmp(env, "user") == 0
  297.               || strcmp(env, "uea") == 0)
  298.              ? USER_ENVIRONMENT
  299.              : (strcmp(env, "virtual") == 0
  300.                 || strcmp(env, "vea") == 0)
  301.              ? VIRTUAL_ENVIRONMENT
  302.              : (strcmp(env, "operating") == 0
  303.                 || strcmp(env, "oea") == 0)
  304.              ? OPERATING_ENVIRONMENT
  305.              : 0);
  306.   if (current_environment == 0)
  307.     error("unreconized /options env property\n");
  308.   if (CURRENT_ENVIRONMENT != current_environment)
  309.     error("target and configured environment conflict\n");
  310.  
  311.   /* fill in the missing ALLIGNMENT information */
  312.   current_alignment
  313.     = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
  314.        ? STRICT_ALIGNMENT
  315.        : NONSTRICT_ALIGNMENT);
  316.   if (CURRENT_ALIGNMENT != current_alignment)
  317.     error("target and configured alignment conflict\n");
  318.  
  319.   /* fill in the missing FLOATING POINT information */
  320.   current_floating_point
  321.     = (device_find_boolean_property(root, "/openprom/options/floating-point?")
  322.        ? HARD_FLOATING_POINT
  323.        : SOFT_FLOATING_POINT);
  324.   if (CURRENT_FLOATING_POINT != current_floating_point)
  325.     error("target and configured floating-point conflict\n");
  326.  
  327.   /* sort out the level of detail for issue modeling */
  328.   current_model_issue
  329.     = device_find_integer_property(root, "/openprom/options/model-issue");
  330.   if (CURRENT_MODEL_ISSUE != current_model_issue)
  331.     error("target and configured model-issue conflict\n");
  332.  
  333.   /* sort out our model architecture - wrong.
  334.  
  335.      FIXME: this should be obtaining the required information from the
  336.      device tree via the "/chosen" property "cpu" which is an instance
  337.      (ihandle) for the only executing processor. By converting that
  338.      ihandle into the corresponding cpu's phandle and then querying
  339.      the "name" property, the cpu type can be determined. Ok? */
  340.  
  341.   model_set(device_find_string_property(root, "/openprom/options/model"));
  342.  
  343.   /* create things */
  344.   system = ZALLOC(psim);
  345.   system->events = event_queue_create();
  346.   system->memory = core_create(root);
  347.   system->monitor = mon_create();
  348.   system->nr_cpus = nr_cpus;
  349.   system->os_emulation = os_emulation;
  350.   system->devices = root;
  351.  
  352.   /* now all the processors attaching to each their per-cpu information */
  353.   for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
  354.     system->processors[cpu_nr] = cpu_create(system,
  355.                         system->memory,
  356.                         system->events,
  357.                         mon_cpu(system->monitor,
  358.                             cpu_nr),
  359.                         system->os_emulation,
  360.                         cpu_nr);
  361.   }
  362.  
  363.   /* dump out the contents of the device tree */
  364.   if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
  365.     device_tree_traverse(root, device_tree_print_device, NULL, NULL);
  366.   if (ppc_trace[trace_dump_device_tree])
  367.     error("");
  368.  
  369.   return system;
  370. }
  371.  
  372.  
  373. /* allow the simulation to stop/restart abnormaly */
  374.  
  375. STATIC_INLINE_PSIM\
  376. (void)
  377. psim_set_halt_and_restart(psim *system,
  378.               void *halt_jmp_buf,
  379.               void *restart_jmp_buf)
  380. {
  381.   system->path_to_halt = halt_jmp_buf;
  382.   system->path_to_restart = restart_jmp_buf;
  383. }
  384.  
  385. STATIC_INLINE_PSIM\
  386. (void)
  387. psim_clear_halt_and_restart(psim *system)
  388. {
  389.   system->path_to_halt = NULL;
  390.   system->path_to_restart = NULL;
  391. }
  392.  
  393. INLINE_PSIM\
  394. (void)
  395. psim_restart(psim *system,
  396.          int current_cpu)
  397. {
  398.   system->last_cpu = current_cpu;
  399.   longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
  400. }
  401.  
  402.  
  403. INLINE_PSIM\
  404. (void)
  405. psim_halt(psim *system,
  406.       int current_cpu,
  407.       unsigned_word cia,
  408.       stop_reason reason,
  409.       int signal)
  410. {
  411.   system->last_cpu = current_cpu;
  412.   system->halt_status.cpu_nr = current_cpu;
  413.   system->halt_status.reason = reason;
  414.   system->halt_status.signal = signal;
  415.   system->halt_status.program_counter = cia;
  416.   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
  417. }
  418.  
  419. INLINE_PSIM\
  420. (psim_status)
  421. psim_get_status(psim *system)
  422. {
  423.   return system->halt_status;
  424. }
  425.  
  426.  
  427. INLINE_PSIM\
  428. (cpu *)
  429. psim_cpu(psim *system,
  430.      int cpu_nr)
  431. {
  432.   if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
  433.     return NULL;
  434.   else
  435.     return system->processors[cpu_nr];
  436. }
  437.  
  438.  
  439. INLINE_PSIM\
  440. (device *)
  441. psim_device(psim *system,
  442.         const char *path)
  443. {
  444.   return device_tree_find_device(system->devices, path);
  445. }
  446.  
  447.  
  448.  
  449. INLINE_PSIM\
  450. (void)
  451. psim_init(psim *system)
  452. {
  453.   int cpu_nr;
  454.  
  455.   /* scrub the monitor */
  456.   mon_init(system->monitor, system->nr_cpus);
  457.   os_emul_init(system->os_emulation, system->nr_cpus);
  458.   event_queue_init(system->events);
  459.  
  460.   /* scrub all the cpus */
  461.   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
  462.     cpu_init(system->processors[cpu_nr]);
  463.  
  464.   /* init all the devices (which updates the cpus) */
  465.   device_tree_init(system->devices, system);
  466.  
  467.   /* now sync each cpu against the initialized state of its registers */
  468.   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
  469.     cpu_synchronize_context(system->processors[cpu_nr]);
  470.     cpu_page_tlb_invalidate_all(system->processors[cpu_nr]);
  471.   }
  472.  
  473.   /* force loop to restart */
  474.   system->last_cpu = system->nr_cpus - 1;
  475. }
  476.  
  477. INLINE_PSIM\
  478. (void)
  479. psim_stack(psim *system,
  480.        char **argv,
  481.        char **envp)
  482. {
  483.   /* pass the stack device the argv/envp and let it work out what to
  484.      do with it */
  485.   device *stack_device = device_tree_find_device(system->devices,
  486.                          "/openprom/init/stack");
  487.   if (stack_device != (device*)0) {
  488.     unsigned_word stack_pointer;
  489.     psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
  490.     device_ioctl(stack_device,
  491.          system,
  492.          NULL, /*cpu*/
  493.          0, /*cia*/
  494.          stack_pointer,
  495.          argv,
  496.          envp);
  497.   }
  498. }
  499.  
  500.  
  501.  
  502. /* EXECUTE REAL CODE: 
  503.  
  504.    Unfortunatly, there are multiple cases to consider vis:
  505.  
  506.        <icache> X <smp> X <events> X <keep-running-flag> X ...
  507.  
  508.    Consequently this function is written in multiple different ways */
  509.  
  510. STATIC_INLINE_PSIM\
  511. (void)
  512. run_until_stop(psim *system,
  513.            volatile int *keep_running)
  514. {
  515.   jmp_buf halt;
  516.   jmp_buf restart;
  517. #if WITH_IDECODE_CACHE_SIZE
  518.   int cpu_nr;
  519.   for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
  520.     cpu_flush_icache(system->processors[cpu_nr]);
  521. #endif
  522.   psim_set_halt_and_restart(system, &halt, &restart);
  523.  
  524. #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
  525.  
  526.   /* CASE 1: No instruction cache and no SMP.
  527.  
  528.      In this case, we can take advantage of the fact that the current
  529.      instruction address does not need to be returned to the cpu
  530.      object after every execution of an instruction.  Instead it only
  531.      needs to be saved when either A. the main loop exits or B. a
  532.      cpu-{halt,restart} call forces the loop to be re-entered.  The
  533.      later functions always save the current cpu instruction
  534.      address. */
  535.  
  536.   if (!setjmp(halt)) {
  537.     do {
  538.       if (!setjmp(restart)) {
  539.     cpu *const processor = system->processors[0];
  540.     unsigned_word cia = cpu_get_program_counter(processor);
  541.     do {
  542.       if (WITH_EVENTS) {
  543.         if (event_queue_tick(system->events)) {
  544.           cpu_set_program_counter(processor, cia);
  545.           event_queue_process(system->events);
  546.           cia = cpu_get_program_counter(processor);
  547.         }
  548.       }
  549.       {
  550.         instruction_word const instruction
  551.           = vm_instruction_map_read(cpu_instruction_map(processor),
  552.                     processor, cia);
  553.         cia = idecode_issue(processor, instruction, cia);
  554.       }
  555.     } while (keep_running == NULL || *keep_running);
  556.     cpu_set_program_counter(processor, cia);
  557.       }
  558.     } while(keep_running == NULL || *keep_running);
  559.   }
  560. #endif
  561.  
  562.  
  563. #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
  564.  
  565.   /* CASE 2: Instruction case but no SMP
  566.  
  567.      Here, the additional complexity comes from there being two
  568.      different cache implementations.  A simple function address cache
  569.      or a full cracked instruction cache */
  570.  
  571.   if (!setjmp(halt)) {
  572.     do {
  573.       if (!setjmp(restart)) {
  574.     cpu *const processor = system->processors[0];
  575.     unsigned_word cia = cpu_get_program_counter(processor);
  576.     do {
  577.       if (WITH_EVENTS)
  578.         if (event_queue_tick(system->events)) {
  579.           cpu_set_program_counter(processor, cia);
  580.           event_queue_process(system->events);
  581.           cia = cpu_get_program_counter(processor);
  582.         }
  583.       { 
  584.         idecode_cache *const cache_entry = cpu_icache_entry(processor,
  585.                                 cia);
  586.         if (cache_entry->address == cia) {
  587.           idecode_semantic *const semantic = cache_entry->semantic;
  588.           cia = semantic(processor, cache_entry, cia);
  589.         }
  590.         else {
  591.           instruction_word const instruction
  592.         = vm_instruction_map_read(cpu_instruction_map(processor),
  593.                       processor,
  594.                       cia);
  595.           idecode_semantic *const semantic = idecode(processor,
  596.                              instruction,
  597.                              cia,
  598.                              cache_entry);
  599.  
  600.           if (WITH_MON != 0)
  601.         mon_event(mon_event_icache_miss, processor, cia);
  602.           cache_entry->address = cia;
  603.           cache_entry->semantic = semantic;
  604.           cia = semantic(processor, cache_entry, cia);
  605.         }
  606.       }
  607.     } while (keep_running == NULL || *keep_running);
  608.     cpu_set_program_counter(processor, cia);
  609.       }
  610.     } while(keep_running == NULL || *keep_running);
  611.   }
  612. #endif
  613.  
  614.  
  615. #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
  616.  
  617.   /* CASE 3: No ICACHE but SMP
  618.  
  619.      The complexity here comes from needing to correctly restart the
  620.      system when it is aborted.  In particular if cpu0 requests a
  621.      restart, the next cpu is still cpu1.  Cpu0 being restarted after
  622.      all the other CPU's and the event queue have been processed */
  623.  
  624.   if (!setjmp(halt)) {
  625.     int first_cpu = setjmp(restart);
  626.     if (first_cpu == 0)
  627.       first_cpu = system->last_cpu + 1;
  628.     do {
  629.       int current_cpu;
  630.       for (current_cpu = first_cpu, first_cpu = 0;
  631.        current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
  632.        current_cpu++) {
  633.     if (WITH_EVENTS && current_cpu == system->nr_cpus) {
  634.       if (event_queue_tick(system->events))
  635.         event_queue_process(system->events);
  636.     }
  637.     else {
  638.       cpu *const processor = system->processors[current_cpu];
  639.       unsigned_word const cia = cpu_get_program_counter(processor);
  640.       instruction_word instruction =
  641.         vm_instruction_map_read(cpu_instruction_map(processor),
  642.                     processor,
  643.                     cia);
  644.       cpu_set_program_counter(processor,
  645.                   idecode_issue(processor, instruction, cia));
  646.     }
  647.     if (!(keep_running == NULL || *keep_running)) {
  648.       system->last_cpu = current_cpu;
  649.       break;
  650.     }
  651.       }
  652.     } while (keep_running == NULL || *keep_running);
  653.   }
  654. #endif
  655.  
  656. #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
  657.  
  658.   /* CASE 4: ICACHE and SMP ...
  659.  
  660.      This time, everything goes wrong.  Need to restart loops
  661.      correctly, need to save the program counter and finally need to
  662.      keep track of each processors current address! */
  663.  
  664.   if (!setjmp(halt)) {
  665.     int first_cpu = setjmp(restart);
  666.     if (!first_cpu)
  667.       first_cpu = system->last_cpu + 1;
  668.     do {
  669.       int current_cpu;
  670.       for (current_cpu = first_cpu, first_cpu = 0;
  671.        current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
  672.        current_cpu++) {
  673.     if (WITH_EVENTS && current_cpu == system->nr_cpus) {
  674.       if (event_queue_tick(system->events))
  675.         event_queue_process(system->events);
  676.     }
  677.     else {
  678.       cpu *processor = system->processors[current_cpu];
  679.       unsigned_word const cia = cpu_get_program_counter(processor);
  680.       idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
  681.       if (cache_entry->address == cia) {
  682.         idecode_semantic *semantic = cache_entry->semantic;
  683.         cpu_set_program_counter(processor,
  684.                     semantic(processor, cache_entry, cia));
  685.       }
  686.       else {
  687.         instruction_word instruction =
  688.           vm_instruction_map_read(cpu_instruction_map(processor),
  689.                       processor,
  690.                       cia);
  691.         idecode_semantic *semantic = idecode(processor,
  692.                          instruction,
  693.                          cia,
  694.                          cache_entry);
  695.  
  696.         if (WITH_MON != 0)
  697.           mon_event(mon_event_icache_miss, system->processors[current_cpu], cia);
  698.         cache_entry->address = cia;
  699.         cache_entry->semantic = semantic;
  700.         cpu_set_program_counter(processor,
  701.                     semantic(processor, cache_entry, cia));
  702.       }
  703.     }
  704.     if (!(keep_running == NULL || *keep_running))
  705.       break;
  706.       }
  707.     } while (keep_running == NULL || *keep_running);
  708.   }
  709. #endif
  710.  
  711.   psim_clear_halt_and_restart(system);
  712. }
  713.  
  714.  
  715. /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
  716.    thing */
  717.  
  718. INLINE_PSIM\
  719. (void)
  720. psim_step(psim *system)
  721. {
  722.   volatile int keep_running = 0;
  723.   run_until_stop(system, &keep_running);
  724. }
  725.  
  726. INLINE_PSIM\
  727. (void)
  728. psim_run(psim *system)
  729. {
  730.   run_until_stop(system, NULL);
  731. }
  732.  
  733. INLINE_PSIM\
  734. (void)
  735. psim_run_until_stop(psim *system,
  736.             volatile int *keep_running)
  737. {
  738.   run_until_stop(system, keep_running);
  739. }
  740.  
  741.  
  742.  
  743. /* storage manipulation functions */
  744.  
  745. INLINE_PSIM\
  746. (void)
  747. psim_read_register(psim *system,
  748.            int which_cpu,
  749.            void *buf,
  750.            const char reg[],
  751.            transfer_mode mode)
  752. {
  753.   register_descriptions description;
  754.   char cooked_buf[sizeof(natural_word)];
  755.   cpu *processor;
  756.  
  757.   /* find our processor */
  758.   if (which_cpu == MAX_NR_PROCESSORS)
  759.     which_cpu = system->last_cpu;
  760.   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
  761.     error("psim_read_register() - invalid processor %d\n", which_cpu);
  762.   processor = system->processors[which_cpu];
  763.  
  764.   /* find the register description */
  765.   description = register_description(reg);
  766.   if (description.type == reg_invalid)
  767.     error("psim_read_register() invalid register name `%s'\n", reg);
  768.  
  769.   /* get the cooked value */
  770.   switch (description.type) {
  771.  
  772.   case reg_gpr:
  773.     *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
  774.     break;
  775.  
  776.   case reg_spr:
  777.     *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
  778.     break;
  779.     
  780.   case reg_sr:
  781.     *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
  782.     break;
  783.  
  784.   case reg_fpr:
  785.     *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
  786.     break;
  787.  
  788.   case reg_pc:
  789.     *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
  790.     break;
  791.  
  792.   case reg_cr:
  793.     *(creg*)cooked_buf = cpu_registers(processor)->cr;
  794.     break;
  795.  
  796.   case reg_msr:
  797.     *(msreg*)cooked_buf = cpu_registers(processor)->msr;
  798.     break;
  799.  
  800.   default:
  801.     printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
  802.             (unsigned long)processor, (unsigned long)buf, reg,
  803.             "read of this register unimplemented");
  804.     break;
  805.  
  806.   }
  807.  
  808.   /* the PSIM internal values are in host order.  To fetch raw data,
  809.      they need to be converted into target order and then returned */
  810.   if (mode == raw_transfer) {
  811.     /* FIXME - assumes that all registers are simple integers */
  812.     switch (description.size) {
  813.     case 1: 
  814.       *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
  815.       break;
  816.     case 2:
  817.       *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
  818.       break;
  819.     case 4:
  820.       *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
  821.       break;
  822.     case 8:
  823.       *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
  824.       break;
  825.     }
  826.   }
  827.   else {
  828.     memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
  829.   }
  830.  
  831. }
  832.  
  833.  
  834.  
  835. INLINE_PSIM\
  836. (void)
  837. psim_write_register(psim *system,
  838.             int which_cpu,
  839.             const void *buf,
  840.             const char reg[],
  841.             transfer_mode mode)
  842. {
  843.   cpu *processor;
  844.   register_descriptions description;
  845.   char cooked_buf[sizeof(natural_word)];
  846.  
  847.   /* find our processor */
  848.   if (which_cpu == MAX_NR_PROCESSORS)
  849.     which_cpu = system->last_cpu;
  850.   if (which_cpu == -1) {
  851.     int i;
  852.     for (i = 0; i < system->nr_cpus; i++)
  853.       psim_write_register(system, i, buf, reg, mode);
  854.     return;
  855.   }
  856.   else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
  857.     error("psim_read_register() - invalid processor %d\n", which_cpu);
  858.   }
  859.  
  860.   processor = system->processors[which_cpu];
  861.  
  862.   /* find the description of the register */
  863.   description = register_description(reg);
  864.   if (description.type == reg_invalid)
  865.     error("psim_write_register() invalid register name %s\n", reg);
  866.  
  867.   /* If the data is comming in raw (target order), need to cook it
  868.      into host order before putting it into PSIM's internal structures */
  869.   if (mode == raw_transfer) {
  870.     switch (description.size) {
  871.     case 1: 
  872.       *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
  873.       break;
  874.     case 2:
  875.       *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
  876.       break;
  877.     case 4:
  878.       *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
  879.       break;
  880.     case 8:
  881.       *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
  882.       break;
  883.     }
  884.   }
  885.   else {
  886.     memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
  887.   }
  888.  
  889.   /* put the cooked value into the register */
  890.   switch (description.type) {
  891.  
  892.   case reg_gpr:
  893.     cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
  894.     break;
  895.  
  896.   case reg_fpr:
  897.     cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
  898.     break;
  899.  
  900.   case reg_pc:
  901.     cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
  902.     break;
  903.  
  904.   case reg_spr:
  905.     cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
  906.     break;
  907.  
  908.   case reg_sr:
  909.     cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
  910.     break;
  911.  
  912.   case reg_cr:
  913.     cpu_registers(processor)->cr = *(creg*)cooked_buf;
  914.     break;
  915.  
  916.   case reg_msr:
  917.     cpu_registers(processor)->msr = *(msreg*)cooked_buf;
  918.     break;
  919.  
  920.   default:
  921.     printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
  922.             (unsigned long)processor, (unsigned long)cooked_buf, reg,
  923.             "read of this register unimplemented");
  924.     break;
  925.  
  926.   }
  927.  
  928. }
  929.  
  930.  
  931.  
  932. INLINE_PSIM\
  933. (unsigned)
  934. psim_read_memory(psim *system,
  935.          int which_cpu,
  936.          void *buffer,
  937.          unsigned_word vaddr,
  938.          unsigned nr_bytes)
  939. {
  940.   cpu *processor;
  941.   if (which_cpu == MAX_NR_PROCESSORS)
  942.     which_cpu = system->last_cpu;
  943.   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
  944.     error("psim_read_memory() invalid cpu\n");
  945.   processor = system->processors[which_cpu];
  946.   return vm_data_map_read_buffer(cpu_data_map(processor),
  947.                  buffer, vaddr, nr_bytes);
  948. }
  949.  
  950.  
  951. INLINE_PSIM\
  952. (unsigned)
  953. psim_write_memory(psim *system,
  954.           int which_cpu,
  955.           const void *buffer,
  956.           unsigned_word vaddr,
  957.           unsigned nr_bytes,
  958.           int violate_read_only_section)
  959. {
  960.   cpu *processor;
  961.   if (which_cpu == MAX_NR_PROCESSORS)
  962.     which_cpu = system->last_cpu;
  963.   if (which_cpu < 0 || which_cpu >= system->nr_cpus)
  964.     error("psim_read_memory() invalid cpu\n");
  965.   processor = system->processors[which_cpu];
  966.   return vm_data_map_write_buffer(cpu_data_map(processor),
  967.                   buffer, vaddr, nr_bytes, 1);
  968. }
  969.  
  970.  
  971. INLINE_PSIM\
  972. (void)
  973. psim_print_info(psim *system,
  974.         int verbose)
  975. {
  976.   mon_print_info(system, system->monitor, verbose);
  977. }
  978.  
  979.  
  980. /* Merge a device tree and a device file. */
  981.  
  982. INLINE_PSIM\
  983. (void)
  984. psim_merge_device_file(device *root,
  985.                const char *file_name)
  986. {
  987.   FILE *description = fopen(file_name, "r");
  988.   int line_nr = 0;
  989.   char device_path[1000];
  990.   device *current = root;
  991.   while (fgets(device_path, sizeof(device_path), description)) {
  992.     /* check all of line was read */
  993.     if (strchr(device_path, '\n') == NULL) {
  994.       fclose(description);
  995.       error("create_filed_device_tree() line %d to long: %s\n",
  996.         line_nr, device_path);
  997.     }
  998.     line_nr++;
  999.     /* parse this line */
  1000.     current = device_tree_add_parsed(current, "%s", device_path);
  1001.   }
  1002.   fclose(description);
  1003. }
  1004.  
  1005.  
  1006. #endif /* _PSIM_C_ */
  1007.