/[gxemul]/trunk/src/cpus/cpu_sparc.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/cpus/cpu_sparc.c

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

revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  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: cpu_sparc.c,v 1.30 2006/06/16 18:31:26 debug Exp $   *  $Id: cpu_sparc.c,v 1.46 2007/06/07 15:36:24 debug Exp $
29   *   *
30   *  SPARC CPU emulation.   *  SPARC CPU emulation.
31   */   */
# Line 39  Line 39 
39  #include "machine.h"  #include "machine.h"
40  #include "memory.h"  #include "memory.h"
41  #include "misc.h"  #include "misc.h"
42    #include "settings.h"
43  #include "symbol.h"  #include "symbol.h"
44    #include "timer.h"
45    
46    
47  #define DYNTRANS_DUALMODE_32  #define DYNTRANS_DUALMODE_32
# Line 47  Line 49 
49  #include "tmp_sparc_head.c"  #include "tmp_sparc_head.c"
50    
51    
52    extern int native_code_translation_enabled;
53    
54  static char *sparc_regnames[N_SPARC_REG] = SPARC_REG_NAMES;  static char *sparc_regnames[N_SPARC_REG] = SPARC_REG_NAMES;
55  static char *sparc_pregnames[N_SPARC_PREG] = SPARC_PREG_NAMES;  static char *sparc_pregnames[N_SPARC_PREG] = SPARC_PREG_NAMES;
56  static char *sparc_regbranch_names[N_SPARC_REGBRANCH_TYPES] =  static char *sparc_regbranch_names[N_SPARC_REGBRANCH_TYPES] =
# Line 90  int sparc_cpu_new(struct cpu *cpu, struc Line 94  int sparc_cpu_new(struct cpu *cpu, struc
94    
95          cpu->instruction_has_delayslot = sparc_cpu_instruction_has_delayslot;          cpu->instruction_has_delayslot = sparc_cpu_instruction_has_delayslot;
96    
97            /*  TODO: Separate this into 64-bit vs 32-bit?  */
98            cpu->translate_v2p = sparc_translate_v2p;
99    
100          if (cpu->is_32bit) {          if (cpu->is_32bit) {
101                    cpu->run_instr = sparc32_run_instr;
102                  cpu->update_translation_table =                  cpu->update_translation_table =
103                      sparc32_update_translation_table;                      sparc32_update_translation_table;
104                  cpu->invalidate_translation_caches =                  cpu->invalidate_translation_caches =
# Line 98  int sparc_cpu_new(struct cpu *cpu, struc Line 106  int sparc_cpu_new(struct cpu *cpu, struc
106                  cpu->invalidate_code_translation =                  cpu->invalidate_code_translation =
107                      sparc32_invalidate_code_translation;                      sparc32_invalidate_code_translation;
108          } else {          } else {
109                    cpu->run_instr = sparc_run_instr;
110                  cpu->update_translation_table = sparc_update_translation_table;                  cpu->update_translation_table = sparc_update_translation_table;
111                  cpu->invalidate_translation_caches =                  cpu->invalidate_translation_caches =
112                      sparc_invalidate_translation_caches;                      sparc_invalidate_translation_caches;
# Line 133  int sparc_cpu_new(struct cpu *cpu, struc Line 142  int sparc_cpu_new(struct cpu *cpu, struc
142          cpu->cd.sparc.tick |= SPARC_TICK_NPT;          cpu->cd.sparc.tick |= SPARC_TICK_NPT;
143    
144          /*  Insert number of Windows and Trap levels into the version reg.:  */          /*  Insert number of Windows and Trap levels into the version reg.:  */
145          cpu->cd.sparc.ver |= MAXWIN | (MAXTL << SPARC_VER_MAXTL_SHIFT);          cpu->cd.sparc.ver |= N_REG_WINDOWS | (MAXTL << SPARC_VER_MAXTL_SHIFT);
146    
147          sparc_init_64bit_dummy_tables(cpu);          /*  Misc. initial settings suitable for userland emulation:  */
148            cpu->cd.sparc.cansave = cpu->cd.sparc.cpu_type.nwindows - 2;
149            cpu->cd.sparc.canrestore = 0;
150            cpu->cd.sparc.cleanwin = 1;
151            cpu->cd.sparc.otherwin = 0;
152    
153            if (cpu->cd.sparc.cansave + cpu->cd.sparc.canrestore
154                + cpu->cd.sparc.otherwin != cpu->cd.sparc.cpu_type.nwindows - 2) {
155                    fatal("Fatal internal error: inconsistent windowing "
156                        "parameters!\n");
157                    exit(1);
158            }
159    
160            if (cpu->cd.sparc.cpu_type.nwindows > N_REG_WINDOWS) {
161                    fatal("Fatal internal error: nwindows = %1 is more than %i\n",
162                        cpu->cd.sparc.cpu_type.nwindows, N_REG_WINDOWS);
163                    exit(1);
164            }
165    
166            CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
167            CPU_SETTINGS_ADD_REGISTER64("y", cpu->cd.sparc.y);
168            CPU_SETTINGS_ADD_REGISTER64("pstate", cpu->cd.sparc.pstate);
169            for (i=0; i<N_SPARC_REG; i++)
170                    CPU_SETTINGS_ADD_REGISTER64(sparc_regnames[i],
171                        cpu->cd.sparc.r[i]);
172            /*  TODO: Handler for writes to the zero register!  */
173    
174            if (native_code_translation_enabled)
175                    cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ,
176                        sparc_timer_sample_tick, cpu);
177    
178          return 1;          return 1;
179  }  }
# Line 236  void sparc_cpu_register_dump(struct cpu Line 274  void sparc_cpu_register_dump(struct cpu
274                                          continue;                                          continue;
275                                  }                                  }
276                                  debug("%s=", sparc_regnames[i]);                                  debug("%s=", sparc_regnames[i]);
277                                  debug("0x%08x", (int) cpu->cd.sparc.r[i]);                                  debug("0x%08"PRIx32,
278                                        (uint32_t) cpu->cd.sparc.r[i]);
279                                  if ((i & 3) < 3)                                  if ((i & 3) < 3)
280                                          debug("  ");                                          debug("  ");
281                                  else                                  else
# Line 265  void sparc_cpu_register_dump(struct cpu Line 304  void sparc_cpu_register_dump(struct cpu
304                          }                          }
305                  }                  }
306          }          }
 }  
