/[gxemul]/trunk/src/machine.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/machine.c

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

revision 41 by dpavlin, Mon Oct 8 16:21:17 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: machine.c,v 1.693 2007/01/28 14:15:29 debug Exp $   *  $Id: machine.c,v 1.704 2007/06/15 17:02:38 debug Exp $
29   */   */
30    
31  #include <stdio.h>  #include <stdio.h>
# Line 35  Line 35 
35  #include <time.h>  #include <time.h>
36  #include <unistd.h>  #include <unistd.h>
37    
 #include "arcbios.h"  
 #include "bus_isa.h"  
 #include "bus_pci.h"  
38  #include "cpu.h"  #include "cpu.h"
 #include "debugger.h"  
39  #include "device.h"  #include "device.h"
 #include "devices.h"  
40  #include "diskimage.h"  #include "diskimage.h"
41  #include "emul.h"  #include "emul.h"
42  #include "machine.h"  #include "machine.h"
43  #include "memory.h"  #include "memory.h"
44  #include "misc.h"  #include "misc.h"
 #include "net.h"  
45  #include "settings.h"  #include "settings.h"
46  #include "symbol.h"  #include "symbol.h"
47    #include "useremul.h"
48    
49    
50  /*  See main.c:  */  /*  See main.c:  */
# Line 69  struct machine_entry *first_machine_entr Line 64  struct machine_entry *first_machine_entr
64  struct machine *machine_new(char *name, struct emul *emul, int id)  struct machine *machine_new(char *name, struct emul *emul, int id)
65  {  {
66          struct machine *m;          struct machine *m;
         m = malloc(sizeof(struct machine));  
         if (m == NULL) {  
                 fprintf(stderr, "machine_new(): out of memory\n");  
                 exit(1);  
         }  
67    
68            CHECK_ALLOCATION(m = malloc(sizeof(struct machine)));
69          memset(m, 0, sizeof(struct machine));          memset(m, 0, sizeof(struct machine));
70    
71          /*  Pointer back to the emul object that this machine belongs to:  */          /*  Pointer back to the emul object that this machine belongs to:  */
72          m->emul = emul;          m->emul = emul;
73    
74          m->name = strdup(name);          CHECK_ALLOCATION(m->name = strdup(name));
75    
76          /*  Full path, e.g. "emul[0].machine[0]":  */          /*  Full path, e.g. "emul[0].machine[0]":  */
77          m->path = malloc(strlen(emul->path) + 20);          CHECK_ALLOCATION(m->path = malloc(strlen(emul->path) + 20));
         if (m->path == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
78          snprintf(m->path, strlen(emul->path) + 20, "%s.machine[%i]",          snprintf(m->path, strlen(emul->path) + 20, "%s.machine[%i]",
79              emul->path, id);              emul->path, id);
80    
# Line 102  struct machine *machine_new(char *name, Line 89  struct machine *machine_new(char *name,
89          m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;          m->byte_order_override = NO_BYTE_ORDER_OVERRIDE;
90          m->boot_kernel_filename = "";          m->boot_kernel_filename = "";
91          m->boot_string_argument = NULL;          m->boot_string_argument = NULL;
92          m->x11_scaledown = 1;          m->x11_md.scaledown = 1;
93          m->x11_scaleup = 1;          m->x11_md.scaleup = 1;
94          m->n_gfx_cards = 1;          m->n_gfx_cards = 1;
         m->dbe_on_nonexistant_memaccess = 1;  
         m->show_symbolic_register_names = 1;  
95          symbol_init(&m->symbol_context);          symbol_init(&m->symbol_context);
96    
97          /*  Settings:  */          /*  Settings:  */
# Line 129  struct machine *machine_new(char *name, Line 114  struct machine *machine_new(char *name,
114          settings_add(m->settings, "n_gfx_cards", 0,          settings_add(m->settings, "n_gfx_cards", 0,
115              SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,              SETTINGS_TYPE_INT, SETTINGS_FORMAT_DECIMAL,
116              (void *) &m->n_gfx_cards);              (void *) &m->n_gfx_cards);
         settings_add(m->settings, "show_symbolic_register_names", 1,  
             SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,  
             (void *) &m->show_symbolic_register_names);  
117          settings_add(m->settings, "statistics_enabled", 1,          settings_add(m->settings, "statistics_enabled", 1,
118              SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,              SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
119              (void *) &m->statistics_enabled);              (void *) &m->statistics_enabled);
# Line 266  int machine_name_to_type(char *stype, ch Line 248  int machine_name_to_type(char *stype, ch
248    
249    
250  /*  /*
251     *  machine_add_breakpoint_string():
252     *
253     *  Add a breakpoint string to the machine. Later (in emul.c) these will be
254     *  converted to actual breakpoints.
255     */
256    void machine_add_breakpoint_string(struct machine *machine, char *str)
257    {
258            int n = machine->breakpoints.n + 1;
259    
260            CHECK_ALLOCATION(machine->breakpoints.string =
261                realloc(machine->breakpoints.string, n * sizeof(char *)));
262            CHECK_ALLOCATION(machine->breakpoints.addr =
263                realloc(machine->breakpoints.addr, n * sizeof(uint64_t)));
264            CHECK_ALLOCATION(machine->breakpoints.string[machine->breakpoints.n] =
265                strdup(optarg));
266    
267            machine->breakpoints.addr[machine->breakpoints.n] = 0;
268            machine->breakpoints.n ++;
269    }
270    
271    
272    /*
273   *  machine_add_tickfunction():   *  machine_add_tickfunction():
274   *   *
275   *  Adds a tick function (a function called every now and then, depending on   *  Adds a tick function (a function called every now and then, depending on
# Line 278  int machine_name_to_type(char *stype, ch Line 282  int machine_name_to_type(char *stype, ch
282   *  The hz value is used in this case.   *  The hz value is used in this case.
283   */   */
284  void machine_add_tickfunction(struct machine *machine, void (*func)  void machine_add_tickfunction(struct machine *machine, void (*func)
285          (struct cpu *, void *), void *extra, int tickshift, double hz)          (struct cpu *, void *), void *extra, int tickshift)
286  {  {
287          int n = machine->n_tick_entries;          int n = machine->tick_functions.n_entries;
288    
289          if (n >= MAX_TICK_FUNCTIONS) {          CHECK_ALLOCATION(machine->tick_functions.ticks_till_next = realloc(
290                  fprintf(stderr, "machine_add_tickfunction(): too "              machine->tick_functions.ticks_till_next, (n+1) * sizeof(int)));
291                      "many tick functions\n");          CHECK_ALLOCATION(machine->tick_functions.ticks_reset_value = realloc(
292                  exit(1);              machine->tick_functions.ticks_reset_value, (n+1) * sizeof(int)));
293          }          CHECK_ALLOCATION(machine->tick_functions.f = realloc(
294                machine->tick_functions.f, (n+1) * sizeof(void *)));
295            CHECK_ALLOCATION(machine->tick_functions.extra = realloc(
296                machine->tick_functions.extra, (n+1) * sizeof(void *)));
297    
298          if (!machine->cycle_accurate) {          /*
299                  /*           *  The dyntrans subsystem wants to run code in relatively
300                   *  The dyntrans subsystem wants to run code in relatively           *  large chunks without checking for external interrupts;
301                   *  large chunks without checking for external interrupts;           *  too low tickshifts are not allowed.
302                   *  too low tickshifts are not allowed.           */
303                   */          if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) {
304                  if (tickshift < N_SAFE_DYNTRANS_LIMIT_SHIFT) {                  fatal("ERROR! tickshift = %i, less than "
305                          fatal("ERROR! tickshift = %i, less than "                      "N_SAFE_DYNTRANS_LIMIT_SHIFT (%i)\n",
306                              "N_SAFE_DYNTRANS_LIMIT_SHIFT (%i)\n",                      tickshift, N_SAFE_DYNTRANS_LIMIT_SHIFT);
307                              tickshift, N_SAFE_DYNTRANS_LIMIT_SHIFT);                  exit(1);
                         exit(1);  
                 }  
308          }          }
309    
310          machine->ticks_till_next[n]   = 0;          machine->tick_functions.ticks_till_next[n]   = 0;
311          machine->ticks_reset_value[n] = 1 << tickshift;          machine->tick_functions.ticks_reset_value[n] = 1 << tickshift;
312          machine->tick_func[n]         = func;          machine->tick_functions.f[n]                 = func;
313          machine->tick_extra[n]        = extra;          machine->tick_functions.extra[n]             = extra;
         machine->tick_hz[n]           = hz;  
314    
315          machine->n_tick_entries ++;          machine->tick_functions.n_entries = n + 1;
316  }  }
317    
318    
# Line 333  void machine_statistics_init(struct mach Line 337  void machine_statistics_init(struct mach
337                  exit(1);                  exit(1);
338          }          }
339    
         machine->statistics_fields = malloc(MAX_STATISTICS_FIELDS + 1);  
