/[gxemul]/trunk/src/machine.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/machine.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 28 by dpavlin, Mon Oct 8 16:20:26 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: machine.c,v 1.664 2006/02/05 10:26:35 debug Exp $   *  $Id: machine.c,v 1.679 2006/07/16 13:32:25 debug Exp $
29   */   */
30    
31  #include <stdio.h>  #include <stdio.h>
32  #include <stdlib.h>  #include <stdlib.h>
33  #include <stdarg.h>  #include <stdarg.h>
 #ifdef SOLARIS  
 /*  TODO: is this strings vs string separation really necessary?  */  
 #include <strings.h>  
 #else  
34  #include <string.h>  #include <string.h>
 #endif  
35  #include <time.h>  #include <time.h>
36  #include <unistd.h>  #include <unistd.h>
37    
# Line 44  Line 39 
39  #include "bus_isa.h"  #include "bus_isa.h"
40  #include "bus_pci.h"  #include "bus_pci.h"
41  #include "cpu.h"  #include "cpu.h"
42    #include "debugger.h"
43  #include "device.h"  #include "device.h"
44  #include "devices.h"  #include "devices.h"
45  #include "diskimage.h"  #include "diskimage.h"
# Line 90  struct machine *machine_new(char *name, Line 86  struct machine *machine_new(char *name,
86          m->serial_nr = 1;          m->serial_nr = 1;
87          m->machine_type = MACHINE_NONE;          m->machine_type = MACHINE_NONE;
88          m->machine_subtype = MACHINE_NONE;          m->machine_subtype = MACHINE_NONE;
 #ifdef BINTRANS  
         m->bintrans_enable = 1;  
         m->old_bintrans_enable = 1;  
 #endif  
89          m->arch_pagesize = 4096;        /*  Should be overriden in          m->arch_pagesize = 4096;        /*  Should be overriden in
90                                              emul.c for other pagesizes.  */                                              emul.c for other pagesizes.  */
         m->dyntrans_alignment_check = 1;  
91          m->prom_emulation = 1;          m->prom_emulation = 1;
92          m->speed_tricks = 1;          m->allow_instruction_combinations = 1;
93          m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;          m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;
94          m->boot_kernel_filename = "";          m->boot_kernel_filename = "";
95          m->boot_string_argument = NULL;          m->boot_string_argument = NULL;
# Line 108  struct machine *machine_new(char *name, Line 99  struct machine *machine_new(char *name,
99          m->n_gfx_cards = 1;          m->n_gfx_cards = 1;
100          m->dbe_on_nonexistant_memaccess = 1;          m->dbe_on_nonexistant_memaccess = 1;
101          m->show_symbolic_register_names = 1;          m->show_symbolic_register_names = 1;
         m->bintrans_size = DEFAULT_BINTRANS_SIZE_IN_MB * 1048576;  