307    
308            if (coprocs & 1) {
309                    int sum;
310    
311  /*                  debug("cpu%i: cwp        = 0x%02x\n", x, cpu->cd.sparc.cwp);
312   *  sparc_cpu_register_match():                  debug("cpu%i: cansave    = 0x%02x\n", x, cpu->cd.sparc.cansave);
313   */                  debug("cpu%i: canrestore = 0x%02x\n", x,
314  void sparc_cpu_register_match(struct machine *m, char *name,                      cpu->cd.sparc.canrestore);
315          int writeflag, uint64_t *valuep, int *match_register)                  debug("cpu%i: otherwin   = 0x%02x\n", x,
316  {                      cpu->cd.sparc.otherwin);
317          int i, cpunr = 0;                  debug("cpu%i: cleanwin   = 0x%02x\n", x,
318                        cpu->cd.sparc.cleanwin);
319    
320                    sum = cpu->cd.sparc.cansave + cpu->cd.sparc.canrestore +
321                        cpu->cd.sparc.otherwin;
322                    debug("cpu%i: cansave + canrestore + otherwin = %i + %i + %i"
323                        " = %i", x, cpu->cd.sparc.cansave, cpu->cd.sparc.canrestore,
324                        cpu->cd.sparc.otherwin, sum);
325                    if (sum == cpu->cd.sparc.cpu_type.nwindows - 2)
326                            debug("  (consistent)\n");
327                    else
328                            debug("  (INCONSISTENT!)\n");
329    
330          /*  CPU number:  */                  debug("cpu%i: wstate: other = %i, normal = %i\n",
331          /*  TODO  */                      x, (cpu->cd.sparc.wstate & SPARC_WSTATE_OTHER_MASK)
332                        >> SPARC_WSTATE_OTHER_SHIFT, cpu->cd.sparc.wstate &
333                        SPARC_WSTATE_NORMAL_MASK);
334    
335                    debug("cpu%i: asi = 0x%02x\n", x, cpu->cd.sparc.asi);
336                    debug("cpu%i: tl  = 0x%02x\n", x, cpu->cd.sparc.tl);
337                    debug("cpu%i: pil = 0x%02x\n", x, cpu->cd.sparc.pil);
338    
339                    for (i=0; i<MAXTL; i++) {
340                            debug("cpu%i: tpc[%i]    = 0x", x, i);
341                            if (bits32)
342                                    debug("%08"PRIx32"\n",
343                                        (uint32_t) cpu->cd.sparc.tpc[i]);
344                            else
345                                    debug("%016"PRIx64"\n",
346                                        (uint64_t) cpu->cd.sparc.tpc[i]);
347    
348          for (i=0; i<N_SPARC_REG; i++) {                          debug("cpu%i: tnpc[%i]   = 0x", x, i);
349                  if (strcasecmp(name, sparc_regnames[i]) == 0) {                          if (bits32)
350                          if (writeflag && i != SPARC_ZEROREG)                                  debug("%08"PRIx32"\n",
351                                  m->cpus[cpunr]->cd.sparc.r[i] = *valuep;                                      (uint32_t) cpu->cd.sparc.tnpc[i]);
352                          else                          else
353                                  *valuep = m->cpus[cpunr]->cd.sparc.r[i];                                  debug("%016"PRIx64"\n",
354                          *match_register = 1;                                      (uint64_t) cpu->cd.sparc.tnpc[i]);
                 }  
         }  
355    
356          if (strcasecmp(name, "pc") == 0) {                          debug("cpu%i: tstate[%i] = 0x", x, i);
357                  if (writeflag) {                          if (bits32)
358                          m->cpus[cpunr]->pc = *valuep;                                  debug("%08"PRIx32"\n",
359                  } else {                                      (uint32_t) cpu->cd.sparc.tstate[i]);
360                          *valuep = m->cpus[cpunr]->pc;                          else
361                  }                                  debug("%016"PRIx64"\n",
362                  *match_register = 1;                                      (uint64_t) cpu->cd.sparc.tstate[i]);
         }  
363    
364          if (strcasecmp(name, "y") == 0) {                          debug("cpu%i: ttype[%i]  = 0x"PRIx32"\n",
365                  if (writeflag) {                              x, i, cpu->cd.sparc.ttype[i]);
                         m->cpus[cpunr]->cd.sparc.y = (uint32_t) *valuep;  
                 } else {  
                         *valuep = (uint32_t) m->cpus[cpunr]->cd.sparc.y;  
366                  }                  }
                 *match_register = 1;  
         }  
367    
368          if (*match_register && m->cpus[cpunr]->is_32bit)                  debug("cpu%i: tba = 0x", x);
369                  (*valuep) &= 0xffffffffULL;                  if (bits32)
370                            debug("%08"PRIx32"\n", (uint32_t) cpu->cd.sparc.tba);
371                    else
372                            debug("%016"PRIx64"\n", (uint64_t) cpu->cd.sparc.tba);
373            }
374  }  }
375    
376    
# Line 326  void sparc_cpu_tlbdump(struct machine *m Line 388  void sparc_cpu_tlbdump(struct machine *m
388  }  }
389    
390    
 static void add_response_word(struct cpu *cpu, char *r, uint64_t value,  
         size_t maxlen, int len)  
 {  
         char *format = (len == 4)? "%08"PRIx64 : "%016"PRIx64;  
         if (len == 4)  
                 value &= 0xffffffffULL;  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {  
                 if (len == 4) {  
                         value = ((value & 0xff) << 24) +  
                                 ((value & 0xff00) << 8) +  
                                 ((value & 0xff0000) >> 8) +  
                                 ((value & 0xff000000) >> 24);  
                 } else {  
                         value = ((value & 0xff) << 56) +  
                                 ((value & 0xff00) << 40) +  
                                 ((value & 0xff0000) << 24) +  
                                 ((value & 0xff000000ULL) << 8) +  
                                 ((value & 0xff00000000ULL) >> 8) +  
                                 ((value & 0xff0000000000ULL) >> 24) +  
                                 ((value & 0xff000000000000ULL) >> 40) +  
                                 ((value & 0xff00000000000000ULL) >> 56);  
                 }  
         }  
         snprintf(r + strlen(r), maxlen - strlen(r), format, (uint64_t)value);  
 }  
   
   
 /*  
  *  sparc_cpu_gdb_stub():  
  *  
  *  Execute a "remote GDB" command. Returns a newly allocated response string  
  *  on success, NULL on failure.  
  */  
 char *sparc_cpu_gdb_stub(struct cpu *cpu, char *cmd)  
 {  
         if (strcmp(cmd, "g") == 0) {  
                 int i;  
                 char *r;  
                 size_t wlen = cpu->is_32bit?  
                     sizeof(uint32_t) : sizeof(uint64_t);  
                 size_t len = 1 + 76 * wlen;  
                 r = malloc(len);  
                 if (r == NULL) {  
                         fprintf(stderr, "out of memory\n");  
                         exit(1);  
                 }  
                 r[0] = '\0';  
                 /*  TODO  */  
                 for (i=0; i<128; i++)  
                         add_response_word(cpu, r, i, len, wlen);  
                 return r;  
         }  
   
         if (cmd[0] == 'p') {  
                 int regnr = strtol(cmd + 1, NULL, 16);  
                 size_t wlen = sizeof(uint32_t);  
                 /*  TODO: cpu->is_32bit? sizeof(uint32_t) : sizeof(uint64_t); */  
                 size_t len = 2 * wlen + 1;  
                 char *r = malloc(len);  
                 r[0] = '\0';  
                 if (regnr >= 0 && regnr < N_SPARC_REG) {  
                         add_response_word(cpu, r,  
                             cpu->cd.sparc.r[regnr], len, wlen);  
                 } else if (regnr == 0x44) {  
                         add_response_word(cpu, r, cpu->pc, len, wlen);  
 /* TODO:  
 20..3f = f0..f31  
 40 = y  
 41 = psr  
 42 = wim  
 43 = tbr  
 45 = npc  
 46 = fsr  
 47 = csr  
 */  
                 } else {  
                         /*  Unimplemented:  */  
                         add_response_word(cpu, r, 0xcc000 + regnr, len, wlen);  
                 }  
                 return r;  
         }  
   
         fatal("sparc_cpu_gdb_stub(): TODO\n");  
         return NULL;  
 }  
   
   
 /*  
  *  sparc_cpu_interrupt():  
  */  
 int sparc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)  
 {  
         fatal("sparc_cpu_interrupt(): TODO\n");  
         return 0;  
 }  
   
   
 /*  
  *  sparc_cpu_interrupt_ack():  
  */  
 int sparc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)  
 {  
         /*  fatal("sparc_cpu_interrupt_ack(): TODO\n");  */  
         return 0;  
 }  
   
   
