/[gxemul]/upstream/0.4.6/src/emul.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.4.6/src/emul.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (hide annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 24404 byte(s)
0.4.6
1 dpavlin 2 /*
2 dpavlin 34 * Copyright (C) 2003-2007 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 42 * $Id: emul.c,v 1.297 2007/06/15 17:02:37 debug Exp $
29 dpavlin 2 *
30     * Emulation startup and misc. routines.
31     */
32    
33     #include <signal.h>
34     #include <stdio.h>
35     #include <stdlib.h>
36     #include <limits.h>
37     #include <stdarg.h>
38     #include <string.h>
39     #include <unistd.h>
40    
41     #include "arcbios.h"
42     #include "cpu.h"
43     #include "emul.h"
44     #include "console.h"
45     #include "debugger.h"
46     #include "device.h"
47     #include "diskimage.h"
48 dpavlin 10 #include "exec_elf.h"
49 dpavlin 2 #include "machine.h"
50     #include "memory.h"
51     #include "mips_cpu_types.h"
52     #include "misc.h"
53     #include "net.h"
54 dpavlin 32 #include "settings.h"
55     #include "timer.h"
56 dpavlin 42 #include "useremul.h"
57 dpavlin 2 #include "x11.h"
58    
59    
60     extern int extra_argc;
61     extern char **extra_argv;
62    
63     extern int verbose;
64     extern int quiet_mode;
65 dpavlin 26 extern int force_debugger_at_exit;
66     extern int single_step;
67     extern int old_show_trace_tree;
68     extern int old_instruction_trace;
69     extern int old_quiet_mode;
70     extern int quiet_mode;
71 dpavlin 42 extern int native_code_translation_enabled;
72 dpavlin 2
73    
74     /*
75 dpavlin 42 * add_breakpoints():
76 dpavlin 2 *
77     * Take the strings breakpoint_string[] and convert to addresses
78     * (and store them in breakpoint_addr[]).
79     *
80     * TODO: This function should be moved elsewhere.
81     */
82 dpavlin 42 static void add_breakpoints(struct machine *m)
83 dpavlin 2 {
84     int i;
85     int string_flag;
86     uint64_t dp;
87    
88 dpavlin 42 for (i=0; i<m->breakpoints.n; i++) {
89 dpavlin 2 string_flag = 0;
90 dpavlin 42 dp = strtoull(m->breakpoints.string[i], NULL, 0);
91 dpavlin 2
92     /*
93     * If conversion resulted in 0, then perhaps it is a
94     * symbol:
95     */
96     if (dp == 0) {
97     uint64_t addr;
98     int res = get_symbol_addr(&m->symbol_context,
99 dpavlin 42 m->breakpoints.string[i], &addr);
100 dpavlin 24 if (!res) {
101 dpavlin 2 fprintf(stderr,
102 dpavlin 24 "ERROR! Breakpoint '%s' could not be"
103 dpavlin 2 " parsed\n",
104 dpavlin 42 m->breakpoints.string[i]);
105     exit(1);
106 dpavlin 24 } else {
107 dpavlin 2 dp = addr;
108     string_flag = 1;
109     }
110     }
111    
112     /*
113     * TODO: It would be nice if things like symbolname+0x1234
114     * were automatically converted into the correct address.
115     */
116    
117 dpavlin 20 if (m->arch == ARCH_MIPS) {
118     if ((dp >> 32) == 0 && ((dp >> 31) & 1))
119     dp |= 0xffffffff00000000ULL;
120     }
121    
122 dpavlin 42 m->breakpoints.addr[i] = dp;
123 dpavlin 2
124 dpavlin 20 debug("breakpoint %i: 0x%llx", i, (long long)dp);
125 dpavlin 2 if (string_flag)
126 dpavlin 42 debug(" (%s)", m->breakpoints.string[i]);
127 dpavlin 2 debug("\n");
128     }
129     }
130    
131    
132     /*
133     * fix_console():
134     */
135     static void fix_console(void)
136     {
137 dpavlin 32 console_deinit_main();
138 dpavlin 2 }
139    
140    
141     /*
142     * emul_new():
143     *
144     * Returns a reasonably initialized struct emul.
145     */
146 dpavlin 34 struct emul *emul_new(char *name, int id)
147 dpavlin 2 {
148     struct emul *e;
149    
150 dpavlin 42 CHECK_ALLOCATION(e = malloc(sizeof(struct emul)));
151 dpavlin 2 memset(e, 0, sizeof(struct emul));
152    
153 dpavlin 42 CHECK_ALLOCATION(e->path = malloc(15));
154 dpavlin 34 snprintf(e->path, 15, "emul[%i]", id);
155    
156 dpavlin 32 e->settings = settings_new();
157    
158     settings_add(e->settings, "n_machines", 0,
159     SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
160     (void *) &e->n_machines);
161    
162     /* TODO: More settings? */
163    
164 dpavlin 2 /* Sane default values: */
165     e->n_machines = 0;
166 dpavlin 10 e->next_serial_nr = 1;
167 dpavlin 2
168     if (name != NULL) {
169 dpavlin 42 CHECK_ALLOCATION(e->name = strdup(name));
170 dpavlin 32 settings_add(e->settings, "name", 0,
171     SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,
172     (void *) &e->name);
173 dpavlin 2 }
174    
175     return e;
176     }
177    
178    
179     /*
180 dpavlin 32 * emul_destroy():
181     *
182     * Destroys a previously created emul object.
183     */
184     void emul_destroy(struct emul *emul)
185     {
186     int i;
187    
188     if (emul->name != NULL) {
189     settings_remove(emul->settings, "name");
190     free(emul->name);
191     }
192    
193     for (i=0; i<emul->n_machines; i++)
194     machine_destroy(emul->machines[i]);
195    
196     if (emul->machines != NULL)
197     free(emul->machines);
198    
199     /* Remove any remaining level-1 settings: */
200     settings_remove_all(emul->settings);
201     settings_destroy(emul->settings);
202    
203     free(emul);
204     }
205    
206    
207     /*
208 dpavlin 2 * emul_add_machine():
209     *
210     * Calls machine_new(), adds the new machine into the emul struct, and
211     * returns a pointer to the new machine.
212     *
213     * This function should be used instead of manually calling machine_new().
214     */
215     struct machine *emul_add_machine(struct emul *e, char *name)
216     {
217     struct machine *m;
218 dpavlin 32 char tmpstr[20];
219     int i;
220 dpavlin 2
221 dpavlin 34 m = machine_new(name, e, e->n_machines);
222 dpavlin 2 m->serial_nr = (e->next_serial_nr ++);
223    
224 dpavlin 42 i = e->n_machines ++;
225 dpavlin 32
226 dpavlin 42 CHECK_ALLOCATION(e->machines = realloc(e->machines,
227     sizeof(struct machine *) * e->n_machines));
228 dpavlin 2
229 dpavlin 32 e->machines[i] = m;
230    
231     snprintf(tmpstr, sizeof(tmpstr), "machine[%i]", i);
232     settings_add(e->settings, tmpstr, 1, SETTINGS_TYPE_SUBSETTINGS, 0,
233     e->machines[i]->settings);
234    
235 dpavlin 2 return m;
236     }
237    
238    
239     /*
240     * add_arc_components():
241     *
242     * This function adds ARCBIOS memory descriptors for the loaded program,
243     * and ARCBIOS components for SCSI devices.
244     */
245     static void add_arc_components(struct machine *m)
246     {
247     struct cpu *cpu = m->cpus[m->bootstrap_cpu];
248     uint64_t start = cpu->pc & 0x1fffffff;
249     uint64_t len = 0xc00000 - start;
250     struct diskimage *d;
251     uint64_t scsicontroller, scsidevice, scsidisk;
252    
253     if ((cpu->pc >> 60) != 0xf) {
254     start = cpu->pc & 0xffffffffffULL;
255     len = 0xc00000 - start;
256     }
257    
258     len += 1048576 * m->memory_offset_in_mb;
259    
260 dpavlin 12 /*
261     * NOTE/TODO: magic 12MB end of load program area
262     *
263     * Hm. This breaks the old FreeBSD/MIPS snapshots...
264     */
265     #if 0
266 dpavlin 2 arcbios_add_memory_descriptor(cpu,
267     0x60000 + m->memory_offset_in_mb * 1048576,
268     start-0x60000 - m->memory_offset_in_mb * 1048576,
269     ARCBIOS_MEM_FreeMemory);
270 dpavlin 12 #endif
271 dpavlin 2 arcbios_add_memory_descriptor(cpu,
272     start, len, ARCBIOS_MEM_LoadedProgram);
273    
274 dpavlin 6 scsicontroller = arcbios_get_scsicontroller(m);
275 dpavlin 2 if (scsicontroller == 0)
276     return;
277    
278     /* TODO: The device 'name' should defined be somewhere else. */
279    
280     d = m->first_diskimage;
281     while (d != NULL) {
282     if (d->type == DISKIMAGE_SCSI) {
283     int a, b, flags = COMPONENT_FLAG_Input;
284     char component_string[100];
285     char *name = "DEC RZ58 (C) DEC2000";
286    
287     /* Read-write, or read-only? */
288     if (d->writable)
289     flags |= COMPONENT_FLAG_Output;
290     else
291     flags |= COMPONENT_FLAG_ReadOnly;
292    
293     a = COMPONENT_TYPE_DiskController;
294     b = COMPONENT_TYPE_DiskPeripheral;
295    
296     if (d->is_a_cdrom) {
297     flags |= COMPONENT_FLAG_Removable;
298     a = COMPONENT_TYPE_CDROMController;
299     b = COMPONENT_TYPE_FloppyDiskPeripheral;
300     name = "NEC CD-ROM CDR-210P 1.0 ";
301     }
302    
303     scsidevice = arcbios_addchild_manual(cpu,
304     COMPONENT_CLASS_ControllerClass,
305     a, flags, 1, 2, d->id, 0xffffffff,
306     name, scsicontroller, NULL, 0);
307    
308     scsidisk = arcbios_addchild_manual(cpu,
309     COMPONENT_CLASS_PeripheralClass,
310     b, flags, 1, 2, 0, 0xffffffff, NULL,
311     scsidevice, NULL, 0);
312    
313     /*
314     * Add device string to component address mappings:
315     * "scsi(0)disk(0)rdisk(0)partition(0)"
316     */
317    
318     if (d->is_a_cdrom) {
319     snprintf(component_string,
320     sizeof(component_string),
321     "scsi(0)cdrom(%i)", d->id);
322 dpavlin 6 arcbios_add_string_to_component(m,
323 dpavlin 2 component_string, scsidevice);
324    
325     snprintf(component_string,
326     sizeof(component_string),
327     "scsi(0)cdrom(%i)fdisk(0)", d->id);
328 dpavlin 6 arcbios_add_string_to_component(m,
329 dpavlin 2 component_string, scsidisk);
330     } else {
331     snprintf(component_string,
332     sizeof(component_string),
333     "scsi(0)disk(%i)", d->id);
334 dpavlin 6 arcbios_add_string_to_component(m,
335 dpavlin 2 component_string, scsidevice);
336    
337     snprintf(component_string,
338     sizeof(component_string),
339     "scsi(0)disk(%i)rdisk(0)", d->id);
340 dpavlin 6 arcbios_add_string_to_component(m,
341 dpavlin 2 component_string, scsidisk);
342     }
343     }
344    
345     d = d->next;
346     }
347     }
348    
349    
350     /*
351     * emul_machine_setup():
352     *
353     * o) Initialize the hardware (RAM, devices, CPUs, ...) which
354     * will be emulated in this machine.
355     *
356     * o) Load ROM code and/or other programs into emulated memory.
357     *
358     * o) Special hacks needed after programs have been loaded.
359     */
360     void emul_machine_setup(struct machine *m, int n_load, char **load_names,
361     int n_devices, char **device_names)
362     {
363     struct cpu *cpu;
364 dpavlin 22 int i, iadd = DEBUG_INDENTATION;
365 dpavlin 6 uint64_t memory_amount, entrypoint = 0, gp = 0, toc = 0;
366 dpavlin 2 int byte_order;
367    
368     debug("machine \"%s\":\n", m->name);
369     debug_indentation(iadd);
370    
371     /* For userland-only, this decides which ARCH/cpu_name to use: */
372     if (m->machine_type == MACHINE_USERLAND && m->userland_emul != NULL) {
373     useremul_name_to_useremul(NULL, m->userland_emul,
374     &m->arch, &m->machine_name, &m->cpu_name);
375     if (m->arch == ARCH_NOARCH) {
376     printf("Unsupported userland emulation mode.\n");
377     exit(1);
378     }
379     }
380    
381     if (m->machine_type == MACHINE_NONE) {
382     fatal("No machine type specified?\n");
383     exit(1);
384     }
385    
386     m->cpu_family = cpu_family_ptr_by_number(m->arch);
387    
388 dpavlin 12 if (m->arch == ARCH_ALPHA)
389     m->arch_pagesize = 8192;
390    
391 dpavlin 2 machine_memsize_fix(m);
392    
393     /*
394     * Create the system's memory:
395     *
396     * (Don't print the amount for userland-only emulation; the
397     * size doesn't matter.)
398     */
399     if (m->machine_type != MACHINE_USERLAND)
400     debug("memory: %i MB", m->physical_ram_in_mb);
401     memory_amount = (uint64_t)m->physical_ram_in_mb * 1048576;
402     if (m->memory_offset_in_mb > 0) {
403     /*
404     * A special hack is used for some SGI models,
405     * where memory is offset by 128MB to leave room for
406     * EISA space and other things.
407     */
408     debug(" (offset by %iMB)", m->memory_offset_in_mb);
409     memory_amount += 1048576 * m->memory_offset_in_mb;
410     }
411 dpavlin 12 m->memory = memory_new(memory_amount, m->arch);
412 dpavlin 2 if (m->machine_type != MACHINE_USERLAND)
413     debug("\n");
414    
415     /* Create CPUs: */
416     if (m->cpu_name == NULL)
417     machine_default_cputype(m);
418     if (m->ncpus == 0) {
419     /* TODO: This should be moved elsewhere... */
420     if (m->machine_type == MACHINE_BEBOX)
421     m->ncpus = 2;
422     else
423     m->ncpus = 1;
424     }
425 dpavlin 42
426     CHECK_ALLOCATION(m->cpus = malloc(sizeof(struct cpu *) * m->ncpus));
427 dpavlin 2 memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
428    
429     debug("cpu0");
430     if (m->ncpus > 1)
431     debug(" .. cpu%i", m->ncpus - 1);
432     debug(": ");
433     for (i=0; i<m->ncpus; i++) {
434     m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
435 dpavlin 24 if (m->cpus[i] == NULL) {
436     fprintf(stderr, "Unable to create CPU object. "
437     "Aborting.");
438     exit(1);
439     }
440 dpavlin 2 }
441     debug("\n");
442    
443     if (m->use_random_bootstrap_cpu)
444     m->bootstrap_cpu = random() % m->ncpus;
445     else
446     m->bootstrap_cpu = 0;
447    
448     cpu = m->cpus[m->bootstrap_cpu];
449    
450     /* Set cpu->useremul_syscall, and use userland_memory_rw: */
451     if (m->userland_emul != NULL) {
452     useremul_name_to_useremul(cpu,
453     m->userland_emul, NULL, NULL, NULL);
454 dpavlin 12
455     switch (m->arch) {
456 dpavlin 42
457 dpavlin 12 case ARCH_ALPHA:
458     cpu->memory_rw = alpha_userland_memory_rw;
459     break;
460 dpavlin 42
461     default:
462     cpu->memory_rw = userland_memory_rw;
463 dpavlin 12 }
464 dpavlin 2 }
465    
466 dpavlin 42 if (m->x11_md.in_use)
467 dpavlin 2 x11_init(m);
468    
469     /* Fill memory with random bytes: */
470     if (m->random_mem_contents) {
471     for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {
472     unsigned char data[256];
473     unsigned int j;
474     for (j=0; j<sizeof(data); j++)
475     data[j] = random() & 255;
476 dpavlin 6 cpu->memory_rw(cpu, m->memory, i, data, sizeof(data),
477     MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS | PHYSICAL);
478 dpavlin 2 }
479     }
480    
481     if (m->userland_emul != NULL) {
482     /*
483     * For userland-only emulation, no machine emulation
484     * is needed.
485     */
486     } else {
487     for (i=0; i<n_devices; i++)
488     device_add(m, device_names[i]);
489    
490     machine_setup(m);
491     }
492    
493     diskimage_dump_info(m);
494 dpavlin 22 console_debug_dump(m);
495 dpavlin 2
496     /* Load files (ROM code, boot code, ...) into memory: */
497     if (n_load == 0) {
498 dpavlin 6 if (m->first_diskimage != NULL) {
499     if (!load_bootblock(m, cpu, &n_load, &load_names)) {
500     fprintf(stderr, "\nNo executable files were"
501     " specified, and booting directly from disk"
502     " failed.\n");
503     exit(1);
504     }
505     } else {
506 dpavlin 2 fprintf(stderr, "No executable file(s) loaded, and "
507     "we are not booting directly from a disk image."
508     "\nAborting.\n");
509     exit(1);
510     }
511     }
512    
513     while (n_load > 0) {
514 dpavlin 6 FILE *tmp_f;
515     char *name_to_load = *load_names;
516     int remove_after_load = 0;
517    
518     /* Special hack for removing temporary files: */
519     if (name_to_load[0] == 8) {
520     name_to_load ++;
521     remove_after_load = 1;
522     }
523    
524     /*
525 dpavlin 10 * gzipped files are automagically gunzipped:
526     * NOTE/TODO: This isn't secure. system() is used.
527 dpavlin 6 */
528     tmp_f = fopen(name_to_load, "r");
529     if (tmp_f != NULL) {
530     unsigned char buf[2]; /* gzip header */
531     memset(buf, 0, sizeof(buf));
532     fread(buf, 1, sizeof(buf), tmp_f);
533     if (buf[0]==0x1f && buf[1]==0x8b) {
534 dpavlin 10 size_t zzlen = strlen(name_to_load)*2 + 100;
535 dpavlin 42 char *zz;
536    
537     CHECK_ALLOCATION(zz = malloc(zzlen));
538 dpavlin 6 debug("gunziping %s\n", name_to_load);
539 dpavlin 42
540 dpavlin 10 /*
541     * gzip header found. If this was a file
542     * extracted from, say, a CDROM image, then it
543     * already has a temporary name. Otherwise we
544     * have to gunzip into a temporary file.
545     */
546     if (remove_after_load) {
547     snprintf(zz, zzlen, "mv %s %s.gz",
548     name_to_load, name_to_load);
549     system(zz);
550     snprintf(zz, zzlen, "gunzip %s.gz",
551     name_to_load);
552     system(zz);
553     } else {
554     /* gunzip into new temp file: */
555     int tmpfile_handle;
556 dpavlin 42 char *new_temp_name;
557     CHECK_ALLOCATION(new_temp_name =
558     strdup("/tmp/gxemul.XXXXXXXXXXXX"));
559 dpavlin 10 tmpfile_handle = mkstemp(new_temp_name);
560     close(tmpfile_handle);
561     snprintf(zz, zzlen, "gunzip -c '%s' > "
562     "%s", name_to_load, new_temp_name);
563     system(zz);
564     name_to_load = new_temp_name;
565     remove_after_load = 1;
566     }
567 dpavlin 6 free(zz);
568     }
569     fclose(tmp_f);
570     }
571    
572 dpavlin 2 byte_order = NO_BYTE_ORDER_OVERRIDE;
573    
574 dpavlin 6 /*
575     * Load the file: :-)
576     */
577     file_load(m, m->memory, name_to_load, &entrypoint,
578 dpavlin 2 m->arch, &gp, &byte_order, &toc);
579    
580 dpavlin 6 if (remove_after_load) {
581     debug("removing %s\n", name_to_load);
582     unlink(name_to_load);
583     }
584    
585 dpavlin 2 if (byte_order != NO_BYTE_ORDER_OVERRIDE)
586     cpu->byte_order = byte_order;
587    
588     cpu->pc = entrypoint;
589    
590     switch (m->arch) {
591 dpavlin 14
592     case ARCH_ALPHA:
593 dpavlin 18 /* For position-independent code: */
594 dpavlin 14 cpu->cd.alpha.r[ALPHA_T12] = cpu->pc;
595     break;
596    
597     case ARCH_ARM:
598 dpavlin 20 if (cpu->pc & 3) {
599     fatal("ARM: lowest bits of pc set: TODO\n");
600     exit(1);
601     }
602 dpavlin 14 cpu->pc &= 0xfffffffc;
603     break;
604    
605 dpavlin 42 case ARCH_M88K:
606     if (cpu->pc & 3) {
607     fatal("M88K: lowest bits of pc set: TODO\n");
608 dpavlin 14 exit(1);
609     }
610 dpavlin 42 cpu->pc &= 0xfffffffc;
611 dpavlin 14 break;
612    
613 dpavlin 2 case ARCH_MIPS:
614 dpavlin 20 if ((cpu->pc >> 32) == 0 && (cpu->pc & 0x80000000ULL))
615 dpavlin 2 cpu->pc |= 0xffffffff00000000ULL;
616    
617     cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;
618    
619     if ((cpu->cd.mips.gpr[MIPS_GPR_GP] >> 32) == 0 &&
620     (cpu->cd.mips.gpr[MIPS_GPR_GP] & 0x80000000ULL))
621     cpu->cd.mips.gpr[MIPS_GPR_GP] |=
622     0xffffffff00000000ULL;
623     break;
624 dpavlin 4
625 dpavlin 2 case ARCH_PPC:
626 dpavlin 6 /* See http://www.linuxbase.org/spec/ELF/ppc64/
627     spec/x458.html for more info. */
628 dpavlin 2 cpu->cd.ppc.gpr[2] = toc;
629 dpavlin 6 /* TODO */
630 dpavlin 14 if (cpu->cd.ppc.bits == 32)
631     cpu->pc &= 0xffffffffULL;
632 dpavlin 2 break;
633 dpavlin 4
634 dpavlin 14 case ARCH_SH:
635 dpavlin 30 if (cpu->cd.sh.cpu_type.bits == 32)
636 dpavlin 14 cpu->pc &= 0xffffffffULL;
637     cpu->pc &= ~1;
638 dpavlin 12 break;
639    
640 dpavlin 2 case ARCH_SPARC:
641     break;
642 dpavlin 4
643 dpavlin 2 default:
644     fatal("emul_machine_setup(): Internal error: "
645     "Unimplemented arch %i\n", m->arch);
646     exit(1);
647     }
648    
649     /*
650     * For userland emulation, the remaining items
651     * on the command line will be passed as parameters
652     * to the emulated program, and will not be treated
653     * as filenames to load into the emulator.
654     * The program's name will be in load_names[0], and the
655     * rest of the parameters in load_names[1] and up.
656     */
657     if (m->userland_emul != NULL)
658     break;
659    
660     n_load --;
661     load_names ++;
662     }
663    
664     if (m->byte_order_override != NO_BYTE_ORDER_OVERRIDE)
665     cpu->byte_order = m->byte_order_override;
666    
667     /* Same byte order and entrypoint for all CPUs: */
668     for (i=0; i<m->ncpus; i++)
669     if (i != m->bootstrap_cpu) {
670     m->cpus[i]->byte_order = cpu->byte_order;
671     m->cpus[i]->pc = cpu->pc;
672     }
673    
674     if (m->userland_emul != NULL)
675     useremul_setup(cpu, n_load, load_names);
676    
677     /* Startup the bootstrap CPU: */
678 dpavlin 30 cpu->running = 1;
679 dpavlin 2
680     /* ... or pause all CPUs, if start_paused is set: */
681     if (m->start_paused) {
682     for (i=0; i<m->ncpus; i++)
683     m->cpus[i]->running = 0;
684     }
685    
686 dpavlin 42 /* Parse and add breakpoints: */
687     add_breakpoints(m);
688 dpavlin 2
689     /* TODO: This is MIPS-specific! */
690 dpavlin 22 if (m->machine_type == MACHINE_PMAX &&
691 dpavlin 2 cpu->cd.mips.cpu_type.mmu_model == MMU3K)
692     add_symbol_name(&m->symbol_context,
693 dpavlin 12 0x9fff0000, 0x10000, "r2k3k_cache", 0, 0);
694 dpavlin 2
695     symbol_recalc_sizes(&m->symbol_context);
696    
697     /* Special hack for ARC/SGI emulation: */
698     if ((m->machine_type == MACHINE_ARC ||
699     m->machine_type == MACHINE_SGI) && m->prom_emulation)
700     add_arc_components(m);
701    
702     debug("starting cpu%i at ", m->bootstrap_cpu);
703     switch (m->arch) {
704 dpavlin 14
705     case ARCH_ARM:
706     /* ARM cpus aren't 64-bit: */
707 dpavlin 38 debug("0x%08"PRIx32, (uint32_t) entrypoint);
708 dpavlin 14 break;
709    
710 dpavlin 2 case ARCH_MIPS:
711 dpavlin 12 if (cpu->is_32bit) {
712 dpavlin 38 debug("0x%08"PRIx32, (uint32_t)
713     m->cpus[m->bootstrap_cpu]->pc);
714 dpavlin 2 if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
715 dpavlin 38 debug(" (gp=0x%08"PRIx32")", (uint32_t)
716     m->cpus[m->bootstrap_cpu]->cd.mips.gpr[
717 dpavlin 2 MIPS_GPR_GP]);
718     } else {
719 dpavlin 38 debug("0x%016"PRIx64, (uint64_t)
720     m->cpus[m->bootstrap_cpu]->pc);
721 dpavlin 2 if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
722 dpavlin 38 debug(" (gp=0x%016"PRIx64")", (uint64_t)
723 dpavlin 2 cpu->cd.mips.gpr[MIPS_GPR_GP]);
724     }
725     break;
726 dpavlin 14
727 dpavlin 2 case ARCH_PPC:
728     if (cpu->cd.ppc.bits == 32)
729 dpavlin 38 debug("0x%08"PRIx32, (uint32_t) entrypoint);
730 dpavlin 2 else
731 dpavlin 38 debug("0x%016"PRIx64, (uint64_t) entrypoint);
732 dpavlin 2 break;
733 dpavlin 14
734 dpavlin 2 default:
735 dpavlin 22 if (cpu->is_32bit)
736 dpavlin 38 debug("0x%08"PRIx32, (uint32_t) cpu->pc);
737 dpavlin 22 else
738 dpavlin 38 debug("0x%016"PRIx64, (uint64_t) cpu->pc);
739 dpavlin 2 }
740     debug("\n");
741    
742     debug_indentation(-iadd);
743     }
744    
745    
746     /*
747     * emul_dumpinfo():
748     *
749     * Dump info about all machines in an emul.
750     */
751     void emul_dumpinfo(struct emul *e)
752     {
753 dpavlin 22 int j, nm, iadd = DEBUG_INDENTATION;
754 dpavlin 2
755     if (e->net != NULL)
756     net_dumpinfo(e->net);
757    
758     nm = e->n_machines;
759     for (j=0; j<nm; j++) {
760     debug("machine %i: \"%s\"\n", j, e->machines[j]->name);
761     debug_indentation(iadd);
762     machine_dumpinfo(e->machines[j]);
763     debug_indentation(-iadd);
764     }
765     }
766    
767    
768     /*
769     * emul_simple_init():
770     *
771     * For a normal setup:
772     *
773     * o) Initialize a network.
774     * o) Initialize one machine.
775     *
776     * For a userland-only setup:
777     *
778     * o) Initialize a "pseudo"-machine.
779     */
780     void emul_simple_init(struct emul *emul)
781     {
782 dpavlin 22 int iadd = DEBUG_INDENTATION;
783 dpavlin 2 struct machine *m;
784    
785     if (emul->n_machines != 1) {
786     fprintf(stderr, "emul_simple_init(): n_machines != 1\n");
787     exit(1);
788     }
789    
790     m = emul->machines[0];
791    
792     if (m->userland_emul == NULL) {
793     debug("Simple setup...\n");
794     debug_indentation(iadd);
795    
796 dpavlin 10 /* Create a simple network: */
797 dpavlin 2 emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
798 dpavlin 32 NET_DEFAULT_IPV4_MASK,
799     NET_DEFAULT_IPV4_LEN,
800     NULL, 0, 0, NULL);
801 dpavlin 2 } else {
802     /* Userland pseudo-machine: */
803     debug("Syscall emulation (userland-only) setup...\n");
804     debug_indentation(iadd);
805     }
806    
807     /* Create the machine: */
808     emul_machine_setup(m, extra_argc, extra_argv, 0, NULL);
809    
810     debug_indentation(-iadd);
811     }
812    
813    
814     /*
815     * emul_create_from_configfile():
816     *
817     * Create an emul struct by reading settings from a configuration file.
818     */
819 dpavlin 34 struct emul *emul_create_from_configfile(char *fname, int id)
820 dpavlin 2 {
821 dpavlin 22 int iadd = DEBUG_INDENTATION;
822 dpavlin 34 struct emul *e = emul_new(fname, id);
823 dpavlin 2
824     debug("Creating emulation from configfile \"%s\":\n", fname);
825     debug_indentation(iadd);
826    
827 dpavlin 24 emul_parse_config(e, fname);
828 dpavlin 2
829     debug_indentation(-iadd);
830     return e;
831     }
832    
833    
834     /*
835     * emul_run():
836     *
837     * o) Set up things needed before running emulations.
838     *
839     * o) Run emulations (one or more, in parallel).
840     *
841     * o) De-initialize things.
842     */
843     void emul_run(struct emul **emuls, int n_emuls)
844     {
845     struct emul *e;
846     int i = 0, j, go = 1, n, anything;
847    
848     if (n_emuls < 1) {
849     fprintf(stderr, "emul_run(): no thing to do\n");
850     return;
851     }
852    
853     atexit(fix_console);
854    
855     /* Initialize the interactive debugger: */
856     debugger_init(emuls, n_emuls);
857    
858 dpavlin 22 /* Run any additional debugger commands before starting: */
859     for (i=0; i<n_emuls; i++) {
860     struct emul *emul = emuls[i];
861     if (emul->n_debugger_cmds > 0) {
862     int j;
863     if (i == 0)
864 dpavlin 42 print_separator_line();
865 dpavlin 22 for (j = 0; j < emul->n_debugger_cmds; j ++) {
866     debug("> %s\n", emul->debugger_cmds[j]);
867     debugger_execute_cmd(emul->debugger_cmds[j],
868     strlen(emul->debugger_cmds[j]));
869     }
870     }
871     }
872    
873 dpavlin 42 print_separator_line();
874 dpavlin 22 debug("\n");
875    
876    
877 dpavlin 2 /*
878     * console_init_main() makes sure that the terminal is in a
879     * reasonable state.
880     *
881     * The SIGINT handler is for CTRL-C (enter the interactive debugger).
882     *
883     * The SIGCONT handler is invoked whenever the user presses CTRL-Z
884     * (or sends SIGSTOP) and then continues. It makes sure that the
885     * terminal is in an expected state.
886     */
887     console_init_main(emuls[0]); /* TODO: what is a good argument? */
888     signal(SIGINT, debugger_activate);
889     signal(SIGCONT, console_sigcont);
890    
891     /* Not in verbose mode? Then set quiet_mode. */
892     if (!verbose)
893     quiet_mode = 1;
894    
895     /* Initialize all CPUs in all machines in all emulations: */
896     for (i=0; i<n_emuls; i++) {
897     e = emuls[i];
898     if (e == NULL)
899     continue;
900     for (j=0; j<e->n_machines; j++)
901 dpavlin 12 cpu_run_init(e->machines[j]);
902 dpavlin 2 }
903    
904 dpavlin 12 /* TODO: Generalize: */
905     if (emuls[0]->machines[0]->show_trace_tree)
906     cpu_functioncall_trace(emuls[0]->machines[0]->cpus[0],
907     emuls[0]->machines[0]->cpus[0]->pc);
908    
909 dpavlin 32 /* Start emulated clocks: */
910     timer_start();
911    
912 dpavlin 2 /*
913     * MAIN LOOP:
914     *
915 dpavlin 42 * Run all emulations in parallel, running instructions from each
916     * cpu in each machine in each emulation.
917 dpavlin 2 */
918     while (go) {
919 dpavlin 42 struct cpu *bootcpu = emuls[0]->machines[0]->cpus[
920     emuls[0]->machines[0]->bootstrap_cpu];
921    
922 dpavlin 2 go = 0;
923    
924 dpavlin 26 /* Flush X11 and serial console output every now and then: */
925 dpavlin 42 if (bootcpu->ninstrs > bootcpu->ninstrs_flush + (1<<19)) {
926 dpavlin 26 x11_check_event(emuls, n_emuls);
927     console_flush();
928 dpavlin 42 bootcpu->ninstrs_flush = bootcpu->ninstrs;
929 dpavlin 26 }
930 dpavlin 2
931 dpavlin 42 if (bootcpu->ninstrs > bootcpu->ninstrs_show + (1<<25)) {
932     bootcpu->ninstrs_since_gettimeofday +=
933     (bootcpu->ninstrs - bootcpu->ninstrs_show);
934 dpavlin 26 cpu_show_cycles(emuls[0]->machines[0], 0);
935 dpavlin 42 bootcpu->ninstrs_show = bootcpu->ninstrs;
936 dpavlin 26 }
937 dpavlin 2
938 dpavlin 26 if (single_step == ENTER_SINGLE_STEPPING) {
939     /* TODO: Cleanup! */
940     old_instruction_trace =
941     emuls[0]->machines[0]->instruction_trace;
942     old_quiet_mode = quiet_mode;
943     old_show_trace_tree =
944     emuls[0]->machines[0]->show_trace_tree;
945     emuls[0]->machines[0]->instruction_trace = 1;
946     emuls[0]->machines[0]->show_trace_tree = 1;
947     quiet_mode = 0;
948     single_step = SINGLE_STEPPING;
949     }
950 dpavlin 24
951 dpavlin 26 if (single_step == SINGLE_STEPPING)
952     debugger();
953    
954 dpavlin 32 for (i=0; i<n_emuls; i++) {
955     e = emuls[i];
956 dpavlin 26
957 dpavlin 32 for (j=0; j<e->n_machines; j++) {
958     anything = machine_run(e->machines[j]);
959     if (anything)
960     go = 1;
961     }
962 dpavlin 2 }
963     }
964    
965 dpavlin 32 /* Stop any running timers: */
966     timer_stop();
967    
968 dpavlin 2 /* Deinitialize all CPUs in all machines in all emulations: */
969     for (i=0; i<n_emuls; i++) {
970     e = emuls[i];
971     if (e == NULL)
972     continue;
973     for (j=0; j<e->n_machines; j++)
974 dpavlin 12 cpu_run_deinit(e->machines[j]);
975 dpavlin 2 }
976    
977     /* force_debugger_at_exit flag set? Then enter the debugger: */
978     if (force_debugger_at_exit) {
979     quiet_mode = 0;
980     debugger_reset();
981     debugger();
982     }
983    
984 dpavlin 32 /* Any machine using X11? Then wait before exiting: */
985 dpavlin 2 n = 0;
986     for (i=0; i<n_emuls; i++)
987     for (j=0; j<emuls[i]->n_machines; j++)
988 dpavlin 42 if (emuls[i]->machines[j]->x11_md.in_use)
989 dpavlin 2 n++;
990     if (n > 0) {
991     printf("Press enter to quit.\n");
992     while (!console_charavail(MAIN_CONSOLE)) {
993     x11_check_event(emuls, n_emuls);
994 dpavlin 32 usleep(10000);
995 dpavlin 2 }
996     console_readchar(MAIN_CONSOLE);
997     }
998    
999 dpavlin 32 console_deinit_main();
1000 dpavlin 2 }
1001    

  ViewVC Help
Powered by ViewVC 1.1.26