/[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 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (13 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 30936 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

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

  ViewVC Help
Powered by ViewVC 1.1.26