/[gxemul]/trunk/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

Diff of /trunk/src/emul.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2 by dpavlin, Mon Oct 8 16:17:48 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: emul.c,v 1.179 2005/03/14 19:14:04 debug Exp $   *  $Id: emul.c,v 1.272 2006/10/31 08:26:56 debug Exp $
29   *   *
30   *  Emulation startup and misc. routines.   *  Emulation startup and misc. routines.
31   */   */
# Line 39  Line 39 
39  #include <unistd.h>  #include <unistd.h>
40    
41  #include "arcbios.h"  #include "arcbios.h"
 #include "bintrans.h"  
42  #include "cpu.h"  #include "cpu.h"
 #include "cpu_mips.h"  
43  #include "emul.h"  #include "emul.h"
44  #include "console.h"  #include "console.h"
45  #include "debugger.h"  #include "debugger.h"
46  #include "device.h"  #include "device.h"
47  #include "diskimage.h"  #include "diskimage.h"
48    #include "exec_elf.h"
49  #include "machine.h"  #include "machine.h"
50  #include "memory.h"  #include "memory.h"
51  #include "mips_cpu_types.h"  #include "mips_cpu_types.h"
52  #include "misc.h"  #include "misc.h"
53  #include "net.h"  #include "net.h"
54    #include "settings.h"
55  #include "sgi_arcbios.h"  #include "sgi_arcbios.h"
56    #include "timer.h"
57  #include "x11.h"  #include "x11.h"
58    
59    
 extern int force_debugger_at_exit;  
   
