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

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

revision 41 by dpavlin, Mon Oct 8 16:22:11 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: cpu_sh.c,v 1.72 2007/04/28 09:44:35 debug Exp $   *  $Id: cpu_sh.c,v 1.75 2007/06/07 15:36:24 debug Exp $
29   *   *
30   *  Hitachi SuperH ("SH") CPU emulation.   *  Hitachi SuperH ("SH") CPU emulation.
31   *   *
32   *  TODO: It would be nice if this could encompass both 64-bit SH5, and   *  TODO: It would be nice if this could encompass both 64-bit SH5, and
33   *        32-bit SH encodings. Right now, it only really supports 32-bit mode.   *        32-bit SH encodings. Right now, it only really supports 32-bit mode.
34     *
35     *  TODO: This actually only works or SH4 so far, not SH3.
36   */   */
37    
38  #include <stdio.h>  #include <stdio.h>
# Line 48  Line 50 
50  #include "misc.h"  #include "misc.h"
51  #include "settings.h"  #include "settings.h"
52  #include "symbol.h"  #include "symbol.h"
53    #include "timer.h"
54    
55  #include "sh4_exception.h"  #include "sh4_exception.h"
56  #include "sh4_mmu.h"  #include "sh4_mmu.h"
# Line 59  Line 62 
62    
63    
64  extern int quiet_mode;  extern int quiet_mode;
65    extern int native_code_translation_enabled;
66    
67  void sh_pc_to_pointers(struct cpu *);  void sh_pc_to_pointers(struct cpu *);
68    
69    void sh3_cpu_interrupt_assert(struct interrupt *interrupt);
70    void sh3_cpu_interrupt_deassert(struct interrupt *interrupt);
71    
72    
73  /*  /*
74   *  sh_cpu_new():   *  sh_cpu_new():
# Line 92  int sh_cpu_new(struct cpu *cpu, struct m Line 99  int sh_cpu_new(struct cpu *cpu, struct m
99          cpu->cd.sh.cpu_type = cpu_type_defs[i];          cpu->cd.sh.cpu_type = cpu_type_defs[i];
100          cpu->byte_order = EMUL_LITTLE_ENDIAN;          cpu->byte_order = EMUL_LITTLE_ENDIAN;
101          cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;          cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
         cpu->cd.sh.compact = 1;         /*  Default to 16-bit opcode mode  */  