391  /*  /*
392   *  sparc_cpu_instruction_has_delayslot():   *  sparc_cpu_instruction_has_delayslot():
393   *   *
# Line 462  int sparc_cpu_instruction_has_delayslot( Line 417  int sparc_cpu_instruction_has_delayslot(
417                  switch (op2) {                  switch (op2) {
418                  case 56:/*  jump and link  */                  case 56:/*  jump and link  */
419                          return 1;                          return 1;
420                    case 57:/*  return  */
421                            return 1;
422                  }                  }
423                  break;                  break;
424          }          }
# Line 510  int sparc_cpu_disassemble_instr(struct c Line 467  int sparc_cpu_disassemble_instr(struct c
467          iword = *(uint32_t *)&instr[0];          iword = *(uint32_t *)&instr[0];
468          iword = BE32_TO_HOST(iword);          iword = BE32_TO_HOST(iword);
469    
470          debug(": %08x", iword);          debug(": %08"PRIx32, iword);
471    
472          if (running && cpu->delay_slot)          if (running && cpu->delay_slot)
473                  debug(" (d)");                  debug(" (d)");
# Line 665  int sparc_cpu_disassemble_instr(struct c Line 622  int sparc_cpu_disassemble_instr(struct c
622                  case 41:rs_name = "psr";                  case 41:rs_name = "psr";
623                          no_rs2 = 1;                          no_rs2 = 1;
624                          break;                          break;
625                  case 42:rs_name = "wim";                  case 42:/*  TODO: something with wim only, on sparc v8?  */
626                            rs_name = sparc_pregnames[rs1];
627                          no_rs2 = 1;                          no_rs2 = 1;
628                          break;                          break;
629                  case 43:/*  ?  */                  case 43:/*  ?  */
# Line 736  int sparc_cpu_disassemble_instr(struct c Line 694  int sparc_cpu_disassemble_instr(struct c
694                          if ((iword >> 13) & 1) {                          if ((iword >> 13) & 1) {
695                                  if (siconst >= -9 && siconst <= 9)                                  if (siconst >= -9 && siconst <= 9)
696                                          debug("%i", siconst);                                          debug("%i", siconst);
697                                    else if (siconst < 0 && (op2 == 0 ||
698                                        op2 == 4 || op2 == 20 || op2 == 60))
699                                            debug("-0x%x", -siconst);
700                                  else                                  else
701                                          debug("0x%x", siconst);                                          debug("0x%x", siconst);
702                          } else {                          } else {
# Line 748  int sparc_cpu_disassemble_instr(struct c Line 709  int sparc_cpu_disassemble_instr(struct c
709                          debug("%%%s", rd_name);                          debug("%%%s", rd_name);
710                  break;                  break;
711    
712          case 3: debug("%s\t", sparc_loadstore_names[op2]);          case 3: mnem = sparc_loadstore_names[op2];
713                    switch (op2) {
714                    case 0: /*  'lduw' was called only 'ld' in pre-v9  */
715                            if (cpu->cd.sparc.cpu_type.v < 9)
716                                    mnem = "ld";
717                            break;
718                    }
719                    debug("%s\t", mnem);
720                  if (op2 & 4)                  if (op2 & 4)
721                          debug("%%%s,", sparc_regnames[rd]);                          debug("%%%s,", sparc_regnames[rd]);
722                  debug("[%%%s", sparc_regnames[rs1]);                  debug("[%%%s", sparc_regnames[rs1]);
# Line 762  int sparc_cpu_disassemble_instr(struct c Line 730  int sparc_cpu_disassemble_instr(struct c
730                                  debug("+%%%s", sparc_regnames[rs2]);                                  debug("+%%%s", sparc_regnames[rs2]);
731                  }                  }
732                  debug("]");                  debug("]");
733                  if (asi != 0)                  if ((op2 & 0x30) == 0x10)
734                          debug("(%i)", asi);                          debug("(%i)", asi);
735                  if (!(op2 & 4))                  if (!(op2 & 4))
736                          debug(",%%%s", sparc_regnames[rd]);                          debug(",%%%s", sparc_regnames[rd]);

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

  ViewVC Help
Powered by ViewVC 1.1.26