machine.cc Source File

Back to the index.

machine.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * Machine registry.
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 
38 #include "cpu.h"
39 #include "device.h"
40 #include "diskimage.h"
41 #include "emul.h"
42 #include "machine.h"
43 #include "memory.h"
44 #include "misc.h"
45 #include "settings.h"
46 #include "symbol.h"
47 
48 
49 /* This is initialized by machine_init(): */
51 
52 
53 /*
54  * machine_new():
55  *
56  * Returns a reasonably initialized struct machine.
57  */
58 struct machine *machine_new(char *name, struct emul *emul, int id)
59 {
60  struct machine *m;
61 
62  CHECK_ALLOCATION(m = (struct machine *) malloc(sizeof(struct machine)));
63  memset(m, 0, sizeof(struct machine));
64 
65  /* Pointer back to the emul object that this machine belongs to: */
66  m->emul = emul;
67 
68  if (name != NULL)
69  CHECK_ALLOCATION(m->name = strdup(name));
70 
71  /* Full path, e.g. "machine[0]": */
72  CHECK_ALLOCATION(m->path = (char *) malloc(20));
73  snprintf(m->path, 20, "machine[%i]", id);
74 
75  /* Sane default values: */
76  m->serial_nr = 1;
79  m->arch_pagesize = 4096; /* Should be overriden in
80  emul.c for other pagesizes. */
81  m->prom_emulation = 1;
84  m->boot_kernel_filename = strdup("");
85  m->boot_string_argument = NULL;
86  m->x11_md.scaledown = 1;
87  m->x11_md.scaleup = 1;
88  m->n_gfx_cards = 1;
90 
91  /* Settings: */
92  m->settings = settings_new();
93  settings_add(m->settings, "name", 0,
95  (void *) &m->name);
96  settings_add(m->settings, "serial_nr", 0,
98  (void *) &m->serial_nr);
99  settings_add(m->settings, "arch_pagesize", 0,
101  (void *) &m->arch_pagesize);
102  settings_add(m->settings, "prom_emulation", 0,
104  (void *) &m->prom_emulation);
105  settings_add(m->settings, "allow_instruction_combinations", 0,
107  (void *) &m->allow_instruction_combinations);
108  settings_add(m->settings, "n_gfx_cards", 0,
110  (void *) &m->n_gfx_cards);
111  settings_add(m->settings, "statistics_enabled", 1,
113  (void *) &m->statistics.enabled);
114 
115  return m;
116 }
117 
118 
119 /*
120  * machine_destroy():
121  *
122  * Destroys a machine object.
123  */
125 {
126  int i;
127 
128  for (i=0; i<machine->ncpus; i++)
129  cpu_destroy(machine->cpus[i]);
130 
131  // TODO: Memory leak; but it's ok, since the whole legacy thing should
132  // be replaced anyway.
133  // if (machine->name != NULL)
134  // free(machine->name);
135 
136  if (machine->path != NULL)
137  free(machine->path);
138 
139  /* Remove any remaining level-1 settings: */
140  settings_remove_all(machine->settings);
141  settings_destroy(machine->settings);
142 
143  free(machine);
144 }
145 
146 
147 /*
148  * machine_name_to_type():
149  *
150  * Take a type and a subtype as strings, and convert them into numeric
151  * values used internally throughout the code.
152  *
153  * Return value is 1 on success, 0 if there was no match.
154  * Also, any errors/warnings are printed using fatal()/debug().
155  */
156 int machine_name_to_type(char *stype, char *ssubtype,
157  int *type, int *subtype, int *arch)
158 {
159  struct machine_entry *me;
160  int i, j, k, nmatches = 0;
161 
162  *type = MACHINE_NONE;
163  *subtype = 0;
164 
165  /* Check stype, and optionally ssubtype: */
166  me = first_machine_entry;
167  while (me != NULL) {
168  for (i=0; i<me->n_aliases; i++)
169  if (strcasecmp(me->aliases[i], stype) == 0) {
170  /* Found a type: */
171  *type = me->machine_type;
172  *arch = me->arch;
173 
174  if (me->n_subtypes == 0)
175  return 1;
176 
177  /* Check for subtype: */
178  for (j=0; j<me->n_subtypes; j++)
179  for (k=0; k<me->subtype[j]->n_aliases;
180  k++)
181  if (strcasecmp(ssubtype,
182  me->subtype[j]->aliases[k]
183  ) == 0) {
184  *subtype = me->subtype[
185  j]->machine_subtype;
186  return 1;
187  }
188 
189  fatal("Unknown subtype '%s' for emulation"
190  " '%s'\n", ssubtype, stype);
191  if (!ssubtype[0])
192  fatal("(Maybe you forgot the -e"
193  " command line option?)\n");
194  exit(1);
195  }
196 
197  me = me->next;
198  }
199 
200  /* Not found? Then just check ssubtype: */
201  me = first_machine_entry;
202  while (me != NULL) {
203  if (me->n_subtypes == 0) {
204  me = me->next;
205  continue;
206  }
207 
208  /* Check for subtype: */
209  for (j=0; j<me->n_subtypes; j++)
210  for (k=0; k<me->subtype[j]->n_aliases; k++)
211  if (strcasecmp(ssubtype, me->subtype[j]->
212  aliases[k]) == 0) {
213  *type = me->machine_type;
214  *arch = me->arch;
215  *subtype = me->subtype[j]->
216  machine_subtype;
217  nmatches ++;
218  }
219 
220  me = me->next;
221  }
222 
223  switch (nmatches) {
224  case 0: fatal("\nSorry, emulation \"%s\"", stype);
225  if (ssubtype != NULL && ssubtype[0] != '\0')
226  fatal(" (subtype \"%s\")", ssubtype);
227  fatal(" is unknown.\n");
228  break;
229  case 1: return 1;
230  default:fatal("\nSorry, multiple matches for \"%s\"", stype);
231  if (ssubtype != NULL && ssubtype[0] != '\0')
232  fatal(" (subtype \"%s\")", ssubtype);
233  fatal(".\n");
234  }
235 
236  *type = MACHINE_NONE;
237  *subtype = 0;
238 
239  fatal("Use the -H command line option to get a list of "
240  "available types and subtypes.\n\n");
241 
242  return 0;
243 }
244 
245 
246 /*
247  * machine_add_breakpoint_string():
248  *
249  * Add a breakpoint string to the machine. Later (in emul.c) these will be
250  * converted to actual breakpoints.
251  */
253 {
254  int n = machine->breakpoints.n + 1;
255 
256  CHECK_ALLOCATION(machine->breakpoints.string = (char **)
257  realloc(machine->breakpoints.string, n * sizeof(char *)));
258  CHECK_ALLOCATION(machine->breakpoints.addr = (uint64_t *)
259  realloc(machine->breakpoints.addr, n * sizeof(uint64_t)));
260  CHECK_ALLOCATION(machine->breakpoints.string[machine->breakpoints.n] =
261  strdup(optarg));
262 
263  machine->breakpoints.addr[machine->breakpoints.n] = 0;
264  machine->breakpoints.n ++;
265 }
266 
267 
268 /*
269  * machine_add_tickfunction():
270  *
271  * Adds a tick function (a function called every now and then, depending on
272  * clock cycle count) to a machine.
273  *
274  * If tickshift is non-zero, a tick will occur every (1 << tickshift) cycles.
275  * This is used for the normal (fast dyntrans) emulation modes.
276  *
277  * If tickshift is zero, then this is a cycle-accurate tick function.
278  * The hz value is used in this case.
279  */
280 void machine_add_tickfunction(struct machine *machine, void (*func)
281  (struct cpu *, void *), void *extra, int tickshift)
282 {
283  int n = machine->tick_functions.n_entries;
284 
285  CHECK_ALLOCATION(machine->tick_functions.ticks_till_next = (int *) realloc(
286  machine->tick_functions.ticks_till_next, (n+1) * sizeof(int)));
287  CHECK_ALLOCATION(machine->tick_functions.ticks_reset_value = (int *) realloc(
288  machine->tick_functions.ticks_reset_value, (n+1) * sizeof(int)));
289  CHECK_ALLOCATION(machine->tick_functions.f = (void (**)(cpu*,void*)) realloc(
290  machine->tick_functions.f, (n+1) * sizeof(void *)));
291  CHECK_ALLOCATION(machine->tick_functions.extra = (void **) realloc(
292  machine->tick_functions.extra, (n+1) * sizeof(void *)));
293 
294  /*
295  * The dyntrans subsystem wants to run code in relatively
296  * large chunks without checking for external interrupts;
297  * too low tickshifts are not allowed.
298  */
299  if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) {
300  fatal("ERROR! tickshift = %i, less than "
301  "N_SAFE_DYNTRANS_LIMIT_SHIFT (%i)\n",
302  tickshift, N_SAFE_DYNTRANS_LIMIT_SHIFT);
303  exit(1);
304  }
305 
306  machine->tick_functions.ticks_till_next[n] = 0;
307  machine->tick_functions.ticks_reset_value[n] = 1 << tickshift;
308  machine->tick_functions.f[n] = func;
309  machine->tick_functions.extra[n] = extra;
310 
311  machine->tick_functions.n_entries = n + 1;
312 }
313 
314 
315 /*
316  * machine_statistics_init():
317  *
318  * Initialize the parts of a machine struct that deal with instruction
319  * statistics gathering.
320  *
321  * Note: The fname argument contains "flags:filename".
322  */
323 void machine_statistics_init(struct machine *machine, char *fname)
324 {
325  int n_fields = 0;
326  char *pcolon = fname;
327  const char *mode = "a"; /* Append by default */
328 
329  machine->allow_instruction_combinations = 0;
330 
331  if (machine->statistics.fields != NULL) {
332  fprintf(stderr, "Only one -s option is allowed.\n");
333  exit(1);
334  }
335 
336  machine->statistics.enabled = 1;
337  CHECK_ALLOCATION(machine->statistics.fields = (char *) malloc(1));
338  machine->statistics.fields[0] = '\0';
339 
340  while (*pcolon && *pcolon != ':')
341  pcolon ++;
342 
343  if (*pcolon != ':') {
344  fprintf(stderr, "The syntax for the -s option is: "
345  "-s flags:filename\nYou omitted the flags. Run g"
346  "xemul -h for a list of available flags.\n");
347  exit(1);
348  }
349 
350  while (*fname != ':') {
351  switch (*fname) {
352 
353  /* Type flags: */
354  case 'v':
355  case 'i':
356  case 'p':
357  CHECK_ALLOCATION(machine->statistics.fields = (char *) realloc(
358  machine->statistics.fields, strlen(
359  machine->statistics.fields) + 2));
360  machine->statistics.fields[n_fields ++] = *fname;
361  machine->statistics.fields[n_fields] = '\0';
362  break;
363 
364  /* Optional flags: */
365  case 'o':
366  mode = "w";
367  break;
368  case 'd':
369  machine->statistics.enabled = 0;
370  break;
371 
372  default:fprintf(stderr, "Unknown flag '%c' used with the"
373  " -s option. Aborting.\n", *fname);
374  exit(1);
375  }
376  fname ++;
377  }
378 
379  fname ++; /* point to the filename after the colon */
380 
381  CHECK_ALLOCATION(machine->statistics.filename = strdup(fname));
382  machine->statistics.file = fopen(machine->statistics.filename, mode);
383 }
384 
385 
386 /*
387  * machine_dumpinfo():
388  *
389  * Dumps info about a machine in some kind of readable format. (Used by
390  * the 'machine' debugger command.)
391  */
392 void machine_dumpinfo(struct machine *m)
393 {
394  int i;
395 
396  debug("serial nr: %i", m->serial_nr);
397  if (m->nr_of_nics > 0)
398  debug(" (nr of NICs: %i)", m->nr_of_nics);
399  debug("\n");
400 
401  debug("memory: %i MB", m->physical_ram_in_mb);
402  if (m->memory_offset_in_mb != 0)
403  debug(" (offset by %i MB)", m->memory_offset_in_mb);
404  if (m->random_mem_contents)
405  debug(", randomized contents");
406  debug("\n");
407 
408  if (!m->prom_emulation)
409  debug("PROM emulation disabled\n");
410 
411  for (i=0; i<m->ncpus; i++)
412  cpu_dumpinfo(m, m->cpus[i]);
413 
414  if (m->ncpus > 1)
415  debug("Bootstrap cpu is nr %i\n", m->bootstrap_cpu);
416 
418  debug("Using slow_serial_interrupts_hack_for_linux\n");
419 
420  if (m->x11_md.in_use) {
421  debug("Using X11");
422  if (m->x11_md.scaledown > 1)
423  debug(", scaledown %i", m->x11_md.scaledown);
424  if (m->x11_md.scaleup > 1)
425  debug(", scaleup %i", m->x11_md.scaleup);
426  if (m->x11_md.n_display_names > 0) {
427  for (i=0; i<m->x11_md.n_display_names; i++) {
428  debug(i? ", " : " (");
429  debug("\"%s\"", m->x11_md.display_names[i]);
430  }
431  debug(")");
432  }
433  debug("\n");
434  }
435 
437 
438  if (m->force_netboot)
439  debug("Forced netboot\n");
440 }
441 
442 
443 /*
444  * machine_setup():
445  *
446  * This function initializes memory, registers, and/or devices
447  * required by specific machine emulations.
448  */
449 void machine_setup(struct machine *machine)
450 {
451  struct memory *mem;
452  struct machine_entry *me;
453 
454  /* Abreviation: :-) */
455  struct cpu *cpu = machine->cpus[machine->bootstrap_cpu];
456 
457  machine->bootdev_id = diskimage_bootdev(machine,
458  &machine->bootdev_type);
459 
460  mem = cpu->mem;
461  machine->machine_name = NULL;
462 
463  /* TODO: Move this somewhere else? */
464  if (machine->boot_string_argument == NULL) {
465  switch (machine->machine_type) {
466  case MACHINE_ARC:
467  machine->boot_string_argument = strdup("-aN");
468  break;
469  case MACHINE_CATS:
470  machine->boot_string_argument = strdup("-A");
471  break;
472  case MACHINE_PMAX:
473  machine->boot_string_argument = strdup("-a");
474  break;
475  default:
476  /* Important, because boot_string_argument should
477  not be set to NULL: */
478  machine->boot_string_argument = strdup("");
479  }
480  }
481 
482 
483  /*
484  * If the machine has a setup function in src/machines/machine_*.c
485  * then use that one, otherwise use the old hardcoded stuff here:
486  */
487 
488  me = first_machine_entry;
489  while (me != NULL) {
490  if (machine->machine_type == me->machine_type &&
491  me->setup != NULL) {
492  me->setup(machine, cpu);
493  break;
494  }
495  me = me->next;
496  }
497 
498  if (me == NULL) {
499  fatal("Unknown emulation type %i\n", machine->machine_type);
500  exit(1);
501  }
502 
503  if (machine->machine_name != NULL)
504  debug("machine: %s", machine->machine_name);
505 
506  if (machine->emulated_hz > 0)
507  debug(" (%.2f MHz)", (float)machine->emulated_hz / 1000000);
508  debug("\n");
509 
510  if (machine->bootstr != NULL) {
511  debug("bootstring%s: %s", (machine->bootarg!=NULL &&
512  strlen(machine->bootarg) >= 1)? "(+bootarg)" : "",
513  machine->bootstr);
514  if (machine->bootarg != NULL && strlen(machine->bootarg) >= 1)
515  debug(" %s", machine->bootarg);
516  debug("\n");
517  }
518 }
519 
520 
521 /*
522  * machine_memsize_fix():
523  *
524  * Sets physical_ram_in_mb (if not already set), and memory_offset_in_mb,
525  * depending on machine type.
526  */
527 void machine_memsize_fix(struct machine *m)
528 {
529  if (m == NULL) {
530  fatal("machine_defaultmemsize(): m == NULL?\n");
531  exit(1);
532  }
533 
534  if (m->physical_ram_in_mb == 0) {
535  struct machine_entry *me = first_machine_entry;
536  while (me != NULL) {
537  if (m->machine_type == me->machine_type &&
538  me->set_default_ram != NULL) {
539  me->set_default_ram(m);
540  break;
541  }
542  me = me->next;
543  }
544  }
545 
546  /* Special SGI memory offsets: (TODO: move this somewhere else) */
547  if (m->machine_type == MACHINE_SGI) {
548  switch (m->machine_subtype) {
549  case 20:
550  case 22:
551  case 24:
552  case 26:
553  m->memory_offset_in_mb = 128;
554  break;
555  case 28:
556  case 30:
557  m->memory_offset_in_mb = 512;
558  break;
559  }
560  }
561 
562  if (m->physical_ram_in_mb == 0)
564 }
565 
566 
567 /*
568  * machine_default_cputype():
569  *
570  * Sets m->cpu_name, if it isn't already set, depending on the machine type.
571  */
572 void machine_default_cputype(struct machine *m)
573 {
574  struct machine_entry *me;
575 
576  if (m == NULL) {
577  fatal("machine_default_cputype(): m == NULL?\n");
578  exit(1);
579  }
580 
581  /* Already set? Then return. */
582  if (m->cpu_name != NULL)
583  return;
584 
585  me = first_machine_entry;
586  while (me != NULL) {
587  if (m->machine_type == me->machine_type &&
588  me->set_default_cpu != NULL) {
589  me->set_default_cpu(m);
590  break;
591  }
592  me = me->next;
593  }
594 
595  if (m->cpu_name == NULL) {
596  fprintf(stderr, "machine_default_cputype(): no default"
597  " cpu for machine type %i subtype %i\n",
599  exit(1);
600  }
601 }
602 
603 
604 /*****************************************************************************/
605 
606 
607 /*
608  * machine_run():
609  *
610  * Run one or more instructions on all CPUs in this machine. (Usually,
611  * around N_SAFE_DYNTRANS_LIMIT instructions will be run by the dyntrans
612  * system.)
613  *
614  * Return value is 1 if any CPU in this machine is still running,
615  * or 0 if all CPUs are stopped.
616  */
617 int machine_run(struct machine *machine)
618 {
619  struct cpu **cpus = machine->cpus;
620  int ncpus = machine->ncpus, cpu0instrs = 0, i, te;
621 
622  for (i=0; i<ncpus; i++) {
623  if (cpus[i]->running) {
624  int instrs_run = cpus[i]->run_instr(cpus[i]);
625  if (i == 0)
626  cpu0instrs += instrs_run;
627  }
628  }
629 
630  /*
631  * Hardware 'ticks': (clocks, interrupt sources...)
632  *
633  * Here, cpu0instrs is the number of instructions executed on cpu0.
634  *
635  * TODO: This should be redesigned into some "mainbus" stuff instead!
636  */
637 
638  for (te=0; te<machine->tick_functions.n_entries; te++) {
639  machine->tick_functions.ticks_till_next[te] -= cpu0instrs;
640  if (machine->tick_functions.ticks_till_next[te] <= 0) {
641  while (machine->tick_functions.ticks_till_next[te]<=0) {
642  machine->tick_functions.ticks_till_next[te] +=
643  machine->tick_functions.
644  ticks_reset_value[te];
645  }
646 
647  machine->tick_functions.f[te](cpus[0],
648  machine->tick_functions.extra[te]);
649  }
650  }
651 
652  /* Is any CPU still alive? */
653  for (i=0; i<ncpus; i++)
654  if (cpus[i]->running)
655  return 1;
656 
657  return 0;
658 }
659 
660 
661 /*****************************************************************************/
662 
663 
664 /*
665  * machine_entry_new():
666  *
667  * This function creates a new machine_entry struct, and fills it with some
668  * valid data; it is up to the caller to add additional data that weren't
669  * passed as arguments to this function, such as alias names and machine
670  * subtypes.
671  */
672 struct machine_entry *machine_entry_new(const char *name, int arch,
673  int oldstyle_type)
674 {
675  struct machine_entry *me;
676 
677  CHECK_ALLOCATION(me = (struct machine_entry *) malloc(sizeof(struct machine_entry)));
678  memset(me, 0, sizeof(struct machine_entry));
679 
680  me->name = name;
681  me->arch = arch;
682  me->machine_type = oldstyle_type;
683  me->n_aliases = 0;
684  me->aliases = NULL;
685  me->n_subtypes = 0;
686  me->setup = NULL;
687 
688  return me;
689 }
690 
691 
692 /*
693  * machine_entry_add_alias():
694  *
695  * This function adds an "alias" to a machine entry.
696  */
697 void machine_entry_add_alias(struct machine_entry *me, const char *name)
698 {
699  me->n_aliases ++;
700 
701  CHECK_ALLOCATION(me->aliases = (char **) realloc(me->aliases,
702  sizeof(char *) * me->n_aliases));
703 
704  me->aliases[me->n_aliases - 1] = strdup(name);
705 }
706 
707 
708 /*
709  * machine_entry_add_subtype():
710  *
711  * This function adds a subtype to a machine entry. The argument list after
712  * oldstyle_subtype is a list of one or more char *, followed by NULL. E.g.:
713  *
714  * machine_entry_add_subtype(me, "Machine X", MACHINE_X,
715  * "machine-x", "x", NULL);
716  */
717 void machine_entry_add_subtype(struct machine_entry *me, const char *name,
718  int oldstyle_subtype, ...)
719 {
720  va_list argp;
721  struct machine_entry_subtype *mes;
722 
723  /* Allocate a new subtype struct: */
724  CHECK_ALLOCATION(mes = (struct machine_entry_subtype *)
725  malloc(sizeof(struct machine_entry_subtype)));
726 
727  /* Add the subtype to the machine entry: */
728  me->n_subtypes ++;
729  CHECK_ALLOCATION(me->subtype = (struct
730  machine_entry_subtype **) realloc(me->subtype, sizeof(struct
732  me->subtype[me->n_subtypes - 1] = mes;
733 
734  /* Fill the struct with subtype data: */
735  memset(mes, 0, sizeof(struct machine_entry_subtype));
736  mes->name = name;
737  mes->machine_subtype = oldstyle_subtype;
738 
739  /* ... and all aliases: */
740  mes->n_aliases = 0;
741  mes->aliases = NULL;
742 
743  va_start(argp, oldstyle_subtype);
744 
745  for (;;) {
746  char *s = va_arg(argp, char *);
747  if (s == NULL)
748  break;
749 
750  mes->n_aliases ++;
751  CHECK_ALLOCATION(mes->aliases = (char **)
752  realloc(mes->aliases, sizeof(char *) * mes->n_aliases));
753 
754  mes->aliases[mes->n_aliases - 1] = s;
755  }
756 
757  va_end(argp);
758 }
759 
760 
761 /*
762  * machine_entry_register():
763  *
764  * Inserts a new machine_entry into the machine entries list.
765  */
766 void machine_entry_register(struct machine_entry *me, int arch)
767 {
768  struct machine_entry *prev, *next;
769 
770  /* Only insert it if the architecture is implemented in this
771  emulator configuration: */
772  if (cpu_family_ptr_by_number(arch) == NULL)
773  return;
774 
775  prev = NULL;
776  next = first_machine_entry;
777 
778  for (;;) {
779  if (next == NULL)
780  break;
781  if (strcasecmp(me->name, next->name) < 0)
782  break;
783 
784  prev = next;
785  next = next->next;
786  }
787 
788  if (prev != NULL)
789  prev->next = me;
790  else
791  first_machine_entry = me;
792  me->next = next;
793 }
794 
795 
796 /*
797  * machine_list_available_types_and_cpus():
798  *
799  * List all available machine types (for example when running the emulator
800  * with just -H as command line argument).
801  */
803 {
804  struct machine_entry *me;
805  int iadd = DEBUG_INDENTATION * 2;
806 
807  debug("Available CPU types:\n\n");
808 
809  debug_indentation(iadd);
811  debug_indentation(-iadd);
812 
813  debug("\nMost of the CPU types are bogus, and not really implemented."
814  " The main effect of\nselecting a specific CPU type is to choose "
815  "what kind of 'id' it will have.\n\nAvailable machine types (with "
816  "aliases) and their subtypes:\n\n");
817 
818  debug_indentation(iadd);
819  me = first_machine_entry;
820 
821  if (me == NULL)
822  fatal("No machines defined!\n");
823 
824  while (me != NULL) {
825  int i, j, iadd2 = DEBUG_INDENTATION;
826 
827  debug("%s [%s] (", me->name,
829  for (i=0; i<me->n_aliases; i++)
830  debug("%s\"%s\"", i? ", " : "", me->aliases[i]);
831  debug(")\n");
832 
833  debug_indentation(iadd2);
834  for (i=0; i<me->n_subtypes; i++) {
835  struct machine_entry_subtype *mes;
836  mes = me->subtype[i];
837  debug("- %s", mes->name);
838  debug(" (");
839  for (j=0; j<mes->n_aliases; j++)
840  debug("%s\"%s\"", j? ", " : "",
841  mes->aliases[j]);
842  debug(")\n");
843  }
844  debug_indentation(-iadd2);
845 
846  me = me->next;
847  }
848  debug_indentation(-iadd);
849 
850  debug("\nMost of the machine types are bogus too. Please read the "
851  "GXemul documentation\nfor information about which machine types "
852  "that actually work. Use the alias\nwhen selecting a machine type "
853  "or subtype, not the real name.\n");
854 
855  debug("\n");
856 }
857 
858 
859 /*
860  * machine_init():
861  *
862  * This function should be called before any other machine_*() function
863  * is used. automachine_init() registers all machines in src/machines/.
864  */
865 void machine_init(void)
866 {
867  if (first_machine_entry != NULL) {
868  fatal("machine_init(): already called?\n");
869  exit(1);
870  }
871 
873 }
874 
void cpu_list_available_types(void)
Definition: cpu.cc:335
void ** extra
Definition: machine.h:77
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int tickshift)
Definition: machine.cc:280
void machine_init(void)
Definition: machine.cc:865
void fatal(const char *fmt,...)
Definition: main.cc:152
int * ticks_till_next
Definition: machine.h:74
int emulated_hz
Definition: machine.h:165
#define DEBUG_INDENTATION
Definition: misc.h:212
int prom_emulation
Definition: machine.h:149
void cpu_dumpinfo(struct machine *m, struct cpu *cpu)
Definition: cpu.cc:318
#define SETTINGS_FORMAT_YESNO
Definition: settings.h:58
char * cpu_name
Definition: machine.h:133
struct settings * settings_new(void)
Definition: settings.cc:88
int arch_pagesize
Definition: machine.h:151
char ** aliases
Definition: machine.h:353
int machine_name_to_type(char *stype, char *ssubtype, int *type, int *subtype, int *arch)
Definition: machine.cc:156
int serial_nr
Definition: machine.h:120
void symbol_init(struct symbol_context *)
Definition: symbol.cc:415
int n_aliases
Definition: machine.h:352
void(* set_default_cpu)(struct machine *)
Definition: machine.h:356
int machine_type
Definition: machine.h:111
int arch
Definition: machine.h:349
struct memory * mem
Definition: cpu.h:362
#define SETTINGS_TYPE_STRING
Definition: settings.h:39
struct breakpoints breakpoints
Definition: machine.h:159
void(* setup)(struct machine *, struct cpu *)
Definition: machine.h:355
void(** f)(struct cpu *, void *)
Definition: machine.h:76
void machine_entry_add_subtype(struct machine_entry *me, const char *name, int oldstyle_subtype,...)
Definition: machine.cc:717
int scaleup
Definition: machine.h:84
int machine_type
Definition: machine.h:350
int n_aliases
Definition: machine.h:341
int slow_serial_interrupts_hack_for_linux
Definition: machine.h:168
#define MACHINE_PMAX
Definition: machine.h:213
void machine_statistics_init(struct machine *machine, char *fname)
Definition: machine.cc:323
void(* set_default_ram)(struct machine *)
Definition: machine.h:357
int machine_run(struct machine *machine)
Definition: machine.cc:617
char ** aliases
Definition: machine.h:342
int(* run_instr)(struct cpu *cpu)
Definition: cpu.h:364
int enabled
Definition: machine.h:66
struct cpu ** cpus
Definition: machine.h:140
#define MACHINE_ARC
Definition: machine.h:218
#define SETTINGS_FORMAT_DECIMAL
Definition: settings.h:52
int physical_ram_in_mb
Definition: machine.h:147
int ncpus
Definition: machine.h:139
int scaledown
Definition: machine.h:83
struct machine_entry_subtype ** subtype
Definition: machine.h:361
#define MACHINE_CATS
Definition: machine.h:240
char * boot_string_argument
Definition: machine.h:171
struct emul * emul
Definition: machine.h:99
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
char * boot_kernel_filename
Definition: machine.h:170
char * path
Definition: machine.h:108
int n_subtypes
Definition: machine.h:360
void machine_entry_add_alias(struct machine_entry *me, const char *name)
Definition: machine.cc:697
int diskimage_bootdev(struct machine *machine, int *typep)
Definition: diskimage.cc:989
void machine_dumpinfo(struct machine *m)
Definition: machine.cc:392
int bootstrap_cpu
Definition: machine.h:136
void cpu_destroy(struct cpu *cpu)
Definition: cpu.cc:140
void settings_destroy(struct settings *settings)
Definition: settings.cc:105
Definition: machine.h:338
int force_netboot
Definition: machine.h:167
#define SETTINGS_FORMAT_STRING
Definition: settings.h:59
void diskimage_dump_info(struct machine *machine)
Definition: diskimage.cc:1087
FILE * file
Definition: machine.h:65
uint8_t running
Definition: cpu.h:353
void machine_list_available_types_and_cpus(void)
Definition: machine.cc:802
void machine_memsize_fix(struct machine *m)
Definition: machine.cc:527
void machine_default_cputype(struct machine *m)
Definition: machine.cc:572
Definition: emul.h:37
struct cpu_family * cpu_family_ptr_by_number(int arch)
Definition: cpu.cc:541
char ** display_names
Definition: machine.h:86
int random_mem_contents
Definition: machine.h:146
struct x11_md x11_md
Definition: machine.h:179
int machine_subtype
Definition: machine.h:339
#define debug
Definition: dev_adb.cc:57
#define NO_BYTE_ORDER_OVERRIDE
Definition: misc.h:162
char * bootstr
Definition: machine.h:155
Definition: cpu.h:326
Definition: machine.h:345
char * name
Definition: cpu.h:261
#define DEFAULT_RAM_IN_MB
Definition: memory.h:40
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
int bootdev_type
Definition: machine.h:153
void debug_indentation(int diff)
Definition: main.cc:120
char * optarg
struct symbol_context symbol_context
Definition: machine.h:144
void settings_remove_all(struct settings *settings)
Definition: settings.cc:441
void settings_add(struct settings *settings, const char *name, int writable, int type, int format, void *ptr)
Definition: settings.cc:334
#define N_SAFE_DYNTRANS_LIMIT_SHIFT
Definition: cpu.h:310
char ** string
Definition: machine.h:59
struct settings * settings
Definition: machine.h:102
#define MACHINE_NONE
Definition: machine.h:262
#define MACHINE_SGI
Definition: machine.h:217
int bootdev_id
Definition: machine.h:154
int in_use
Definition: machine.h:82
struct machine_entry * next
Definition: machine.h:346
int allow_instruction_combinations
Definition: machine.h:166
struct machine_entry * machine_entry_new(const char *name, int arch, int oldstyle_type)
Definition: machine.cc:672
const char * name
Definition: machine.h:105
void machine_destroy(struct machine *machine)
Definition: machine.cc:124
const char * name
Definition: machine.h:340
int nr_of_nics
Definition: machine.h:121
struct statistics statistics
Definition: machine.h:176
Definition: memory.h:75
int n_display_names
Definition: machine.h:85
char * fields
Definition: machine.h:67
#define SETTINGS_TYPE_INT
Definition: settings.h:40
int * ticks_reset_value
Definition: machine.h:75
struct machine * machine_new(char *name, struct emul *emul, int id)
Definition: machine.cc:58
int memory_offset_in_mb
Definition: machine.h:148
int arch
Definition: machine.h:110
void automachine_init(void)
Definition: automachine.cc:84
char * filename
Definition: machine.h:64
int machine_subtype
Definition: machine.h:112
void machine_setup(struct machine *machine)
Definition: machine.cc:449
uint64_t * addr
Definition: machine.h:60
struct machine_entry * first_machine_entry
Definition: machine.cc:50
void machine_entry_register(struct machine_entry *me, int arch)
Definition: machine.cc:766
struct tick_functions tick_functions
Definition: machine.h:131
int n_entries
Definition: machine.h:71
const char * machine_name
Definition: machine.h:115
const char * name
Definition: machine.h:351
int byte_order_override
Definition: machine.h:135
void machine_add_breakpoint_string(struct machine *machine, char *str)
Definition: machine.cc:252
int n_gfx_cards
Definition: machine.h:173
char * bootarg
Definition: machine.h:156

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13