/[gxemul]/trunk/src/emul.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/emul.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: emul.c,v 1.247 2006/02/04 12:27:12 debug Exp $   *  $Id: emul.c,v 1.272 2006/10/31 08:26:56 debug Exp $
29   *   *
30   *  Emulation startup and misc. routines.   *  Emulation startup and misc. routines.
31   */   */
# Line 39  Line 39 
39  #include <unistd.h>  #include <unistd.h>
40    
41  #include "arcbios.h"  #include "arcbios.h"
 #include "bintrans.h"  
42  #include "cpu.h"  #include "cpu.h"
43  #include "emul.h"  #include "emul.h"
44  #include "console.h"  #include "console.h"
# Line 52  Line 51 
51  #include "mips_cpu_types.h"  #include "mips_cpu_types.h"
52  #include "misc.h"  #include "misc.h"
53  #include "net.h"  #include "net.h"
54    #include "settings.h"
55  #include "sgi_arcbios.h"  #include "sgi_arcbios.h"
56    #include "timer.h"
57  #include "x11.h"  #include "x11.h"
58    
59    
 extern int force_debugger_at_exit;  
   
60  extern int extra_argc;  extern int extra_argc;
61  extern char **extra_argv;  extern char **extra_argv;
62    
63  extern int verbose;  extern int verbose;
64  extern int quiet_mode;  extern int quiet_mode;
65    extern int force_debugger_at_exit;
66    extern int single_step;
67    extern int old_show_trace_tree;
68    extern int old_instruction_trace;
69    extern int old_quiet_mode;
70    extern int quiet_mode;
71    
72  extern struct emul *debugger_emul;  extern struct emul *debugger_emul;
73  extern struct diskimage *diskimages[];  extern struct diskimage *diskimages[];
# Line 105  static void add_dump_points(struct machi Line 110  static void add_dump_points(struct machi
110                          uint64_t addr;                          uint64_t addr;
111                          int res = get_symbol_addr(&m->symbol_context,                          int res = get_symbol_addr(&m->symbol_context,
112                              m->breakpoint_string[i], &addr);                              m->breakpoint_string[i], &addr);
113                          if (!res)                          if (!res) {
114                                  fprintf(stderr,                                  fprintf(stderr,
115                                      "WARNING! Breakpoint '%s' could not be"                                      "ERROR! Breakpoint '%s' could not be"
116                                          " parsed\n",                                          " parsed\n",
117                                      m->breakpoint_string[i]);                                      m->breakpoint_string[i]);
118                          else {                          } else {
119                                  dp = addr;                                  dp = addr;
120                                  string_flag = 1;                                  string_flag = 1;
121                          }                          }
# Line 141  static void add_dump_points(struct machi Line 146  static void add_dump_points(struct machi
146   */   */
147  static void fix_console(void)  static void fix_console(void)
148  {  {
149          console_deinit();          console_deinit_main();
150  }  }
151    
152    
# Line 560  static int load_bootblock(struct machine Line 565  static int load_bootblock(struct machine
565    
566                  /*  Convert loadaddr to uncached:  */                  /*  Convert loadaddr to uncached:  */
567                  if ((bootblock_loadaddr & 0xf0000000ULL) != 0x80000000 &&                  if ((bootblock_loadaddr & 0xf0000000ULL) != 0x80000000 &&
568                      (bootblock_loadaddr & 0xf0000000ULL) != 0xa0000000)                      (bootblock_loadaddr & 0xf0000000ULL) != 0xa0000000) {
569                          fatal("\nWARNING! Weird load address 0x%08x.\n\n",                          fatal("\nWARNING! Weird load address 0x%08"PRIx32
570                              (int)bootblock_loadaddr);                              " for SCSI id %i.\n\n",
571                                (uint32_t)bootblock_loadaddr, boot_disk_id);
572                            if (bootblock_loadaddr == 0) {
573                                    fatal("I'm assuming that this is _not_ a "
574                                        "DEC bootblock.\nAre you sure you are"
575                                        " booting from the correct disk?\n");
576                                    exit(1);
577                            }
578                    }
579    
580                  bootblock_loadaddr &= 0x0fffffffULL;                  bootblock_loadaddr &= 0x0fffffffULL;
581                  bootblock_loadaddr |= 0xffffffffa0000000ULL;                  bootblock_loadaddr |= 0xffffffffa0000000ULL;
582    
# Line 687  static int load_bootblock(struct machine Line 701  static int load_bootblock(struct machine
701                  iso_type = 3;                  iso_type = 3;
702    
703          if (iso_type != 0) {          if (iso_type != 0) {
704                  /*  We can't load a kernel if the name                  /*
705                      isn't specified.  */                   *  If the user specified a kernel name, then load it from
706                     *  disk.
707                     */
708                  if (cpu->machine->boot_kernel_filename == NULL ||                  if (cpu->machine->boot_kernel_filename == NULL ||
709                      cpu->machine->boot_kernel_filename[0] == '\0')                      cpu->machine->boot_kernel_filename[0] == '\0')
710                          fatal("\nISO9660 filesystem, but no kernel "                          fatal("\nISO9660 filesystem, but no kernel "
# Line 711  static int load_bootblock(struct machine Line 727  static int load_bootblock(struct machine
727          }          }
728          if (bootblock_buf[0x000] == 'E' && bootblock_buf[0x001] == 'R' &&          if (bootblock_buf[0x000] == 'E' && bootblock_buf[0x001] == 'R' &&
729              bootblock_buf[0x200] == 'P' && bootblock_buf[0x201] == 'M') {              bootblock_buf[0x200] == 'P' && bootblock_buf[0x201] == 'M') {
                 /*  We can't load a kernel if the name  
                     isn't specified.  */  
730                  if (cpu->machine->boot_kernel_filename == NULL ||                  if (cpu->machine->boot_kernel_filename == NULL ||
731                      cpu->machine->boot_kernel_filename[0] == '\0')                      cpu->machine->boot_kernel_filename[0] == '\0')
732                          fatal("\nApple partition table, but no kernel "                          fatal("\nApple partition table, but no kernel "
# Line 744  struct emul *emul_new(char *name) Line 758  struct emul *emul_new(char *name)
758    
759          memset(e, 0, sizeof(struct emul));          memset(e, 0, sizeof(struct emul));
760    
761            e->settings = settings_new();
762    
763            settings_add(e->settings, "n_machines", 0,
764                SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
765                (void *) &e->n_machines);
766    
767            /*  TODO: More settings?  */
768    
769          /*  Sane default values:  */          /*  Sane default values:  */
770          e->n_machines = 0;          e->n_machines = 0;
771          e->next_serial_nr = 1;          e->next_serial_nr = 1;
# Line 754  struct emul *emul_new(char *name) Line 776  struct emul *emul_new(char *name)
776                          fprintf(stderr, "out of memory in emul_new()\n");                          fprintf(stderr, "out of memory in emul_new()\n");
777                          exit(1);                          exit(1);
778                  }                  }
779    
780                    settings_add(e->settings, "name", 0,
781                        SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,
782                        (void *) &e->name);
783          }          }
784    
785          return e;          return e;
# Line 761  struct emul *emul_new(char *name) Line 787  struct emul *emul_new(char *name)
787    
788    
789  /*  /*
790     *  emul_destroy():
791     *
792     *  Destroys a previously created emul object.
793     */
794    void emul_destroy(struct emul *emul)
795    {
796            int i;
797    
798            if (emul->name != NULL) {
799                    settings_remove(emul->settings, "name");
800                    free(emul->name);
801            }
802    
803            for (i=0; i<emul->n_machines; i++)
804                    machine_destroy(emul->machines[i]);
805    
806            if (emul->machines != NULL)
807                    free(emul->machines);
808    
809            /*  Remove any remaining level-1 settings:  */
810            settings_remove_all(emul->settings);
811            settings_destroy(emul->settings);
812    
813            free(emul);
814    }
815    
816    
817    /*
818   *  emul_add_machine():   *  emul_add_machine():
819   *   *
820   *  Calls machine_new(), adds the new machine into the emul struct, and   *  Calls machine_new(), adds the new machine into the emul struct, and
# Line 771  struct emul *emul_new(char *name) Line 825  struct emul *emul_new(char *name)
825  struct machine *emul_add_machine(struct emul *e, char *name)  struct machine *emul_add_machine(struct emul *e, char *name)
826  {  {
827          struct machine *m;          struct machine *m;
828            char tmpstr[20];
829            int i;
830    
831          m = machine_new(name, e);          m = machine_new(name, e);
832          m->serial_nr = (e->next_serial_nr ++);          m->serial_nr = (e->next_serial_nr ++);
833    
834            i = e->n_machines;
835    
836          e->n_machines ++;          e->n_machines ++;
837          e->machines = realloc(e->machines,          e->machines = realloc(e->machines,
838              sizeof(struct machine *) * e->n_machines);              sizeof(struct machine *) * e->n_machines);
# Line 783  struct machine *emul_add_machine(struct Line 841  struct machine *emul_add_machine(struct
841                  exit(1);                  exit(1);
842          }          }
843    
844          e->machines[e->n_machines - 1] = m;          e->machines[i] = m;
845    
846            snprintf(tmpstr, sizeof(tmpstr), "machine[%i]", i);
847            settings_add(e->settings, tmpstr, 1, SETTINGS_TYPE_SUBSETTINGS, 0,
848                e->machines[i]->settings);
849    
850          return m;          return m;
851  }  }
852    
# Line 940  void emul_machine_setup(struct machine * Line 1003  void emul_machine_setup(struct machine *
1003          if (m->arch == ARCH_ALPHA)          if (m->arch == ARCH_ALPHA)
1004                  m->arch_pagesize = 8192;                  m->arch_pagesize = 8192;
1005    
         if (m->arch != ARCH_MIPS)  
                 m->bintrans_enable = 0;  
   
1006          machine_memsize_fix(m);          machine_memsize_fix(m);
1007    
1008          /*          /*
# Line 990  void emul_machine_setup(struct machine * Line 1050  void emul_machine_setup(struct machine *
1050          }          }
1051          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
1052    
         /*  Initialize dynamic binary translation, if available:  */  
         if (m->bintrans_enable)  
                 bintrans_init(m, m->memory);  
   
1053          debug("cpu0");          debug("cpu0");
1054          if (m->ncpus > 1)          if (m->ncpus > 1)
1055                  debug(" .. cpu%i", m->ncpus - 1);                  debug(" .. cpu%i", m->ncpus - 1);
1056          debug(": ");          debug(": ");
1057          for (i=0; i<m->ncpus; i++) {          for (i=0; i<m->ncpus; i++) {
1058                  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);                  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
1059                  if (m->bintrans_enable)                  if (m->cpus[i] == NULL) {
1060                          bintrans_init_cpu(m->cpus[i]);                          fprintf(stderr, "Unable to create CPU object. "
1061                                "Aborting.");
1062                            exit(1);
1063                    }
1064          }          }
1065          debug("\n");          debug("\n");
1066    
# Line 1012  void emul_machine_setup(struct machine * Line 1071  void emul_machine_setup(struct machine *
1071                  m->cpus[m->ncpus] = cpu_new(m->memory, m,                  m->cpus[m->ncpus] = cpu_new(m->memory, m,
1072                      0  /*  use 0 here to show info with debug()  */,                      0  /*  use 0 here to show info with debug()  */,
1073                      "Allegrex" /*  TODO  */);                      "Allegrex" /*  TODO  */);
                 if (m->bintrans_enable)  
                         bintrans_init_cpu(m->cpus[m->ncpus]);  
1074                  debug("\n");                  debug("\n");
1075                  m->ncpus ++;                  m->ncpus ++;
1076          }          }
# Line 1240  void emul_machine_setup(struct machine * Line 1297  void emul_machine_setup(struct machine *
1297                          }                          }
1298                          break;                          break;
1299    
1300                    case ARCH_AVR32:
1301                            cpu->pc = (uint32_t) cpu->pc;
1302                            if (cpu->pc & 1) {
1303                                    fatal("AVR32: lowest bit of pc set: TODO\n");
1304                                    exit(1);
1305                            }
1306                            break;
1307    
1308                    case ARCH_RCA180X:
1309                            cpu->pc &= 0xffff;
1310                            break;
1311    
1312                  case ARCH_HPPA:                  case ARCH_HPPA:
1313                          break;                          break;
1314    
# Line 1274  void emul_machine_setup(struct machine * Line 1343  void emul_machine_setup(struct machine *
1343                          break;                          break;
1344    
1345                  case ARCH_SH:                  case ARCH_SH:
1346                          if (cpu->cd.sh.bits == 32)                          if (cpu->cd.sh.cpu_type.bits == 32)
1347                                  cpu->pc &= 0xffffffffULL;                                  cpu->pc &= 0xffffffffULL;
1348                          cpu->pc &= ~1;                          cpu->pc &= ~1;
1349                          break;                          break;
# Line 1282  void emul_machine_setup(struct machine * Line 1351  void emul_machine_setup(struct machine *
1351                  case ARCH_SPARC:                  case ARCH_SPARC:
1352                          break;                          break;
1353    
1354                    case ARCH_TRANSPUTER:
1355                            cpu->pc &= 0xffffffffULL;
1356                            break;
1357    
1358                  case ARCH_X86:                  case ARCH_X86:
1359                          /*                          /*
1360                           *  NOTE: The toc field is used to indicate an ELF32                           *  NOTE: The toc field is used to indicate an ELF32
# Line 1335  void emul_machine_setup(struct machine * Line 1408  void emul_machine_setup(struct machine *
1408                  useremul_setup(cpu, n_load, load_names);                  useremul_setup(cpu, n_load, load_names);
1409    
1410          /*  Startup the bootstrap CPU:  */          /*  Startup the bootstrap CPU:  */
1411          cpu->bootstrap_cpu_flag = 1;          cpu->running = 1;
         cpu->running            = 1;  
