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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26