/[gxemul]/upstream/0.4.4/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.4/src/machine.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26