340          machine->statistics_enabled = 1;          machine->statistics_enabled = 1;
341            CHECK_ALLOCATION(machine->statistics_fields = malloc(1));
342            machine->statistics_fields[0] = '\0';
343    
344          while (*pcolon && *pcolon != ':')          while (*pcolon && *pcolon != ':')
345                  pcolon ++;                  pcolon ++;
# Line 353  void machine_statistics_init(struct mach Line 358  void machine_statistics_init(struct mach
358                  case 'v':                  case 'v':
359                  case 'i':                  case 'i':
360                  case 'p':                  case 'p':
361                            CHECK_ALLOCATION(machine->statistics_fields = realloc(
362                                machine->statistics_fields, strlen(
363                                machine->statistics_fields) + 2));
364                          machine->statistics_fields[n_fields ++] = *fname;                          machine->statistics_fields[n_fields ++] = *fname;
                         if (n_fields >= MAX_STATISTICS_FIELDS) {  
                                 fprintf(stderr, "Internal error: Too many "  
                                     "statistics fields used. Increase "  
                                     "MAX_STATISTICS_FIELDS.\n");  
                                 exit(1);  
                         }  
365                          machine->statistics_fields[n_fields] = '\0';                          machine->statistics_fields[n_fields] = '\0';
366                          break;                          break;
367    
# Line 380  void machine_statistics_init(struct mach Line 382  void machine_statistics_init(struct mach
382    
383          fname ++;       /*  point to the filename after the colon  */          fname ++;       /*  point to the filename after the colon  */
384    
385          machine->statistics_filename = strdup(fname);          CHECK_ALLOCATION(machine->statistics_filename = strdup(fname));
386          machine->statistics_file = fopen(machine->statistics_filename, mode);          machine->statistics_file = fopen(machine->statistics_filename, mode);
387  }  }
388    
# Line 405  void machine_dumpinfo(struct machine *m) Line 407  void machine_dumpinfo(struct machine *m)
407                  debug(" (offset by %i MB)", m->memory_offset_in_mb);                  debug(" (offset by %i MB)", m->memory_offset_in_mb);
408          if (m->random_mem_contents)          if (m->random_mem_contents)
409                  debug(", randomized contents");                  debug(", randomized contents");
         if (m->dbe_on_nonexistant_memaccess)  
                 debug(", dbe_on_nonexistant_memaccess");  