1412    
1413          /*  ... or pause all CPUs, if start_paused is set:  */          /*  ... or pause all CPUs, if start_paused is set:  */
1414          if (m->start_paused) {          if (m->start_paused) {
# Line 1355  void emul_machine_setup(struct machine * Line 1427  void emul_machine_setup(struct machine *
1427    
1428          symbol_recalc_sizes(&m->symbol_context);          symbol_recalc_sizes(&m->symbol_context);
1429    
         if (m->max_random_cycles_per_chunk > 0)  
                 debug("using random cycle chunks (1 to %i cycles)\n",  
                     m->max_random_cycles_per_chunk);  
   
1430          /*  Special hack for ARC/SGI emulation:  */          /*  Special hack for ARC/SGI emulation:  */
1431          if ((m->machine_type == MACHINE_ARC ||          if ((m->machine_type == MACHINE_ARC ||
1432              m->machine_type == MACHINE_SGI) && m->prom_emulation)              m->machine_type == MACHINE_SGI) && m->prom_emulation)
# Line 1470  void emul_simple_init(struct emul *emul) Line 1538  void emul_simple_init(struct emul *emul)
1538    
1539                  /*  Create a simple network:  */                  /*  Create a simple network:  */
1540                  emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,                  emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
1541                      "10.0.0.0", 8, NULL, 0, 0);                      NET_DEFAULT_IPV4_MASK,
1542                        NET_DEFAULT_IPV4_LEN,
1543                        NULL, 0, 0, NULL);
1544          } else {          } else {
1545                  /*  Userland pseudo-machine:  */                  /*  Userland pseudo-machine:  */
1546                  debug("Syscall emulation (userland-only) setup...\n");                  debug("Syscall emulation (userland-only) setup...\n");
# Line 1493  struct emul *emul_create_from_configfile Line 1563  struct emul *emul_create_from_configfile
1563  {  {
1564          int iadd = DEBUG_INDENTATION;          int iadd = DEBUG_INDENTATION;
1565          struct emul *e = emul_new(fname);          struct emul *e = emul_new(fname);
         FILE *f;  
         char buf[128];  
         size_t len;  
1566    
1567          debug("Creating emulation from configfile \"%s\":\n", fname);          debug("Creating emulation from configfile \"%s\":\n", fname);
1568          debug_indentation(iadd);          debug_indentation(iadd);
1569    
1570          f = fopen(fname, "r");          emul_parse_config(e, fname);
         if (f == NULL) {  
                 perror(fname);  
                 exit(1);  
         }  
   
         /*  Read header: (must be !!gxemul)  */  
         len = fread(buf, 1, 8, f);  
         if (len != 8 || strncmp(buf, "!!gxemul", 8) != 0) {  
                 fprintf(stderr, "%s: must start with '!!gxemul'\n", fname);  
                 exit(1);  
         }  
   
         /*  Restart from beginning:  */  
         rewind(f);  
1571    
         emul_parse_config(e, f);  
   
         fclose(f);  
1572          debug_indentation(-iadd);          debug_indentation(-iadd);
1573          return e;          return e;
1574  }  }
# Line 1599  void emul_run(struct emul **emuls, int n Line 1649  void emul_run(struct emul **emuls, int n
1649                  cpu_functioncall_trace(emuls[0]->machines[0]->cpus[0],                  cpu_functioncall_trace(emuls[0]->machines[0]->cpus[0],
1650                      emuls[0]->machines[0]->cpus[0]->pc);                      emuls[0]->machines[0]->cpus[0]->pc);
1651    
1652            /*  Start emulated clocks:  */
1653            timer_start();
1654    
1655          /*          /*
1656           *  MAIN LOOP:           *  MAIN LOOP:
1657           *           *
# Line 1608  void emul_run(struct emul **emuls, int n Line 1661  void emul_run(struct emul **emuls, int n
1661          while (go) {          while (go) {
1662                  go = 0;                  go = 0;
1663    
1664                  x11_check_event(emuls, n_emuls);                  /*  Flush X11 and serial console output every now and then:  */
1665                    if (emuls[0]->machines[0]->ninstrs >
1666                        emuls[0]->machines[0]->ninstrs_flush + (1<<19)) {
1667                            x11_check_event(emuls, n_emuls);
1668                            console_flush();
1669                            emuls[0]->machines[0]->ninstrs_flush =
1670                                emuls[0]->machines[0]->ninstrs;
1671                    }
1672    
1673                    if (emuls[0]->machines[0]->ninstrs >
1674                        emuls[0]->machines[0]->ninstrs_show + (1<<25)) {
1675                            emuls[0]->machines[0]->ninstrs_since_gettimeofday +=
1676                                (emuls[0]->machines[0]->ninstrs -
1677                                 emuls[0]->machines[0]->ninstrs_show);
1678                            cpu_show_cycles(emuls[0]->machines[0], 0);
1679                            emuls[0]->machines[0]->ninstrs_show =
1680                                emuls[0]->machines[0]->ninstrs;
1681                    }
1682    
1683                    if (single_step == ENTER_SINGLE_STEPPING) {
1684                            /*  TODO: Cleanup!  */
1685                            old_instruction_trace =
1686                                emuls[0]->machines[0]->instruction_trace;
1687                            old_quiet_mode = quiet_mode;
1688                            old_show_trace_tree =
1689                                emuls[0]->machines[0]->show_trace_tree;
1690                            emuls[0]->machines[0]->instruction_trace = 1;
1691                            emuls[0]->machines[0]->show_trace_tree = 1;
1692                            quiet_mode = 0;
1693                            single_step = SINGLE_STEPPING;
1694                    }
1695    
1696                    if (single_step == SINGLE_STEPPING)
1697                            debugger();
1698    
1699                  for (i=0; i<n_emuls; i++) {                  for (i=0; i<n_emuls; i++) {
1700                          e = emuls[i];                          e = emuls[i];
                         if (e == NULL)  
                                 continue;  
1701    
1702                          for (j=0; j<e->n_machines; j++) {                          for (j=0; j<e->n_machines; j++) {
1703                                  /*  TODO: cpu_run() is a strange name, since                                  if (e->machines[j]->gdb.port > 0)
1704                                      there can be multiple cpus in a machine  */                                          debugger_gdb_check_incoming(
1705                                  anything = cpu_run(e, e->machines[j]);                                              e->machines[j]);
1706    
1707                                    anything = machine_run(e->machines[j]);
1708                                  if (anything)                                  if (anything)
1709                                          go = 1;                                          go = 1;
1710                          }                          }
1711                  }                  }
1712          }          }
1713    
1714            /*  Stop any running timers:  */
1715            timer_stop();
1716    
1717          /*  Deinitialize all CPUs in all machines in all emulations:  */          /*  Deinitialize all CPUs in all machines in all emulations:  */
1718          for (i=0; i<n_emuls; i++) {          for (i=0; i<n_emuls; i++) {
1719                  e = emuls[i];                  e = emuls[i];
# Line 1641  void emul_run(struct emul **emuls, int n Line 1730  void emul_run(struct emul **emuls, int n
1730                  debugger();                  debugger();
1731          }          }
1732    
1733          /*  Any machine using X11? Then we should wait before exiting:  */          /*  Any machine using X11? Then wait before exiting:  */
1734          n = 0;          n = 0;
1735          for (i=0; i<n_emuls; i++)          for (i=0; i<n_emuls; i++)
1736                  for (j=0; j<emuls[i]->n_machines; j++)                  for (j=0; j<emuls[i]->n_machines; j++)
# Line 1651  void emul_run(struct emul **emuls, int n Line 1740  void emul_run(struct emul **emuls, int n
1740                  printf("Press enter to quit.\n");                  printf("Press enter to quit.\n");
1741                  while (!console_charavail(MAIN_CONSOLE)) {                  while (!console_charavail(MAIN_CONSOLE)) {
1742                          x11_check_event(emuls, n_emuls);                          x11_check_event(emuls, n_emuls);
1743                          usleep(1);                          usleep(10000);
1744                  }                  }
1745                  console_readchar(MAIN_CONSOLE);                  console_readchar(MAIN_CONSOLE);
1746          }          }
1747    
1748          console_deinit();          console_deinit_main();
1749  }  }
1750    

Legend:
Removed from v.22  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26