/[gxemul]/trunk/src/machine.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/machine.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 29399 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26