/[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 21 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_sparc.c,v 1.4 2005/11/13 00:14:07 debug Exp $   *  $Id: cpu_sparc.c,v 1.11 2005/12/11 21:34:43 debug Exp $
29   *   *
30   *  SPARC CPU emulation.   *  SPARC CPU emulation.
31   */   */
# Line 41  Line 41 
41  #include "misc.h"  #include "misc.h"
42  #include "symbol.h"  #include "symbol.h"
43    
44    
45  #define DYNTRANS_DUALMODE_32  #define DYNTRANS_DUALMODE_32
 /*  #define DYNTRANS_32  */  
46  #include "tmp_sparc_head.c"  #include "tmp_sparc_head.c"
47    
48    
49    static char *sparc_regnames[N_SPARC_REG] = SPARC_REG_NAMES;
50    static char *sparc_regbranch_names[N_SPARC_REGBRANCH_TYPES] =
51            SPARC_REGBRANCH_NAMES;
52    static char *sparc_branch_names[N_SPARC_BRANCH_TYPES] = SPARC_BRANCH_NAMES;
53    static char *sparc_alu_names[N_ALU_INSTR_TYPES] = SPARC_ALU_NAMES;
54    static char *sparc_loadstore_names[N_LOADSTORE_TYPES] = SPARC_LOADSTORE_NAMES;
55    
56    
57  /*  /*
58   *  sparc_cpu_new():   *  sparc_cpu_new():
59   *   *
# Line 57  Line 65 
65  int sparc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,  int sparc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
66          int cpu_id, char *cpu_type_name)          int cpu_id, char *cpu_type_name)
67  {  {
68          if (strcasecmp(cpu_type_name, "SPARCv9") != 0)          int any_cache = 0;
69            int i = 0;
70            struct sparc_cpu_type_def cpu_type_defs[] = SPARC_CPU_TYPE_DEFS;
71    
72            /*  Scan the cpu_type_defs list for this cpu type:  */
73            while (cpu_type_defs[i].name != NULL) {
74                    if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
75                            break;
76                    }
77                    i++;
78            }
79            if (cpu_type_defs[i].name == NULL)
80                  return 0;                  return 0;
81    
82          cpu->memory_rw = sparc_memory_rw;          cpu->memory_rw = sparc_memory_rw;
         cpu->update_translation_table = sparc_update_translation_table;  
         cpu->invalidate_translation_caches =  
             sparc_invalidate_translation_caches;  
         cpu->invalidate_code_translation =  
             sparc_invalidate_code_translation;  
