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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26