102          symbol_init(&m->symbol_context);          symbol_init(&m->symbol_context);
103    
104          return m;          return m;
# Line 219  int machine_name_to_type(char *stype, ch Line 209  int machine_name_to_type(char *stype, ch
209   *   *
210   *  Adds a tick function (a function called every now and then, depending on   *  Adds a tick function (a function called every now and then, depending on
211   *  clock cycle count) to a machine.   *  clock cycle count) to a machine.
212     *
213     *  If tickshift is non-zero, a tick will occur every (1 << tickshift) cycles.
214     *  This is used for the normal (fast dyntrans) emulation modes.
215     *
216     *  If tickshift is zero, then this is a cycle-accurate tick function.
217     *  The hz value is used in this case.
218   */   */
219  void machine_add_tickfunction(struct machine *machine, void (*func)  void machine_add_tickfunction(struct machine *machine, void (*func)
220          (struct cpu *, void *), void *extra, int clockshift)          (struct cpu *, void *), void *extra, int tickshift, double hz)
221  {  {
222          int n = machine->n_tick_entries;          int n = machine->n_tick_entries;
223    
# Line 231  void machine_add_tickfunction(struct mac Line 227  void machine_add_tickfunction(struct mac
227                  exit(1);                  exit(1);
228          }          }
229    
230          /*  Don't use too low clockshifts, that would be too inefficient          if (!machine->cycle_accurate) {
231              with bintrans.  */                  /*
232          if (clockshift < N_SAFE_BINTRANS_LIMIT_SHIFT)                   *  The dyntrans subsystem wants to run code in relatively
233                  fatal("WARNING! clockshift = %i, less than "                   *  large chunks without checking for external interrupts,
234                      "N_SAFE_BINTRANS_LIMIT_SHIFT (%i)\n",                   *  so we cannot allow too low tickshifts:
235                      clockshift, N_SAFE_BINTRANS_LIMIT_SHIFT);                   */
236                    if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) {
237                            fatal("ERROR! tickshift = %i, less than "
238                                "N_SAFE_DYNTRANS_LIMIT_SHIFT (%i)\n",
239                                tickshift, N_SAFE_DYNTRANS_LIMIT_SHIFT);
240                            exit(1);
241                    }
242            }
243    
244          machine->ticks_till_next[n]   = 0;          machine->ticks_till_next[n]   = 0;
245          machine->ticks_reset_value[n] = 1 << clockshift;          machine->ticks_reset_value[n] = 1 << tickshift;
246          machine->tick_func[n]         = func;          machine->tick_func[n]         = func;
247          machine->tick_extra[n]        = extra;          machine->tick_extra[n]        = extra;
248            machine->tick_hz[n]           = hz;
249    
250          machine->n_tick_entries ++;          machine->n_tick_entries ++;
251  }  }
252    
253    
254  /*  /*
255     *  machine_statistics_init():
256     *
257     *  Initialize the parts of a machine struct that deal with instruction
258     *  statistics gathering.
259     *
260     *  Note: The fname argument contains "flags:filename".
261     */
262    void machine_statistics_init(struct machine *machine, char *fname)
263    {
264            int n_fields = 0;
265            char *pcolon = fname;
266            char *mode = "a";       /*  Append by default  */
267    
268            machine->allow_instruction_combinations = 0;
269    
270            if (machine->statistics_fields != NULL) {
271                    fprintf(stderr, "Only one -s option is allowed.\n");
272                    exit(1);
273            }
274    
275            machine->statistics_fields = malloc(MAX_STATISTICS_FIELDS + 1);
276            machine->statistics_enabled = 1;
277    
278            while (*pcolon && *pcolon != ':')
279                    pcolon ++;
280    
281            if (*pcolon != ':') {
282                    fprintf(stderr, "The syntax for the -s option is:    "
283                        "-s flags:filename\nYou omitted the flags. Run g"
284                        "xemul -h for a list of available flags.\n");
285                    exit(1);
286            }
287    
288            while (*fname != ':') {
289                    switch (*fname) {
290    
291                    /*  Type flags:  */
292                    case 'v':
293                    case 'i':
294                    case 'p':
295                            machine->statistics_fields[n_fields ++] = *fname;
296                            if (n_fields >= MAX_STATISTICS_FIELDS) {
297                                    fprintf(stderr, "Internal error: Too many "
298                                        "statistics fields used. Increase "
299                                        "MAX_STATISTICS_FIELDS.\n");
300                                    exit(1);
301                            }
302                            machine->statistics_fields[n_fields] = '\0';
303                            break;
304    
305                    /*  Optional flags:  */
306                    case 'o':
307                            mode = "w";
308                            break;
309                    case 'd':
310                            machine->statistics_enabled = 0;
311                            break;
312    
313                    default:fprintf(stderr, "Unknown flag '%c' used with the"
314                                " -s option. Aborting.\n", *fname);
315                            exit(1);
316                    }
317                    fname ++;
318            }
319    
320            fname ++;       /*  point to the filename after the colon  */
321    
322            machine->statistics_filename = strdup(fname);
323            machine->statistics_file = fopen(machine->statistics_filename, mode);
324    }
325    
326    
327    /*
328   *  machine_bus_register():   *  machine_bus_register():
329   *   *
330   *  Registers a bus in a machine.   *  Registers a bus in a machine.
# Line 323  void machine_dumpinfo(struct machine *m) Line 400  void machine_dumpinfo(struct machine *m)
400                  debug(", dbe_on_nonexistant_memaccess");                  debug(", dbe_on_nonexistant_memaccess");
401          debug("\n");          debug("\n");
402    
         if (m->single_step_on_bad_addr)  
                 debug("single-step on bad addresses\n");  
   
         if (m->arch == ARCH_MIPS) {  
                 if (m->bintrans_enable)  
                         debug("bintrans enabled (%i MB cache)\n",  
                             (int) (m->bintrans_size / 1048576));  
                 else  
                         debug("bintrans disabled, other speedtricks %s\n",  
                             m->speed_tricks? "enabled" : "disabled");  
         }  
   
403          debug("clock: ");          debug("clock: ");
404          if (m->automatic_clock_adjustment)          if (m->automatic_clock_adjustment)
405                  debug("adjusted automatically");                  debug("adjusted automatically");
# Line 899  void machine_default_cputype(struct mach Line 964  void machine_default_cputype(struct mach
964  }  }
965    
966    
967    /*****************************************************************************/
968    
969    
970    /*
971     *  machine_run():
972     *
973     *  Run one or more instructions on all CPUs in this machine. (Usually,
974     *  around N_SAFE_DYNTRANS_LIMIT instructions will be run by the dyntrans
975     *  system.)
976     *
977     *  Return value is 1 if any CPU in this machine is still running,
978     *  or 0 if all CPUs are stopped.
979     */
980    int machine_run(struct machine *machine)
981    {
982            struct cpu **cpus = machine->cpus;
983            int ncpus = machine->ncpus, cpu0instrs = 0, i, te;
984    
985            for (i=0; i<ncpus; i++) {
986                    if (cpus[i]->running) {
987                            int instrs_run = cpus[i]->run_instr(cpus[i]);
988                            if (i == 0)
989                                    cpu0instrs += instrs_run;
990                    }
991            }
992    
993            /*
994             *  Hardware 'ticks':  (clocks, interrupt sources...)
995             *
996             *  Here, cpu0instrs is the number of instructions executed on cpu0.
997             *
998             *  TODO: This should be redesigned into some "mainbus" stuff instead!
999             */
1000    
1001            machine->ninstrs += cpu0instrs;
1002    
1003            for (te=0; te<machine->n_tick_entries; te++) {
1004                    machine->ticks_till_next[te] -= cpu0instrs;
1005                    if (machine->ticks_till_next[te] <= 0) {
1006                            while (machine->ticks_till_next[te] <= 0) {
1007                                    machine->ticks_till_next[te] +=
1008                                        machine->ticks_reset_value[te];
1009                            }
1010    
1011                            machine->tick_func[te](cpus[0],
1012                                machine->tick_extra[te]);
1013                    }
1014            }
1015    
1016            /*  Is any CPU still alive?  */
1017            for (i=0; i<ncpus; i++)
1018                    if (cpus[i]->running)
1019                            return 1;
1020    
1021            return 0;
1022    }
1023    
1024    
1025    /*****************************************************************************/
1026    
1027    
1028  /*  /*
1029   *  machine_entry_new():   *  machine_entry_new():
1030   *   *
1031   *  This function creates a new machine_entry struct, and fills it with some   *  This function creates a new machine_entry struct, and fills it with some
1032   *  valid data; it is up to the caller to add additional data that weren't   *  valid data; it is up to the caller to add additional data that weren't
1033   *  passed as arguments to this function.   *  passed as arguments to this function, such as alias names and machine
1034     *  subtypes.
1035   */   */
1036  struct machine_entry *machine_entry_new(const char *name,  struct machine_entry *machine_entry_new(const char *name, int arch,
1037          int arch, int oldstyle_type, int n_aliases, int n_subtypes)          int oldstyle_type)
1038  {  {
1039          struct machine_entry *me;          struct machine_entry *me;
1040    
# Line 922  struct machine_entry *machine_entry_new( Line 1049  struct machine_entry *machine_entry_new(
1049          me->name = name;          me->name = name;
1050          me->arch = arch;          me->arch = arch;
1051          me->machine_type = oldstyle_type;          me->machine_type = oldstyle_type;
1052          me->n_aliases = n_aliases;          me->n_aliases = 0;
1053          me->aliases = malloc(sizeof(char *) * n_aliases);          me->aliases = NULL;
1054          if (me->aliases == NULL) {          me->n_subtypes = 0;
                 fprintf(stderr, "machine_entry_new(): out of memory (2)\n");  
                 exit(1);  
         }  
         me->n_subtypes = n_subtypes;  
1055          me->setup = NULL;          me->setup = NULL;
1056    
1057          if (n_subtypes > 0) {          return me;
1058                  me->subtype = malloc(sizeof(struct machine_entry_subtype *) *  }
1059                      n_subtypes);  
1060                  if (me->subtype == NULL) {  
1061                          fprintf(stderr, "machine_entry_new(): out of "  /*
1062                              "memory (3)\n");   *  machine_entry_add_alias():
1063                          exit(1);   *
1064                  }   *  This function adds an "alias" to a machine entry.
1065     */
1066    void machine_entry_add_alias(struct machine_entry *me, const char *name)
1067    {
1068            me->n_aliases ++;
1069            me->aliases = realloc(me->aliases, sizeof(char *) * me->n_aliases);
1070            if (me->aliases == NULL) {
1071                    fprintf(stderr, "out of memory\n");
1072                    exit(1);
1073          }          }
1074    
1075          return me;          me->aliases[me->n_aliases - 1] = (char *) name;
1076  }  }
1077    
1078    
1079  /*  /*
1080   *  machine_entry_subtype_new():   *  machine_entry_add_subtype():
1081   *   *
1082   *  This function creates a new machine_entry_subtype struct, and fills it with   *  This function adds a subtype to a machine entry. The argument list after
1083   *  some valid data; it is up to the caller to add additional data that weren't   *  oldstyle_subtype is a list of one or more char *, followed by NULL. E.g.:
  *  passed as arguments to this function.  
1084   *   *
1085   *  For internal use.   *      machine_entry_add_subtype(me, "Machine X", MACHINE_X,
1086     *          "machine-x", "x", NULL);
1087   */   */
1088  struct machine_entry_subtype *machine_entry_subtype_new(  void machine_entry_add_subtype(struct machine_entry *me, const char *name,
1089          const char *name, int oldstyle_type, int n_aliases)          int oldstyle_subtype, ...)
1090  {  {
1091            va_list argp;
1092          struct machine_entry_subtype *mes;          struct machine_entry_subtype *mes;
1093    
1094            /*  Allocate a new subtype struct:  */
1095          mes = malloc(sizeof(struct machine_entry_subtype));          mes = malloc(sizeof(struct machine_entry_subtype));
1096          if (mes == NULL) {          if (mes == NULL) {
1097                  fprintf(stderr, "machine_entry_subtype_new(): out "                  fprintf(stderr, "machine_entry_subtype_new(): out "
# Line 966  struct machine_entry_subtype *machine_en Line 1099  struct machine_entry_subtype *machine_en
1099                  exit(1);                  exit(1);
1100          }          }
1101    
1102            /*  Add the subtype to the machine entry:  */
1103            me->n_subtypes ++;
1104            me->subtype = realloc(me->subtype, sizeof(struct
1105                machine_entry_subtype *) * me->n_subtypes);
1106            if (me->subtype == NULL) {
1107                    fprintf(stderr, "out of memory\n");
1108                    exit(1);
1109            }
1110            me->subtype[me->n_subtypes - 1] = mes;
1111    
1112            /*  Fill the struct with subtype data:  */
1113          memset(mes, 0, sizeof(struct machine_entry_subtype));          memset(mes, 0, sizeof(struct machine_entry_subtype));
1114          mes->name = name;          mes->name = name;
1115          mes->machine_subtype = oldstyle_type;          mes->machine_subtype = oldstyle_subtype;
1116          mes->n_aliases = n_aliases;  
1117          mes->aliases = malloc(sizeof(char *) * n_aliases);          /*  ... and all aliases:  */
1118          if (mes->aliases == NULL) {          mes->n_aliases = 0;
1119                  fprintf(stderr, "machine_entry_subtype_new(): "          mes->aliases = NULL;
1120                      "out of memory (2)\n");  
1121                  exit(1);          va_start(argp, oldstyle_subtype);
1122    
1123            for (;;) {
1124                    char *s = va_arg(argp, char *);
1125                    if (s == NULL)
1126                            break;
1127    
1128                    mes->n_aliases ++;
1129                    mes->aliases = realloc(mes->aliases, sizeof(char *) *
1130                        mes->n_aliases);
1131                    if (mes->aliases == NULL) {
1132                            fprintf(stderr, "out of memory\n");
1133                            exit(1);
1134                    }
1135    
1136                    mes->aliases[mes->n_aliases - 1] = s;
1137          }          }
1138    
1139          return mes;          va_end(argp);
1140  }  }
1141    
1142    
1143  /*  /*
1144   *  machine_entry_add():   *  machine_entry_register():
1145   *   *
1146   *  Inserts a new machine_entry into the machine entries list.   *  Inserts a new machine_entry into the machine entries list.
1147   */   */
1148  void machine_entry_add(struct machine_entry *me, int arch)  void machine_entry_register(struct machine_entry *me, int arch)
1149  {  {
1150          struct machine_entry *prev, *next;          struct machine_entry *prev, *next;
1151    
# Line 1075  void machine_list_available_types_and_cp Line 1234  void machine_list_available_types_and_cp
1234              "that actually work. Use the alias\nwhen selecting a machine type "              "that actually work. Use the alias\nwhen selecting a machine type "
1235              "or subtype, not the real name.\n");              "or subtype, not the real name.\n");
1236    
1237    #ifdef UNSTABLE_DEVEL
1238          debug("\n");          debug("\n");
1239    
1240          useremul_list_emuls();          useremul_list_emuls();
1241          debug("Userland emulation works for programs with the complexity"          debug("Userland emulation works for programs with the complexity"
1242              " of Hello World,\nbut not much more.\n");              " of Hello World,\nbut not much more.\n");
1243    #endif
1244  }  }
1245    
1246    

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

  ViewVC Help
Powered by ViewVC 1.1.26