/[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

Annotation of /trunk/src/machine.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (hide annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 6 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 dpavlin 2 /*
2 dpavlin 22 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 dpavlin 2 *
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 dpavlin 26 * $Id: machine.c,v 1.673 2006/06/24 19:52:27 debug Exp $
29 dpavlin 2 */
30    
31     #include <stdio.h>
32     #include <stdlib.h>
33     #include <stdarg.h>
34     #ifdef SOLARIS
35 dpavlin 22 /* TODO: is this strings vs string separation really necessary? */
36 dpavlin 2 #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 dpavlin 20 #include "bus_isa.h"
45 dpavlin 2 #include "bus_pci.h"
46     #include "cpu.h"
47 dpavlin 26 #include "debugger.h"
48 dpavlin 2 #include "device.h"
49     #include "devices.h"
50     #include "diskimage.h"
51     #include "emul.h"
52     #include "machine.h"
53 dpavlin 22 #include "machine_interrupts.h"
54 dpavlin 2 #include "memory.h"
55     #include "misc.h"
56     #include "net.h"
57     #include "symbol.h"
58    
59 dpavlin 12
60 dpavlin 6 /* See main.c: */
61     extern int quiet_mode;
62 dpavlin 22 extern int verbose;
63 dpavlin 6
64    
65 dpavlin 2 /* This is initialized by machine_init(): */
66 dpavlin 22 struct machine_entry *first_machine_entry = NULL;
67 dpavlin 2
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 dpavlin 10 m->serial_nr = 1;
92 dpavlin 2 m->machine_type = MACHINE_NONE;
93     m->machine_subtype = MACHINE_NONE;
94 dpavlin 12 m->arch_pagesize = 4096; /* Should be overriden in
95     emul.c for other pagesizes. */
96     m->dyntrans_alignment_check = 1;
97 dpavlin 2 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 dpavlin 20 m->x11_scaleup = 1;
105 dpavlin 2 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 dpavlin 12 int i, j, k, nmatches = 0;
128 dpavlin 2
129     *type = MACHINE_NONE;
130     *subtype = 0;
131    
132 dpavlin 12 /* Check stype, and optionally ssubtype: */
133 dpavlin 2 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 dpavlin 6 fatal("Unknown subtype '%s' for emulation"
157 dpavlin 2 " '%s'\n", ssubtype, stype);
158 dpavlin 6 if (!ssubtype[0])
159     fatal("(Maybe you forgot the -e"
160     " command line option?)\n");
161 dpavlin 2 exit(1);
162     }
163    
164     me = me->next;
165     }
166    
167 dpavlin 12 /* 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 dpavlin 2 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 dpavlin 24 *
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 dpavlin 2 */
225     void machine_add_tickfunction(struct machine *machine, void (*func)
226 dpavlin 24 (struct cpu *, void *), void *extra, int tickshift, double hz)
227 dpavlin 2 {
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 dpavlin 24 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 dpavlin 2
250     machine->ticks_till_next[n] = 0;
251 dpavlin 24 machine->ticks_reset_value[n] = 1 << tickshift;
252 dpavlin 2 machine->tick_func[n] = func;
253     machine->tick_extra[n] = extra;
254 dpavlin 24 machine->tick_hz[n] = hz;
255 dpavlin 2
256     machine->n_tick_entries ++;
257     }
258    
259    
260 dpavlin 22 /*
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 dpavlin 2
270 dpavlin 22 new = zeroed_alloc(sizeof(struct machine_bus));
271     new->name = strdup(busname);
272     new->debug_dump = debug_dump;
273     new->extra = extra;
274 dpavlin 2
275 dpavlin 22 /* 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 dpavlin 2 {
298 dpavlin 22 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 dpavlin 2 }
310    
311    
312     /*
313 dpavlin 22 * 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 dpavlin 2 * 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 dpavlin 12 * 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 dpavlin 2 * 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 dpavlin 14 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
520 dpavlin 2 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 dpavlin 14 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
545 dpavlin 2 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 dpavlin 22 size_t psize = 1024; /* 1024 256 64 16 4 1 */
564 dpavlin 6
565 dpavlin 14 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
566 dpavlin 2 addr = (int64_t)(int32_t)addr;
567    
568 dpavlin 6 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 dpavlin 2 }
579 dpavlin 6 psize >>= 2;
580 dpavlin 2 }
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 dpavlin 22 * target address. (Useful for e.g. ARCBIOS environment initialization.)
592 dpavlin 2 */
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 dpavlin 14 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
619 dpavlin 2 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 dpavlin 4 * 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 dpavlin 14 if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)
643 dpavlin 4 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 dpavlin 2 * 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 dpavlin 22 struct machine_entry *me;
730 dpavlin 2
731     /* Abreviation: :-) */
732     struct cpu *cpu = machine->cpus[machine->bootstrap_cpu];
733    
734 dpavlin 22 machine->bootdev_id = diskimage_bootdev(machine,
735     &machine->bootdev_type);
736 dpavlin 2
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 dpavlin 16 case MACHINE_CATS:
747     machine->boot_string_argument = "-A";
748     break;
749 dpavlin 22 case MACHINE_PMAX:
750 dpavlin 2 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 dpavlin 22 /*
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 dpavlin 2
765 dpavlin 22 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 dpavlin 2 break;
771     }
772 dpavlin 22 me = me->next;
773     }
774 dpavlin 2
775 dpavlin 22 if (me == NULL) {
776 dpavlin 2 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 dpavlin 20 /* Default fake speed: 5 MHz */
788 dpavlin 2 if (machine->emulated_hz < 1)
789 dpavlin 20 machine->emulated_hz = 5000000;
790 dpavlin 2
791 dpavlin 22 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 dpavlin 2 debug("\n");
798     }
799 dpavlin 22
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 dpavlin 2 }
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 dpavlin 22 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 dpavlin 2 break;
832     }
833 dpavlin 22 me = me->next;
834 dpavlin 2 }
835     }
836    
837 dpavlin 6 /* Special hack for hpcmips machines: */
838     if (m->machine_type == MACHINE_HPCMIPS) {
839 dpavlin 2 m->dbe_on_nonexistant_memaccess = 0;
840     }
841    
842 dpavlin 22 /* Special SGI memory offsets: (TODO: move this somewhere else) */
843 dpavlin 2 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 dpavlin 22 * Sets m->cpu_name, if it isn't already set, depending on the machine type.
867 dpavlin 2 */
868     void machine_default_cputype(struct machine *m)
869     {
870 dpavlin 22 struct machine_entry *me;
871    
872 dpavlin 2 if (m == NULL) {
873     fatal("machine_default_cputype(): m == NULL?\n");
874     exit(1);
875     }
876    
877 dpavlin 22 /* Already set? Then return. */
878 dpavlin 2 if (m->cpu_name != NULL)
879     return;
880    
881 dpavlin 22 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 dpavlin 2 break;
887     }
888 dpavlin 22 me = me->next;
889 dpavlin 2 }
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 dpavlin 26 /*****************************************************************************/
901    
902    
903 dpavlin 2 /*
904 dpavlin 26 * 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 dpavlin 2 * 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 dpavlin 26 * passed as arguments to this function, such as alias names and machine
968     * subtypes.
969 dpavlin 2 */
970 dpavlin 26 struct machine_entry *machine_entry_new(const char *name, int arch,
971     int oldstyle_type)
972 dpavlin 2 {
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 dpavlin 26 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 dpavlin 2 if (me->aliases == NULL) {
1005 dpavlin 26 fprintf(stderr, "out of memory\n");
1006 dpavlin 2 exit(1);
1007     }
1008    
1009 dpavlin 26 me->aliases[me->n_aliases - 1] = (char *) name;
1010 dpavlin 2 }
1011    
1012    
1013     /*
1014 dpavlin 26 * machine_entry_add_subtype():
1015 dpavlin 2 *
1016 dpavlin 26 * 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 dpavlin 2 *
1019 dpavlin 26 * machine_entry_add_subtype(me, "Machine X", MACHINE_X,
1020     * "machine-x", "x", NULL);
1021 dpavlin 2 */
1022 dpavlin 26 void machine_entry_add_subtype(struct machine_entry *me, const char *name,
1023     int oldstyle_subtype, ...)
1024 dpavlin 2 {
1025 dpavlin 26 va_list argp;
1026 dpavlin 2 struct machine_entry_subtype *mes;
1027    
1028 dpavlin 26 /* Allocate a new subtype struct: */
1029 dpavlin 2 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 dpavlin 26 /* 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 dpavlin 2 memset(mes, 0, sizeof(struct machine_entry_subtype));
1048     mes->name = name;
1049 dpavlin 26 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 dpavlin 2 }
1072    
1073 dpavlin 26 va_end(argp);
1074 dpavlin 2 }
1075    
1076    
1077     /*
1078 dpavlin 26 * machine_entry_register():
1079 dpavlin 22 *
1080     * Inserts a new machine_entry into the machine entries list.
1081     */
1082 dpavlin 26 void machine_entry_register(struct machine_entry *me, int arch)
1083 dpavlin 22 {
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 dpavlin 2 * 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 dpavlin 22 int iadd = DEBUG_INDENTATION * 2;
1122 dpavlin 2
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 dpavlin 22 int i, j, iadd = DEBUG_INDENTATION;
1142 dpavlin 2
1143 dpavlin 22 debug("%s [%s] (", me->name,
1144     cpu_family_ptr_by_number(me->arch)->name);
1145 dpavlin 2 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 dpavlin 20 "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 dpavlin 2
1171 dpavlin 24 #ifdef UNSTABLE_DEVEL
1172 dpavlin 2 debug("\n");
1173    
1174     useremul_list_emuls();
1175 dpavlin 12 debug("Userland emulation works for programs with the complexity"
1176     " of Hello World,\nbut not much more.\n");
1177 dpavlin 24 #endif
1178 dpavlin 2 }
1179    
1180    
1181     /*
1182     * machine_init():
1183     *
1184     * This function should be called before any other machine_*() function
1185 dpavlin 22 * is used. automachine_init() registers all machines in src/machines/.
1186 dpavlin 2 */
1187     void machine_init(void)
1188     {
1189 dpavlin 22 if (first_machine_entry != NULL) {
1190     fatal("machine_init(): already called?\n");
1191     exit(1);
1192 dpavlin 14 }
1193    
1194 dpavlin 22 automachine_init();
1195 dpavlin 2 }
1196    

  ViewVC Help
Powered by ViewVC 1.1.26