60  extern int extra_argc;  extern int extra_argc;
61  extern char **extra_argv;  extern char **extra_argv;
62    
63  extern int verbose;  extern int verbose;
64  extern int quiet_mode;  extern int quiet_mode;
65    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    
72  extern struct emul *debugger_emul;  extern struct emul *debugger_emul;
73  extern struct diskimage *diskimages[];  extern struct diskimage *diskimages[];
74    
75    static char *diskimage_types[] = DISKIMAGE_TYPES;
76    
77    
78    static void print_separator(void)
79    {
80            int i = 79;
81            while (i-- > 0)
82                    debug("-");
83            debug("\n");
84    }
85    
86    
87  /*  /*
88   *  add_dump_points():   *  add_dump_points():
# Line 94  static void add_dump_points(struct machi Line 110  static void add_dump_points(struct machi
110                          uint64_t addr;                          uint64_t addr;
111                          int res = get_symbol_addr(&m->symbol_context,                          int res = get_symbol_addr(&m->symbol_context,
112                              m->breakpoint_string[i], &addr);                              m->breakpoint_string[i], &addr);
113                          if (!res)                          if (!res) {
114                                  fprintf(stderr,                                  fprintf(stderr,
115                                      "WARNING! Breakpoint '%s' could not be"                                      "ERROR! Breakpoint '%s' could not be"
116                                          " parsed\n",                                          " parsed\n",
117                                      m->breakpoint_string[i]);                                      m->breakpoint_string[i]);
118                          else {                          } else {
119                                  dp = addr;                                  dp = addr;
120                                  string_flag = 1;                                  string_flag = 1;
121                          }                          }
# Line 110  static void add_dump_points(struct machi Line 126  static void add_dump_points(struct machi
126                   *  were automatically converted into the correct address.                   *  were automatically converted into the correct address.
127                   */                   */
128    
129                  if ((dp >> 32) == 0 && ((dp >> 31) & 1))                  if (m->arch == ARCH_MIPS) {
130                          dp |= 0xffffffff00000000ULL;                          if ((dp >> 32) == 0 && ((dp >> 31) & 1))
131                                    dp |= 0xffffffff00000000ULL;
132                    }
133    
134                  m->breakpoint_addr[i] = dp;                  m->breakpoint_addr[i] = dp;
135    
136                  debug("breakpoint %i: 0x%016llx", i, (long long)dp);                  debug("breakpoint %i: 0x%llx", i, (long long)dp);
137                  if (string_flag)                  if (string_flag)
138                          debug(" (%s)", m->breakpoint_string[i]);                          debug(" (%s)", m->breakpoint_string[i]);
139                  debug("\n");                  debug("\n");
# Line 127  static void add_dump_points(struct machi Line 146  static void add_dump_points(struct machi
146   */   */
147  static void fix_console(void)  static void fix_console(void)
148  {  {
149          console_deinit();          console_deinit_main();
150    }
151    
152    
153    /*
154     *  iso_load_bootblock():
155     *
156     *  Try to load a kernel from an ISO 9660 disk image. iso_type is 1 for
157     *  "CD001" (standard), 2 for "CDW01" (ECMA), and 3 for "CDROM" (Sierra).
158     *
159     *  TODO: This function uses too many magic offsets and so on; it should be
160     *  cleaned up some day.
161     *
162     *  Returns 1 on success, 0 on failure.
163     */
164    static int iso_load_bootblock(struct machine *m, struct cpu *cpu,
165            int disk_id, int disk_type, int iso_type, unsigned char *buf,
166            int *n_loadp, char ***load_namesp)
167    {
168            char str[35];
169            int filenr, i, ofs, dirlen, res = 0, res2, iadd = DEBUG_INDENTATION;
170            int found_dir;
171            uint64_t dirofs;
172            uint64_t fileofs, filelen;
173            unsigned char *dirbuf = NULL, *dp;
174            unsigned char *match_entry = NULL;
175            char *p, *filename_orig;
176            char *filename = strdup(cpu->machine->boot_kernel_filename);
177            unsigned char *filebuf = NULL;
178            char *tmpfname = NULL;
179            char **new_array;
180            int tmpfile_handle;
181    
182            if (filename == NULL) {
183                    fatal("out of memory\n");
184                    exit(1);
185            }
186            filename_orig = filename;
187    
188            debug("ISO9660 boot:\n");
189            debug_indentation(iadd);
190    
191            /*  Volume ID:  */
192            ofs = iso_type == 3? 48 : 40;
193            memcpy(str, buf + ofs, sizeof(str));
194            str[32] = '\0';  i = 31;
195            while (i >= 0 && str[i]==' ')
196                    str[i--] = '\0';
197            if (str[0])
198                    debug("\"%s\"", str);
199            else {
200                    /*  System ID:  */
201                    ofs = iso_type == 3? 16 : 8;
202                    memcpy(str, buf + ofs, sizeof(str));
203                    str[32] = '\0';  i = 31;
204                    while (i >= 0 && str[i]==' ')
205                            str[i--] = '\0';
206                    if (str[0])
207                            debug("\"%s\"", str);
208                    else
209                            debug("(no ID)");
210            }
211    
212            debug(":%s\n", filename);
213    
214    
215            /*
216             *  Traverse the directory structure to find the kernel.
217             */
218    
219            dirlen = buf[0x84] + 256*buf[0x85] + 65536*buf[0x86];
220            if (dirlen != buf[0x8b] + 256*buf[0x8a] + 65536*buf[0x89])
221                    fatal("WARNING: Root directory length mismatch?\n");
222    
223            dirofs = (int64_t)(buf[0x8c] + (buf[0x8d] << 8) + (buf[0x8e] << 16) +
224                ((uint64_t)buf[0x8f] << 24)) * 2048;
225    
226            /*  debug("root = %i bytes at 0x%llx\n", dirlen, (long long)dirofs);  */
227    
228            dirbuf = malloc(dirlen);
229            if (dirbuf == NULL) {
230                    fatal("out of memory in iso_load_bootblock()\n");
231                    exit(1);
232            }
233    
234            res2 = diskimage_access(m, disk_id, disk_type, 0, dirofs, dirbuf,
235                dirlen);
236            if (!res2) {
237                    fatal("Couldn't read the disk image. Aborting.\n");
238                    goto ret;
239            }
240    
241            found_dir = 1;  /*  Assume root dir  */
242            dp = dirbuf; filenr = 1;
243            p = NULL;
244            while (dp < dirbuf + dirlen) {
245                    size_t i, nlen = dp[0];
246                    int x = dp[2] + (dp[3] << 8) + (dp[4] << 16) +
247                        ((uint64_t)dp[5] << 24);
248                    int y = dp[6] + (dp[7] << 8);
249                    char direntry[65];
250    
251                    dp += 8;
252    
253                    /*
254                     *  As long as there is an \ or / in the filename, then we
255                     *  have not yet found the directory.
256                     */
257                    p = strchr(filename, '/');
258                    if (p == NULL)
259                            p = strchr(filename, '\\');
260    
261                    /*  debug("%i%s: %i, %i, \"", filenr, filenr == found_dir?
262                        " [CURRENT]" : "", x, y);  */
263                    for (i=0; i<nlen && i<sizeof(direntry)-1; i++)
264                            if (dp[i]) {
265                                    direntry[i] = dp[i];
266                                    /*  debug("%c", dp[i]);  */
267                            } else
268                                    break;
269                    /*  debug("\"\n");  */
270                    direntry[i] = '\0';
271    
272                    /*  A directory name match?  */
273                    if (p != NULL && strncasecmp(filename, direntry, nlen) == 0
274                        && nlen == (size_t)p - (size_t)filename && found_dir == y) {
275                            found_dir = filenr;
276                            filename = p+1;
277                            dirofs = 2048 * (int64_t)x;
278                    }
279    
280                    dp += nlen;
281    
282                    /*  16-bit aligned lenght:  */
283                    if (nlen & 1)
284                            dp ++;
285    
286                    filenr ++;
287            }
288    
289            p = strchr(filename, '/');
290            if (p == NULL)
291                    p = strchr(filename, '\\');
292    
293            if (p != NULL) {
294                    char *blah = filename_orig;
295    
296                    fatal("could not find '%s' in /", filename);
297    
298                    /*  Print the first part of the filename:  */
299                    while (blah != filename)
300                            fatal("%c", *blah++);
301                    
302                    fatal("\n");
303                    goto ret;
304            }
305    
306            /*  debug("dirofs = 0x%llx\n", (long long)dirofs);  */
307    
308            /*  Free the old dirbuf, and allocate a new one:  */
309            free(dirbuf);
310            dirbuf = malloc(512);
311            if (dirbuf == NULL) {
312                    fatal("out of memory in iso_load_bootblock()\n");
313                    exit(1);
314            }
315    
316            for (;;) {
317                    size_t len, i;
318    
319                    /*  Too close to another sector? Then realign.  */
320                    if ((dirofs & 2047) + 70 > 2047) {
321                            dirofs = (dirofs | 2047) + 1;
322                            /*  debug("realign dirofs = 0x%llx\n", dirofs);  */
323                    }
324    
325                    res2 = diskimage_access(m, disk_id, disk_type, 0, dirofs,
326                        dirbuf, 256);
327                    if (!res2) {
328                            fatal("Couldn't read the disk image. Aborting.\n");
329                            goto ret;
330                    }
331    
332                    dp = dirbuf;
333                    len = dp[0];
334                    if (len < 2)
335                            break;
336    
337                    /*
338                     *  TODO: Actually parse the directory entry!
339                     *
340                     *  Haha, this must be rewritten.
341                     */
342                    for (i=32; i<len; i++) {
343                            if (i < len - strlen(filename))
344                                    if (strncasecmp(filename, (char *)dp + i,
345                                        strlen(filename)) == 0) {
346                                            /*  The filename was found somewhere
347                                                in the directory entry.  */
348                                            if (match_entry != NULL) {
349                                                    fatal("TODO: I'm too lazy to"
350                                                        " implement a correct "
351                                                        "directory parser right "
352                                                        "now... (BUG)\n");
353                                                    exit(1);
354                                            }
355                                            match_entry = malloc(512);
356                                            if (match_entry == NULL) {
357                                                    fatal("out of memory\n");
358                                                    exit(1);
359                                            }
360                                            memcpy(match_entry, dp, 512);
361                                            break;
362                                    }
363                    }
364    
365                    dirofs += len;
366            }
367    
368            if (match_entry == NULL) {
369                    char *blah = filename_orig;
370    
371                    fatal("could not find '%s' in /", filename);
372    
373                    /*  Print the first part of the filename:  */
374                    while (blah != filename)
375                            fatal("%c", *blah++);
376                    
377                    fatal("\n");
378                    goto ret;
379            }
380    
381            fileofs = match_entry[2] + (match_entry[3] << 8) +
382                (match_entry[4] << 16) + ((uint64_t)match_entry[5] << 24);
383            filelen = match_entry[10] + (match_entry[11] << 8) +
384                (match_entry[12] << 16) + ((uint64_t)match_entry[13] << 24);
385            fileofs *= 2048;
386    
387            /*  debug("filelen=%llx fileofs=%llx\n", (long long)filelen,
388                (long long)fileofs);  */
389    
390            filebuf = malloc(filelen);
391            if (filebuf == NULL) {
392                    fatal("could not allocate %lli bytes to read the file"
393                        " from the disk image!\n", (long long)filelen);
394                    goto ret;
395            }
396    
397            tmpfname = strdup("/tmp/gxemul.XXXXXXXXXXXX");
398    
399            res2 = diskimage_access(m, disk_id, disk_type, 0, fileofs, filebuf,
400                filelen);
401            if (!res2) {
402                    fatal("could not read the file from the disk image!\n");
403                    goto ret;
404            }
405    
406            tmpfile_handle = mkstemp(tmpfname);
407            if (tmpfile_handle < 0) {
408                    fatal("could not create %s\n", tmpfname);
409                    exit(1);
410            }
411            write(tmpfile_handle, filebuf, filelen);
412            close(tmpfile_handle);
413    
414            debug("extracted %lli bytes into %s\n", (long long)filelen, tmpfname);
415    
416            /*  Add the temporary filename to the load_namesp array:  */
417            (*n_loadp)++;
418            new_array = malloc(sizeof(char *) * (*n_loadp));
419            if (new_array == NULL) {
420                    fatal("out of memory\n");
421                    exit(1);
422            }
423            memcpy(new_array, *load_namesp, sizeof(char *) * (*n_loadp));
424            *load_namesp = new_array;
425    
426            /*  This adds a Backspace char in front of the filename; this
427                is a special hack which causes the file to be removed once
428                it has been loaded.  */
429            tmpfname = realloc(tmpfname, strlen(tmpfname) + 2);
430            memmove(tmpfname + 1, tmpfname, strlen(tmpfname) + 1);
431            tmpfname[0] = 8;
432    
433            (*load_namesp)[*n_loadp - 1] = tmpfname;
434    
435            res = 1;
436    
437    ret:
438            if (dirbuf != NULL)
439                    free(dirbuf);
440    
441            if (filebuf != NULL)
442                    free(filebuf);
443    
444            if (match_entry != NULL)
445                    free(match_entry);
446    
447            free(filename_orig);
448    
449            debug_indentation(-iadd);
450            return res;
451    }
452    
453    
454    /*
455     *  apple_load_bootblock():
456     *
457     *  Try to load a kernel from a disk image with an Apple Partition Table.
458     *
459     *  TODO: This function uses too many magic offsets and so on; it should be
460     *  cleaned up some day. See http://www.awprofessional.com/articles/
461     *      article.asp?p=376123&seqNum=3&rl=1  for some info on the Apple
462     *  partition format.
463     *
464     *  Returns 1 on success, 0 on failure.
465     */
466    static int apple_load_bootblock(struct machine *m, struct cpu *cpu,
467            int disk_id, int disk_type, int *n_loadp, char ***load_namesp)
468    {
469            unsigned char buf[0x8000];
470            int res, partnr, n_partitions = 0, n_hfs_partitions = 0;
471            uint64_t hfs_start, hfs_length;
472    
473            res = diskimage_access(m, disk_id, disk_type, 0, 0x0, buf, sizeof(buf));
474            if (!res) {
475                    fatal("apple_load_bootblock: couldn't read the disk "
476                        "image. Aborting.\n");
477                    return 0;
478            }
479    
480            partnr = 0;
481            do {
482                    int start, length;
483                    int ofs = 0x200 * (partnr + 1);
484                    if (partnr == 0)
485                            n_partitions = buf[ofs + 7];
486                    start = ((uint64_t)buf[ofs + 8] << 24) + (buf[ofs + 9] << 16) +
487                        (buf[ofs + 10] << 8) + buf[ofs + 11];
488                    length = ((uint64_t)buf[ofs+12] << 24) + (buf[ofs + 13] << 16) +
489                        (buf[ofs + 14] << 8) + buf[ofs + 15];
490    
491                    debug("partition %i: '%s', type '%s', start %i, length %i\n",
492                        partnr, buf + ofs + 0x10, buf + ofs + 0x30,
493                        start, length);
494    
495                    if (strcmp((char *)buf + ofs + 0x30, "Apple_HFS") == 0) {
496                            n_hfs_partitions ++;
497                            hfs_start = 512 * start;
498                            hfs_length = 512 * length;
499                    }
500    
501                    /*  Any more partitions?  */
502                    partnr ++;
503            } while (partnr < n_partitions);
504    
505            if (n_hfs_partitions == 0) {
506                    fatal("Error: No HFS partition found! TODO\n");
507                    return 0;
508            }
509            if (n_hfs_partitions >= 2) {
510                    fatal("Error: Too many HFS partitions found! TODO\n");
511                    return 0;
512            }
513    
514            return 0;
515  }  }
516    
517    
# Line 138  static void fix_console(void) Line 522  static void fix_console(void)
522   *  loading a bootblock from a specific disk offset into memory, and executing   *  loading a bootblock from a specific disk offset into memory, and executing
523   *  that, instead of requiring a separate kernel file.  It is then up to the   *  that, instead of requiring a separate kernel file.  It is then up to the
524   *  bootblock to load a kernel.   *  bootblock to load a kernel.
525     *
526     *  Returns 1 on success, 0 on failure.
527   */   */
528  static void load_bootblock(struct machine *m, struct cpu *cpu)  static int load_bootblock(struct machine *m, struct cpu *cpu,
529            int *n_loadp, char ***load_namesp)
530  {  {
531          int boot_disk_id;          int boot_disk_id, boot_disk_type = 0, n_blocks, res, readofs,
532                iso_type, retval = 0;
533          unsigned char minibuf[0x20];          unsigned char minibuf[0x20];
534          unsigned char *bootblock_buf;          unsigned char *bootblock_buf;
535          uint64_t bootblock_offset;          uint64_t bootblock_offset;
536          uint64_t bootblock_loadaddr, bootblock_pc;          uint64_t bootblock_loadaddr, bootblock_pc;
         int n_blocks, res, readofs;  
537    
538          boot_disk_id = diskimage_bootdev(m);          boot_disk_id = diskimage_bootdev(m, &boot_disk_type);
539          if (boot_disk_id < 0)          if (boot_disk_id < 0)
540                  return;                  return 0;
541    
542          switch (m->machine_type) {          switch (m->machine_type) {
543          case MACHINE_DEC:          case MACHINE_PMAX:
544                  /*                  /*
545                   *  The first few bytes of a disk contains information about                   *  The first few bytes of a disk contains information about
546                   *  where the bootblock(s) are located. (These are all 32-bit                   *  where the bootblock(s) are located. (These are all 32-bit
# Line 170  static void load_bootblock(struct machin Line 557  static void load_bootblock(struct machin
557                   *  nr of blocks to read and offset are repeated until nr of                   *  nr of blocks to read and offset are repeated until nr of
558                   *  blocks to read is zero.                   *  blocks to read is zero.
559                   */                   */
560                  res = diskimage_access(m, boot_disk_id, 0, 0,                  res = diskimage_access(m, boot_disk_id, boot_disk_type, 0, 0,
561                      minibuf, sizeof(minibuf));                      minibuf, sizeof(minibuf));
562    
563                  bootblock_loadaddr = minibuf[0x10] + (minibuf[0x11] << 8)                  bootblock_loadaddr = minibuf[0x10] + (minibuf[0x11] << 8)
564                    + (minibuf[0x12] << 16) + (minibuf[0x13] << 24);                    + (minibuf[0x12] << 16) + ((uint64_t)minibuf[0x13] << 24);
565    
566                  /*  Convert loadaddr to uncached:  */                  /*  Convert loadaddr to uncached:  */
567                  if ((bootblock_loadaddr & 0xf0000000ULL) != 0x80000000 &&                  if ((bootblock_loadaddr & 0xf0000000ULL) != 0x80000000 &&
568                      (bootblock_loadaddr & 0xf0000000ULL) != 0xa0000000)                      (bootblock_loadaddr & 0xf0000000ULL) != 0xa0000000) {
569                          fatal("\nWARNING! Weird load address 0x%08x.\n\n",                          fatal("\nWARNING! Weird load address 0x%08"PRIx32
570                              (int)bootblock_loadaddr);                              " for SCSI id %i.\n\n",
571                                (uint32_t)bootblock_loadaddr, boot_disk_id);
572                            if (bootblock_loadaddr == 0) {
573                                    fatal("I'm assuming that this is _not_ a "
574                                        "DEC bootblock.\nAre you sure you are"
575                                        " booting from the correct disk?\n");
576                                    exit(1);
577                            }
578                    }
579    
580                  bootblock_loadaddr &= 0x0fffffffULL;                  bootblock_loadaddr &= 0x0fffffffULL;
581                  bootblock_loadaddr |= 0xffffffffa0000000ULL;                  bootblock_loadaddr |= 0xffffffffa0000000ULL;
582    
583                  bootblock_pc = minibuf[0x14] + (minibuf[0x15] << 8)                  bootblock_pc = minibuf[0x14] + (minibuf[0x15] << 8)
584                    + (minibuf[0x16] << 16) + (minibuf[0x17] << 24);                    + (minibuf[0x16] << 16) + ((uint64_t)minibuf[0x17] << 24);
585    
586                  bootblock_pc &= 0x0fffffffULL;                  bootblock_pc &= 0x0fffffffULL;
587                  bootblock_pc |= 0xffffffffa0000000ULL;                  bootblock_pc |= 0xffffffffa0000000ULL;
# Line 197  static void load_bootblock(struct machin Line 593  static void load_bootblock(struct machin
593                  readofs = 0x18;                  readofs = 0x18;
594    
595                  for (;;) {                  for (;;) {
596                          res = diskimage_access(m, boot_disk_id, 0, readofs,                          res = diskimage_access(m, boot_disk_id, boot_disk_type,
597                              minibuf, sizeof(minibuf));                              0, readofs, minibuf, sizeof(minibuf));
598                          if (!res) {                          if (!res) {
599                                  printf("couldn't read disk?\n");                                  fatal("Couldn't read the disk image. "
600                                  exit(1);                                      "Aborting.\n");
601                                    return 0;
602                          }                          }
603    
604                          n_blocks = minibuf[0] + (minibuf[1] << 8)                          n_blocks = minibuf[0] + (minibuf[1] << 8)
605                            + (minibuf[2] << 16) + (minibuf[3] << 24);                            + (minibuf[2] << 16) + ((uint64_t)minibuf[3] << 24);
606    
607                          bootblock_offset = (minibuf[4] + (minibuf[5] << 8)                          bootblock_offset = (minibuf[4] + (minibuf[5] << 8) +
608                            + (minibuf[6] << 16) + (minibuf[7] << 24)) * 512;                            (minibuf[6]<<16) + ((uint64_t)minibuf[7]<<24)) * 512;
609    
610                          if (n_blocks < 1)                          if (n_blocks < 1)
611                                  break;                                  break;
# Line 226  static void load_bootblock(struct machin Line 623  static void load_bootblock(struct machin
623                                  exit(1);                                  exit(1);
624                          }                          }
625    
626                          res = diskimage_access(m, boot_disk_id, 0,                          res = diskimage_access(m, boot_disk_id, boot_disk_type,
627                              bootblock_offset, bootblock_buf, n_blocks * 512);                              0, bootblock_offset, bootblock_buf, n_blocks * 512);
628                          if (!res) {                          if (!res) {
629                                  fatal("WARNING: could not load bootblocks from"                                  fatal("WARNING: could not load bootblocks from"
630                                      " disk offset 0x%llx\n",                                      " disk offset 0x%llx\n",
# Line 243  static void load_bootblock(struct machin Line 640  static void load_bootblock(struct machin
640                  }                  }
641    
642                  debug(readofs == 0x18? ": no blocks?\n" : " blocks\n");                  debug(readofs == 0x18? ": no blocks?\n" : " blocks\n");
643                  break;                  return 1;
644          default:  
645                  fatal("Booting from disk without a separate kernel "          case MACHINE_X86:
646                      "doesn't work in this emulation mode.\n");                  /*  TODO: "El Torito" etc?  */
647                    if (diskimage_is_a_cdrom(cpu->machine, boot_disk_id,
648                        boot_disk_type))
649                            break;
650    
651                    bootblock_buf = malloc(512);
652                    if (bootblock_buf == NULL) {
653                            fprintf(stderr, "Out of memory.\n");
654                            exit(1);
655                    }
656    
657                    debug("loading PC bootsector from %s id %i\n",
658                        diskimage_types[boot_disk_type], boot_disk_id);
659    
660                    res = diskimage_access(m, boot_disk_id, boot_disk_type, 0, 0,
661                        bootblock_buf, 512);
662                    if (!res) {
663                            fatal("Couldn't read the disk image. Aborting.\n");
664                            return 0;
665                    }
666    
667                    if (bootblock_buf[510] != 0x55 || bootblock_buf[511] != 0xaa)
668                            debug("WARNING! The 0x55,0xAA marker is missing! "
669                                "Booting anyway.\n");
670                    store_buf(cpu, 0x7c00, (char *)bootblock_buf, 512);
671                    free(bootblock_buf);
672    
673                    return 1;
674            }
675    
676    
677            /*
678             *  Try reading a kernel manually from the disk. The code here
679             *  does not rely on machine-dependent boot blocks etc.
680             */
681            /*  ISO9660: (0x800 bytes at 0x8000)  */
682            bootblock_buf = malloc(0x800);
683            if (bootblock_buf == NULL) {
684                    fprintf(stderr, "Out of memory.\n");
685                  exit(1);                  exit(1);
686          }          }
687    
688            res = diskimage_access(m, boot_disk_id, boot_disk_type,
689                0, 0x8000, bootblock_buf, 0x800);
690            if (!res) {
691                    fatal("Couldn't read the disk image. Aborting.\n");
692                    return 0;
693            }
694    
695            iso_type = 0;
696            if (strncmp((char *)bootblock_buf+1, "CD001", 5) == 0)
697                    iso_type = 1;
698            if (strncmp((char *)bootblock_buf+1, "CDW01", 5) == 0)
699                    iso_type = 2;
700            if (strncmp((char *)bootblock_buf+1, "CDROM", 5) == 0)
701                    iso_type = 3;
702    
703            if (iso_type != 0) {
704                    /*
705                     *  If the user specified a kernel name, then load it from
706                     *  disk.
707                     */
708                    if (cpu->machine->boot_kernel_filename == NULL ||
709                        cpu->machine->boot_kernel_filename[0] == '\0')
710                            fatal("\nISO9660 filesystem, but no kernel "
711                                "specified? (Use the -j option.)\n");
712                    else
713                            retval = iso_load_bootblock(m, cpu, boot_disk_id,
714                                boot_disk_type, iso_type, bootblock_buf,
715                                n_loadp, load_namesp);
716            }
717    
718            if (retval != 0)
719                    goto ret_ok;
720    
721            /*  Apple parition table:  */
722            res = diskimage_access(m, boot_disk_id, boot_disk_type,
723                0, 0x0, bootblock_buf, 0x800);
724            if (!res) {
725                    fatal("Couldn't read the disk image. Aborting.\n");
726                    return 0;
727            }
728            if (bootblock_buf[0x000] == 'E' && bootblock_buf[0x001] == 'R' &&
729                bootblock_buf[0x200] == 'P' && bootblock_buf[0x201] == 'M') {
730                    if (cpu->machine->boot_kernel_filename == NULL ||
731                        cpu->machine->boot_kernel_filename[0] == '\0')
732                            fatal("\nApple partition table, but no kernel "
733                                "specified? (Use the -j option.)\n");
734                    else
735                            retval = apple_load_bootblock(m, cpu, boot_disk_id,
736                                boot_disk_type, n_loadp, load_namesp);
737            }
738    
739    ret_ok:
740            free(bootblock_buf);
741            return retval;
742  }  }
743    
744    
# Line 268  struct emul *emul_new(char *name) Line 758  struct emul *emul_new(char *name)
758    
759          memset(e, 0, sizeof(struct emul));          memset(e, 0, sizeof(struct emul));
760    
761            e->settings = settings_new();
762    
763            settings_add(e->settings, "n_machines", 0,
764                SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
765                (void *) &e->n_machines);
766    
767            /*  TODO: More settings?  */
768    
769          /*  Sane default values:  */          /*  Sane default values:  */
770          e->n_machines = 0;          e->n_machines = 0;
771            e->next_serial_nr = 1;
772    
773          if (name != NULL) {          if (name != NULL) {
774                  e->name = strdup(name);                  e->name = strdup(name);
# Line 277  struct emul *emul_new(char *name) Line 776  struct emul *emul_new(char *name)
776                          fprintf(stderr, "out of memory in emul_new()\n");                          fprintf(stderr, "out of memory in emul_new()\n");
777                          exit(1);                          exit(1);
778                  }                  }
779    
780                    settings_add(e->settings, "name", 0,
781                        SETTINGS_TYPE_STRING, SETTINGS_FORMAT_STRING,
782                        (void *) &e->name);
783          }          }
784    
785          return e;          return e;
# Line 284  struct emul *emul_new(char *name) Line 787  struct emul *emul_new(char *name)
787    
788    
789  /*  /*
790     *  emul_destroy():
791     *
792     *  Destroys a previously created emul object.
793     */
794    void emul_destroy(struct emul *emul)
795    {
796            int i;
797    
798            if (emul->name != NULL) {
799                    settings_remove(emul->settings, "name");
800                    free(emul->name);
801            }
802    
803            for (i=0; i<emul->n_machines; i++)
804                    machine_destroy(emul->machines[i]);
805    
806            if (emul->machines != NULL)
807                    free(emul->machines);
808    
809            /*  Remove any remaining level-1 settings:  */
810            settings_remove_all(emul->settings);
811            settings_destroy(emul->settings);
812    
813            free(emul);
814    }
815    
816    
817    /*
818   *  emul_add_machine():   *  emul_add_machine():
819   *   *
820   *  Calls machine_new(), adds the new machine into the emul struct, and   *  Calls machine_new(), adds the new machine into the emul struct, and
# Line 294  struct emul *emul_new(char *name) Line 825  struct emul *emul_new(char *name)
825  struct machine *emul_add_machine(struct emul *e, char *name)  struct machine *emul_add_machine(struct emul *e, char *name)
826  {  {
827          struct machine *m;          struct machine *m;
828            char tmpstr[20];
829            int i;
830    
831          m = machine_new(name, e);          m = machine_new(name, e);
832          m->serial_nr = (e->next_serial_nr ++);          m->serial_nr = (e->next_serial_nr ++);
833    
834            i = e->n_machines;
835    
836          e->n_machines ++;          e->n_machines ++;
837          e->machines = realloc(e->machines,          e->machines = realloc(e->machines,
838              sizeof(struct machine *) * e->n_machines);              sizeof(struct machine *) * e->n_machines);
# Line 306  struct machine *emul_add_machine(struct Line 841  struct machine *emul_add_machine(struct
841                  exit(1);                  exit(1);
842          }          }
843    
844          e->machines[e->n_machines - 1] = m;          e->machines[i] = m;
845    
846            snprintf(tmpstr, sizeof(tmpstr), "machine[%i]", i);
847            settings_add(e->settings, tmpstr, 1, SETTINGS_TYPE_SUBSETTINGS, 0,
848                e->machines[i]->settings);
849    
850          return m;          return m;
851  }  }
852    
# Line 332  static void add_arc_components(struct ma Line 872  static void add_arc_components(struct ma
872    
873          len += 1048576 * m->memory_offset_in_mb;          len += 1048576 * m->memory_offset_in_mb;
874    
875          /*  NOTE/TODO: magic 12MB end of load program area  */          /*
876             *  NOTE/TODO: magic 12MB end of load program area
877             *
878             *  Hm. This breaks the old FreeBSD/MIPS snapshots...
879             */
880    #if 0
881          arcbios_add_memory_descriptor(cpu,          arcbios_add_memory_descriptor(cpu,
882              0x60000 + m->memory_offset_in_mb * 1048576,              0x60000 + m->memory_offset_in_mb * 1048576,
883              start-0x60000 - m->memory_offset_in_mb * 1048576,              start-0x60000 - m->memory_offset_in_mb * 1048576,
884              ARCBIOS_MEM_FreeMemory);              ARCBIOS_MEM_FreeMemory);
885    #endif
886          arcbios_add_memory_descriptor(cpu,          arcbios_add_memory_descriptor(cpu,
887              start, len, ARCBIOS_MEM_LoadedProgram);              start, len, ARCBIOS_MEM_LoadedProgram);
888    
889          scsicontroller = arcbios_get_scsicontroller();          scsicontroller = arcbios_get_scsicontroller(m);
890          if (scsicontroller == 0)          if (scsicontroller == 0)
891                  return;                  return;
892    
# Line 388  static void add_arc_components(struct ma Line 934  static void add_arc_components(struct ma
934                                  snprintf(component_string,                                  snprintf(component_string,
935                                      sizeof(component_string),                                      sizeof(component_string),
936                                      "scsi(0)cdrom(%i)", d->id);                                      "scsi(0)cdrom(%i)", d->id);
937                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
938                                      component_string, scsidevice);                                      component_string, scsidevice);
939    
940                                  snprintf(component_string,                                  snprintf(component_string,
941                                      sizeof(component_string),                                      sizeof(component_string),
942                                      "scsi(0)cdrom(%i)fdisk(0)", d->id);                                      "scsi(0)cdrom(%i)fdisk(0)", d->id);
943                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
944                                      component_string, scsidisk);                                      component_string, scsidisk);
945                          } else {                          } else {
946                                  snprintf(component_string,                                  snprintf(component_string,
947                                      sizeof(component_string),                                      sizeof(component_string),
948                                      "scsi(0)disk(%i)", d->id);                                      "scsi(0)disk(%i)", d->id);
949                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
950                                      component_string, scsidevice);                                      component_string, scsidevice);
951    
952                                  snprintf(component_string,                                  snprintf(component_string,
953                                      sizeof(component_string),                                      sizeof(component_string),
954                                      "scsi(0)disk(%i)rdisk(0)", d->id);                                      "scsi(0)disk(%i)rdisk(0)", d->id);
955                                  arcbios_add_string_to_component(                                  arcbios_add_string_to_component(m,
956                                      component_string, scsidisk);                                      component_string, scsidisk);
957                          }                          }
958                  }                  }
# Line 429  static void add_arc_components(struct ma Line 975  static void add_arc_components(struct ma
975  void emul_machine_setup(struct machine *m, int n_load, char **load_names,  void emul_machine_setup(struct machine *m, int n_load, char **load_names,
976          int n_devices, char **device_names)          int n_devices, char **device_names)
977  {  {
         struct emul *emul;  
978          struct cpu *cpu;          struct cpu *cpu;
979          int i, iadd=4;          int i, iadd = DEBUG_INDENTATION;
980          uint64_t addr, memory_amount, entrypoint = 0, gp = 0, toc = 0;          uint64_t memory_amount, entrypoint = 0, gp = 0, toc = 0;
981          int byte_order;          int byte_order;
982    
         emul = m->emul;  
   
983          debug("machine \"%s\":\n", m->name);          debug("machine \"%s\":\n", m->name);
984          debug_indentation(iadd);          debug_indentation(iadd);
985    
# Line 457  void emul_machine_setup(struct machine * Line 1000  void emul_machine_setup(struct machine *
1000    
1001          m->cpu_family = cpu_family_ptr_by_number(m->arch);          m->cpu_family = cpu_family_ptr_by_number(m->arch);
1002    
1003            if (m->arch == ARCH_ALPHA)
1004                    m->arch_pagesize = 8192;
1005    
1006          machine_memsize_fix(m);          machine_memsize_fix(m);
1007    
1008          /*          /*
# Line 477  void emul_machine_setup(struct machine * Line 1023  void emul_machine_setup(struct machine *
1023                  debug(" (offset by %iMB)", m->memory_offset_in_mb);                  debug(" (offset by %iMB)", m->memory_offset_in_mb);
1024                  memory_amount += 1048576 * m->memory_offset_in_mb;                  memory_amount += 1048576 * m->memory_offset_in_mb;
1025          }          }
1026          m->memory = memory_new(memory_amount);          m->memory = memory_new(memory_amount, m->arch);
1027          if (m->machine_type != MACHINE_USERLAND)          if (m->machine_type != MACHINE_USERLAND)
1028                  debug("\n");                  debug("\n");
1029    
# Line 504  void emul_machine_setup(struct machine * Line 1050  void emul_machine_setup(struct machine *
1050          }          }
1051          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);          memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
1052    
         /*  Initialize dynamic binary translation, if available:  */  
         if (m->bintrans_enable)  
                 bintrans_init(m, m->memory);  
   
1053          debug("cpu0");          debug("cpu0");
1054          if (m->ncpus > 1)          if (m->ncpus > 1)
1055                  debug(" .. cpu%i", m->ncpus - 1);                  debug(" .. cpu%i", m->ncpus - 1);
1056          debug(": ");          debug(": ");
1057          for (i=0; i<m->ncpus; i++) {          for (i=0; i<m->ncpus; i++) {
1058                  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);                  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
1059                  if (m->bintrans_enable)                  if (m->cpus[i] == NULL) {
1060                          bintrans_init_cpu(m->cpus[i]);                          fprintf(stderr, "Unable to create CPU object. "
1061                                "Aborting.");
1062                            exit(1);
1063                    }
1064          }          }
1065          debug("\n");          debug("\n");
1066    
1067    #if 0
1068            /*  Special case: The Playstation Portable has an additional CPU:  */
1069            if (m->machine_type == MACHINE_PSP) {
1070                    debug("cpu%i: ", m->ncpus);
1071                    m->cpus[m->ncpus] = cpu_new(m->memory, m,
1072                        0  /*  use 0 here to show info with debug()  */,
1073                        "Allegrex" /*  TODO  */);
1074                    debug("\n");
1075                    m->ncpus ++;
1076            }
1077    #endif
1078    
1079          if (m->use_random_bootstrap_cpu)          if (m->use_random_bootstrap_cpu)
1080                  m->bootstrap_cpu = random() % m->ncpus;                  m->bootstrap_cpu = random() % m->ncpus;
1081          else          else
# Line 530  void emul_machine_setup(struct machine * Line 1087  void emul_machine_setup(struct machine *
1087          if (m->userland_emul != NULL) {          if (m->userland_emul != NULL) {
1088                  useremul_name_to_useremul(cpu,                  useremul_name_to_useremul(cpu,
1089                      m->userland_emul, NULL, NULL, NULL);                      m->userland_emul, NULL, NULL, NULL);
1090                  cpu->memory_rw = userland_memory_rw;  
1091                    switch (m->arch) {
1092    #ifdef ENABLE_ALPHA
1093                    case ARCH_ALPHA:
1094                            cpu->memory_rw = alpha_userland_memory_rw;
1095                            break;
1096    #endif
1097                    default:cpu->memory_rw = userland_memory_rw;
1098                    }
1099          }          }
1100    
1101          if (m->use_x11)          if (m->use_x11)
1102                  x11_init(m);                  x11_init(m);
1103    
1104          /*  Fill memory with random bytes:  */          /*  Fill memory with random bytes:  */
         /*  TODO: This is MIPS-specific!  */  
1105          if (m->random_mem_contents) {          if (m->random_mem_contents) {
1106                  for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {                  for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {
1107                          unsigned char data[256];                          unsigned char data[256];
1108                          unsigned int j;                          unsigned int j;
1109                          for (j=0; j<sizeof(data); j++)                          for (j=0; j<sizeof(data); j++)
1110                                  data[j] = random() & 255;                                  data[j] = random() & 255;
1111                          addr = 0xffffffff80000000ULL + i;                          cpu->memory_rw(cpu, m->memory, i, data, sizeof(data),
1112                          cpu->memory_rw(cpu, m->memory, addr, data, sizeof(data),                              MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS | PHYSICAL);
                             MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS);  
1113                  }                  }
1114          }          }
1115    
         if ((m->machine_type == MACHINE_ARC ||  
             m->machine_type == MACHINE_SGI) && m->prom_emulation)  
                 arcbios_init();  
   
1116          if (m->userland_emul != NULL) {          if (m->userland_emul != NULL) {
1117                  /*                  /*
1118                   *  For userland-only emulation, no machine emulation                   *  For userland-only emulation, no machine emulation
# Line 567  void emul_machine_setup(struct machine * Line 1126  void emul_machine_setup(struct machine *
1126          }          }
1127    
1128          diskimage_dump_info(m);          diskimage_dump_info(m);
1129            console_debug_dump(m);
1130    
1131          /*  Load files (ROM code, boot code, ...) into memory:  */          /*  Load files (ROM code, boot code, ...) into memory:  */
1132          if (n_load == 0) {          if (n_load == 0) {
1133                  if (m->first_diskimage != NULL)                  if (m->first_diskimage != NULL) {
1134                          load_bootblock(m, cpu);                          if (!load_bootblock(m, cpu, &n_load, &load_names)) {
1135                  else {                                  fprintf(stderr, "\nNo executable files were"
1136                                        " specified, and booting directly from disk"
1137                                        " failed.\n");
1138                                    exit(1);
1139                            }
1140                    } else {
1141                          fprintf(stderr, "No executable file(s) loaded, and "                          fprintf(stderr, "No executable file(s) loaded, and "
1142                              "we are not booting directly from a disk image."                              "we are not booting directly from a disk image."
1143                              "\nAborting.\n");                              "\nAborting.\n");
# Line 581  void emul_machine_setup(struct machine * Line 1146  void emul_machine_setup(struct machine *
1146          }          }
1147    
1148          while (n_load > 0) {          while (n_load > 0) {
1149                    FILE *tmp_f;
1150                    char *name_to_load = *load_names;
1151                    int remove_after_load = 0;
1152    
1153                    /*  Special hack for removing temporary files:  */
1154                    if (name_to_load[0] == 8) {
1155                            name_to_load ++;
1156                            remove_after_load = 1;
1157                    }
1158    
1159                    /*
1160                     *  gzipped files are automagically gunzipped:
1161                     *  NOTE/TODO: This isn't secure. system() is used.
1162                     */
1163                    tmp_f = fopen(name_to_load, "r");
1164                    if (tmp_f != NULL) {
1165                            unsigned char buf[2];           /*  gzip header  */
1166                            memset(buf, 0, sizeof(buf));
1167                            fread(buf, 1, sizeof(buf), tmp_f);
1168                            if (buf[0]==0x1f && buf[1]==0x8b) {
1169                                    size_t zzlen = strlen(name_to_load)*2 + 100;
1170                                    char *zz = malloc(zzlen);
1171                                    debug("gunziping %s\n", name_to_load);
1172                                    /*
1173                                     *  gzip header found.  If this was a file
1174                                     *  extracted from, say, a CDROM image, then it
1175                                     *  already has a temporary name. Otherwise we
1176                                     *  have to gunzip into a temporary file.
1177                                     */
1178                                    if (remove_after_load) {
1179                                            snprintf(zz, zzlen, "mv %s %s.gz",
1180                                                name_to_load, name_to_load);
1181                                            system(zz);
1182                                            snprintf(zz, zzlen, "gunzip %s.gz",
1183                                                name_to_load);
1184                                            system(zz);
1185                                    } else {
1186                                            /*  gunzip into new temp file:  */
1187                                            int tmpfile_handle;
1188                                            char *new_temp_name =
1189                                                strdup("/tmp/gxemul.XXXXXXXXXXXX");
1190                                            tmpfile_handle = mkstemp(new_temp_name);
1191                                            close(tmpfile_handle);
1192                                            snprintf(zz, zzlen, "gunzip -c '%s' > "
1193                                                "%s", name_to_load, new_temp_name);
1194                                            system(zz);
1195                                            name_to_load = new_temp_name;
1196                                            remove_after_load = 1;
1197                                    }
1198                                    free(zz);
1199                            }
1200                            fclose(tmp_f);
1201                    }
1202    
1203                    /*
1204                     *  Ugly (but usable) hack for Playstation Portable:  If the
1205                     *  filename ends with ".pbp" and the file contains an ELF
1206                     *  header, then extract the ELF file into a temporary file.
1207                     */
1208                    if (strlen(name_to_load) > 4 && strcasecmp(name_to_load +
1209                        strlen(name_to_load) - 4, ".pbp") == 0 &&
1210                        (tmp_f = fopen(name_to_load, "r")) != NULL) {
1211                            off_t filesize, j, found=0;
1212                            unsigned char *buf;
1213                            fseek(tmp_f, 0, SEEK_END);
1214                            filesize = ftello(tmp_f);
1215                            fseek(tmp_f, 0, SEEK_SET);
1216                            buf = malloc(filesize);
1217                            if (buf == NULL) {
1218                                    fprintf(stderr, "out of memory while trying"
1219                                        " to read %s\n", name_to_load);
1220                                    exit(1);
1221                            }
1222                            fread(buf, 1, filesize, tmp_f);
1223                            fclose(tmp_f);
1224                            /*  Search for the ELF header, from offset 1 (!):  */
1225                            for (j=1; j<filesize - 4; j++)
1226                                    if (memcmp(buf + j, ELFMAG, SELFMAG) == 0) {
1227                                            found = j;
1228                                            break;
1229                                    }
1230                            if (found != 0) {
1231                                    int tmpfile_handle;
1232                                    char *new_temp_name =
1233                                        strdup("/tmp/gxemul.XXXXXXXXXXXX");
1234                                    debug("extracting ELF from %s (offset 0x%x)\n",
1235                                        name_to_load, (int)found);
1236                                    tmpfile_handle = mkstemp(new_temp_name);
1237                                    write(tmpfile_handle, buf + found,
1238                                        filesize - found);
1239                                    close(tmpfile_handle);
1240                                    name_to_load = new_temp_name;
1241                                    remove_after_load = 1;
1242                            }
1243                    }
1244    
1245                    /*  Special things required _before_ loading the file:  */
1246                    switch (m->arch) {
1247                    case ARCH_X86:
1248                            /*
1249                             *  X86 machines normally don't need to load any files,
1250                             *  they can boot from disk directly. Therefore, an x86
1251                             *  machine usually boots up in 16-bit real mode. When
1252                             *  loading a 32-bit (or even 64-bit) ELF, that's not
1253                             *  very nice, hence this special case.
1254                             */
1255                            pc_bios_simple_pmode_setup(cpu);
1256                            break;
1257                    }
1258    
1259                  byte_order = NO_BYTE_ORDER_OVERRIDE;                  byte_order = NO_BYTE_ORDER_OVERRIDE;
1260    
1261                  file_load(m, m->memory, *load_names, &entrypoint,                  /*
1262                     *  Load the file:  :-)
1263                     */
1264                    file_load(m, m->memory, name_to_load, &entrypoint,
1265                      m->arch, &gp, &byte_order, &toc);                      m->arch, &gp, &byte_order, &toc);
1266    
1267                    if (remove_after_load) {
1268                            debug("removing %s\n", name_to_load);
1269                            unlink(name_to_load);
1270                    }
1271    
1272                  if (byte_order != NO_BYTE_ORDER_OVERRIDE)                  if (byte_order != NO_BYTE_ORDER_OVERRIDE)
1273                          cpu->byte_order = byte_order;                          cpu->byte_order = byte_order;
1274    
1275                  cpu->pc = entrypoint;                  cpu->pc = entrypoint;
1276    
1277                  switch (m->arch) {                  switch (m->arch) {
1278    
1279                    case ARCH_ALPHA:
1280                            /*  For position-independent code:  */
1281                            cpu->cd.alpha.r[ALPHA_T12] = cpu->pc;
1282                            break;
1283    
1284                    case ARCH_ARM:
1285                            if (cpu->pc & 3) {
1286                                    fatal("ARM: lowest bits of pc set: TODO\n");
1287                                    exit(1);
1288                            }
1289                            cpu->pc &= 0xfffffffc;
1290                            break;
1291    
1292                    case ARCH_AVR:
1293                            cpu->pc &= 0xfffff;
1294                            if (cpu->pc & 1) {
1295                                    fatal("AVR: lowest bit of pc set: TODO\n");
1296                                    exit(1);
1297                            }
1298                            break;
1299    
1300                    case ARCH_AVR32:
1301                            cpu->pc = (uint32_t) cpu->pc;
1302                            if (cpu->pc & 1) {
1303                                    fatal("AVR32: lowest bit of pc set: TODO\n");
1304                                    exit(1);
1305                            }
1306                            break;
1307    
1308                    case ARCH_RCA180X:
1309                            cpu->pc &= 0xffff;
1310                            break;
1311    
1312                    case ARCH_HPPA:
1313                            break;
1314    
1315                    case ARCH_I960:
1316                            break;
1317    
1318                    case ARCH_IA64:
1319                            break;
1320    
1321                    case ARCH_M68K:
1322                            break;
1323    
1324                  case ARCH_MIPS:                  case ARCH_MIPS:
1325                          if ((cpu->pc >> 32) == 0                          if ((cpu->pc >> 32) == 0 && (cpu->pc & 0x80000000ULL))
                             && (cpu->pc & 0x80000000ULL))  
1326                                  cpu->pc |= 0xffffffff00000000ULL;                                  cpu->pc |= 0xffffffff00000000ULL;
1327    
1328                          cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;                          cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;
# Line 604  void emul_machine_setup(struct machine * Line 1332  void emul_machine_setup(struct machine *
1332                                  cpu->cd.mips.gpr[MIPS_GPR_GP] |=                                  cpu->cd.mips.gpr[MIPS_GPR_GP] |=
1333                                      0xffffffff00000000ULL;                                      0xffffffff00000000ULL;
1334                          break;                          break;
1335    
1336                  case ARCH_PPC:                  case ARCH_PPC:
1337                            /*  See http://www.linuxbase.org/spec/ELF/ppc64/
1338                                spec/x458.html for more info.  */
1339                          cpu->cd.ppc.gpr[2] = toc;                          cpu->cd.ppc.gpr[2] = toc;
1340                            /*  TODO  */
1341                            if (cpu->cd.ppc.bits == 32)
1342                                    cpu->pc &= 0xffffffffULL;
1343                          break;                          break;
1344                  case ARCH_SPARC:  
1345                    case ARCH_SH:
1346                            if (cpu->cd.sh.cpu_type.bits == 32)
1347                                    cpu->pc &= 0xffffffffULL;
1348                            cpu->pc &= ~1;
1349                          break;                          break;
1350                  case ARCH_URISC:  
1351                    case ARCH_SPARC:
1352                          break;                          break;
1353                  case ARCH_HPPA:  
1354                    case ARCH_TRANSPUTER:
1355                            cpu->pc &= 0xffffffffULL;
1356                          break;                          break;
1357                  case ARCH_ALPHA:  
1358                    case ARCH_X86:
1359                            /*
1360                             *  NOTE: The toc field is used to indicate an ELF32
1361                             *  or ELF64 load.
1362                             */
1363                            switch (toc) {
1364                            case 0: /*  16-bit? TODO  */
1365                                    cpu->pc &= 0xffffffffULL;
1366                                    break;
1367                            case 1: /*  32-bit.  */
1368                                    cpu->pc &= 0xffffffffULL;
1369                                    break;
1370                            case 2: /*  64-bit:  TODO  */
1371                                    fatal("64-bit x86 load. TODO\n");
1372                                    exit(1);
1373                            }
1374                          break;                          break;
1375    
1376                  default:                  default:
1377                          fatal("emul_machine_setup(): Internal error: "                          fatal("emul_machine_setup(): Internal error: "
1378                              "Unimplemented arch %i\n", m->arch);                              "Unimplemented arch %i\n", m->arch);
# Line 650  void emul_machine_setup(struct machine * Line 1408  void emul_machine_setup(struct machine *
1408                  useremul_setup(cpu, n_load, load_names);                  useremul_setup(cpu, n_load, load_names);
1409    
1410          /*  Startup the bootstrap CPU:  */          /*  Startup the bootstrap CPU:  */
1411          cpu->bootstrap_cpu_flag = 1;          cpu->running = 1;
         cpu->running            = 1;  
1412    
1413          /*  ... or pause all CPUs, if start_paused is set:  */          /*  ... or pause all CPUs, if start_paused is set:  */
1414          if (m->start_paused) {          if (m->start_paused) {
# Line 663  void emul_machine_setup(struct machine * Line 1420  void emul_machine_setup(struct machine *
1420          add_dump_points(m);          add_dump_points(m);
1421    
1422          /*  TODO: This is MIPS-specific!  */          /*  TODO: This is MIPS-specific!  */
1423          if (m->machine_type == MACHINE_DEC &&          if (m->machine_type == MACHINE_PMAX &&
1424              cpu->cd.mips.cpu_type.mmu_model == MMU3K)              cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1425                  add_symbol_name(&m->symbol_context,                  add_symbol_name(&m->symbol_context,
1426                      0x9fff0000, 0x10000, "r2k3k_cache", 0);                      0x9fff0000, 0x10000, "r2k3k_cache", 0, 0);
1427    
1428          symbol_recalc_sizes(&m->symbol_context);          symbol_recalc_sizes(&m->symbol_context);
1429    
         if (m->max_random_cycles_per_chunk > 0)  
                 debug("using random cycle chunks (1 to %i cycles)\n",  
                     m->max_random_cycles_per_chunk);  
   
1430          /*  Special hack for ARC/SGI emulation:  */          /*  Special hack for ARC/SGI emulation:  */
1431          if ((m->machine_type == MACHINE_ARC ||          if ((m->machine_type == MACHINE_ARC ||
1432              m->machine_type == MACHINE_SGI) && m->prom_emulation)              m->machine_type == MACHINE_SGI) && m->prom_emulation)
# Line 681  void emul_machine_setup(struct machine * Line 1434  void emul_machine_setup(struct machine *
1434    
1435          debug("starting cpu%i at ", m->bootstrap_cpu);          debug("starting cpu%i at ", m->bootstrap_cpu);
1436          switch (m->arch) {          switch (m->arch) {
1437    
1438            case ARCH_ARM:
1439                    /*  ARM cpus aren't 64-bit:  */
1440                    debug("0x%08x", (int)entrypoint);
1441                    break;
1442    
1443            case ARCH_AVR:
1444                    /*  Atmel AVR uses a 16-bit or 22-bit program counter:  */
1445                    debug("0x%04x", (int)entrypoint);
1446                    break;
1447    
1448          case ARCH_MIPS:          case ARCH_MIPS:
1449                  if (cpu->cd.mips.cpu_type.isa_level < 3 ||                  if (cpu->is_32bit) {
                     cpu->cd.mips.cpu_type.isa_level == 32) {  
1450                          debug("0x%08x", (int)m->cpus[                          debug("0x%08x", (int)m->cpus[
1451                              m->bootstrap_cpu]->pc);                              m->bootstrap_cpu]->pc);
1452                          if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)                          if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
# Line 698  void emul_machine_setup(struct machine * Line 1461  void emul_machine_setup(struct machine *
1461                                      cpu->cd.mips.gpr[MIPS_GPR_GP]);                                      cpu->cd.mips.gpr[MIPS_GPR_GP]);
1462                  }                  }
1463                  break;                  break;
1464    
1465          case ARCH_PPC:          case ARCH_PPC:
1466                  if (cpu->cd.ppc.bits == 32)                  if (cpu->cd.ppc.bits == 32)
1467                          debug("0x%08x", (int)entrypoint);                          debug("0x%08x", (int)entrypoint);
1468                  else                  else
1469                          debug("0x%016llx", (long long)entrypoint);                          debug("0x%016llx", (long long)entrypoint);
1470                  break;                  break;
1471          case ARCH_URISC:  
1472                  {          case ARCH_X86:
1473                          char tmps[100];                  debug("0x%04x:0x%llx", cpu->cd.x86.s[X86_S_CS],
1474                          unsigned char buf[sizeof(uint64_t)];                      (long long)cpu->pc);
   
                         cpu->memory_rw(cpu, m->memory, 0, buf, sizeof(buf),  
                             MEM_READ, CACHE_NONE | NO_EXCEPTIONS);  
   
                         entrypoint = 0;  
                         for (i=0; i<cpu->cd.urisc.wordlen/8; i++) {  
                                 entrypoint <<= 8;  
                                 if (cpu->byte_order == EMUL_BIG_ENDIAN)  
                                         entrypoint += buf[i];  
                                 else  
                                         entrypoint += buf[cpu->  
                                             cd.urisc.wordlen/8 - 1 - i];  
                         }  
   
                         sprintf(tmps, "0x%%0%illx", cpu->cd.urisc.wordlen / 4);  
                         debug(tmps, (long long)entrypoint);  
                         cpu->pc = entrypoint;  
                 }  
1475                  break;                  break;
1476    
1477          default:          default:
1478                  debug("0x%016llx", (long long)entrypoint);                  if (cpu->is_32bit)
1479                            debug("0x%08x", (int)cpu->pc);
1480                    else
1481                            debug("0x%016llx", (long long)cpu->pc);
1482          }          }
1483          debug("\n");          debug("\n");
1484    
# Line 743  void emul_machine_setup(struct machine * Line 1493  void emul_machine_setup(struct machine *
1493   */   */
1494  void emul_dumpinfo(struct emul *e)  void emul_dumpinfo(struct emul *e)
1495  {  {
1496          int j, nm, iadd = 4;          int j, nm, iadd = DEBUG_INDENTATION;
1497    
1498          if (e->net != NULL)          if (e->net != NULL)
1499                  net_dumpinfo(e->net);                  net_dumpinfo(e->net);
# Line 772  void emul_dumpinfo(struct emul *e) Line 1522  void emul_dumpinfo(struct emul *e)
1522   */   */
1523  void emul_simple_init(struct emul *emul)  void emul_simple_init(struct emul *emul)
1524  {  {
1525          int iadd=4;          int iadd = DEBUG_INDENTATION;
1526          struct machine *m;          struct machine *m;
1527    
1528          if (emul->n_machines != 1) {          if (emul->n_machines != 1) {
# Line 786  void emul_simple_init(struct emul *emul) Line 1536  void emul_simple_init(struct emul *emul)
1536                  debug("Simple setup...\n");                  debug("Simple setup...\n");
1537                  debug_indentation(iadd);                  debug_indentation(iadd);
1538    
1539                  /*  Create a network:  */                  /*  Create a simple network:  */
1540                  emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,                  emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
1541                      "10.0.0.0", 8);                      NET_DEFAULT_IPV4_MASK,
1542                        NET_DEFAULT_IPV4_LEN,
1543                        NULL, 0, 0, NULL);
1544          } else {          } else {
1545                  /*  Userland pseudo-machine:  */                  /*  Userland pseudo-machine:  */
1546                  debug("Syscall emulation (userland-only) setup...\n");                  debug("Syscall emulation (userland-only) setup...\n");
# Line 809  void emul_simple_init(struct emul *emul) Line 1561  void emul_simple_init(struct emul *emul)
1561   */   */
1562  struct emul *emul_create_from_configfile(char *fname)  struct emul *emul_create_from_configfile(char *fname)
1563  {  {
1564          int iadd = 4;          int iadd = DEBUG_INDENTATION;
1565          struct emul *e = emul_new(fname);          struct emul *e = emul_new(fname);
         FILE *f;  
         char buf[128];  
         size_t len;  
1566    
1567          debug("Creating emulation from configfile \"%s\":\n", fname);          debug("Creating emulation from configfile \"%s\":\n", fname);
1568          debug_indentation(iadd);          debug_indentation(iadd);
1569    
1570          f = fopen(fname, "r");          emul_parse_config(e, fname);
         if (f == NULL) {  
                 perror(fname);  
                 exit(1);  
         }  
1571    
         /*  Read header: (must be !!gxemul)  */  
         len = fread(buf, 1, 8, f);  
         if (len != 8 || strncmp(buf, "!!gxemul", 8) != 0) {  
                 fprintf(stderr, "%s: must start with '!!gxemul'\n", fname);  
                 exit(1);  
         }  
   
         /*  Restart from beginning:  */  
         rewind(f);  
   
         emul_parse_config(e, f);  
   
         fclose(f);  
1572          debug_indentation(-iadd);          debug_indentation(-iadd);
1573          return e;          return e;
1574  }  }
# Line 863  void emul_run(struct emul **emuls, int n Line 1595  void emul_run(struct emul **emuls, int n
1595    
1596          atexit(fix_console);          atexit(fix_console);
1597    
         i = 79;  
         while (i-- > 0)  
                 debug("-");  
         debug("\n\n");  
   
1598          /*  Initialize the interactive debugger:  */          /*  Initialize the interactive debugger:  */
1599          debugger_init(emuls, n_emuls);          debugger_init(emuls, n_emuls);
1600    
1601            /*  Run any additional debugger commands before starting:  */
1602            for (i=0; i<n_emuls; i++) {
1603                    struct emul *emul = emuls[i];
1604                    if (emul->n_debugger_cmds > 0) {
1605                            int j;
1606                            if (i == 0)
1607                                    print_separator();
1608                            for (j = 0; j < emul->n_debugger_cmds; j ++) {
1609                                    debug("> %s\n", emul->debugger_cmds[j]);
1610                                    debugger_execute_cmd(emul->debugger_cmds[j],
1611                                        strlen(emul->debugger_cmds[j]));
1612                            }
1613                    }
1614            }
1615    
1616            print_separator();
1617            debug("\n");
1618    
1619    
1620          /*          /*
1621           *  console_init_main() makes sure that the terminal is in a           *  console_init_main() makes sure that the terminal is in a
1622           *  reasonable state.           *  reasonable state.
# Line 895  void emul_run(struct emul **emuls, int n Line 1641  void emul_run(struct emul **emuls, int n
1641                  if (e == NULL)                  if (e == NULL)
1642                          continue;                          continue;
1643                  for (j=0; j<e->n_machines; j++)                  for (j=0; j<e->n_machines; j++)
1644                          cpu_run_init(e, e->machines[j]);                          cpu_run_init(e->machines[j]);
1645          }          }
1646    
1647            /*  TODO: Generalize:  */
1648            if (emuls[0]->machines[0]->show_trace_tree)
1649                    cpu_functioncall_trace(emuls[0]->machines[0]->cpus[0],
1650                        emuls[0]->machines[0]->cpus[0]->pc);
1651    
1652            /*  Start emulated clocks:  */
1653            timer_start();
1654    
1655          /*          /*
1656           *  MAIN LOOP:           *  MAIN LOOP:
1657           *           *
# Line 907  void emul_run(struct emul **emuls, int n Line 1661  void emul_run(struct emul **emuls, int n
1661          while (go) {          while (go) {
1662                  go = 0;                  go = 0;
1663    
1664                  x11_check_event(emuls, n_emuls);                  /*  Flush X11 and serial console output every now and then:  */
1665                    if (emuls[0]->machines[0]->ninstrs >
1666                        emuls[0]->machines[0]->ninstrs_flush + (1<<19)) {
1667                            x11_check_event(emuls, n_emuls);
1668                            console_flush();
1669                            emuls[0]->machines[0]->ninstrs_flush =
1670                                emuls[0]->machines[0]->ninstrs;
1671                    }
1672    
1673                    if (emuls[0]->machines[0]->ninstrs >
1674                        emuls[0]->machines[0]->ninstrs_show + (1<<25)) {
1675                            emuls[0]->machines[0]->ninstrs_since_gettimeofday +=
1676                                (emuls[0]->machines[0]->ninstrs -
1677                                 emuls[0]->machines[0]->ninstrs_show);
1678                            cpu_show_cycles(emuls[0]->machines[0], 0);
1679                            emuls[0]->machines[0]->ninstrs_show =
1680                                emuls[0]->machines[0]->ninstrs;
1681                    }
1682    
1683                    if (single_step == ENTER_SINGLE_STEPPING) {
1684                            /*  TODO: Cleanup!  */
1685                            old_instruction_trace =
1686                                emuls[0]->machines[0]->instruction_trace;
1687                            old_quiet_mode = quiet_mode;
1688                            old_show_trace_tree =
1689                                emuls[0]->machines[0]->show_trace_tree;
1690                            emuls[0]->machines[0]->instruction_trace = 1;
1691                            emuls[0]->machines[0]->show_trace_tree = 1;
1692                            quiet_mode = 0;
1693                            single_step = SINGLE_STEPPING;
1694                    }
1695    
1696                    if (single_step == SINGLE_STEPPING)
1697                            debugger();
1698    
1699                  for (i=0; i<n_emuls; i++) {                  for (i=0; i<n_emuls; i++) {
1700                          e = emuls[i];                          e = emuls[i];
                         if (e == NULL)  
                                 continue;  
1701    
1702                          for (j=0; j<e->n_machines; j++) {                          for (j=0; j<e->n_machines; j++) {
1703                                  /*  TODO: cpu_run() is a strange name, since                                  if (e->machines[j]->gdb.port > 0)
1704                                      there can be multiple cpus in a machine  */                                          debugger_gdb_check_incoming(
1705                                  anything = cpu_run(e, e->machines[j]);                                              e->machines[j]);
1706    
1707                                    anything = machine_run(e->machines[j]);
1708                                  if (anything)                                  if (anything)
1709                                          go = 1;                                          go = 1;
1710                          }                          }
1711                  }                  }
1712          }          }
1713    
1714            /*  Stop any running timers:  */
1715            timer_stop();
1716    
1717          /*  Deinitialize all CPUs in all machines in all emulations:  */          /*  Deinitialize all CPUs in all machines in all emulations:  */
1718          for (i=0; i<n_emuls; i++) {          for (i=0; i<n_emuls; i++) {
1719                  e = emuls[i];                  e = emuls[i];
1720                  if (e == NULL)                  if (e == NULL)
1721                          continue;                          continue;
1722                  for (j=0; j<e->n_machines; j++)                  for (j=0; j<e->n_machines; j++)
1723                          cpu_run_deinit(e, e->machines[j]);                          cpu_run_deinit(e->machines[j]);
1724          }          }
1725    
1726          /*  force_debugger_at_exit flag set? Then enter the debugger:  */          /*  force_debugger_at_exit flag set? Then enter the debugger:  */
# Line 940  void emul_run(struct emul **emuls, int n Line 1730  void emul_run(struct emul **emuls, int n
1730                  debugger();                  debugger();
1731          }          }
1732    
1733          /*  Any machine using X11? Then we should wait before exiting:  */          /*  Any machine using X11? Then wait before exiting:  */
1734          n = 0;          n = 0;
1735          for (i=0; i<n_emuls; i++)          for (i=0; i<n_emuls; i++)
1736                  for (j=0; j<emuls[i]->n_machines; j++)                  for (j=0; j<emuls[i]->n_machines; j++)
# Line 950  void emul_run(struct emul **emuls, int n Line 1740  void emul_run(struct emul **emuls, int n
1740                  printf("Press enter to quit.\n");                  printf("Press enter to quit.\n");
1741                  while (!console_charavail(MAIN_CONSOLE)) {                  while (!console_charavail(MAIN_CONSOLE)) {
1742                          x11_check_event(emuls, n_emuls);                          x11_check_event(emuls, n_emuls);
1743                          usleep(1);                          usleep(10000);
1744                  }                  }
1745                  console_readchar(MAIN_CONSOLE);                  console_readchar(MAIN_CONSOLE);
1746          }          }
1747    
1748          console_deinit();          console_deinit_main();
1749  }  }
1750    

Legend:
Removed from v.2  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26