/[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 2 by dpavlin, Mon Oct 8 16:17:48 2007 UTC revision 38 by dpavlin, Mon Oct 8 16:21:53 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: emul.c,v 1.179 2005/03/14 19:14:04 debug Exp $   *  $Id: emul.c,v 1.282 2007/04/11 15:15:31 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"
 #include "cpu_mips.h"  
43  #include "emul.h"  #include "emul.h"
44  #include "console.h"  #include "console.h"
45  #include "debugger.h"  #include "debugger.h"
46  #include "device.h"  #include "device.h"
47  #include "diskimage.h"  #include "diskimage.h"
48    #include "exec_elf.h"
49  #include "machine.h"  #include "machine.h"
50  #include "memory.h"  #include "memory.h"
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[];
74    
75    
76    static void print_separator(void)
77    {
78            int i = 79;
79            while (i-- > 0)
80                    debug("-");
81            debug("\n");
82    }
83    
84    
85  /*  /*
86   *  add_dump_points():   *  add_dump_points():
87   *   *
# Line 94  static void add_dump_points(struct machi Line 108  static void add_dump_points(struct machi
108                          uint64_t addr;                          uint64_t addr;
109                          int res = get_symbol_addr(&m->symbol_context,                          int res = get_symbol_addr(&m->symbol_context,
110                              m->breakpoint_string[i], &addr);                              m->breakpoint_string[i], &addr);
111                          if (!res)                          if (!res) {
112                                  fprintf(stderr,                                  fprintf(stderr,
113                                      "WARNING! Breakpoint '%s' could not be"                                      "ERROR! Breakpoint '%s' could not be"
114                                          " parsed\n",                                          " parsed\n",
115                                      m->breakpoint_string[i]);                                      m->breakpoint_string[i]);
116                          else {                          } else {
117                                  dp = addr;                                  dp = addr;
118                                  string_flag = 1;                                  string_flag = 1;
119                          }                          }
# Line 110  static void add_dump_points(struct machi Line 124  static void add_dump_points(struct machi
124                   *  were automatically converted into the correct address.                   *  were automatically converted into the correct address.
125                   */                   */
126    
127                  if ((dp >> 32) == 0 && ((dp >> 31) & 1))                  if (m->arch == ARCH_MIPS) {
128                          dp |= 0xffffffff00000000ULL;                          if ((dp >> 32) == 0 && ((dp >> 31) & 1))
129                                    dp |= 0xffffffff00000000ULL;
130                    }
131    
132                  m->breakpoint_addr[i] = dp;                  m->breakpoint_addr[i] = dp;
133    
134                  debug("breakpoint %i: 0x%016llx", i, (long long)dp);                  debug("breakpoint %i: 0x%llx", i, (long long)dp);
135                  if (string_flag)                  if (string_flag)
136                          debug(" (%s)", m->breakpoint_string[i]);                          debug(" (%s)", m->breakpoint_string[i]);
137                  debug("\n");                  debug("\n");
# Line 127  static void add_dump_points(struct machi Line 144  static void add_dump_points(struct machi
144   */   */
145  static void fix_console(void)  static void fix_console(void)
146  {  {
147          console_deinit();          console_deinit_main();
 }  
   
   
 /*  
  *  load_bootblock():  
  *  
  *  For some emulation modes, it is possible to boot from a harddisk image by  
  *  loading a bootblock from a specific disk offset into memory, and executing  
  *  that, instead of requiring a separate kernel file.  It is then up to the  
  *  bootblock to load a kernel.  
  */  
 static void load_bootblock(struct machine *m, struct cpu *cpu)  
 {  
         int boot_disk_id;  
         unsigned char minibuf[0x20];  
         unsigned char *bootblock_buf;  
         uint64_t bootblock_offset;  
         uint64_t bootblock_loadaddr, bootblock_pc;  
         int n_blocks, res, readofs;  
   
         boot_disk_id = diskimage_bootdev(m);  
         if (boot_disk_id < 0)  
                 return;  
   
         switch (m->machine_type) {  
         case MACHINE_DEC:  
                 /*  
                  *  The first few bytes of a disk contains information about  
                  *  where the bootblock(s) are located. (These are all 32-bit  
                  *  little-endian words.)  
                  *  
                  *  Offset 0x10 = load address  
                  *         0x14 = initial PC value  
                  *         0x18 = nr of 512-byte blocks to read  
                  *         0x1c = offset on disk to where the bootblocks  
                  *                are (in 512-byte units)  
                  *         0x20 = nr of blocks to read...  
                  *         0x24 = offset...  
                  *  
                  *  nr of blocks to read and offset are repeated until nr of  
                  *  blocks to read is zero.  
                  */  
                 res = diskimage_access(m, boot_disk_id, 0, 0,  
                     minibuf, sizeof(minibuf));  
   
                 bootblock_loadaddr = minibuf[0x10] + (minibuf[0x11] << 8)  
                   + (minibuf[0x12] << 16) + (minibuf[0x13] << 24);  
   
                 /*  Convert loadaddr to uncached:  */  
                 if ((bootblock_loadaddr & 0xf0000000ULL) != 0x80000000 &&  
                     (bootblock_loadaddr & 0xf0000000ULL) != 0xa0000000)  
                         fatal("\nWARNING! Weird load address 0x%08x.\n\n",  
                             (int)bootblock_loadaddr);  
                 bootblock_loadaddr &= 0x0fffffffULL;  
                 bootblock_loadaddr |= 0xffffffffa0000000ULL;  
   
                 bootblock_pc = minibuf[0x14] + (minibuf[0x15] << 8)  
                   + (minibuf[0x16] << 16) + (minibuf[0x17] << 24);  
   
                 bootblock_pc &= 0x0fffffffULL;  
                 bootblock_pc |= 0xffffffffa0000000ULL;  
                 cpu->pc = bootblock_pc;  
   
                 debug("DEC boot: loadaddr=0x%08x, pc=0x%08x",  
                     (int)bootblock_loadaddr, (int)bootblock_pc);  
   
                 readofs = 0x18;  
   
                 for (;;) {  
                         res = diskimage_access(m, boot_disk_id, 0, readofs,  
                             minibuf, sizeof(minibuf));  
                         if (!res) {  
                                 printf("couldn't read disk?\n");  
                                 exit(1);  
                         }  
   
                         n_blocks = minibuf[0] + (minibuf[1] << 8)  
                           + (minibuf[2] << 16) + (minibuf[3] << 24);  
   
                         bootblock_offset = (minibuf[4] + (minibuf[5] << 8)  
                           + (minibuf[6] << 16) + (minibuf[7] << 24)) * 512;  
   
                         if (n_blocks < 1)  
                                 break;  
   
                         debug(readofs == 0x18? ": %i" : " + %i", n_blocks);  
   
                         if (n_blocks * 512 > 65536)  
                                 fatal("\nWARNING! Unusually large bootblock "  
                                     "(%i bytes)\n\n", n_blocks * 512);  
   
                         bootblock_buf = malloc(n_blocks * 512);  
                         if (bootblock_buf == NULL) {  
                                 fprintf(stderr, "out of memory in "  
                                     "load_bootblock()\n");  
                                 exit(1);  
                         }  
   
                         res = diskimage_access(m, boot_disk_id, 0,  
                             bootblock_offset, bootblock_buf, n_blocks * 512);  
                         if (!res) {  
                                 fatal("WARNING: could not load bootblocks from"  
                                     " disk offset 0x%llx\n",  
                                     (long long)bootblock_offset);  
                         }  
   
                         store_buf(cpu, bootblock_loadaddr,  
                             (char *)bootblock_buf, n_blocks * 512);  
   
                         bootblock_loadaddr += 512*n_blocks;  
                         free(bootblock_buf);  
                         readofs += 8;  
                 }  
   
                 debug(readofs == 0x18? ": no blocks?\n" : " blocks\n");  
                 break;  
         default:  
                 fatal("Booting from disk without a separate kernel "  
                     "doesn't work in this emulation mode.\n");  
                 exit(1);  
         }  
148  }  }
149    
150    
# Line 257  static void load_bootblock(struct machin Line 153  static void load_bootblock(struct machin
153   *   *
154   *  Returns a reasonably initialized struct emul.   *  Returns a reasonably initialized struct emul.
155   */   */
156  struct emul *emul_new(char *name)  struct emul *emul_new(char *name, int id)
157  {  {
158          struct emul *e;          struct emul *e;
159          e = malloc(sizeof(struct emul));          e = malloc(sizeof(struct emul));
# Line 268  struct emul *emul_new(char *name) Line 164  struct emul *emul_new(char *name)
164    
165          memset(e, 0, sizeof(struct emul));          memset(e, 0, sizeof(struct emul));
166    
167            e->path = malloc(15);
168            if (e->path == NULL) {
169                    fprintf(stderr, "out of memory\n");
170                    exit(1);
171            }
172            snprintf(e->path, 15, "emul[%i]", id);
173    
174            e->settings = settings_new();
175    
176            settings_add(e->settings, "n_machines", 0,
177                SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
178                (void *) &e->n_machines);
179    
180            /*  TODO: More settings?  */
181    
182          /*  Sane default values:  */          /*  Sane default values:  */
183          e->n_machines = 0;          e->n_machines = 0;
184            e->next_serial_nr = 1;
185    
186          if (name != NULL) {          if (name != NULL) {
187                  e->name = strdup(name);                  e->name = strdup(name);
# Line 277  struct emul *emul_new(char *name) Line 189  struct emul *emul_new(char *name)
189                          fprintf(stderr, "out of memory in emul_new()\n");                          fprintf(stderr, "out of memory in emul_new()\n");
190                          exit(1);                          exit(1);
191                  }                  }
192    
193                    settings_add(e->settings, "name", 0,
194                        SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,
195                        (void *) &e->name);
196          }          }
197    
198          return e;          return e;
# Line 284  struct emul *emul_new(char *name) Line 200  struct emul *emul_new(char *name)
200    
201    
202  /*  /*
203     *  emul_destroy():
204     *
205     *  Destroys a previously created emul object.
206     */
207    void emul_destroy(struct emul *emul)
208    {
209            int i;
210    
211            if (emul->name != NULL) {
212                    settings_remove(emul->settings, "name");
213                    free(emul->name);
214            }
215    
216            for (i=0; i<emul->n_machines; i++)
217                    machine_destroy(emul->machines[i]);
218    
219            if (emul->machines != NULL)
220                    free(emul->machines);
221    
222            /*  Remove any remaining level-1 settings:  */
223            settings_remove_all(emul->settings);
224            settings_destroy(emul->settings);
225    
226            free(emul);
227    }
228    
229    
230    /*
231   *  emul_add_machine():   *  emul_add_machine():
232   *   *
233   *  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 294  struct emul *emul_new(char *name) Line 238  struct emul *emul_new(char *name)
238  struct machine *emul_add_machine(struct emul *e, char *name)  struct machine *emul_add_machine(struct emul *e, char *name)
239  {  {
240          struct machine *m;          struct machine *m;
241            char tmpstr[20];
242            int i;
243    
244          m = machine_new(name, e);          m = machine_new(name, e, e->n_machines);
245          m->serial_nr = (e->next_serial_nr ++);          m->serial_nr = (e->next_serial_nr ++);
246    
247            i = e->n_machines;
248    
249          e->n_machines ++;          e->n_machines ++;
250          e->machines = realloc(e->machines,          e->machines = realloc(e->machines,
251              sizeof(struct machine *) * e->n_machines);              sizeof(struct machine *) * e->n_machines);
# Line 306  struct machine *emul_add_machine(struct Line 254  struct machine *emul_add_machine(struct
254                  exit(1);                  exit(1);
255          }          }
256    
257          e->machines[e->n_machines - 1] = m;          e->machines[i] = m;
258    
259            snprintf(tmpstr, sizeof(tmpstr), "machine[%i]", i);
260            settings_add(e->settings, tmpstr, 1, SETTINGS_TYPE_SUBSETTINGS, 0,
261                e->machines[i]->settings);
262    
263          return m;          return m;
264  }  }
265    
# Line 332  static void add_arc_components(struct ma Line 285  static void add_arc_components(struct ma
285    
286          len += 1048576 * m->memory_offset_in_mb;          len += 1048576 * m->memory_offset_in_mb;
287    
288          /*  NOTE/TODO: magic 12MB end of load program area  */          /*
289             *  NOTE/TODO: magic 12MB end of load program area
290             *
291             *  Hm. This breaks the old FreeBSD/MIPS snapshots...
292             */
293    #if 0
294          arcbios_add_memory_descriptor(cpu,          arcbios_add_memory_descriptor(cpu,
295              0x60000 + m->memory_offset_in_mb * 1048576,              0x60000 + m->memory_offset_in_mb * 1048576,
296              start-0x60000 - m->memory_offset_in_mb * 1048576,              start-0x60000 - m->memory_offset_in_mb * 1048576,
297              ARCBIOS_MEM_FreeMemory);              ARCBIOS_MEM_FreeMemory);
298    #endif
299          arcbios_add_memory_descriptor(cpu,          arcbios_add_memory_descriptor(cpu,
300              start, len, ARCBIOS_MEM_LoadedProgram);              start, len, ARCBIOS_MEM_LoadedProgram);
301    
302          scsicontroller = arcbios_get_scsicontroller();          scsicontroller = arcbios_get_scsicontroller(m);
303          if (scsicontroller == 0)          if (scsicontroller == 0)
304                  return;                  return;
305    
# Line 388  static void add_arc_components(struct ma Line 347  static void add_arc_components(struct ma
347                                  snprintf(component_string,                                  snprintf(component_string,
348                                      sizeof(component_string),                                      sizeof(component_string),
349                                      "scsi(0)cdrom(%i)", d->id);                                      "scsi(0)cdrom(%i)", d->id);
350                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
351                                      component_string, scsidevice);                                      component_string, scsidevice);
352    
353                                  snprintf(component_string,                                  snprintf(component_string,
354                                      sizeof(component_string),                                      sizeof(component_string),
355                                      "scsi(0)cdrom(%i)fdisk(0)", d->id);                                      "scsi(0)cdrom(%i)fdisk(0)", d->id);
356                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
357                                      component_string, scsidisk);                                      component_string, scsidisk);
358                          } else {                          } else {
359                                  snprintf(component_string,                                  snprintf(component_string,
360                                      sizeof(component_string),                                      sizeof(component_string),
361                                      "scsi(0)disk(%i)", d->id);                                      "scsi(0)disk(%i)", d->id);
362                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
363                                      component_string, scsidevice);                                      component_string, scsidevice);
364    
365                                  snprintf(component_string,                                  snprintf(component_string,
366                                      sizeof(component_string),                                      sizeof(component_string),
367                                      "scsi(0)disk(%i)rdisk(0)", d->id);                                      "scsi(0)disk(%i)rdisk(0)", d->id);
368                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
369                                      component_string, scsidisk);                                      component_string, scsidisk);
370                          }                          }
371                  }                  }
# Line 429  static void add_arc_components(struct ma Line 388  static void add_arc_components(struct ma
388  void emul_machine_setup(struct machine *m, int n_load, char **load_names,  void emul_machine_setup(struct machine *m, int n_load, char **load_names,
389          int n_devices, char **device_names)          int n_devices, char **device_names)
390  {  {
         struct emul *emul;  
391          struct cpu *cpu;          struct cpu *cpu;
392          int i, iadd=4;          int i, iadd = DEBUG_INDENTATION;
393          uint64_t addr, memory_amount, entrypoint = 0, gp = 0, toc = 0;          uint64_t memory_amount, entrypoint = 0, gp = 0, toc = 0;
394          int byte_order;          int byte_order;
395    
         emul = m->emul;  
   
396          debug("machine \"%s\":\n", m->name);          debug("machine \"%s\":\n", m->name);
397          debug_indentation(iadd);          debug_indentation(iadd);
398    
# Line 457  void emul_machine_setup(struct machine * Line 413  void emul_machine_setup(struct machine *
413    
414          m->cpu_family = cpu_family_ptr_by_number(m->arch);          m->cpu_family = cpu_family_ptr_by_number(m->arch);
415    
416            if (m->arch == ARCH_ALPHA)
417                    m->arch_pagesize = 8192;
418    
419          machine_memsize_fix(m);          machine_memsize_fix(m);
420    
421          /*          /*
# Line 477  void emul_machine_setup(struct machine * Line 436  void emul_machine_setup(struct machine *
436                  debug(" (offset by %iMB)", m->memory_offset_in_mb);                  debug(" (offset by %iMB)", m->memory_offset_in_mb);
437                  memory_amount += 1048576 * m->memory_offset_in_mb;                  memory_amount += 1048576 * m->memory_offset_in_mb;
438          }          }
439          m->memory = memory_new(memory_amount);          m->memory = memory_new(memory_amount, m->arch);
440          if (m->machine_type != MACHINE_USERLAND)          if (m->machine_type != MACHINE_USERLAND)
441                  debug("\n");                  debug("\n");
442    
# Line 504  void emul_machine_setup(struct machine * Line 463  void emul_machine_setup(struct machine *
463          }          }
464          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
465    
         /*  Initialize dynamic binary translation, if available:  */  
         if (m->bintrans_enable)  
                 bintrans_init(m, m->memory);  
   
466          debug("cpu0");          debug("cpu0");
467          if (m->ncpus > 1)          if (m->ncpus > 1)
468                  debug(" .. cpu%i", m->ncpus - 1);                  debug(" .. cpu%i", m->ncpus - 1);
469          debug(": ");          debug(": ");
470          for (i=0; i<m->ncpus; i++) {          for (i=0; i<m->ncpus; i++) {
471                  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);                  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
472                  if (m->bintrans_enable)                  if (m->cpus[i] == NULL) {
473                          bintrans_init_cpu(m->cpus[i]);                          fprintf(stderr, "Unable to create CPU object. "
474                                "Aborting.");
475                            exit(1);
476                    }
477          }          }
478          debug("\n");          debug("\n");
479    
480    #if 0
481            /*  Special case: The Playstation Portable has an additional CPU:  */
482            if (m->machine_type == MACHINE_PSP) {
483                    debug("cpu%i: ", m->ncpus);
484                    m->cpus[m->ncpus] = cpu_new(m->memory, m,
485                        0  /*  use 0 here to show info with debug()  */,
486                        "Allegrex" /*  TODO  */);
487                    debug("\n");
488                    m->ncpus ++;
489            }
490    #endif
491    
492          if (m->use_random_bootstrap_cpu)          if (m->use_random_bootstrap_cpu)
493                  m->bootstrap_cpu = random() % m->ncpus;                  m->bootstrap_cpu = random() % m->ncpus;
494          else          else
# Line 530  void emul_machine_setup(struct machine * Line 500  void emul_machine_setup(struct machine *
500          if (m->userland_emul != NULL) {          if (m->userland_emul != NULL) {
501                  useremul_name_to_useremul(cpu,                  useremul_name_to_useremul(cpu,
502                      m->userland_emul, NULL, NULL, NULL);                      m->userland_emul, NULL, NULL, NULL);
503                  cpu->memory_rw = userland_memory_rw;  
504                    switch (m->arch) {
505    #ifdef ENABLE_ALPHA
506                    case ARCH_ALPHA:
507                            cpu->memory_rw = alpha_userland_memory_rw;
508                            break;
509    #endif
510                    default:cpu->memory_rw = userland_memory_rw;
511                    }
512          }          }
513    
514          if (m->use_x11)          if (m->use_x11)
515                  x11_init(m);                  x11_init(m);
516    
517          /*  Fill memory with random bytes:  */          /*  Fill memory with random bytes:  */
         /*  TODO: This is MIPS-specific!  */  
518          if (m->random_mem_contents) {          if (m->random_mem_contents) {
519                  for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {                  for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {
520                          unsigned char data[256];                          unsigned char data[256];
521                          unsigned int j;                          unsigned int j;
522                          for (j=0; j<sizeof(data); j++)                          for (j=0; j<sizeof(data); j++)
523                                  data[j] = random() & 255;                                  data[j] = random() & 255;
524                          addr = 0xffffffff80000000ULL + i;                          cpu->memory_rw(cpu, m->memory, i, data, sizeof(data),
525                          cpu->memory_rw(cpu, m->memory, addr, data, sizeof(data),                              MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS | PHYSICAL);
                             MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS);  
526                  }                  }
527          }          }
528    
         if ((m->machine_type == MACHINE_ARC ||  
             m->machine_type == MACHINE_SGI) && m->prom_emulation)  
                 arcbios_init();  
   
529          if (m->userland_emul != NULL) {          if (m->userland_emul != NULL) {
530                  /*                  /*
531                   *  For userland-only emulation, no machine emulation                   *  For userland-only emulation, no machine emulation
# Line 567  void emul_machine_setup(struct machine * Line 539  void emul_machine_setup(struct machine *
539          }          }
540    
541          diskimage_dump_info(m);          diskimage_dump_info(m);
542            console_debug_dump(m);
543    
544          /*  Load files (ROM code, boot code, ...) into memory:  */          /*  Load files (ROM code, boot code, ...) into memory:  */
545          if (n_load == 0) {          if (n_load == 0) {
546                  if (m->first_diskimage != NULL)                  if (m->first_diskimage != NULL) {
547                          load_bootblock(m, cpu);                          if (!load_bootblock(m, cpu, &n_load, &load_names)) {
548                  else {                                  fprintf(stderr, "\nNo executable files were"
549                                        " specified, and booting directly from disk"
550                                        " failed.\n");
551                                    exit(1);
552                            }
553                    } else {
554                          fprintf(stderr, "No executable file(s) loaded, and "                          fprintf(stderr, "No executable file(s) loaded, and "
555                              "we are not booting directly from a disk image."                              "we are not booting directly from a disk image."
556                              "\nAborting.\n");                              "\nAborting.\n");
# Line 581  void emul_machine_setup(struct machine * Line 559  void emul_machine_setup(struct machine *
559          }          }
560    
561          while (n_load > 0) {          while (n_load > 0) {
562                    FILE *tmp_f;
563                    char *name_to_load = *load_names;
564                    int remove_after_load = 0;
565    
566                    /*  Special hack for removing temporary files:  */
567                    if (name_to_load[0] == 8) {
568                            name_to_load ++;
569                            remove_after_load = 1;
570                    }
571    
572                    /*
573                     *  gzipped files are automagically gunzipped:
574                     *  NOTE/TODO: This isn't secure. system() is used.
575                     */
576                    tmp_f = fopen(name_to_load, "r");
577                    if (tmp_f != NULL) {
578                            unsigned char buf[2];           /*  gzip header  */
579                            memset(buf, 0, sizeof(buf));
580                            fread(buf, 1, sizeof(buf), tmp_f);
581                            if (buf[0]==0x1f && buf[1]==0x8b) {
582                                    size_t zzlen = strlen(name_to_load)*2 + 100;
583                                    char *zz = malloc(zzlen);
584                                    debug("gunziping %s\n", name_to_load);
585                                    /*
586                                     *  gzip header found.  If this was a file
587                                     *  extracted from, say, a CDROM image, then it
588                                     *  already has a temporary name. Otherwise we
589                                     *  have to gunzip into a temporary file.
590                                     */
591                                    if (remove_after_load) {
592                                            snprintf(zz, zzlen, "mv %s %s.gz",
593                                                name_to_load, name_to_load);
594                                            system(zz);
595                                            snprintf(zz, zzlen, "gunzip %s.gz",
596                                                name_to_load);
597                                            system(zz);
598                                    } else {
599                                            /*  gunzip into new temp file:  */
600                                            int tmpfile_handle;
601                                            char *new_temp_name =
602                                                strdup("/tmp/gxemul.XXXXXXXXXXXX");
603                                            tmpfile_handle = mkstemp(new_temp_name);
604                                            close(tmpfile_handle);
605                                            snprintf(zz, zzlen, "gunzip -c '%s' > "
606                                                "%s", name_to_load, new_temp_name);
607                                            system(zz);
608                                            name_to_load = new_temp_name;
609                                            remove_after_load = 1;
610                                    }
611                                    free(zz);
612                            }
613                            fclose(tmp_f);
614                    }
615    
616                    /*
617                     *  Ugly (but usable) hack for Playstation Portable:  If the
618                     *  filename ends with ".pbp" and the file contains an ELF
619                     *  header, then extract the ELF file into a temporary file.
620                     */
621                    if (strlen(name_to_load) > 4 && strcasecmp(name_to_load +
622                        strlen(name_to_load) - 4, ".pbp") == 0 &&
623                        (tmp_f = fopen(name_to_load, "r")) != NULL) {
624                            off_t filesize, j, found=0;
625                            unsigned char *buf;
626                            fseek(tmp_f, 0, SEEK_END);
627                            filesize = ftello(tmp_f);
628                            fseek(tmp_f, 0, SEEK_SET);
629                            buf = malloc(filesize);
630                            if (buf == NULL) {
631                                    fprintf(stderr, "out of memory while trying"
632                                        " to read %s\n", name_to_load);
633                                    exit(1);
634                            }
635                            fread(buf, 1, filesize, tmp_f);
636                            fclose(tmp_f);
637                            /*  Search for the ELF header, from offset 1 (!):  */
638                            for (j=1; j<filesize - 4; j++)
639                                    if (memcmp(buf + j, ELFMAG, SELFMAG) == 0) {
640                                            found = j;
641                                            break;
642                                    }
643                            if (found != 0) {
644                                    int tmpfile_handle;
645                                    char *new_temp_name =
646                                        strdup("/tmp/gxemul.XXXXXXXXXXXX");
647                                    debug("extracting ELF from %s (offset 0x%x)\n",
648                                        name_to_load, (int)found);
649                                    tmpfile_handle = mkstemp(new_temp_name);
650                                    write(tmpfile_handle, buf + found,
651                                        filesize - found);
652                                    close(tmpfile_handle);
653                                    name_to_load = new_temp_name;
654                                    remove_after_load = 1;
655                            }
656                    }
657    
658                  byte_order = NO_BYTE_ORDER_OVERRIDE;                  byte_order = NO_BYTE_ORDER_OVERRIDE;
659    
660                  file_load(m, m->memory, *load_names, &entrypoint,                  /*
661                     *  Load the file:  :-)
662                     */
663                    file_load(m, m->memory, name_to_load, &entrypoint,
664                      m->arch, &gp, &byte_order, &toc);                      m->arch, &gp, &byte_order, &toc);
665    
666                    if (remove_after_load) {
667                            debug("removing %s\n", name_to_load);
668                            unlink(name_to_load);
669                    }
670    
671                  if (byte_order != NO_BYTE_ORDER_OVERRIDE)                  if (byte_order != NO_BYTE_ORDER_OVERRIDE)
672                          cpu->byte_order = byte_order;                          cpu->byte_order = byte_order;
673    
674                  cpu->pc = entrypoint;                  cpu->pc = entrypoint;
675    
676                  switch (m->arch) {                  switch (m->arch) {
677    
678                    case ARCH_ALPHA:
679                            /*  For position-independent code:  */
680                            cpu->cd.alpha.r[ALPHA_T12] = cpu->pc;
681                            break;
682    
683                    case ARCH_ARM:
684                            if (cpu->pc & 3) {
685                                    fatal("ARM: lowest bits of pc set: TODO\n");
686                                    exit(1);
687                            }
688                            cpu->pc &= 0xfffffffc;
689                            break;
690    
691                    case ARCH_AVR:
692                            cpu->pc &= 0xfffff;
693                            if (cpu->pc & 1) {
694                                    fatal("AVR: lowest bit of pc set: TODO\n");
695                                    exit(1);
696                            }
697                            break;
698    
699                    case ARCH_M68K:
700                            break;
701    
702                  case ARCH_MIPS:                  case ARCH_MIPS:
703                          if ((cpu->pc >> 32) == 0                          if ((cpu->pc >> 32) == 0 && (cpu->pc & 0x80000000ULL))
                             && (cpu->pc & 0x80000000ULL))  
704                                  cpu->pc |= 0xffffffff00000000ULL;                                  cpu->pc |= 0xffffffff00000000ULL;
705    
706                          cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;                          cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;
# Line 604  void emul_machine_setup(struct machine * Line 710  void emul_machine_setup(struct machine *
710                                  cpu->cd.mips.gpr[MIPS_GPR_GP] |=                                  cpu->cd.mips.gpr[MIPS_GPR_GP] |=
711                                      0xffffffff00000000ULL;                                      0xffffffff00000000ULL;
712                          break;                          break;
713    
714                  case ARCH_PPC:                  case ARCH_PPC:
715                            /*  See http://www.linuxbase.org/spec/ELF/ppc64/
716                                spec/x458.html for more info.  */
717                          cpu->cd.ppc.gpr[2] = toc;                          cpu->cd.ppc.gpr[2] = toc;
718                            /*  TODO  */
719                            if (cpu->cd.ppc.bits == 32)
720                                    cpu->pc &= 0xffffffffULL;
721                          break;                          break;
722                  case ARCH_SPARC:  
723                          break;                  case ARCH_SH:
724                  case ARCH_URISC:                          if (cpu->cd.sh.cpu_type.bits == 32)
725                          break;                                  cpu->pc &= 0xffffffffULL;
726                  case ARCH_HPPA:                          cpu->pc &= ~1;
727                          break;                          break;
728                  case ARCH_ALPHA:  
729                    case ARCH_SPARC:
730                          break;                          break;
731    
732                  default:                  default:
733                          fatal("emul_machine_setup(): Internal error: "                          fatal("emul_machine_setup(): Internal error: "
734                              "Unimplemented arch %i\n", m->arch);                              "Unimplemented arch %i\n", m->arch);
# Line 650  void emul_machine_setup(struct machine * Line 764  void emul_machine_setup(struct machine *
764                  useremul_setup(cpu, n_load, load_names);                  useremul_setup(cpu, n_load, load_names);
765    
766          /*  Startup the bootstrap CPU:  */          /*  Startup the bootstrap CPU:  */
767          cpu->bootstrap_cpu_flag = 1;          cpu->running = 1;
         cpu->running            = 1;  
768    
769          /*  ... or pause all CPUs, if start_paused is set:  */          /*  ... or pause all CPUs, if start_paused is set:  */
770          if (m->start_paused) {          if (m->start_paused) {
# Line 663  void emul_machine_setup(struct machine * Line 776  void emul_machine_setup(struct machine *
776          add_dump_points(m);          add_dump_points(m);
777    
778          /*  TODO: This is MIPS-specific!  */          /*  TODO: This is MIPS-specific!  */
779          if (m->machine_type == MACHINE_DEC &&          if (m->machine_type == MACHINE_PMAX &&
780              cpu->cd.mips.cpu_type.mmu_model == MMU3K)              cpu->cd.mips.cpu_type.mmu_model == MMU3K)
781                  add_symbol_name(&m->symbol_context,                  add_symbol_name(&m->symbol_context,
782                      0x9fff0000, 0x10000, "r2k3k_cache", 0);                      0x9fff0000, 0x10000, "r2k3k_cache", 0, 0);
783    
784          symbol_recalc_sizes(&m->symbol_context);          symbol_recalc_sizes(&m->symbol_context);
785    
         if (m->max_random_cycles_per_chunk > 0)  
                 debug("using random cycle chunks (1 to %i cycles)\n",  
                     m->max_random_cycles_per_chunk);  
   
786          /*  Special hack for ARC/SGI emulation:  */          /*  Special hack for ARC/SGI emulation:  */
787          if ((m->machine_type == MACHINE_ARC ||          if ((m->machine_type == MACHINE_ARC ||
788              m->machine_type == MACHINE_SGI) && m->prom_emulation)              m->machine_type == MACHINE_SGI) && m->prom_emulation)
# Line 681  void emul_machine_setup(struct machine * Line 790  void emul_machine_setup(struct machine *
790    
791          debug("starting cpu%i at ", m->bootstrap_cpu);          debug("starting cpu%i at ", m->bootstrap_cpu);
792          switch (m->arch) {          switch (m->arch) {
793    
794            case ARCH_ARM:
795                    /*  ARM cpus aren't 64-bit:  */
796                    debug("0x%08"PRIx32, (uint32_t) entrypoint);
797                    break;
798    
799            case ARCH_AVR:
800                    /*  Atmel AVR uses a 16-bit or 22-bit program counter:  */
801                    debug("0x%04x", (int) entrypoint);
802                    break;
803    
804          case ARCH_MIPS:          case ARCH_MIPS:
805                  if (cpu->cd.mips.cpu_type.isa_level < 3 ||                  if (cpu->is_32bit) {
806                      cpu->cd.mips.cpu_type.isa_level == 32) {                          debug("0x%08"PRIx32, (uint32_t)
807                          debug("0x%08x", (int)m->cpus[                              m->cpus[m->bootstrap_cpu]->pc);
                             m->bootstrap_cpu]->pc);  
808                          if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)                          if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
809                                  debug(" (gp=0x%08x)", (int)m->cpus[                                  debug(" (gp=0x%08"PRIx32")", (uint32_t)
810                                      m->bootstrap_cpu]->cd.mips.gpr[                                      m->cpus[m->bootstrap_cpu]->cd.mips.gpr[
811                                      MIPS_GPR_GP]);                                      MIPS_GPR_GP]);
812                  } else {                  } else {
813                          debug("0x%016llx", (long long)m->cpus[                          debug("0x%016"PRIx64, (uint64_t)
814                              m->bootstrap_cpu]->pc);                              m->cpus[m->bootstrap_cpu]->pc);
815                          if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)                          if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
816                                  debug(" (gp=0x%016llx)", (long long)                                  debug(" (gp=0x%016"PRIx64")", (uint64_t)
817                                      cpu->cd.mips.gpr[MIPS_GPR_GP]);                                      cpu->cd.mips.gpr[MIPS_GPR_GP]);
818                  }                  }
819                  break;                  break;
820    
821          case ARCH_PPC:          case ARCH_PPC:
822                  if (cpu->cd.ppc.bits == 32)                  if (cpu->cd.ppc.bits == 32)
823                          debug("0x%08x", (int)entrypoint);                          debug("0x%08"PRIx32, (uint32_t) entrypoint);
824                  else                  else
825                          debug("0x%016llx", (long long)entrypoint);                          debug("0x%016"PRIx64, (uint64_t) entrypoint);
                 break;  
         case ARCH_URISC:  
                 {  
                         char tmps[100];  
                         unsigned char buf[sizeof(uint64_t)];  
   
                         cpu->memory_rw(cpu, m->memory, 0, buf, sizeof(buf),  
                             MEM_READ, CACHE_NONE | NO_EXCEPTIONS);  
   
                         entrypoint = 0;  
                         for (i=0; i<cpu->cd.urisc.wordlen/8; i++) {  
                                 entrypoint <<= 8;  
                                 if (cpu->byte_order == EMUL_BIG_ENDIAN)  
                                         entrypoint += buf[i];  
                                 else  
                                         entrypoint += buf[cpu->  
                                             cd.urisc.wordlen/8 - 1 - i];  
                         }  
   
                         sprintf(tmps, "0x%%0%illx", cpu->cd.urisc.wordlen / 4);  
                         debug(tmps, (long long)entrypoint);  
                         cpu->pc = entrypoint;  
                 }  
826                  break;                  break;
827    
828          default:          default:
829                  debug("0x%016llx", (long long)entrypoint);                  if (cpu->is_32bit)
830                            debug("0x%08"PRIx32, (uint32_t) cpu->pc);
831                    else
832                            debug("0x%016"PRIx64, (uint64_t) cpu->pc);
833          }          }
834          debug("\n");          debug("\n");
835    
# Line 743  void emul_machine_setup(struct machine * Line 844  void emul_machine_setup(struct machine *
844   */   */
845  void emul_dumpinfo(struct emul *e)  void emul_dumpinfo(struct emul *e)
846  {  {
847          int j, nm, iadd = 4;          int j, nm, iadd = DEBUG_INDENTATION;
848    
849          if (e->net != NULL)          if (e->net != NULL)
850                  net_dumpinfo(e->net);                  net_dumpinfo(e->net);
# Line 772  void emul_dumpinfo(struct emul *e) Line 873  void emul_dumpinfo(struct emul *e)
873   */   */
874  void emul_simple_init(struct emul *emul)  void emul_simple_init(struct emul *emul)
875  {  {
876          int iadd=4;          int iadd = DEBUG_INDENTATION;
877          struct machine *m;          struct machine *m;
878    
879          if (emul->n_machines != 1) {          if (emul->n_machines != 1) {
# Line 786  void emul_simple_init(struct emul *emul) Line 887  void emul_simple_init(struct emul *emul)
887                  debug("Simple setup...\n");                  debug("Simple setup...\n");
888                  debug_indentation(iadd);                  debug_indentation(iadd);
889    
890                  /*  Create a network:  */                  /*  Create a simple network:  */
891                  emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,                  emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
892                      "10.0.0.0", 8);                      NET_DEFAULT_IPV4_MASK,
893                        NET_DEFAULT_IPV4_LEN,
894                        NULL, 0, 0, NULL);
895          } else {          } else {
896                  /*  Userland pseudo-machine:  */                  /*  Userland pseudo-machine:  */
897                  debug("Syscall emulation (userland-only) setup...\n");                  debug("Syscall emulation (userland-only) setup...\n");
# Line 807  void emul_simple_init(struct emul *emul) Line 910  void emul_simple_init(struct emul *emul)
910   *   *
911   *  Create an emul struct by reading settings from a configuration file.   *  Create an emul struct by reading settings from a configuration file.
912   */   */
913  struct emul *emul_create_from_configfile(char *fname)  struct emul *emul_create_from_configfile(char *fname, int id)
914  {  {
915          int iadd = 4;          int iadd = DEBUG_INDENTATION;
916          struct emul *e = emul_new(fname);          struct emul *e = emul_new(fname, id);
         FILE *f;  
         char buf[128];  
         size_t len;  
917    
918          debug("Creating emulation from configfile \"%s\":\n", fname);          debug("Creating emulation from configfile \"%s\":\n", fname);
919          debug_indentation(iadd);          debug_indentation(iadd);
920    
921          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);  
922    
         emul_parse_config(e, f);  
   
         fclose(f);  
923          debug_indentation(-iadd);          debug_indentation(-iadd);
924          return e;          return e;
925  }  }
# Line 863  void emul_run(struct emul **emuls, int n Line 946  void emul_run(struct emul **emuls, int n
946    
947          atexit(fix_console);          atexit(fix_console);
948    
         i = 79;  
         while (i-- > 0)  
                 debug("-");  
         debug("\n\n");  
   
949          /*  Initialize the interactive debugger:  */          /*  Initialize the interactive debugger:  */
950          debugger_init(emuls, n_emuls);          debugger_init(emuls, n_emuls);
951    
952            /*  Run any additional debugger commands before starting:  */
953            for (i=0; i<n_emuls; i++) {
954                    struct emul *emul = emuls[i];
955                    if (emul->n_debugger_cmds > 0) {
956                            int j;
957                            if (i == 0)
958                                    print_separator();
959                            for (j = 0; j < emul->n_debugger_cmds; j ++) {
960                                    debug("> %s\n", emul->debugger_cmds[j]);
961                                    debugger_execute_cmd(emul->debugger_cmds[j],
962                                        strlen(emul->debugger_cmds[j]));
963                            }
964                    }
965            }
966    
967            print_separator();
968            debug("\n");
969    
970    
971          /*          /*
972           *  console_init_main() makes sure that the terminal is in a           *  console_init_main() makes sure that the terminal is in a
973           *  reasonable state.           *  reasonable state.
# Line 895  void emul_run(struct emul **emuls, int n Line 992  void emul_run(struct emul **emuls, int n
992                  if (e == NULL)                  if (e == NULL)
993                          continue;                          continue;
994                  for (j=0; j<e->n_machines; j++)                  for (j=0; j<e->n_machines; j++)
995                          cpu_run_init(e, e->machines[j]);                          cpu_run_init(e->machines[j]);
996          }          }
997    
998            /*  TODO: Generalize:  */
999            if (emuls[0]->machines[0]->show_trace_tree)
1000                    cpu_functioncall_trace(emuls[0]->machines[0]->cpus[0],
1001                        emuls[0]->machines[0]->cpus[0]->pc);
1002    
1003            /*  Start emulated clocks:  */
1004            timer_start();
1005    
1006          /*          /*
1007           *  MAIN LOOP:           *  MAIN LOOP:
1008           *           *
# Line 907  void emul_run(struct emul **emuls, int n Line 1012  void emul_run(struct emul **emuls, int n
1012          while (go) {          while (go) {
1013                  go = 0;                  go = 0;
1014    
1015                  x11_check_event(emuls, n_emuls);                  /*  Flush X11 and serial console output every now and then:  */
1016                    if (emuls[0]->machines[0]->ninstrs >
1017                        emuls[0]->machines[0]->ninstrs_flush + (1<<19)) {
1018                            x11_check_event(emuls, n_emuls);
1019                            console_flush();
1020                            emuls[0]->machines[0]->ninstrs_flush =
1021                                emuls[0]->machines[0]->ninstrs;
1022                    }
1023    
1024                    if (emuls[0]->machines[0]->ninstrs >
1025                        emuls[0]->machines[0]->ninstrs_show + (1<<25)) {
1026                            emuls[0]->machines[0]->ninstrs_since_gettimeofday +=
1027                                (emuls[0]->machines[0]->ninstrs -
1028                                 emuls[0]->machines[0]->ninstrs_show);
1029                            cpu_show_cycles(emuls[0]->machines[0], 0);
1030                            emuls[0]->machines[0]->ninstrs_show =
1031                                emuls[0]->machines[0]->ninstrs;
1032                    }
1033    
1034                    if (single_step == ENTER_SINGLE_STEPPING) {
1035                            /*  TODO: Cleanup!  */
1036                            old_instruction_trace =
1037                                emuls[0]->machines[0]->instruction_trace;
1038                            old_quiet_mode = quiet_mode;
1039                            old_show_trace_tree =
1040                                emuls[0]->machines[0]->show_trace_tree;
1041                            emuls[0]->machines[0]->instruction_trace = 1;
1042                            emuls[0]->machines[0]->show_trace_tree = 1;
1043                            quiet_mode = 0;
1044                            single_step = SINGLE_STEPPING;
1045                    }
1046    
1047                    if (single_step == SINGLE_STEPPING)
1048                            debugger();
1049    
1050                  for (i=0; i<n_emuls; i++) {                  for (i=0; i<n_emuls; i++) {
1051                          e = emuls[i];                          e = emuls[i];
                         if (e == NULL)  
                                 continue;  
1052    
1053                          for (j=0; j<e->n_machines; j++) {                          for (j=0; j<e->n_machines; j++) {
1054                                  /*  TODO: cpu_run() is a strange name, since                                  anything = machine_run(e->machines[j]);
                                     there can be multiple cpus in a machine  */  
                                 anything = cpu_run(e, e->machines[j]);  
1055                                  if (anything)                                  if (anything)
1056                                          go = 1;                                          go = 1;
1057                          }                          }
1058                  }                  }
1059          }          }
1060    
1061            /*  Stop any running timers:  */
1062            timer_stop();
1063    
1064          /*  Deinitialize all CPUs in all machines in all emulations:  */          /*  Deinitialize all CPUs in all machines in all emulations:  */
1065          for (i=0; i<n_emuls; i++) {          for (i=0; i<n_emuls; i++) {
1066                  e = emuls[i];                  e = emuls[i];
1067                  if (e == NULL)                  if (e == NULL)
1068                          continue;                          continue;
1069                  for (j=0; j<e->n_machines; j++)                  for (j=0; j<e->n_machines; j++)
1070                          cpu_run_deinit(e, e->machines[j]);                          cpu_run_deinit(e->machines[j]);
1071          }          }
1072    
1073          /*  force_debugger_at_exit flag set? Then enter the debugger:  */          /*  force_debugger_at_exit flag set? Then enter the debugger:  */
# Line 940  void emul_run(struct emul **emuls, int n Line 1077  void emul_run(struct emul **emuls, int n
1077                  debugger();                  debugger();
1078          }          }
1079    
1080          /*  Any machine using X11? Then we should wait before exiting:  */          /*  Any machine using X11? Then wait before exiting:  */
1081          n = 0;          n = 0;
1082          for (i=0; i<n_emuls; i++)          for (i=0; i<n_emuls; i++)
1083                  for (j=0; j<emuls[i]->n_machines; j++)                  for (j=0; j<emuls[i]->n_machines; j++)
# Line 950  void emul_run(struct emul **emuls, int n Line 1087  void emul_run(struct emul **emuls, int n
1087                  printf("Press enter to quit.\n");                  printf("Press enter to quit.\n");
1088                  while (!console_charavail(MAIN_CONSOLE)) {                  while (!console_charavail(MAIN_CONSOLE)) {
1089                          x11_check_event(emuls, n_emuls);                          x11_check_event(emuls, n_emuls);
1090                          usleep(1);                          usleep(10000);
1091                  }                  }
1092                  console_readchar(MAIN_CONSOLE);                  console_readchar(MAIN_CONSOLE);
1093          }          }
1094    
1095          console_deinit();          console_deinit_main();
1096  }  }
1097    

Legend:
Removed from v.2  
changed lines
  Added in v.38

  ViewVC Help
Powered by ViewVC 1.1.26