410          debug("\n");          debug("\n");
411    
412          if (!m->prom_emulation)          if (!m->prom_emulation)
# Line 421  void machine_dumpinfo(struct machine *m) Line 421  void machine_dumpinfo(struct machine *m)
421          if (m->slow_serial_interrupts_hack_for_linux)          if (m->slow_serial_interrupts_hack_for_linux)
422                  debug("Using slow_serial_interrupts_hack_for_linux\n");                  debug("Using slow_serial_interrupts_hack_for_linux\n");
423    
424          if (m->use_x11) {          if (m->x11_md.in_use) {
425                  debug("Using X11");                  debug("Using X11");
426                  if (m->x11_scaledown > 1)                  if (m->x11_md.scaledown > 1)
427                          debug(", scaledown %i", m->x11_scaledown);                          debug(", scaledown %i", m->x11_md.scaledown);
428                  if (m->x11_scaleup > 1)                  if (m->x11_md.scaleup > 1)
429                          debug(", scaleup %i", m->x11_scaleup);                          debug(", scaleup %i", m->x11_md.scaleup);
430                  if (m->x11_n_display_names > 0) {                  if (m->x11_md.n_display_names > 0) {
431                          for (i=0; i<m->x11_n_display_names; i++) {                          for (i=0; i<m->x11_md.n_display_names; i++) {
432                                  debug(i? ", " : " (");                                  debug(i? ", " : " (");
433                                  debug("\"%s\"", m->x11_display_names[i]);                                  debug("\"%s\"", m->x11_md.display_names[i]);
434                          }                          }
435                          debug(")");                          debug(")");
436                  }                  }
# Line 445  void machine_dumpinfo(struct machine *m) Line 445  void machine_dumpinfo(struct machine *m)
445    
446    
447  /*  /*
  *  dump_mem_string():  
  *  
  *  Dump the contents of emulated RAM as readable text.  Bytes that aren't  
  *  readable are dumped in [xx] notation, where xx is in hexadecimal.  
  *  Dumping ends after DUMP_MEM_STRING_MAX bytes, or when a terminating  
  *  zero byte is found.  
  */  
 #define DUMP_MEM_STRING_MAX     45  
 void dump_mem_string(struct cpu *cpu, uint64_t addr)  
 {  
         int i;  
         for (i=0; i<DUMP_MEM_STRING_MAX; i++) {  
                 unsigned char ch = '\0';  
   
                 cpu->memory_rw(cpu, cpu->mem, addr + i, &ch, sizeof(ch),  
                     MEM_READ, CACHE_DATA | NO_EXCEPTIONS);  
                 if (ch == '\0')  
                         return;  
                 if (ch >= ' ' && ch < 126)  
                         debug("%c", ch);    
                 else  
                         debug("[%02x]", ch);  
         }  
 }  
   
   
 /*  
  *  store_byte():  
  *  
  *  Stores a byte in emulated ram. (Helper function.)  
  */  
 void store_byte(struct cpu *cpu, uint64_t addr, uint8_t data)  
 {  
         if ((addr >> 32) == 0)  
                 addr = (int64_t)(int32_t)addr;  
         cpu->memory_rw(cpu, cpu->mem,  
             addr, &data, sizeof(data), MEM_WRITE, CACHE_DATA);  
 }  
   
   
 /*  
  *  store_string():  
  *  
  *  Stores chars into emulated RAM until a zero byte (string terminating  
  *  character) is found. The zero byte is also copied.  
  *  (strcpy()-like helper function, host-RAM-to-emulated-RAM.)  
  */  
 void store_string(struct cpu *cpu, uint64_t addr, char *s)  
 {  
         do {  
                 store_byte(cpu, addr++, *s);  
         } while (*s++);  
 }  
   
   
 /*  
  *  add_environment_string():  
  *  
  *  Like store_string(), but advances the pointer afterwards. The most  
  *  obvious use is to place a number of strings (such as environment variable  
  *  strings) after one-another in emulated memory.  
  */  
 void add_environment_string(struct cpu *cpu, char *s, uint64_t *addr)  
 {  
         store_string(cpu, *addr, s);  
         (*addr) += strlen(s) + 1;  
 }  
   
   
 /*  
  *  add_environment_string_dual():  
  *  
  *  Add "dual" environment strings, one for the variable name and one for the  
  *  value, and update pointers afterwards.  
  */  
 void add_environment_string_dual(struct cpu *cpu,  
         uint64_t *ptrp, uint64_t *addrp, char *s1, char *s2)  
 {  
         uint64_t ptr = *ptrp, addr = *addrp;  
   
         store_32bit_word(cpu, ptr, addr);  
         ptr += sizeof(uint32_t);  
         if (addr != 0) {  
                 store_string(cpu, addr, s1);  
                 addr += strlen(s1) + 1;  
         }  
         store_32bit_word(cpu, ptr, addr);  
         ptr += sizeof(uint32_t);  
         if (addr != 0) {  
                 store_string(cpu, addr, s2);  
                 addr += strlen(s2) + 1;  
         }  
   
         *ptrp = ptr;  
         *addrp = addr;  
 }  
   
   
 /*  
  *  store_64bit_word():  
  *  
  *  Stores a 64-bit word in emulated RAM.  Byte order is taken into account.  
  *  Helper function.  
  */  
 int store_64bit_word(struct cpu *cpu, uint64_t addr, uint64_t data64)  
 {  
         unsigned char data[8];  
         if ((addr >> 32) == 0)  
                 addr = (int64_t)(int32_t)addr;  
         data[0] = (data64 >> 56) & 255;  
         data[1] = (data64 >> 48) & 255;  
         data[2] = (data64 >> 40) & 255;  
         data[3] = (data64 >> 32) & 255;  
         data[4] = (data64 >> 24) & 255;  
         data[5] = (data64 >> 16) & 255;  
         data[6] = (data64 >> 8) & 255;  
         data[7] = (data64) & 255;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;  
                 tmp = data[1]; data[1] = data[6]; data[6] = tmp;  
                 tmp = data[2]; data[2] = data[5]; data[5] = tmp;  
                 tmp = data[3]; data[3] = data[4]; data[4] = tmp;  
         }  
         return cpu->memory_rw(cpu, cpu->mem,  
             addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);  
 }  
   
   
 /*  
  *  store_32bit_word():  
  *  
  *  Stores a 32-bit word in emulated RAM.  Byte order is taken into account.  
  *  (This function takes a 64-bit word as argument, to suppress some  
  *  warnings, but only the lowest 32 bits are used.)  
  */  
 int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)  
 {  
         unsigned char data[4];  
   
         /*  TODO: REMOVE THIS once everything is more stable!  */  
         if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)  
                 addr = (int64_t)(int32_t)addr;  
   
         data[0] = (data32 >> 24) & 255;  
         data[1] = (data32 >> 16) & 255;  
         data[2] = (data32 >> 8) & 255;  
         data[3] = (data32) & 255;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;  
                 tmp = data[1]; data[1] = data[2]; data[2] = tmp;  
         }  
         return cpu->memory_rw(cpu, cpu->mem,  
             addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);  
 }  
   
   
 /*  
  *  store_16bit_word():  
  *  
  *  Stores a 16-bit word in emulated RAM.  Byte order is taken into account.  
  *  (This function takes a 64-bit word as argument, to suppress some  
  *  warnings, but only the lowest 16 bits are used.)  
  */  
 int store_16bit_word(struct cpu *cpu, uint64_t addr, uint64_t data16)  
 {  
         unsigned char data[2];  
   
         /*  TODO: REMOVE THIS once everything is more stable!  */  
         if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)  
                 addr = (int64_t)(int32_t)addr;  
   
         data[0] = (data16 >> 8) & 255;  
         data[1] = (data16) & 255;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;  
         }  
         return cpu->memory_rw(cpu, cpu->mem,  
             addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);  
 }  
   
   
 /*  
  *  store_buf():  
  *  
  *  memcpy()-like helper function, from host RAM to emulated RAM.  
  */  
 void store_buf(struct cpu *cpu, uint64_t addr, char *s, size_t len)  
 {  
         size_t psize = 1024;    /*  1024 256 64 16 4 1  */  
   
         /*  TODO: REMOVE THIS once everything is more stable!  */  
         if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)  
                 addr = (int64_t)(int32_t)addr;  
   
         while (len != 0) {  
                 if ((addr & (psize-1)) == 0) {  
                         while (len >= psize) {  
                                 cpu->memory_rw(cpu, cpu->mem, addr,  
                                     (unsigned char *)s, psize, MEM_WRITE,  
                                     CACHE_DATA);  
                                 addr += psize;  
                                 s += psize;  
                                 len -= psize;  
                         }  
                 }  
                 psize >>= 2;  
         }  
   
         while (len-- != 0)  
                 store_byte(cpu, addr++, *s++);  
 }  
   
   
 /*  
  *  store_pointer_and_advance():  
  *  
  *  Stores a 32-bit or 64-bit pointer in emulated RAM, and advances the  
  *  target address. (Useful for e.g. ARCBIOS environment initialization.)  
  */  
 void store_pointer_and_advance(struct cpu *cpu, uint64_t *addrp,  
         uint64_t data, int flag64)  
 {  
         uint64_t addr = *addrp;  
         if (flag64) {  
                 store_64bit_word(cpu, addr, data);  
                 addr += 8;  
         } else {  
                 store_32bit_word(cpu, addr, data);  
                 addr += 4;  
         }  
         *addrp = addr;  
 }  
   
   
 /*  
  *  load_64bit_word():  
  *  
  *  Helper function. Emulated byte order is taken into account.  
  */  
 uint64_t load_64bit_word(struct cpu *cpu, uint64_t addr)  
 {  
         unsigned char data[8];  
   
         cpu->memory_rw(cpu, cpu->mem,  
             addr, data, sizeof(data), MEM_READ, CACHE_DATA);  
   
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;  
                 tmp = data[1]; data[1] = data[6]; data[6] = tmp;  
                 tmp = data[2]; data[2] = data[5]; data[5] = tmp;  
                 tmp = data[3]; data[3] = data[4]; data[4] = tmp;  
         }  
   
         return  
             ((uint64_t)data[0] << 56) + ((uint64_t)data[1] << 48) +  
             ((uint64_t)data[2] << 40) + ((uint64_t)data[3] << 32) +  
             ((uint64_t)data[4] << 24) + ((uint64_t)data[5] << 16) +  
             ((uint64_t)data[6] << 8) + (uint64_t)data[7];  
 }  
   
   
 /*  
  *  load_32bit_word():  
  *  
  *  Helper function. Emulated byte order is taken into account.  
  */  
 uint32_t load_32bit_word(struct cpu *cpu, uint64_t addr)  
 {  
         unsigned char data[4];  
   
         /*  TODO: REMOVE THIS once everything is more stable!  */  
         if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)  
                 addr = (int64_t)(int32_t)addr;  
   
         cpu->memory_rw(cpu, cpu->mem,  
             addr, data, sizeof(data), MEM_READ, CACHE_DATA);  
   
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;  
                 tmp = data[1]; data[1] = data[2]; data[2] = tmp;  
         }  
   
         return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];  
 }  
   
   
 /*  
  *  load_16bit_word():  
  *  
  *  Helper function. Emulated byte order is taken into account.  
  */  
 uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr)  
 {  
         unsigned char data[2];  
   
         /*  TODO: REMOVE THIS once everything is more stable!  */  
         if (cpu->machine->arch == ARCH_MIPS && (addr >> 32) == 0)  
                 addr = (int64_t)(int32_t)addr;  
   
         cpu->memory_rw(cpu, cpu->mem,  
             addr, data, sizeof(data), MEM_READ, CACHE_DATA);  
   
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;  
         }  
   
         return (data[0] << 8) + data[1];  
 }  
   
   
 /*  
  *  store_64bit_word_in_host():  
  *  
  *  Stores a 64-bit word in the _host's_ RAM.  Emulated byte order is taken  
  *  into account.  This is useful when building structs in the host's RAM  
  *  which will later be copied into emulated RAM.  
  */  
 void store_64bit_word_in_host(struct cpu *cpu,  
         unsigned char *data, uint64_t data64)  
 {  
         data[0] = (data64 >> 56) & 255;  
         data[1] = (data64 >> 48) & 255;  
         data[2] = (data64 >> 40) & 255;  
         data[3] = (data64 >> 32) & 255;  
         data[4] = (data64 >> 24) & 255;  
         data[5] = (data64 >> 16) & 255;  
         data[6] = (data64 >> 8) & 255;  
         data[7] = (data64) & 255;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;  
                 tmp = data[1]; data[1] = data[6]; data[6] = tmp;  
                 tmp = data[2]; data[2] = data[5]; data[5] = tmp;  
                 tmp = data[3]; data[3] = data[4]; data[4] = tmp;  
         }  
 }  
   
   
 /*  
  *  store_32bit_word_in_host():  
  *  
  *  See comment for store_64bit_word_in_host().  
  *  
  *  (Note:  The data32 parameter is a uint64_t. This is done to suppress  
  *  some warnings.)  
  */  
 void store_32bit_word_in_host(struct cpu *cpu,  
         unsigned char *data, uint64_t data32)  
 {  
         data[0] = (data32 >> 24) & 255;  
         data[1] = (data32 >> 16) & 255;  
         data[2] = (data32 >> 8) & 255;  
         data[3] = (data32) & 255;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;  
                 tmp = data[1]; data[1] = data[2]; data[2] = tmp;  
         }  
 }  
   
   
 /*  
  *  store_16bit_word_in_host():  
  *  
  *  See comment for store_64bit_word_in_host().  
  */  
 void store_16bit_word_in_host(struct cpu *cpu,  
         unsigned char *data, uint16_t data16)  
 {  
         data[0] = (data16 >> 8) & 255;  
         data[1] = (data16) & 255;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;  
         }  
 }  
   
   
 /*  
448   *  machine_setup():   *  machine_setup():
449   *   *
450   *  This (rather large) function initializes memory, registers, and/or devices   *  This (rather large) function initializes memory, registers, and/or devices
# Line 895  void machine_setup(struct machine *machi Line 519  void machine_setup(struct machine *machi
519                          debug(" %s", machine->bootarg);                          debug(" %s", machine->bootarg);
520                  debug("\n");                  debug("\n");
521          }          }
   
         if (!machine->stable)  
                 fatal("!\n!  NOTE: This machine type is not implemented well"  
                     " enough yet to run\n!  any real-world code!"  
                     " (At least, it hasn't been verified to do so.)\n!\n"  
                     "!  Please read the GXemul documentation for information"  
                     " about which\n!  machine types that actually work.\n!\n");  
522  }  }
523    
524    
# Line 930  void machine_memsize_fix(struct machine Line 547  void machine_memsize_fix(struct machine
547                  }                  }
548          }          }
549    
         /*  Special hack for hpcmips machines:  */  
         if (m->machine_type == MACHINE_HPCMIPS) {  
                 m->dbe_on_nonexistant_memaccess = 0;  
         }  
   
