/[gxemul]/upstream/0.4.3/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

Contents of /upstream/0.4.3/src/machine.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (show annotations)
Mon Oct 8 16:21:06 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 33190 byte(s)
0.4.3
1 /*
2 * Copyright (C) 2003-2006 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 * $Id: machine.c,v 1.689 2006/10/04 11:56:40 debug Exp $
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 "arcbios.h"
39 #include "bus_isa.h"
40 #include "bus_pci.h"
41 #include "cpu.h"
42 #include "debugger.h"
43 #include "device.h"
44 #include "devices.h"
45 #include "diskimage.h"
46 #include "emul.h"
47 #include "machine.h"
48 #include "machine_interrupts.h"
49 #include "memory.h"
50 #include "misc.h"
51 #include "net.h"
52 #include "settings.h"
53 #include "symbol.h"
54
55
56 /* See main.c: */
57 extern int quiet_mode;
58 extern int verbose;
59
60
61 /* This is initialized by machine_init(): */
62 struct machine_entry *first_machine_entry = NULL;
63
64
65 /*
66 * machine_new():
67 *
68 * Returns a reasonably initialized struct machine.
69 */
70 struct machine *machine_new(char *name, struct emul *emul)
71 {
72 struct machine *m;
73 m = malloc(sizeof(struct machine));
74 if (m == NULL) {
75 fprintf(stderr, "machine_new(): out of memory\n");
76 exit(1);
77 }
78
79 memset(m, 0, sizeof(struct machine));
80
81 /* Pointer back to the emul object that this machine belongs to: */
82 m->emul = emul;
83
84 m->name = strdup(name);
85
86 /* Sane default values: */
87 m->serial_nr = 1;
88 m->machine_type = MACHINE_NONE;
89 m->machine_subtype = MACHINE_NONE;
90 m->arch_pagesize = 4096; /* Should be overriden in
91 emul.c for other pagesizes. */
92 m->prom_emulation = 1;
93 m->allow_instruction_combinations = 1;
94 m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;
95 m->boot_kernel_filename = "";
96 m->boot_string_argument = NULL;
97 m->x11_scaledown = 1;
98 m->x11_scaleup = 1;
99 m->n_gfx_cards = 1;
100 m->dbe_on_nonexistant_memaccess = 1;
101 m->show_symbolic_register_names = 1;
102 symbol_init(&m->symbol_context);
103
104 /* Settings: */
105 m->settings = settings_new();
106 settings_add(m->settings, "name", 0,
107 SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,
108 (void *) &m->name);
109 settings_add(m->settings, "serial_nr", 0,
110 SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
111 (void *) &m->serial_nr);
112 settings_add(m->settings, "arch_pagesize", 0,
113 SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
114 (void *) &m->arch_pagesize);
115 settings_add(m->settings, "prom_emulation", 0,
116 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
117 (void *) &m->prom_emulation);
118 settings_add(m->settings, "allow_instruction_combinations", 0,
119 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
120 (void *) &m->allow_instruction_combinations);
121 settings_add(m->settings, "n_gfx_cards", 0,
122 SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
123 (void *) &m->n_gfx_cards);
124 settings_add(m->settings, "show_symbolic_register_names", 1,
125 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
126 (void *) &m->show_symbolic_register_names);
127 settings_add(m->settings, "statistics_enabled", 1,
128 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
129 (void *) &m->statistics_enabled);
130
131 return m;
132 }
133
134
135 /*
136 * machine_destroy():
137 *
138 * Destroys a machine object.
139 */
140 void machine_destroy(struct machine *machine)
141 {
142 int i;
143
144 for (i=0; i<machine->ncpus; i++)
145 cpu_destroy(machine->cpus[i]);
146
147 if (machine->name != NULL)
148 free(machine->name);
149
150 /* Remove any remaining level-1 settings: */
151 settings_remove_all(machine->settings);
152 settings_destroy(machine->settings);
153
154 free(machine);
155 }
156
157
158 /*
159 * machine_name_to_type():
160 *
161 * Take a type and a subtype as strings, and convert them into numeric
162 * values used internally throughout the code.
163 *
164 * Return value is 1 on success, 0 if there was no match.
165 * Also, any errors/warnings are printed using fatal()/debug().
166 */
167 int machine_name_to_type(char *stype, char *ssubtype,
168 int *type, int *subtype, int *arch)
169 {
170 struct machine_entry *me;
171 int i, j, k, nmatches = 0;
172
173 *type = MACHINE_NONE;
174 *subtype = 0;
175
176 /* Check stype, and optionally ssubtype: */
177 me = first_machine_entry;
178 while (me != NULL) {
179 for (i=0; i<me->n_aliases; i++)
180 if (strcasecmp(me->aliases[i], stype) == 0) {
181 /* Found a type: */
182 *type = me->machine_type;
183 *arch = me->arch;
184
185 if (me->n_subtypes == 0)
186 return 1;
187
188 /* Check for subtype: */
189 for (j=0; j<me->n_subtypes; j++)
190 for (k=0; k<me->subtype[j]->n_aliases;
191 k++)
192 if (strcasecmp(ssubtype,
193 me->subtype[j]->aliases[k]
194 ) == 0) {
195 *subtype = me->subtype[
196 j]->machine_subtype;
197 return 1;
198 }
199
200 fatal("Unknown subtype '%s' for emulation"
201 " '%s'\n", ssubtype, stype);
202 if (!ssubtype[0])
203 fatal("(Maybe you forgot the -e"
204 " command line option?)\n");
205 exit(1);
206 }
207
208 me = me->next;
209 }
210
211 /* Not found? Then just check ssubtype: */
212 me = first_machine_entry;
213 while (me != NULL) {
214 if (me->n_subtypes == 0) {
215 me = me->next;
216 continue;
217 }
218
219 /* Check for subtype: */
220 for (j=0; j<me->n_subtypes; j++)
221 for (k=0; k<me->subtype[j]->n_aliases; k++)
222 if (strcasecmp(ssubtype, me->subtype[j]->
223 aliases[k]) == 0) {
224 *type = me->machine_type;
225 *arch = me->arch;
226 *subtype = me->subtype[j]->
227 machine_subtype;
228 nmatches ++;
229 }
230
231 me = me->next;
232 }
233
234 switch (nmatches) {
235 case 0: fatal("\nSorry, emulation \"%s\"", stype);
236 if (ssubtype != NULL && ssubtype[0] != '\0')
237 fatal(" (subtype \"%s\")", ssubtype);
238 fatal(" is unknown.\n");
239 break;
240 case 1: return 1;
241 default:fatal("\nSorry, multiple matches for \"%s\"", stype);
242 if (ssubtype != NULL && ssubtype[0] != '\0')
243 fatal(" (subtype \"%s\")", ssubtype);
244 fatal(".\n");
245 }
246
247 *type = MACHINE_NONE;
248 *subtype = 0;
249
250 fatal("Use the -H command line option to get a list of "
251 "available types and subtypes.\n\n");
252
253 return 0;
254 }
255
256
257 /*
258 * machine_add_tickfunction():
259 *
260 * Adds a tick function (a function called every now and then, depending on
261 * clock cycle count) to a machine.
262 *
263 * If tickshift is non-zero, a tick will occur every (1 << tickshift) cycles.
264 * This is used for the normal (fast dyntrans) emulation modes.
265 *
266 * If tickshift is zero, then this is a cycle-accurate tick function.
267 * The hz value is used in this case.
268 */
269 void machine_add_tickfunction(struct machine *machine, void (*func)
270 (struct cpu *, void *), void *extra, int tickshift, double hz)
271 {
272 int n = machine->n_tick_entries;
273
274 if (n >= MAX_TICK_FUNCTIONS) {
275 fprintf(stderr, "machine_add_tickfunction(): too "
276 "many tick functions\n");
277 exit(1);
278 }
279
280 if (!machine->cycle_accurate) {
281 /*
282 * The dyntrans subsystem wants to run code in relatively
283 * large chunks without checking for external interrupts;
284 * too low tickshifts are not allowed.
285 */
286 if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) {
287 fatal("ERROR! tickshift = %i, less than "
288 "N_SAFE_DYNTRANS_LIMIT_SHIFT (%i)\n",
289 tickshift, N_SAFE_DYNTRANS_LIMIT_SHIFT);
290 exit(1);
291 }
292 }
293
294 machine->ticks_till_next[n] = 0;
295 machine->ticks_reset_value[n] = 1 << tickshift;
296 machine->tick_func[n] = func;
297 machine->tick_extra[n] = extra;
298 machine->tick_hz[n] = hz;
299
300 machine->n_tick_entries ++;
301 }
302
303
304 /*
305 * machine_statistics_init():
306 *
307 * Initialize the parts of a machine struct that deal with instruction
308 * statistics gathering.
309 *
310 * Note: The fname argument contains "flags:filename".
311 */
312 void machine_statistics_init(struct machine *machine, char *fname)
313 {
314 int n_fields = 0;
315 char *pcolon = fname;
316 char *mode = "a"; /* Append by default */
317
318 machine->allow_instruction_combinations = 0;
319
320 if (machine->statistics_fields != NULL) {
321 fprintf(stderr, "Only one -s option is allowed.\n");
322 exit(1);
323 }
324
325 machine->statistics_fields = malloc(MAX_STATISTICS_FIELDS + 1);
326 machine->statistics_enabled = 1;
327
328 while (*pcolon && *pcolon != ':')
329 pcolon ++;
330
331 if (*pcolon != ':') {
332 fprintf(stderr, "The syntax for the -s option is: "
333 "-s flags:filename\nYou omitted the flags. Run g"
334 "xemul -h for a list of available flags.\n");
335 exit(1);
336 }
337
338 while (*fname != ':') {
339 switch (*fname) {
340
341 /* Type flags: */
342 case 'v':
343 case 'i':
344 case 'p':
345 machine->statistics_fields[n_fields ++] = *fname;
346 if (n_fields >= MAX_STATISTICS_FIELDS) {
347 fprintf(stderr, "Internal error: Too many "
348 "statistics fields used. Increase "
349 "MAX_STATISTICS_FIELDS.\n");
350 exit(1);
351 }
352 machine->statistics_fields[n_fields] = '\0';
353 break;
354
355 /* Optional flags: */
356 case 'o':
357 mode = "w";
358 break;
359 case 'd':
360 machine->statistics_enabled = 0;
361 break;
362
363 default:fprintf(stderr, "Unknown flag '%c' used with the"
364 " -s option. Aborting.\n", *fname);
365 exit(1);
366 }
367 fname ++;
368 }
369
370 fname ++; /* point to the filename after the colon */
371
372 machine->statistics_filename = strdup(fname);
373 machine->statistics_file = fopen(machine->statistics_filename, mode);
374 }
375
376
377 /*
378 * machine_bus_register():
379 *
380 * Registers a bus in a machine.
381 */
382 void machine_bus_register(struct machine *machine, char *busname,
383 void (*debug_dump)(void *), void *extra)
384 {
385 struct machine_bus *tmp, *last = NULL, *new;
386
387 new = zeroed_alloc(sizeof(struct machine_bus));
388 new->name = strdup(busname);
389 new->debug_dump = debug_dump;
390 new->extra = extra;
391
392 /* Register last in the bus list: */
393 tmp = machine->first_bus;
394 while (tmp != NULL) {
395 last = tmp;
396 tmp = tmp->next;
397 }
398
399 if (last == NULL)
400 machine->first_bus = new;
401 else
402 last->next = new;
403
404 machine->n_busses ++;
405 }
406
407
408 /*
409 * machine_dump_bus_info():
410 *
411 * Dumps info about registered busses.
412 */
413 void machine_dump_bus_info(struct machine *m)
414 {
415 struct machine_bus *bus = m->first_bus;
416 int iadd = DEBUG_INDENTATION;
417
418 if (m->n_busses > 0)
419 debug("busses:\n");
420 debug_indentation(iadd);
421 while (bus != NULL) {
422 bus->debug_dump(bus->extra);
423 bus = bus->next;
424 }
425 debug_indentation(-iadd);
426 }
427
428
429 /*
430 * machine_dumpinfo():
431 *
432 * Dumps info about a machine in some kind of readable format. (Used by
433 * the 'machine' debugger command.)
434 */
435 void machine_dumpinfo(struct machine *m)
436 {
437 int i;
438
439 debug("serial nr: %i", m->serial_nr);
440 if (m->nr_of_nics > 0)
441 debug(" (nr of NICs: %i)", m->nr_of_nics);
442 debug("\n");
443
444 debug("memory: %i MB", m->physical_ram_in_mb);
445 if (m->memory_offset_in_mb != 0)
446 debug(" (offset by %i MB)", m->memory_offset_in_mb);
447 if (m->random_mem_contents)
448 debug(", randomized contents");
449 if (m->dbe_on_nonexistant_memaccess)
450 debug(", dbe_on_nonexistant_memaccess");
451 debug("\n");
452
453 if (!m->prom_emulation)
454 debug("PROM emulation disabled\n");
455
456 for (i=0; i<m->ncpus; i++)
457 cpu_dumpinfo(m, m->cpus[i]);
458
459 if (m->ncpus > 1)
460 debug("Bootstrap cpu is nr %i\n", m->bootstrap_cpu);
461
462 if (m->slow_serial_interrupts_hack_for_linux)
463 debug("Using slow_serial_interrupts_hack_for_linux\n");
464
465 if (m->use_x11) {
466 debug("Using X11");
467 if (m->x11_scaledown > 1)
468 debug(", scaledown %i", m->x11_scaledown);
469 if (m->x11_scaleup > 1)
470 debug(", scaleup %i", m->x11_scaleup);
471 if (m->x11_n_display_names > 0) {
472 for (i=0; i<m->x11_n_display_names; i++) {
473 debug(i? ", " : " (");
474 debug("\"%s\"", m->x11_display_names[i]);
475 }
476 debug(")");
477 }
478 debug("\n");
479 }
480
481 machine_dump_bus_info(m);
482
483 diskimage_dump_info(m);
484
485 if (m->force_netboot)
486 debug("Forced netboot\n");
487 }
488
489
490 /*
491 * dump_mem_string():
492 *
493 * Dump the contents of emulated RAM as readable text. Bytes that aren't
494 * readable are dumped in [xx] notation, where xx is in hexadecimal.
495 * Dumping ends after DUMP_MEM_STRING_MAX bytes, or when a terminating
496 * zero byte is found.
497 */
498 #define DUMP_MEM_STRING_MAX 45
499 void dump_mem_string(struct cpu *cpu, uint64_t addr)
500 {
501 int i;
502 for (i=0; i<DUMP_MEM_STRING_MAX; i++) {
503 unsigned char ch = '\0';
504
505 cpu->memory_rw(cpu, cpu->mem, addr + i, &ch, sizeof(ch),
506 MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
507 if (ch == '\0')
508 return;
509 if (ch >= ' ' && ch < 126)
510 debug("%c", ch);
511 else
512 debug("[%02x]", ch);
513 }
514 }
515
516
517 /*
518 * store_byte():
519 *
520 * Stores a byte in emulated ram. (Helper function.)
521 */
522 void store_byte(struct cpu *cpu, uint64_t addr, uint8_t data)
523 {
524 if ((addr >> 32) == 0)
525 addr = (int64_t)(int32_t)addr;
526 cpu->memory_rw(cpu, cpu->mem,
527 addr, &data, sizeof(data), MEM_WRITE, CACHE_DATA);
528 }
529
530
531 /*
532 * store_string():
533 *
534 * Stores chars into emulated RAM until a zero byte (string terminating
535 * character) is found. The zero byte is also copied.
536 * (strcpy()-like helper function, host-RAM-to-emulated-RAM.)
537 */
538 void store_string(struct cpu *cpu, uint64_t addr, char *s)
539 {
540 do {
541 store_byte(cpu, addr++, *s);
542 } while (*s++);
543 }
544
545
546 /*
547 * add_environment_string():
548 *
549 * Like store_string(), but advances the pointer afterwards. The most
550 * obvious use is to place a number of strings (such as environment variable
551 * strings) after one-another in emulated memory.
552 */
553 void add_environment_string(struct cpu *cpu, char *s, uint64_t *addr)
554 {
555 store_string(cpu, *addr, s);
556 (*addr) += strlen(s) + 1;
557 }
558
559
560 /*
561 * add_environment_string_dual():
562 *
563 * Add "dual" environment strings, one for the variable name and one for the
564 * value, and update pointers afterwards.
565 */
566 void add_environment_string_dual(struct cpu *cpu,
567 uint64_t *ptrp, uint64_t *addrp, char *s1, char *s2)
568 {
569 uint64_t ptr = *ptrp, addr = *addrp;
570
571 store_32bit_word(cpu, ptr, addr);
572 ptr += sizeof(uint32_t);
573 if (addr != 0) {
574 store_string(cpu, addr, s1);
575 addr += strlen(s1) + 1;
576 }
577 store_32bit_word(cpu, ptr, addr);
578 ptr += sizeof(uint32_t);
579 if (addr != 0) {
580 store_string(cpu, addr, s2);
581 addr += strlen(s2) + 1;
582 }
583
584 *ptrp = ptr;
585 *addrp = addr;
586 }
587
588
589 /*
590 * store_64bit_word():
591 *
592 * Stores a 64-bit word in emulated RAM. Byte order is taken into account.
593 * Helper function.
594 */
595 int store_64bit_word(struct cpu *cpu, uint64_t addr, uint64_t data64)
596 {
597 unsigned char data[8];
598 if ((addr >> 32) == 0)
599 addr = (int64_t)(int32_t)addr;
600 data[0] = (data64 >> 56) & 255;
601 data[1] = (data64 >> 48) & 255;
602 data[2] = (data64 >> 40) & 255;
603 data[3] = (data64 >> 32) & 255;
604 data[4] = (data64 >> 24) & 255;
605 data[5] = (data64 >> 16) & 255;
606 data[6] = (data64 >> 8) & 255;
607 data[7] = (data64) & 255;
608 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
609 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
610 tmp = data[1]; data[1] = data[6]; data[6] = tmp;
611 tmp = data[2]; data[2] = data[5]; data[5] = tmp;
612 tmp = data[3]; data[3] = data[4]; data[4] = tmp;
613 }
614 return cpu->memory_rw(cpu, cpu->mem,
615 addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
616 }
617
618
619 /*
620 * store_32bit_word():
621 *
622 * Stores a 32-bit word in emulated RAM. Byte order is taken into account.
623 * (This function takes a 64-bit word as argument, to suppress some
624 * warnings, but only the lowest 32 bits are used.)
625 */
626 int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)
627 {
628 unsigned char data[4];
629
630 /* TODO: REMOVE THIS once everything is more stable! */
631 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
632 addr = (int64_t)(int32_t)addr;
633
634 data[0] = (data32 >> 24) & 255;
635 data[1] = (data32 >> 16) & 255;
636 data[2] = (data32 >> 8) & 255;
637 data[3] = (data32) & 255;
638 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
639 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
640 tmp = data[1]; data[1] = data[2]; data[2] = tmp;
641 }
642 return cpu->memory_rw(cpu, cpu->mem,
643 addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
644 }
645
646
647 /*
648 * store_16bit_word():
649 *
650 * Stores a 16-bit word in emulated RAM. Byte order is taken into account.
651 * (This function takes a 64-bit word as argument, to suppress some
652 * warnings, but only the lowest 16 bits are used.)
653 */
654 int store_16bit_word(struct cpu *cpu, uint64_t addr, uint64_t data16)
655 {
656 unsigned char data[2];
657
658 /* TODO: REMOVE THIS once everything is more stable! */
659 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
660 addr = (int64_t)(int32_t)addr;
661
662 data[0] = (data16 >> 8) & 255;
663 data[1] = (data16) & 255;
664 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
665 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
666 }
667 return cpu->memory_rw(cpu, cpu->mem,
668 addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
669 }
670
671
672 /*
673 * store_buf():
674 *
675 * memcpy()-like helper function, from host RAM to emulated RAM.
676 */
677 void store_buf(struct cpu *cpu, uint64_t addr, char *s, size_t len)
678 {
679 size_t psize = 1024; /* 1024 256 64 16 4 1 */
680
681 /* TODO: REMOVE THIS once everything is more stable! */
682 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
683 addr = (int64_t)(int32_t)addr;
684
685 while (len != 0) {
686 if ((addr & (psize-1)) == 0) {
687 while (len >= psize) {
688 cpu->memory_rw(cpu, cpu->mem, addr,
689 (unsigned char *)s, psize, MEM_WRITE,
690 CACHE_DATA);
691 addr += psize;
692 s += psize;
693 len -= psize;
694 }
695 }
696 psize >>= 2;
697 }
698
699 while (len-- != 0)
700 store_byte(cpu, addr++, *s++);
701 }
702
703
704 /*
705 * store_pointer_and_advance():
706 *
707 * Stores a 32-bit or 64-bit pointer in emulated RAM, and advances the
708 * target address. (Useful for e.g. ARCBIOS environment initialization.)
709 */
710 void store_pointer_and_advance(struct cpu *cpu, uint64_t *addrp,
711 uint64_t data, int flag64)
712 {
713 uint64_t addr = *addrp;
714 if (flag64) {
715 store_64bit_word(cpu, addr, data);
716 addr += 8;
717 } else {
718 store_32bit_word(cpu, addr, data);
719 addr += 4;
720 }
721 *addrp = addr;
722 }
723
724
725 /*
726 * load_64bit_word():
727 *
728 * Helper function. Emulated byte order is taken into account.
729 */
730 uint64_t load_64bit_word(struct cpu *cpu, uint64_t addr)
731 {
732 unsigned char data[8];
733
734 cpu->memory_rw(cpu, cpu->mem,
735 addr, data, sizeof(data), MEM_READ, CACHE_DATA);
736
737 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
738 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
739 tmp = data[1]; data[1] = data[6]; data[6] = tmp;
740 tmp = data[2]; data[2] = data[5]; data[5] = tmp;
741 tmp = data[3]; data[3] = data[4]; data[4] = tmp;
742 }
743
744 return
745 ((uint64_t)data[0] << 56) + ((uint64_t)data[1] << 48) +
746 ((uint64_t)data[2] << 40) + ((uint64_t)data[3] << 32) +
747 ((uint64_t)data[4] << 24) + ((uint64_t)data[5] << 16) +
748 ((uint64_t)data[6] << 8) + (uint64_t)data[7];
749 }
750
751
752 /*
753 * load_32bit_word():
754 *
755 * Helper function. Emulated byte order is taken into account.
756 */
757 uint32_t load_32bit_word(struct cpu *cpu, uint64_t addr)
758 {
759 unsigned char data[4];
760
761 /* TODO: REMOVE THIS once everything is more stable! */
762 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
763 addr = (int64_t)(int32_t)addr;
764
765 cpu->memory_rw(cpu, cpu->mem,
766 addr, data, sizeof(data), MEM_READ, CACHE_DATA);
767
768 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
769 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
770 tmp = data[1]; data[1] = data[2]; data[2] = tmp;
771 }
772
773 return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
774 }
775
776
777 /*
778 * load_16bit_word():
779 *
780 * Helper function. Emulated byte order is taken into account.
781 */
782 uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr)
783 {
784 unsigned char data[2];
785
786 /* TODO: REMOVE THIS once everything is more stable! */
787 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
788 addr = (int64_t)(int32_t)addr;
789
790 cpu->memory_rw(cpu, cpu->mem,
791 addr, data, sizeof(data), MEM_READ, CACHE_DATA);
792
793 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
794 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
795 }
796
797 return (data[0] << 8) + data[1];
798 }
799
800
801 /*
802 * store_64bit_word_in_host():
803 *
804 * Stores a 64-bit word in the _host's_ RAM. Emulated byte order is taken
805 * into account. This is useful when building structs in the host's RAM
806 * which will later be copied into emulated RAM.
807 */
808 void store_64bit_word_in_host(struct cpu *cpu,
809 unsigned char *data, uint64_t data64)
810 {
811 data[0] = (data64 >> 56) & 255;
812 data[1] = (data64 >> 48) & 255;
813 data[2] = (data64 >> 40) & 255;
814 data[3] = (data64 >> 32) & 255;
815 data[4] = (data64 >> 24) & 255;
816 data[5] = (data64 >> 16) & 255;
817 data[6] = (data64 >> 8) & 255;
818 data[7] = (data64) & 255;
819 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
820 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
821 tmp = data[1]; data[1] = data[6]; data[6] = tmp;
822 tmp = data[2]; data[2] = data[5]; data[5] = tmp;
823 tmp = data[3]; data[3] = data[4]; data[4] = tmp;
824 }
825 }
826
827
828 /*
829 * store_32bit_word_in_host():
830 *
831 * See comment for store_64bit_word_in_host().
832 *
833 * (Note: The data32 parameter is a uint64_t. This is done to suppress
834 * some warnings.)
835 */
836 void store_32bit_word_in_host(struct cpu *cpu,
837 unsigned char *data, uint64_t data32)
838 {
839 data[0] = (data32 >> 24) & 255;
840 data[1] = (data32 >> 16) & 255;
841 data[2] = (data32 >> 8) & 255;
842 data[3] = (data32) & 255;
843 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
844 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
845 tmp = data[1]; data[1] = data[2]; data[2] = tmp;
846 }
847 }
848
849
850 /*
851 * store_16bit_word_in_host():
852 *
853 * See comment for store_64bit_word_in_host().
854 */
855 void store_16bit_word_in_host(struct cpu *cpu,
856 unsigned char *data, uint16_t data16)
857 {
858 data[0] = (data16 >> 8) & 255;
859 data[1] = (data16) & 255;
860 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
861 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
862 }
863 }
864
865
866 /*
867 * machine_setup():
868 *
869 * This (rather large) function initializes memory, registers, and/or devices
870 * required by specific machine emulations.
871 */
872 void machine_setup(struct machine *machine)
873 {
874 struct memory *mem;
875 struct machine_entry *me;
876
877 /* Abreviation: :-) */
878 struct cpu *cpu = machine->cpus[machine->bootstrap_cpu];
879
880 machine->bootdev_id = diskimage_bootdev(machine,
881 &machine->bootdev_type);
882
883 mem = cpu->mem;
884 machine->machine_name = NULL;
885
886 /* TODO: Move this somewhere else? */
887 if (machine->boot_string_argument == NULL) {
888 switch (machine->machine_type) {
889 case MACHINE_ARC:
890 machine->boot_string_argument = "-aN";
891 break;
892 case MACHINE_CATS:
893 machine->boot_string_argument = "-A";
894 break;
895 case MACHINE_PMAX:
896 machine->boot_string_argument = "-a";
897 break;
898 default:
899 /* Important, because boot_string_argument should
900 not be set to NULL: */
901 machine->boot_string_argument = "";
902 }
903 }
904
905
906 /*
907 * If the machine has a setup function in src/machines/machine_*.c
908 * then use that one, otherwise use the old hardcoded stuff here:
909 */
910
911 me = first_machine_entry;
912 while (me != NULL) {
913 if (machine->machine_type == me->machine_type &&
914 me->setup != NULL) {
915 me->setup(machine, cpu);
916 break;
917 }
918 me = me->next;
919 }
920
921 if (me == NULL) {
922 fatal("Unknown emulation type %i\n", machine->machine_type);
923 exit(1);
924 }
925
926 if (machine->machine_name != NULL)
927 debug("machine: %s", machine->machine_name);
928
929 if (machine->emulated_hz > 0)
930 debug(" (%.2f MHz)", (float)machine->emulated_hz / 1000000);
931 debug("\n");
932
933 if (machine->bootstr != NULL) {
934 debug("bootstring%s: %s", (machine->bootarg!=NULL &&
935 strlen(machine->bootarg) >= 1)? "(+bootarg)" : "",
936 machine->bootstr);
937 if (machine->bootarg != NULL && strlen(machine->bootarg) >= 1)
938 debug(" %s", machine->bootarg);
939 debug("\n");
940 }
941
942 if (verbose >= 2)
943 machine_dump_bus_info(machine);
944
945 if (!machine->stable)
946 fatal("!\n! NOTE: This machine type is not implemented well"
947 " enough yet to run\n! any real-world code!"
948 " (At least, it hasn't been verified to do so.)\n!\n"
949 "! Please read the GXemul documentation for information"
950 " about which\n! machine types that actually work.\n!\n");
951 }
952
953
954 /*
955 * machine_memsize_fix():
956 *
957 * Sets physical_ram_in_mb (if not already set), and memory_offset_in_mb,
958 * depending on machine type.
959 */
960 void machine_memsize_fix(struct machine *m)
961 {
962 if (m == NULL) {
963 fatal("machine_defaultmemsize(): m == NULL?\n");
964 exit(1);
965 }
966
967 if (m->physical_ram_in_mb == 0) {
968 struct machine_entry *me = first_machine_entry;
969 while (me != NULL) {
970 if (m->machine_type == me->machine_type &&
971 me->set_default_ram != NULL) {
972 me->set_default_ram(m);
973 break;
974 }
975 me = me->next;
976 }
977 }
978
979 /* Special hack for hpcmips machines: */
980 if (m->machine_type == MACHINE_HPCMIPS) {
981 m->dbe_on_nonexistant_memaccess = 0;
982 }
983
984 /* Special SGI memory offsets: (TODO: move this somewhere else) */
985 if (m->machine_type == MACHINE_SGI) {
986 switch (m->machine_subtype) {
987 case 20:
988 case 22:
989 case 24:
990 case 26:
991 m->memory_offset_in_mb = 128;
992 break;
993 case 28:
994 case 30:
995 m->memory_offset_in_mb = 512;
996 break;
997 }
998 }
999
1000 if (m->physical_ram_in_mb == 0)
1001 m->physical_ram_in_mb = DEFAULT_RAM_IN_MB;
1002 }
1003
1004
1005 /*
1006 * machine_default_cputype():
1007 *
1008 * Sets m->cpu_name, if it isn't already set, depending on the machine type.
1009 */
1010 void machine_default_cputype(struct machine *m)
1011 {
1012 struct machine_entry *me;
1013
1014 if (m == NULL) {
1015 fatal("machine_default_cputype(): m == NULL?\n");
1016 exit(1);
1017 }
1018
1019 /* Already set? Then return. */
1020 if (m->cpu_name != NULL)
1021 return;
1022
1023 me = first_machine_entry;
1024 while (me != NULL) {
1025 if (m->machine_type == me->machine_type &&
1026 me->set_default_cpu != NULL) {
1027 me->set_default_cpu(m);
1028 break;
1029 }
1030 me = me->next;
1031 }
1032
1033 if (m->cpu_name == NULL) {
1034 fprintf(stderr, "machine_default_cputype(): no default"
1035 " cpu for machine type %i subtype %i\n",
1036 m->machine_type, m->machine_subtype);
1037 exit(1);
1038 }
1039 }
1040
1041
1042 /*****************************************************************************/
1043
1044
1045 /*
1046 * machine_run():
1047 *
1048 * Run one or more instructions on all CPUs in this machine. (Usually,
1049 * around N_SAFE_DYNTRANS_LIMIT instructions will be run by the dyntrans
1050 * system.)
1051 *
1052 * Return value is 1 if any CPU in this machine is still running,
1053 * or 0 if all CPUs are stopped.
1054 */
1055 int machine_run(struct machine *machine)
1056 {
1057 struct cpu **cpus = machine->cpus;
1058 int ncpus = machine->ncpus, cpu0instrs = 0, i, te;
1059
1060 for (i=0; i<ncpus; i++) {
1061 if (cpus[i]->running) {
1062 int instrs_run = cpus[i]->run_instr(cpus[i]);
1063 if (i == 0)
1064 cpu0instrs += instrs_run;
1065 }
1066 }
1067
1068 /*
1069 * Hardware 'ticks': (clocks, interrupt sources...)
1070 *
1071 * Here, cpu0instrs is the number of instructions executed on cpu0.
1072 *
1073 * TODO: This should be redesigned into some "mainbus" stuff instead!
1074 */
1075
1076 machine->ninstrs += cpu0instrs;
1077
1078 for (te=0; te<machine->n_tick_entries; te++) {
1079 machine->ticks_till_next[te] -= cpu0instrs;
1080 if (machine->ticks_till_next[te] <= 0) {
1081 while (machine->ticks_till_next[te] <= 0) {
1082 machine->ticks_till_next[te] +=
1083 machine->ticks_reset_value[te];
1084 }
1085
1086 machine->tick_func[te](cpus[0],
1087 machine->tick_extra[te]);
1088 }
1089 }
1090
1091 /* Is any CPU still alive? */
1092 for (i=0; i<ncpus; i++)
1093 if (cpus[i]->running)
1094 return 1;
1095
1096 return 0;
1097 }
1098
1099
1100 /*****************************************************************************/
1101
1102
1103 /*
1104 * machine_entry_new():
1105 *
1106 * This function creates a new machine_entry struct, and fills it with some
1107 * valid data; it is up to the caller to add additional data that weren't
1108 * passed as arguments to this function, such as alias names and machine
1109 * subtypes.
1110 */
1111 struct machine_entry *machine_entry_new(const char *name, int arch,
1112 int oldstyle_type)
1113 {
1114 struct machine_entry *me;
1115
1116 me = malloc(sizeof(struct machine_entry));
1117 if (me == NULL) {
1118 fprintf(stderr, "machine_entry_new(): out of memory (1)\n");
1119 exit(1);
1120 }
1121
1122 memset(me, 0, sizeof(struct machine_entry));
1123
1124 me->name = name;
1125 me->arch = arch;
1126 me->machine_type = oldstyle_type;
1127 me->n_aliases = 0;
1128 me->aliases = NULL;
1129 me->n_subtypes = 0;
1130 me->setup = NULL;
1131
1132 return me;
1133 }
1134
1135
1136 /*
1137 * machine_entry_add_alias():
1138 *
1139 * This function adds an "alias" to a machine entry.
1140 */
1141 void machine_entry_add_alias(struct machine_entry *me, const char *name)
1142 {
1143 me->n_aliases ++;
1144 me->aliases = realloc(me->aliases, sizeof(char *) * me->n_aliases);
1145 if (me->aliases == NULL) {
1146 fprintf(stderr, "out of memory\n");
1147 exit(1);
1148 }
1149
1150 me->aliases[me->n_aliases - 1] = (char *) name;
1151 }
1152
1153
1154 /*
1155 * machine_entry_add_subtype():
1156 *
1157 * This function adds a subtype to a machine entry. The argument list after
1158 * oldstyle_subtype is a list of one or more char *, followed by NULL. E.g.:
1159 *
1160 * machine_entry_add_subtype(me, "Machine X", MACHINE_X,
1161 * "machine-x", "x", NULL);
1162 */
1163 void machine_entry_add_subtype(struct machine_entry *me, const char *name,
1164 int oldstyle_subtype, ...)
1165 {
1166 va_list argp;
1167 struct machine_entry_subtype *mes;
1168
1169 /* Allocate a new subtype struct: */
1170 mes = malloc(sizeof(struct machine_entry_subtype));
1171 if (mes == NULL) {
1172 fprintf(stderr, "machine_entry_subtype_new(): out "
1173 "of memory (1)\n");
1174 exit(1);
1175 }
1176
1177 /* Add the subtype to the machine entry: */
1178 me->n_subtypes ++;
1179 me->subtype = realloc(me->subtype, sizeof(struct
1180 machine_entry_subtype *) * me->n_subtypes);
1181 if (me->subtype == NULL) {
1182 fprintf(stderr, "out of memory\n");
1183 exit(1);
1184 }
1185 me->subtype[me->n_subtypes - 1] = mes;
1186
1187 /* Fill the struct with subtype data: */
1188 memset(mes, 0, sizeof(struct machine_entry_subtype));
1189 mes->name = name;
1190 mes->machine_subtype = oldstyle_subtype;
1191
1192 /* ... and all aliases: */
1193 mes->n_aliases = 0;
1194 mes->aliases = NULL;
1195
1196 va_start(argp, oldstyle_subtype);
1197
1198 for (;;) {
1199 char *s = va_arg(argp, char *);
1200 if (s == NULL)
1201 break;
1202
1203 mes->n_aliases ++;
1204 mes->aliases = realloc(mes->aliases, sizeof(char *) *
1205 mes->n_aliases);
1206 if (mes->aliases == NULL) {
1207 fprintf(stderr, "out of memory\n");
1208 exit(1);
1209 }
1210
1211 mes->aliases[mes->n_aliases - 1] = s;
1212 }
1213
1214 va_end(argp);
1215 }
1216
1217
1218 /*
1219 * machine_entry_register():
1220 *
1221 * Inserts a new machine_entry into the machine entries list.
1222 */
1223 void machine_entry_register(struct machine_entry *me, int arch)
1224 {
1225 struct machine_entry *prev, *next;
1226
1227 /* Only insert it if the architecture is implemented in this
1228 emulator configuration: */
1229 if (cpu_family_ptr_by_number(arch) == NULL)
1230 return;
1231
1232 prev = NULL;
1233 next = first_machine_entry;
1234
1235 for (;;) {
1236 if (next == NULL)
1237 break;
1238 if (strcasecmp(me->name, next->name) < 0)
1239 break;
1240
1241 prev = next;
1242 next = next->next;
1243 }
1244
1245 if (prev != NULL)
1246 prev->next = me;
1247 else
1248 first_machine_entry = me;
1249 me->next = next;
1250 }
1251
1252
1253 /*
1254 * machine_list_available_types_and_cpus():
1255 *
1256 * List all available machine types (for example when running the emulator
1257 * with just -H as command line argument).
1258 */
1259 void machine_list_available_types_and_cpus(void)
1260 {
1261 struct machine_entry *me;
1262 int iadd = DEBUG_INDENTATION * 2;
1263
1264 debug("Available CPU types:\n\n");
1265
1266 debug_indentation(iadd);
1267 cpu_list_available_types();
1268 debug_indentation(-iadd);
1269
1270 debug("\nMost of the CPU types are bogus, and not really implemented."
1271 " The main effect of\nselecting a specific CPU type is to choose "
1272 "what kind of 'id' it will have.\n\nAvailable machine types (with "
1273 "aliases) and their subtypes:\n\n");
1274
1275 debug_indentation(iadd);
1276 me = first_machine_entry;
1277
1278 if (me == NULL)
1279 fatal("No machines defined!\n");
1280
1281 while (me != NULL) {
1282 int i, j, iadd = DEBUG_INDENTATION;
1283
1284 debug("%s [%s] (", me->name,
1285 cpu_family_ptr_by_number(me->arch)->name);
1286 for (i=0; i<me->n_aliases; i++)
1287 debug("%s\"%s\"", i? ", " : "", me->aliases[i]);
1288 debug(")\n");
1289
1290 debug_indentation(iadd);
1291 for (i=0; i<me->n_subtypes; i++) {
1292 struct machine_entry_subtype *mes;
1293 mes = me->subtype[i];
1294 debug("- %s", mes->name);
1295 debug(" (");
1296 for (j=0; j<mes->n_aliases; j++)
1297 debug("%s\"%s\"", j? ", " : "",
1298 mes->aliases[j]);
1299 debug(")\n");
1300 }
1301 debug_indentation(-iadd);
1302
1303 me = me->next;
1304 }
1305 debug_indentation(-iadd);
1306
1307 debug("\nMost of the machine types are bogus too. Please read the "
1308 "GXemul documentation\nfor information about which machine types "
1309 "that actually work. Use the alias\nwhen selecting a machine type "
1310 "or subtype, not the real name.\n");
1311
1312 #ifdef UNSTABLE_DEVEL
1313 debug("\n");
1314
1315 useremul_list_emuls();
1316 debug("Userland emulation works for programs with the complexity"
1317 " of Hello World,\nbut not much more.\n");
1318 #endif
1319 }
1320
1321
1322 /*
1323 * machine_init():
1324 *
1325 * This function should be called before any other machine_*() function
1326 * is used. automachine_init() registers all machines in src/machines/.
1327 */
1328 void machine_init(void)
1329 {
1330 if (first_machine_entry != NULL) {
1331 fatal("machine_init(): already called?\n");
1332 exit(1);
1333 }
1334
1335 automachine_init();
1336 }
1337

  ViewVC Help
Powered by ViewVC 1.1.26