83    
84          cpu->byte_order = EMUL_BIG_ENDIAN;          cpu->cd.sparc.cpu_type = cpu_type_defs[i];
85          cpu->is_32bit = 0;          cpu->name              = cpu->cd.sparc.cpu_type.name;
86            cpu->byte_order        = EMUL_BIG_ENDIAN;
87            cpu->is_32bit = (cpu->cd.sparc.cpu_type.bits == 32)? 1 : 0;
88    
89            if (cpu->is_32bit) {
90                    cpu->update_translation_table =
91                        sparc32_update_translation_table;
92                    cpu->invalidate_translation_caches =
93                        sparc32_invalidate_translation_caches;
94                    cpu->invalidate_code_translation =
95                        sparc32_invalidate_code_translation;
96            } else {
97                    cpu->update_translation_table = sparc_update_translation_table;
98                    cpu->invalidate_translation_caches =
99                        sparc_invalidate_translation_caches;
100                    cpu->invalidate_code_translation =
101                        sparc_invalidate_code_translation;
102            }
103    
104          /*  Only show name and caches etc for CPU nr 0 (in SMP machines):  */          /*  Only show name and caches etc for CPU nr 0 (in SMP machines):  */
105          if (cpu_id == 0) {          if (cpu_id == 0) {
106                  debug("%s", cpu->name);                  debug("%s", cpu->name);
107    
108                    if (cpu->cd.sparc.cpu_type.icache_shift != 0)
109                            any_cache = 1;
110                    if (cpu->cd.sparc.cpu_type.dcache_shift != 0)
111                            any_cache = 1;
112                    if (cpu->cd.sparc.cpu_type.l2cache_shift != 0)
113                            any_cache = 1;
114    
115                    if (any_cache) {
116                            debug(" (I+D = %i+%i KB", (int)
117                                (1 << (cpu->cd.sparc.cpu_type.icache_shift-10)),
118                                (int)(1<<(cpu->cd.sparc.cpu_type.dcache_shift-10)));
119                            if (cpu->cd.sparc.cpu_type.l2cache_shift != 0) {
120                                    debug(", L2 = %i KB",
121                                        (int)(1 << (cpu->cd.sparc.cpu_type.
122                                        l2cache_shift-10)));
123                            }
124                            debug(")");
125                    }
126          }          }
127    
128          return 1;          return 1;
# Line 86  int sparc_cpu_new(struct cpu *cpu, struc Line 136  int sparc_cpu_new(struct cpu *cpu, struc
136   */   */
137  void sparc_cpu_list_available_types(void)  void sparc_cpu_list_available_types(void)
138  {  {
139          debug("SPARCv9\n");          int i, j;
140          /*  TODO  */          struct sparc_cpu_type_def tdefs[] = SPARC_CPU_TYPE_DEFS;
141    
142            i = 0;
143            while (tdefs[i].name != NULL) {
144                    debug("%s", tdefs[i].name);
145                    for (j=10 - strlen(tdefs[i].name); j>0; j--)
146                            debug(" ");
147                    i++;
148                    if ((i % 6) == 0 || tdefs[i].name == NULL)
149                            debug("\n");
150            }
151  }  }
152    
153    
# Line 96  void sparc_cpu_list_available_types(void Line 156  void sparc_cpu_list_available_types(void
156   */   */
157  void sparc_cpu_dumpinfo(struct cpu *cpu)  void sparc_cpu_dumpinfo(struct cpu *cpu)
158  {  {
159          debug("\n");          debug(", %i-bit\n", cpu->cd.sparc.cpu_type.bits);
         /*  TODO  */  
160  }  }
161    
162    
# Line 113  void sparc_cpu_register_dump(struct cpu Line 172  void sparc_cpu_register_dump(struct cpu
172  {  {
173          char *symbol;          char *symbol;
174          uint64_t offset;          uint64_t offset;
175          int x = cpu->cpu_id;          int i, x = cpu->cpu_id;
176          int bits32 = 0;          int bits32 = cpu->is_32bit;
177    
178          if (gprs) {          if (gprs) {
179                  /*  Special registers (pc, ...) first:  */                  /*  Special registers (pc, ...) first:  */
180                  symbol = get_symbol_name(&cpu->machine->symbol_context,                  symbol = get_symbol_name(&cpu->machine->symbol_context,
181                      cpu->pc, &offset);                      cpu->pc, &offset);
182    
183                  debug("cpu%i: pc  = 0x", x);                  debug("cpu%i: pc = 0x", x);
184                  if (bits32)                  if (bits32)
185                          debug("%08x", (int)cpu->pc);                          debug("%08x", (int)cpu->pc);
186                  else                  else
187                          debug("%016llx", (long long)cpu->pc);                          debug("%016llx", (long long)cpu->pc);
188                  debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");                  debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");
189    
190                  /*  TODO  */                  if (bits32) {
191                            for (i=0; i<N_SPARC_REG; i++) {
192                                    if ((i & 3) == 0)
193                                            debug("cpu%i: ", x);
194                                    /*  Skip the zero register:  */
195                                    if (i==0) {
196                                            debug("               ");
197                                            continue;
198                                    }
199                                    debug("%s=", sparc_regnames[i]);
200                                    debug("0x%08x", (int) cpu->cd.sparc.r[i]);
201                                    if ((i & 3) < 3)
202                                            debug("  ");
203                                    else
204                                            debug("\n");
205                            }
206                    } else {
207                            for (i=0; i<N_SPARC_REG; i++) {
208                                    int r = ((i >> 1) & 15) | ((i&1) << 4);
209                                    if ((i & 1) == 0)
210                                            debug("cpu%i: ", x);
211                                    /*  Skip the zero register:  */
212                                    if (r==0) {
213                                            debug("                         ");
214                                            continue;
215                                    }
216                                    debug("%s = ", sparc_regnames[r]);
217                                    debug("0x%016llx", (long long)
218                                        cpu->cd.sparc.r[r]);
219                                    if ((i & 1) < 1)
220                                            debug("  ");
221                                    else
222                                            debug("\n");
223                            }
224                    }
225          }          }
226  }  }
227    
# Line 191  int sparc_cpu_interrupt_ack(struct cpu * Line 284  int sparc_cpu_interrupt_ack(struct cpu *
284  int sparc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,  int sparc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
285          int running, uint64_t dumpaddr, int bintrans)          int running, uint64_t dumpaddr, int bintrans)
286  {  {
287          uint64_t offset;          uint64_t offset, tmp;
288          uint32_t iword;          uint32_t iword;
289          int hi6;          int hi2, op2, rd, rs1, rs2, siconst, btype, tmps, no_rd = 0;
290          char *symbol;          int asi, no_rs1 = 0, no_rs2 = 0, jmpl = 0, shift_x = 0, cc, p;
291            char *symbol, *mnem;
292    
293          if (running)          if (running)
294                  dumpaddr = cpu->pc;                  dumpaddr = cpu->pc;
# Line 207  int sparc_cpu_disassemble_instr(struct c Line 301  int sparc_cpu_disassemble_instr(struct c
301          if (cpu->machine->ncpus > 1 && running)          if (cpu->machine->ncpus > 1 && running)
302                  debug("cpu%i: ", cpu->cpu_id);                  debug("cpu%i: ", cpu->cpu_id);
303    
304  /*      if (cpu->cd.sparc.bits == 32)          if (cpu->is_32bit)
305                  debug("%08x", (int)dumpaddr);                  debug("%08x", (int)dumpaddr);
306          else          else
307  */              debug("%016llx", (long long)dumpaddr);                  debug("%016llx", (long long)dumpaddr);
308    
309          iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)          iword = *(uint32_t *)&instr[0];
310              + instr[3];          iword = BE32_TO_HOST(iword);
311    
312          debug(": %08x\t", iword);          debug(": %08x\t", iword);
313    
314          /*          /*
315           *  Decode the instruction:           *  Decode the instruction:
316             *
317             *  http://www.cs.unm.edu/~maccabe/classes/341/labman/node9.html is a
318             *  good quick description of SPARC instruction encoding.
319           */           */
320    
321          hi6 = iword >> 26;          hi2 = iword >> 30;
322            rd = (iword >> 25) & 31;
323          switch (hi6) {          btype = rd & (N_SPARC_BRANCH_TYPES - 1);
324          default:          rs1 = (iword >> 14) & 31;
325                  /*  TODO  */          asi = (iword >> 5) & 0xff;
326                  debug("unimplemented hi6 = 0x%02x", hi6);          rs2 = iword & 31;
327            siconst = (int16_t)((iword & 0x1fff) << 3) >> 3;
328            op2 = (hi2 == 0)? ((iword >> 22) & 7) : ((iword >> 19) & 0x3f);
329            cc = (iword >> 20) & 3;
330            p = (iword >> 19) & 1;
331    
332            switch (hi2) {
333    
334            case 0: switch (op2) {
335    
336                    case 0: debug("illtrap\t0x%x", iword & 0x3fffff);
337                            break;
338    
339                    case 1:
340                    case 2:
341                    case 3: if (op2 == 3)
342                                    debug("%s", sparc_regbranch_names[btype & 7]);
343                            else
344                                    debug("%s", sparc_branch_names[btype]);
345                            if (rd & 16)
346                                    debug(",a");
347                            tmps = iword;
348                            switch (op2) {
349                            case 1: tmps <<= 13;
350                                    tmps >>= 11;
351                                    if (!p)
352                                            debug(",pn");
353                                    debug("\t%%%s,", cc==0 ? "icc" :
354                                        (cc==2 ? "xcc" : "UNKNOWN"));
355                                    break;
356                            case 2: tmps <<= 10;
357                                    tmps >>= 8;
358                                    debug("\t");
359                                    break;
360                            case 3: if (btype & 8)
361                                            debug("(INVALID)");
362                                    if (!p)
363                                            debug(",pn");
364                                    debug("\t%%%s,", sparc_regnames[rs1]);
365                                    tmps = ((iword & 0x300000) >> 6)
366                                        | (iword & 0x3fff);
367                                    tmps <<= 16;
368                                    tmps >>= 14;
369                                    break;
370                            }
371                            tmp = (int64_t)(int32_t)tmps;
372                            tmp += dumpaddr;
373                            debug("0x%llx", (long long)tmp);
374                            symbol = get_symbol_name(&cpu->machine->
375                                symbol_context, tmp, &offset);
376                            if (symbol != NULL)
377                                    debug(" \t<%s>", symbol);
378                            break;
379    
380                    case 4: if (rd == 0) {
381                                    debug("nop");
382                                    break;
383                            }
384                            debug("sethi\t%%hi(0x%x),", (iword & 0x3fffff) << 10);
385                            debug("%%%s", sparc_regnames[rd]);
386                            break;
387    
388                    default:debug("UNIMPLEMENTED hi2=%i, op2=0x%x", hi2, op2);
389                    }
390                    break;
391    
392            case 1: tmp = (int32_t)iword << 2;
393                    tmp += dumpaddr;
394                    debug("call\t0x%llx", (long long)tmp);
395                    symbol = get_symbol_name(&cpu->machine->symbol_context,
396                        tmp, &offset);
397                    if (symbol != NULL)
398                            debug(" \t<%s>", symbol);
399                    break;
400    
401            case 2: mnem = sparc_alu_names[op2];
402                    switch (op2) {
403                    case 0: /*  add  */
404                            if (rd == rs1 && (iword & 0x3fff) == 0x2001) {
405                                    mnem = "inc";
406                                    no_rs1 = no_rs2 = 1;
407                            }
408                            break;
409                    case 2: /*  or  */
410                            if (rs1 == 0) {
411                                    mnem = "mov";
412                                    no_rs1 = 1;
413                            }
414                            break;
415                    case 4: /*  sub  */
416                            if (rd == rs1 && (iword & 0x3fff) == 0x2001) {
417                                    mnem = "dec";
418                                    no_rs1 = no_rs2 = 1;
419                            }
420                            break;
421                    case 20:/*  subcc  */
422                            if (rd == 0) {
423                                    mnem = "cmp";
424                                    no_rd = 1;
425                            }
426                            break;
427                    case 37:/*  sll  */
428                    case 38:/*  srl  */
429                    case 39:/*  sra  */
430                            if (siconst & 0x1000) {
431                                    siconst &= 0x3f;
432                                    shift_x = 1;
433                            } else
434                                    siconst &= 0x1f;
435                            break;
436                    case 43:/*  ?  */
437                            if (iword == 0x81580000) {
438                                    mnem = "flushw";
439                                    no_rs1 = no_rs2 = no_rd = 1;
440                            }
441                            break;
442                    case 49:/*  ?  */
443                            if (iword == 0x83880000) {
444                                    mnem = "restored";
445                                    no_rs1 = no_rs2 = no_rd = 1;
446                            }
447                            break;
448                    case 56:/*  jmpl  */
449                            jmpl = 1;
450                            if (iword == 0x81c7e008) {
451                                    mnem = "ret";
452                                    no_rs1 = no_rs2 = no_rd = 1;
453                            }
454                            if (iword == 0x81c3e008) {
455                                    mnem = "retl";
456                                    no_rs1 = no_rs2 = no_rd = 1;
457                            }
458                            break;
459                    case 61:/*  restore  */
460                            if (iword == 0x81e80000)
461                                    no_rs1 = no_rs2 = no_rd = 1;
462                            break;
463                    case 62:if (iword == 0x83f00000) {
464                                    mnem = "retry";
465                                    no_rs1 = no_rs2 = no_rd = 1;
466                            }
467                            break;
468                    }
469                    debug("%s", mnem);
470                    if (shift_x)
471                            debug("x");
472                    debug("\t");
473                    if (!no_rs1)
474                            debug("%%%s", sparc_regnames[rs1]);
475                    if (!no_rs1 && !no_rs2) {
476                            if (jmpl)
477                                    debug("+");
478                            else
479                                    debug(",");
480                    }
481                    if (!no_rs2) {
482                            if ((iword >> 13) & 1) {
483                                    if (siconst >= -9 && siconst <= 9)
484                                            debug("%i", siconst);
485                                    else
486                                            debug("0x%x", siconst);
487                            } else {
488                                    debug("%%%s", sparc_regnames[rs2]);
489                            }
490                    }
491                    if ((!no_rs1 || !no_rs2) && !no_rd)
492                            debug(",");
493                    if (!no_rd)
494                            debug("%%%s", sparc_regnames[rd]);
495                    break;
496    
497            case 3: debug("%s\t", sparc_loadstore_names[op2]);
498                    if (op2 & 4)
499                            debug("%%%s,", sparc_regnames[rd]);
500                    debug("[%%%s", sparc_regnames[rs1]);
501                    if ((iword >> 13) & 1) {
502                            if (siconst > 0)
503                                    debug("+");
504                            if (siconst != 0)
505                                    debug("%i", siconst);
506                    } else {
507                            if (rs2 != 0)
508                                    debug("+%%%s", sparc_regnames[rs2]);
509                    }
510                    debug("]");
511                    if (asi != 0)
512                            debug("(%i)", asi);
513                    if (!(op2 & 4))
514                            debug(",%%%s", sparc_regnames[rd]);
515                    break;
516          }          }
517    
518          debug("\n");          debug("\n");

Legend:
Removed from v.21  
changed lines
  Added in v.22

  ViewVC Help
Powered by ViewVC 1.1.26