/[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 40 by dpavlin, Mon Oct 8 16:22:11 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: emul.c,v 1.284 2007/04/19 15:18:15 debug Exp $   *  $Id: emul.c,v 1.297 2007/06/15 17:02:37 debug Exp $
29   *   *
30   *  Emulation startup and misc. routines.   *  Emulation startup and misc. routines.
31   */   */
# Line 52  Line 52 
52  #include "misc.h"  #include "misc.h"
53  #include "net.h"  #include "net.h"
54  #include "settings.h"  #include "settings.h"
 #include "sgi_arcbios.h"  
55  #include "timer.h"  #include "timer.h"
56    #include "useremul.h"
57  #include "x11.h"  #include "x11.h"
58    
59    
# Line 68  extern int old_show_trace_tree; Line 68  extern int old_show_trace_tree;
68  extern int old_instruction_trace;  extern int old_instruction_trace;
69  extern int old_quiet_mode;  extern int old_quiet_mode;
70  extern int quiet_mode;  extern int quiet_mode;
71    extern int native_code_translation_enabled;
 extern struct emul *debugger_emul;  
 extern struct diskimage *diskimages[];  
   
   
 static void print_separator(void)  
 {  
         int i = 79;  
         while (i-- > 0)  
                 debug("-");  
         debug("\n");  
 }  
72    
73    
74  /*  /*
75   *  add_dump_points():   *  add_breakpoints():
76   *   *
77   *  Take the strings breakpoint_string[] and convert to addresses   *  Take the strings breakpoint_string[] and convert to addresses
78   *  (and store them in breakpoint_addr[]).   *  (and store them in breakpoint_addr[]).
79   *   *
80   *  TODO: This function should be moved elsewhere.   *  TODO: This function should be moved elsewhere.
81   */   */
82  static void add_dump_points(struct machine *m)  static void add_breakpoints(struct machine *m)
83  {  {
84          int i;          int i;
85          int string_flag;          int string_flag;
86          uint64_t dp;          uint64_t dp;
87    
88          for (i=0; i<m->n_breakpoints; i++) {          for (i=0; i<m->breakpoints.n; i++) {
89                  string_flag = 0;                  string_flag = 0;
90                  dp = strtoull(m->breakpoint_string[i], NULL, 0);                  dp = strtoull(m->breakpoints.string[i], NULL, 0);
91    
92                  /*                  /*
93                   *  If conversion resulted in 0, then perhaps it is a                   *  If conversion resulted in 0, then perhaps it is a
# Line 107  static void add_dump_points(struct machi Line 96  static void add_dump_points(struct machi
96                  if (dp == 0) {                  if (dp == 0) {
97                          uint64_t addr;                          uint64_t addr;
98                          int res = get_symbol_addr(&m->symbol_context,                          int res = get_symbol_addr(&m->symbol_context,
99                              m->breakpoint_string[i], &addr);                              m->breakpoints.string[i], &addr);
100                          if (!res) {                          if (!res) {
101                                  fprintf(stderr,                                  fprintf(stderr,
102                                      "ERROR! Breakpoint '%s' could not be"                                      "ERROR! Breakpoint '%s' could not be"
103                                          " parsed\n",                                          " parsed\n",
104                                      m->breakpoint_string[i]);                                      m->breakpoints.string[i]);
105                                    exit(1);
106                          } else {                          } else {
107                                  dp = addr;                                  dp = addr;
108                                  string_flag = 1;                                  string_flag = 1;
# Line 129  static void add_dump_points(struct machi Line 119  static void add_dump_points(struct machi
119                                  dp |= 0xffffffff00000000ULL;                                  dp |= 0xffffffff00000000ULL;
120                  }                  }
121    
122                  m->breakpoint_addr[i] = dp;                  m->breakpoints.addr[i] = dp;
123    
124                  debug("breakpoint %i: 0x%llx", i, (long long)dp);                  debug("breakpoint %i: 0x%llx", i, (long long)dp);
125                  if (string_flag)                  if (string_flag)
126                          debug(" (%s)", m->breakpoint_string[i]);                          debug(" (%s)", m->breakpoints.string[i]);
127                  debug("\n");                  debug("\n");
128          }          }
129  }  }
# Line 156  static void fix_console(void) Line 146  static void fix_console(void)
146  struct emul *emul_new(char *name, int id)  struct emul *emul_new(char *name, int id)
147  {  {
148          struct emul *e;          struct emul *e;
         e = malloc(sizeof(struct emul));  
         if (e == NULL) {  
                 fprintf(stderr, "out of memory in emul_new()\n");  
                 exit(1);  
         }  
149    
150            CHECK_ALLOCATION(e = malloc(sizeof(struct emul)));
151          memset(e, 0, sizeof(struct emul));          memset(e, 0, sizeof(struct emul));
152    
153          e->path = malloc(15);          CHECK_ALLOCATION(e->path = malloc(15));
         if (e->path == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
154          snprintf(e->path, 15, "emul[%i]", id);          snprintf(e->path, 15, "emul[%i]", id);
155    
156          e->settings = settings_new();          e->settings = settings_new();
# Line 184  struct emul *emul_new(char *name, int id Line 166  struct emul *emul_new(char *name, int id
166          e->next_serial_nr = 1;          e->next_serial_nr = 1;
167    
168          if (name != NULL) {          if (name != NULL) {
169                  e->name = strdup(name);                  CHECK_ALLOCATION(e->name = strdup(name));
                 if (e->name == NULL) {  
                         fprintf(stderr, "out of memory in emul_new()\n");  
                         exit(1);  
                 }  
   
170                  settings_add(e->settings, "name", 0,                  settings_add(e->settings, "name", 0,
171                      SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,                      SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,
172                      (void *) &e->name);                      (void *) &e->name);
# Line 244  struct machine *emul_add_machine(struct Line 221  struct machine *emul_add_machine(struct
221          m = machine_new(name, e, e->n_machines);          m = machine_new(name, e, e->n_machines);
222          m->serial_nr = (e->next_serial_nr ++);          m->serial_nr = (e->next_serial_nr ++);
223    
224          i = e->n_machines;          i = e->n_machines ++;
225    
226          e->n_machines ++;          CHECK_ALLOCATION(e->machines = realloc(e->machines,
227          e->machines = realloc(e->machines,              sizeof(struct machine *) * e->n_machines));
             sizeof(struct machine *) * e->n_machines);  
         if (e->machines == NULL) {  
                 fprintf(stderr, "emul_add_machine(): out of memory\n");  
                 exit(1);  
         }  
228    
229          e->machines[i] = m;          e->machines[i] = m;
230    
# Line 447  void emul_machine_setup(struct machine * Line 419  void emul_machine_setup(struct machine *
419                  /*  TODO: This should be moved elsewhere...  */                  /*  TODO: This should be moved elsewhere...  */
420                  if (m->machine_type == MACHINE_BEBOX)                  if (m->machine_type == MACHINE_BEBOX)
421                          m->ncpus = 2;                          m->ncpus = 2;
                 else if (m->machine_type == MACHINE_ARC &&  
                     m->machine_subtype == MACHINE_ARC_NEC_R96)  
                         m->ncpus = 2;  
                 else if (m->machine_type == MACHINE_ARC &&  
                     m->machine_subtype == MACHINE_ARC_NEC_R98)  
                         m->ncpus = 4;  
422                  else                  else
423                          m->ncpus = 1;                          m->ncpus = 1;
424          }          }
425          m->cpus = malloc(sizeof(struct cpu *) * m->ncpus);  
426          if (m->cpus == NULL) {          CHECK_ALLOCATION(m->cpus = malloc(sizeof(struct cpu *) * m->ncpus));
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
427          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
428    
429          debug("cpu0");          debug("cpu0");
# Line 477  void emul_machine_setup(struct machine * Line 440  void emul_machine_setup(struct machine *
440          }          }
441          debug("\n");          debug("\n");
442    
 #if 0  
         /*  Special case: The Playstation Portable has an additional CPU:  */  
         if (m->machine_type == MACHINE_PSP) {  
                 debug("cpu%i: ", m->ncpus);  
                 m->cpus[m->ncpus] = cpu_new(m->memory, m,  
                     0  /*  use 0 here to show info with debug()  */,  
                     "Allegrex" /*  TODO  */);  
                 debug("\n");  
                 m->ncpus ++;  
         }  
 #endif  
   
443          if (m->use_random_bootstrap_cpu)          if (m->use_random_bootstrap_cpu)
444                  m->bootstrap_cpu = random() % m->ncpus;                  m->bootstrap_cpu = random() % m->ncpus;
445          else          else
# Line 502  void emul_machine_setup(struct machine * Line 453  void emul_machine_setup(struct machine *
453                      m->userland_emul, NULL, NULL, NULL);                      m->userland_emul, NULL, NULL, NULL);
454    
455                  switch (m->arch) {                  switch (m->arch) {
456  #ifdef ENABLE_ALPHA  
457                  case ARCH_ALPHA:                  case ARCH_ALPHA:
458                          cpu->memory_rw = alpha_userland_memory_rw;                          cpu->memory_rw = alpha_userland_memory_rw;
459                          break;                          break;
460  #endif  
461                  default:cpu->memory_rw = userland_memory_rw;                  default:
462                            cpu->memory_rw = userland_memory_rw;
463                  }                  }
464          }          }
465    
466          if (m->use_x11)          if (m->x11_md.in_use)
467                  x11_init(m);                  x11_init(m);
468    
469          /*  Fill memory with random bytes:  */          /*  Fill memory with random bytes:  */
# Line 580  void emul_machine_setup(struct machine * Line 532  void emul_machine_setup(struct machine *
532                          fread(buf, 1, sizeof(buf), tmp_f);                          fread(buf, 1, sizeof(buf), tmp_f);
533                          if (buf[0]==0x1f && buf[1]==0x8b) {                          if (buf[0]==0x1f && buf[1]==0x8b) {
534                                  size_t zzlen = strlen(name_to_load)*2 + 100;                                  size_t zzlen = strlen(name_to_load)*2 + 100;
535                                  char *zz = malloc(zzlen);                                  char *zz;
536    
537                                    CHECK_ALLOCATION(zz = malloc(zzlen));
538                                  debug("gunziping %s\n", name_to_load);                                  debug("gunziping %s\n", name_to_load);
539    
540                                  /*                                  /*
541                                   *  gzip header found.  If this was a file                                   *  gzip header found.  If this was a file
542                                   *  extracted from, say, a CDROM image, then it                                   *  extracted from, say, a CDROM image, then it
# Line 598  void emul_machine_setup(struct machine * Line 553  void emul_machine_setup(struct machine *
553                                  } else {                                  } else {
554                                          /*  gunzip into new temp file:  */                                          /*  gunzip into new temp file:  */
555                                          int tmpfile_handle;                                          int tmpfile_handle;
556                                          char *new_temp_name =                                          char *new_temp_name;
557                                              strdup("/tmp/gxemul.XXXXXXXXXXXX");                                          CHECK_ALLOCATION(new_temp_name =
558                                                strdup("/tmp/gxemul.XXXXXXXXXXXX"));
559                                          tmpfile_handle = mkstemp(new_temp_name);                                          tmpfile_handle = mkstemp(new_temp_name);
560                                          close(tmpfile_handle);                                          close(tmpfile_handle);
561                                          snprintf(zz, zzlen, "gunzip -c '%s' > "                                          snprintf(zz, zzlen, "gunzip -c '%s' > "
# Line 613  void emul_machine_setup(struct machine * Line 569  void emul_machine_setup(struct machine *
569                          fclose(tmp_f);                          fclose(tmp_f);
570                  }                  }
571    
                 /*  
                  *  Ugly (but usable) hack for Playstation Portable:  If the  
                  *  filename ends with ".pbp" and the file contains an ELF  
                  *  header, then extract the ELF file into a temporary file.  
                  */  
                 if (strlen(name_to_load) > 4 && strcasecmp(name_to_load +  
                     strlen(name_to_load) - 4, ".pbp") == 0 &&  
                     (tmp_f = fopen(name_to_load, "r")) != NULL) {  
                         off_t filesize, j, found=0;  
                         unsigned char *buf;  
                         fseek(tmp_f, 0, SEEK_END);  
                         filesize = ftello(tmp_f);  
                         fseek(tmp_f, 0, SEEK_SET);  
                         buf = malloc(filesize);  
                         if (buf == NULL) {  
                                 fprintf(stderr, "out of memory while trying"  
                                     " to read %s\n", name_to_load);  
                                 exit(1);  
                         }  
                         fread(buf, 1, filesize, tmp_f);  
                         fclose(tmp_f);  
                         /*  Search for the ELF header, from offset 1 (!):  */  
                         for (j=1; j<filesize - 4; j++)  
                                 if (memcmp(buf + j, ELFMAG, SELFMAG) == 0) {  
                                         found = j;  
                                         break;  
                                 }  
                         if (found != 0) {  
                                 int tmpfile_handle;  
                                 char *new_temp_name =  
                                     strdup("/tmp/gxemul.XXXXXXXXXXXX");  
                                 debug("extracting ELF from %s (offset 0x%x)\n",  
                                     name_to_load, (int)found);  
                                 tmpfile_handle = mkstemp(new_temp_name);  
                                 write(tmpfile_handle, buf + found,  
                                     filesize - found);  
                                 close(tmpfile_handle);  
                                 name_to_load = new_temp_name;  
                                 remove_after_load = 1;  
                         }  
                 }  
   
572                  byte_order = NO_BYTE_ORDER_OVERRIDE;                  byte_order = NO_BYTE_ORDER_OVERRIDE;
573    
574                  /*                  /*
# Line 688  void emul_machine_setup(struct machine * Line 602  void emul_machine_setup(struct machine *
602                          cpu->pc &= 0xfffffffc;                          cpu->pc &= 0xfffffffc;
603                          break;                          break;
604    
605                  case ARCH_AVR:                  case ARCH_M88K:
606                          cpu->pc &= 0xfffff;                          if (cpu->pc & 3) {
607                          if (cpu->pc & 1) {                                  fatal("M88K: lowest bits of pc set: TODO\n");
                                 fatal("AVR: lowest bit of pc set: TODO\n");  
608                                  exit(1);                                  exit(1);
609                          }                          }
610                          break;                          cpu->pc &= 0xfffffffc;
   
                 case ARCH_M88K:  
611                          break;                          break;
612    
613                  case ARCH_MIPS:                  case ARCH_MIPS:
# Line 772  void emul_machine_setup(struct machine * Line 683  void emul_machine_setup(struct machine *
683                          m->cpus[i]->running = 0;                          m->cpus[i]->running = 0;
684          }          }
685    
686          /*  Add PC dump points:  */          /*  Parse and add breakpoints:  */
687          add_dump_points(m);          add_breakpoints(m);
688    
689          /*  TODO: This is MIPS-specific!  */          /*  TODO: This is MIPS-specific!  */
690          if (m->machine_type == MACHINE_PMAX &&          if (m->machine_type == MACHINE_PMAX &&
# Line 796  void emul_machine_setup(struct machine * Line 707  void emul_machine_setup(struct machine *
707                  debug("0x%08"PRIx32, (uint32_t) entrypoint);                  debug("0x%08"PRIx32, (uint32_t) entrypoint);
708                  break;                  break;
709    
         case ARCH_AVR:  
                 /*  Atmel AVR uses a 16-bit or 22-bit program counter:  */  
                 debug("0x%04x", (int) entrypoint);  
                 break;  
   
710          case ARCH_MIPS:          case ARCH_MIPS:
711                  if (cpu->is_32bit) {                  if (cpu->is_32bit) {
712                          debug("0x%08"PRIx32, (uint32_t)                          debug("0x%08"PRIx32, (uint32_t)
# Line 955  void emul_run(struct emul **emuls, int n Line 861  void emul_run(struct emul **emuls, int n
861                  if (emul->n_debugger_cmds > 0) {                  if (emul->n_debugger_cmds > 0) {
862                          int j;                          int j;
863                          if (i == 0)                          if (i == 0)
864                                  print_separator();                                  print_separator_line();
865                          for (j = 0; j < emul->n_debugger_cmds; j ++) {                          for (j = 0; j < emul->n_debugger_cmds; j ++) {
866                                  debug("> %s\n", emul->debugger_cmds[j]);                                  debug("> %s\n", emul->debugger_cmds[j]);
867                                  debugger_execute_cmd(emul->debugger_cmds[j],                                  debugger_execute_cmd(emul->debugger_cmds[j],
# Line 964  void emul_run(struct emul **emuls, int n Line 870  void emul_run(struct emul **emuls, int n
870                  }                  }
871          }          }
872    
873          print_separator();          print_separator_line();
874          debug("\n");          debug("\n");
875    
876    
# Line 1006  void emul_run(struct emul **emuls, int n Line 912  void emul_run(struct emul **emuls, int n
912          /*          /*
913           *  MAIN LOOP:           *  MAIN LOOP:
914           *           *
915           *  Run all emulations in parallel, running each machine in           *  Run all emulations in parallel, running instructions from each
916           *  each emulation.           *  cpu in each machine in each emulation.
917           */           */
918          while (go) {          while (go) {
919                    struct cpu *bootcpu = emuls[0]->machines[0]->cpus[
920                        emuls[0]->machines[0]->bootstrap_cpu];
921    
922                  go = 0;                  go = 0;
923    
924                  /*  Flush X11 and serial console output every now and then:  */                  /*  Flush X11 and serial console output every now and then:  */
925                  if (emuls[0]->machines[0]->ninstrs >                  if (bootcpu->ninstrs > bootcpu->ninstrs_flush + (1<<19)) {
                     emuls[0]->machines[0]->ninstrs_flush + (1<<19)) {  
926                          x11_check_event(emuls, n_emuls);                          x11_check_event(emuls, n_emuls);
927                          console_flush();                          console_flush();
928                          emuls[0]->machines[0]->ninstrs_flush =                          bootcpu->ninstrs_flush = bootcpu->ninstrs;
                             emuls[0]->machines[0]->ninstrs;  
929                  }                  }
930    
931                  if (emuls[0]->machines[0]->ninstrs >                  if (bootcpu->ninstrs > bootcpu->ninstrs_show + (1<<25)) {
932                      emuls[0]->machines[0]->ninstrs_show + (1<<25)) {                          bootcpu->ninstrs_since_gettimeofday +=
933                          emuls[0]->machines[0]->ninstrs_since_gettimeofday +=                              (bootcpu->ninstrs - bootcpu->ninstrs_show);
                             (emuls[0]->machines[0]->ninstrs -  
                              emuls[0]->machines[0]->ninstrs_show);  
934                          cpu_show_cycles(emuls[0]->machines[0], 0);                          cpu_show_cycles(emuls[0]->machines[0], 0);
935                          emuls[0]->machines[0]->ninstrs_show =                          bootcpu->ninstrs_show = bootcpu->ninstrs;
                             emuls[0]->machines[0]->ninstrs;  
936                  }                  }
937    
938                  if (single_step == ENTER_SINGLE_STEPPING) {                  if (single_step == ENTER_SINGLE_STEPPING) {
# Line 1081  void emul_run(struct emul **emuls, int n Line 985  void emul_run(struct emul **emuls, int n
985          n = 0;          n = 0;
986          for (i=0; i<n_emuls; i++)          for (i=0; i<n_emuls; i++)
987                  for (j=0; j<emuls[i]->n_machines; j++)                  for (j=0; j<emuls[i]->n_machines; j++)
988                          if (emuls[i]->machines[j]->use_x11)                          if (emuls[i]->machines[j]->x11_md.in_use)
989                                  n++;                                  n++;
990          if (n > 0) {          if (n > 0) {
991                  printf("Press enter to quit.\n");                  printf("Press enter to quit.\n");

Legend:
Removed from v.40  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26