550          /*  Special SGI memory offsets:  (TODO: move this somewhere else)  */          /*  Special SGI memory offsets:  (TODO: move this somewhere else)  */
551          if (m->machine_type == MACHINE_SGI) {          if (m->machine_type == MACHINE_SGI) {
552                  switch (m->machine_subtype) {                  switch (m->machine_subtype) {
# Line 1027  int machine_run(struct machine *machine) Line 639  int machine_run(struct machine *machine)
639           *  TODO: This should be redesigned into some "mainbus" stuff instead!           *  TODO: This should be redesigned into some "mainbus" stuff instead!
640           */           */
641    
642          machine->ninstrs += cpu0instrs;          for (te=0; te<machine->tick_functions.n_entries; te++) {
643                    machine->tick_functions.ticks_till_next[te] -= cpu0instrs;
644          for (te=0; te<machine->n_tick_entries; te++) {                  if (machine->tick_functions.ticks_till_next[te] <= 0) {
645                  machine->ticks_till_next[te] -= cpu0instrs;                          while (machine->tick_functions.ticks_till_next[te]<=0) {
646                  if (machine->ticks_till_next[te] <= 0) {                                  machine->tick_functions.ticks_till_next[te] +=
647                          while (machine->ticks_till_next[te] <= 0) {                                      machine->tick_functions.
648                                  machine->ticks_till_next[te] +=                                      ticks_reset_value[te];
                                     machine->ticks_reset_value[te];  
649                          }                          }
650    
651                          machine->tick_func[te](cpus[0],                          machine->tick_functions.f[te](cpus[0],
652                              machine->tick_extra[te]);                              machine->tick_functions.extra[te]);
653                  }                  }
654          }          }
655    
# Line 1067  struct machine_entry *machine_entry_new( Line 678  struct machine_entry *machine_entry_new(
678  {  {
679          struct machine_entry *me;          struct machine_entry *me;
680    
681          me = malloc(sizeof(struct machine_entry));          CHECK_ALLOCATION(me = malloc(sizeof(struct machine_entry)));
         if (me == NULL) {  
                 fprintf(stderr, "machine_entry_new(): out of memory (1)\n");  
                 exit(1);  
         }  
   
682          memset(me, 0, sizeof(struct machine_entry));          memset(me, 0, sizeof(struct machine_entry));
683    
684          me->name = name;          me->name = name;
# Line 1095  struct machine_entry *machine_entry_new( Line 701  struct machine_entry *machine_entry_new(
701  void machine_entry_add_alias(struct machine_entry *me, const char *name)  void machine_entry_add_alias(struct machine_entry *me, const char *name)
702  {  {
703          me->n_aliases ++;          me->n_aliases ++;
704          me->aliases = realloc(me->aliases, sizeof(char *) * me->n_aliases);  
705          if (me->aliases == NULL) {          CHECK_ALLOCATION(me->aliases = realloc(me->aliases,
706                  fprintf(stderr, "out of memory\n");              sizeof(char *) * me->n_aliases));
                 exit(1);  
         }  
707    
708          me->aliases[me->n_aliases - 1] = (char *) name;          me->aliases[me->n_aliases - 1] = (char *) name;
709  }  }
# Line 1121  void machine_entry_add_subtype(struct ma Line 725  void machine_entry_add_subtype(struct ma
725          struct machine_entry_subtype *mes;          struct machine_entry_subtype *mes;
726    
727          /*  Allocate a new subtype struct:  */          /*  Allocate a new subtype struct:  */
728          mes = malloc(sizeof(struct machine_entry_subtype));          CHECK_ALLOCATION(mes = malloc(sizeof(struct machine_entry_subtype)));
         if (mes == NULL) {  
                 fprintf(stderr, "machine_entry_subtype_new(): out "  
                     "of memory (1)\n");  
                 exit(1);  
         }  
729    
730          /*  Add the subtype to the machine entry:  */          /*  Add the subtype to the machine entry:  */
731          me->n_subtypes ++;          me->n_subtypes ++;
732          me->subtype = realloc(me->subtype, sizeof(struct          CHECK_ALLOCATION(me->subtype = realloc(me->subtype, sizeof(struct
733              machine_entry_subtype *) * me->n_subtypes);              machine_entry_subtype *) * me->n_subtypes));
         if (me->subtype == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
734          me->subtype[me->n_subtypes - 1] = mes;          me->subtype[me->n_subtypes - 1] = mes;
735    
736          /*  Fill the struct with subtype data:  */          /*  Fill the struct with subtype data:  */
# Line 1155  void machine_entry_add_subtype(struct ma Line 750  void machine_entry_add_subtype(struct ma
750                          break;                          break;
751    
752                  mes->n_aliases ++;                  mes->n_aliases ++;
753                  mes->aliases = realloc(mes->aliases, sizeof(char *) *                  CHECK_ALLOCATION(mes->aliases =
754                      mes->n_aliases);                      realloc(mes->aliases, sizeof(char *) * mes->n_aliases));
                 if (mes->aliases == NULL) {  
                         fprintf(stderr, "out of memory\n");  
                         exit(1);  
                 }  
755    
756                  mes->aliases[mes->n_aliases - 1] = s;                  mes->aliases[mes->n_aliases - 1] = s;
757          }          }
# Line 1263  void machine_list_available_types_and_cp Line 854  void machine_list_available_types_and_cp
854              "that actually work. Use the alias\nwhen selecting a machine type "              "that actually work. Use the alias\nwhen selecting a machine type "
855              "or subtype, not the real name.\n");              "or subtype, not the real name.\n");
856    
 #ifdef UNSTABLE_DEVEL  
857          debug("\n");          debug("\n");
858    
859          useremul_list_emuls();          useremul_list_emuls();
860          debug("Userland emulation works for programs with the complexity"          debug("Userland emulation works for programs with the complexity"
861              " of Hello World,\nbut not much more.\n");              " of Hello World,\nbut not much more.\n");
 #endif  
862  }  }
863    
864    

Legend:
Removed from v.41  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26