102    
103          if (!cpu->is_32bit) {          if (!cpu->is_32bit) {
104                  fatal("SH64 emulation not implemented. Sorry.\n");                  fatal("SH64 emulation not implemented. Sorry.\n");
# Line 171  int sh_cpu_new(struct cpu *cpu, struct m Line 177  int sh_cpu_new(struct cpu *cpu, struct m
177          }          }
178    
179          /*  Register the CPU's interrupts:  */          /*  Register the CPU's interrupts:  */
180          for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) {          if (cpu->cd.sh.cpu_type.arch == 4) {
181                    for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) {
182                            struct interrupt template;
183                            char name[100];
184                            snprintf(name, sizeof(name), "%s.irq[0x%x]",
185                                cpu->path, i);
186                            memset(&template, 0, sizeof(template));
187                            template.line = i;
188                            template.name = name;
189                            template.extra = cpu;
190                            template.interrupt_assert = sh_cpu_interrupt_assert;
191                            template.interrupt_deassert = sh_cpu_interrupt_deassert;
192                            interrupt_handler_register(&template);
193                    }
194            } else {
195                  struct interrupt template;                  struct interrupt template;
                 char name[100];  
                 snprintf(name, sizeof(name), "%s.irq[0x%x]", cpu->path, i);  
196                  memset(&template, 0, sizeof(template));                  memset(&template, 0, sizeof(template));
197                  template.line = i;                  template.line = i;
198                  template.name = name;                  template.name = cpu->path;
199                  template.extra = cpu;                  template.extra = cpu;
200                  template.interrupt_assert = sh_cpu_interrupt_assert;                  template.interrupt_assert = sh3_cpu_interrupt_assert;
201                  template.interrupt_deassert = sh_cpu_interrupt_deassert;                  template.interrupt_deassert = sh3_cpu_interrupt_deassert;
202                  interrupt_handler_register(&template);                  interrupt_handler_register(&template);
203          }          }
204    
# Line 206  int sh_cpu_new(struct cpu *cpu, struct m Line 224  int sh_cpu_new(struct cpu *cpu, struct m
224    
225          sh_update_interrupt_priorities(cpu);          sh_update_interrupt_priorities(cpu);
226    
227            if (native_code_translation_enabled)
228                    cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ,
229                        sh_timer_sample_tick, cpu);
230    
231          return 1;          return 1;
232  }  }
233    
# Line 269  void sh_update_interrupt_priorities(stru Line 291  void sh_update_interrupt_priorities(stru
291    
292    
293  /*  /*
294     *  sh3_cpu_interrupt_assert():
295     *  sh3_cpu_interrupt_deassert():
296     */
297    void sh3_cpu_interrupt_assert(struct interrupt *interrupt)
298    {
299            /*  TODO  */
300    }
301    void sh3_cpu_interrupt_deassert(struct interrupt *interrupt)
302    {
303            /*  TODO  */
304    }      
305    
306    
307    /*
308   *  sh_cpu_interrupt_assert():   *  sh_cpu_interrupt_assert():
309   */   */
310  void sh_cpu_interrupt_assert(struct interrupt *interrupt)  void sh_cpu_interrupt_assert(struct interrupt *interrupt)
# Line 423  void sh_cpu_register_dump(struct cpu *cp Line 459  void sh_cpu_register_dump(struct cpu *cp
459  {  {
460          char *symbol;          char *symbol;
461          uint64_t offset;          uint64_t offset;
462          int i, x = cpu->cpu_id, nregs = cpu->cd.sh.compact? 16 : 64;          int i, x = cpu->cpu_id;
463    
464          if (gprs) {          if (gprs) {
465                  /*  Special registers (pc, ...) first:  */                  /*  Special registers (pc, ...) first:  */
# Line 454  void sh_cpu_register_dump(struct cpu *cp Line 490  void sh_cpu_register_dump(struct cpu *cp
490                      "  gbr = 0x%08"PRIx32"\n", x, (uint32_t)cpu->cd.sh.mach,                      "  gbr = 0x%08"PRIx32"\n", x, (uint32_t)cpu->cd.sh.mach,
491                      (uint32_t)cpu->cd.sh.macl, (uint32_t)cpu->cd.sh.gbr);                      (uint32_t)cpu->cd.sh.macl, (uint32_t)cpu->cd.sh.gbr);
492    
493                  for (i=0; i<nregs; i++) {                  for (i=0; i<SH_N_GPRS; i++) {
494                          if ((i % 4) == 0)                          if ((i % 4) == 0)
495                                  debug("cpu%i:", x);                                  debug("cpu%i:", x);
496                          debug(" r%-2i = 0x%08x ", i, (int)cpu->cd.sh.r[i]);                          debug(" r%-2i = 0x%08x ", i, (int)cpu->cd.sh.r[i]);
# Line 724  void sh_exception(struct cpu *cpu, int e Line 760  void sh_exception(struct cpu *cpu, int e
760    
761    
762  /*  /*
763   *  sh_cpu_disassemble_instr_compact():   *  sh_cpu_disassemble_instr():
764   *   *
765   *  SHcompact instruction disassembly. The top 4 bits of each 16-bit   *  SHcompact instruction disassembly. The top 4 bits of each 16-bit
766   *  instruction word is used as the main opcode. For most instructions, the   *  instruction word is used as the main opcode. For most instructions, the
767   *  lowest 4 or 8 bits then select sub-opcode.   *  lowest 4 or 8 bits then select sub-opcode.
768     *
769     *  This function convert an instruction word into human readable format,
770     *  for instruction tracing.
771     *
772     *  If running is 1, cpu->pc should be the address of the instruction.
773     *
774     *  If running is 0, things that depend on the runtime environment (eg.
775     *  register contents) will not be shown, and addr will be used instead of
776     *  cpu->pc for relative addresses.
777   */   */
778  int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr,  int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
779          int running, uint64_t dumpaddr)          int running, uint64_t dumpaddr)
780  {  {
781          char *symbol;          char *symbol;
# Line 738  int sh_cpu_disassemble_instr_compact(str Line 783  int sh_cpu_disassemble_instr_compact(str
783          uint16_t iword;          uint16_t iword;
784          int hi4, lo4, lo8, r8, r4;          int hi4, lo4, lo8, r8, r4;
785    
786            if (running)
787                    dumpaddr = cpu->pc;
788    
789            symbol = get_symbol_name(&cpu->machine->symbol_context,
790                dumpaddr, &offset);
791            if (symbol != NULL && offset==0)
792                    debug("<%s>\n", symbol);
793    
794            if (cpu->machine->ncpus > 1 && running)
795                    debug("cpu%i: ", cpu->cpu_id);
796    
797            debug("%08"PRIx32, (uint32_t) dumpaddr);
798    
799          if (cpu->byte_order == EMUL_BIG_ENDIAN)          if (cpu->byte_order == EMUL_BIG_ENDIAN)
800                  iword = (instr[0] << 8) + instr[1];                  iword = (instr[0] << 8) + instr[1];
801          else          else
# Line 747  int sh_cpu_disassemble_instr_compact(str Line 805  int sh_cpu_disassemble_instr_compact(str
805          hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;          hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
806          r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;          r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;
807    
808    
809          /*          /*
810           *  Decode the instruction:           *  Decode the instruction:
811           */           */
# Line 1336  int sh_cpu_disassemble_instr_compact(str Line 1395  int sh_cpu_disassemble_instr_compact(str
1395    
1396          return sizeof(iword);          return sizeof(iword);
1397  }  }
   
   
 /*  
  *  sh_cpu_disassemble_instr():  
  *  
  *  Convert an instruction word into human readable format, for instruction  
  *  tracing.  
  *  
  *  If running is 1, cpu->pc should be the address of the instruction.  
  *  
  *  If running is 0, things that depend on the runtime environment (eg.  
  *  register contents) will not be shown, and addr will be used instead of  
  *  cpu->pc for relative addresses.  
  */  
 int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,  
         int running, uint64_t dumpaddr)  
 {  
         uint64_t offset;  
         uint32_t iword;  
         char *symbol;  
   
         if (running)  
                 dumpaddr = cpu->pc;  
   
         symbol = get_symbol_name(&cpu->machine->symbol_context,  
             dumpaddr, &offset);  
         if (symbol != NULL && offset==0)  
                 debug("<%s>\n", symbol);  
   
         if (cpu->machine->ncpus > 1 && running)  
                 debug("cpu%i: ", cpu->cpu_id);  
   
         if (cpu->cd.sh.cpu_type.bits == 32)  
                 debug("%08x", (int)dumpaddr);  
         else  
                 debug("%016llx", (long long)dumpaddr);  
   
         if (cpu->cd.sh.compact)  
                 return sh_cpu_disassemble_instr_compact(cpu, instr,  
                     running, dumpaddr);  
   
         if (cpu->byte_order == EMUL_BIG_ENDIAN)  
                 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)  
                     + instr[3];  
         else  
                 iword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8)  
                     + instr[0];  
   
         debug(": %08x\t", iword);  
   
         /*  
          *  Decode the instruction:  
          */  
   
         debug("TODO\n");  
   
         return sizeof(iword);  
 }  
1398    
1399    
1400  #include "tmp_sh_tail.c"  #include "tmp_sh_tail.c"

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

  ViewVC Help
Powered by ViewVC 1.1.26