/[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 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC revision 40 by dpavlin, Mon Oct 8 16:22:11 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_sh.c,v 1.53 2006/10/31 11:07:05 debug Exp $   *  $Id: cpu_sh.c,v 1.72 2007/04/28 09:44:35 debug Exp $
29   *   *
30   *  Hitachi SuperH ("SH") CPU emulation.   *  Hitachi SuperH ("SH") CPU emulation.
31   *   *
# Line 42  Line 42 
42  #include "cpu.h"  #include "cpu.h"
43  #include "device.h"  #include "device.h"
44  #include "float_emul.h"  #include "float_emul.h"
45    #include "interrupt.h"
46  #include "machine.h"  #include "machine.h"
47  #include "memory.h"  #include "memory.h"
48  #include "misc.h"  #include "misc.h"
# Line 132  int sh_cpu_new(struct cpu *cpu, struct m Line 133  int sh_cpu_new(struct cpu *cpu, struct m
133          CPU_SETTINGS_ADD_REGISTER32("gbr", cpu->cd.sh.gbr);          CPU_SETTINGS_ADD_REGISTER32("gbr", cpu->cd.sh.gbr);
134          CPU_SETTINGS_ADD_REGISTER32("macl", cpu->cd.sh.macl);          CPU_SETTINGS_ADD_REGISTER32("macl", cpu->cd.sh.macl);
135          CPU_SETTINGS_ADD_REGISTER32("mach", cpu->cd.sh.mach);          CPU_SETTINGS_ADD_REGISTER32("mach", cpu->cd.sh.mach);
136            CPU_SETTINGS_ADD_REGISTER32("expevt", cpu->cd.sh.expevt);
137            CPU_SETTINGS_ADD_REGISTER32("intevt", cpu->cd.sh.intevt);
138            CPU_SETTINGS_ADD_REGISTER32("tra", cpu->cd.sh.tra);
139          CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.sh.fpscr);          CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.sh.fpscr);
140          CPU_SETTINGS_ADD_REGISTER32("fpul", cpu->cd.sh.fpul);          CPU_SETTINGS_ADD_REGISTER32("fpul", cpu->cd.sh.fpul);
141          for (i=0; i<SH_N_GPRS; i++) {          for (i=0; i<SH_N_GPRS; i++) {
# Line 166  int sh_cpu_new(struct cpu *cpu, struct m Line 170  int sh_cpu_new(struct cpu *cpu, struct m
170                  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_lo[i]);                  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_lo[i]);
171          }          }
172    
173            /*  Register the CPU's interrupts:  */
174            for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) {
175                    struct interrupt template;
176                    char name[100];
177                    snprintf(name, sizeof(name), "%s.irq[0x%x]", cpu->path, i);
178                    memset(&template, 0, sizeof(template));
179                    template.line = i;
180                    template.name = name;
181                    template.extra = cpu;
182                    template.interrupt_assert = sh_cpu_interrupt_assert;
183                    template.interrupt_deassert = sh_cpu_interrupt_deassert;
184                    interrupt_handler_register(&template);
185            }
186    
187          /*  SH4-specific memory mapped registers, TLBs, caches, etc:  */          /*  SH4-specific memory mapped registers, TLBs, caches, etc:  */
188          if (cpu->cd.sh.cpu_type.arch == 4)          if (cpu->cd.sh.cpu_type.arch == 4) {
189                  device_add(machine, "sh4");                  cpu->cd.sh.pcic_pcibus = device_add(machine, "sh4");
190    
191                    /*
192                     *  Interrupt Controller initial values, according to the
193                     *  SH7760 manual:
194                     */
195                    cpu->cd.sh.intc_iprd = 0xda74;
196                    cpu->cd.sh.intc_intmsk00 = 0xf3ff7fff;
197                    cpu->cd.sh.intc_intmsk04 = 0x00ffffff;
198                    /*  All others are zero.  */
199    
200                    /*  TODO: Initial priorities?  */
201                    cpu->cd.sh.intc_intpri00 = 0x33333333;
202                    cpu->cd.sh.intc_intpri04 = 0x33333333;
203                    cpu->cd.sh.intc_intpri08 = 0x33333333;
204                    cpu->cd.sh.intc_intpri0c = 0x33333333;
205            }
206    
207            sh_update_interrupt_priorities(cpu);
208    
209          return 1;          return 1;
210  }  }
211    
212    
213  /*  /*
214     *  sh_update_interrupt_priorities():
215     *
216     *  SH interrupts are a bit complicated; there are several intc registers
217     *  controlling priorities for various peripherals:
218     *
219     *  Register:  Bits 15..12  11..8  7..4      3..0
220     *  ---------  -----------  -----  ----      ----
221     *  ipra       TMU0         TMU1   TMU2      Reserved
222     *  iprb       WDT          REF    Reserved  Reserved
223     *  iprc       GPIO         DMAC   Reserved  H-UDI
224     *  iprd       IRL0         IRL1   IRL2      IRL3
225     *
226     *  Register:  31..28  27..24  23..20  19..16  15..12  11..8   7..4   3..0
227     *  ---------  ------  ------  ------  ------  ------  -----   ----   ----
228     *  intpri00   IRQ4    IRQ5    IRQ6    IRQ7    Rsrvd.  Rsrvd.  Rsrvd. Reserved
229     *  intpri04   HCAN2,0 HCAN2,1 SSI(0)  SSI(1)  HAC(0)  HAC(1)  I2C(0) I2C(1)
230     *  intpri08   USB     LCDC    DMABRG  SCIF(0) SCIF(1) SCIF(2) SIM    HSPI
231     *  intpri0c   Reserv. Reserv. MMCIF   Reserv. MFI     Rsrvd.  ADC    CMT
232     */
233    void sh_update_interrupt_priorities(struct cpu *cpu)
234    {
235            int i;
236    
237            /*
238             *  Set priorities of known interrupts, without affecting the
239             *  SH_INT_ASSERTED bit:
240             */
241    
242            for (i=SH4_INTEVT_IRQ0; i<=SH4_INTEVT_IRQ14; i+=0x20) {
243                    cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
244                    cpu->cd.sh.int_prio_and_pending[i/0x20] |= (15 - ((i -
245                        SH4_INTEVT_IRQ0) / 0x20));
246            }
247    
248            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU0_TUNI0 / 0x20] &=
249                ~SH_INT_PRIO_MASK;
250            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU0_TUNI0 / 0x20] |=
251                (cpu->cd.sh.intc_ipra >> 12) & 0xf;
252    
253            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU1_TUNI1 / 0x20] &=
254                ~SH_INT_PRIO_MASK;
255            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU1_TUNI1 / 0x20] |=
256                (cpu->cd.sh.intc_ipra >> 8) & 0xf;
257    
258            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU2_TUNI2 / 0x20] &=
259                ~SH_INT_PRIO_MASK;
260            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU2_TUNI2 / 0x20] |=
261                (cpu->cd.sh.intc_ipra >> 4) & 0xf;
262    
263            for (i=SH4_INTEVT_SCIF_ERI; i<=SH4_INTEVT_SCIF_TXI; i+=0x20) {
264                    cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
265                    cpu->cd.sh.int_prio_and_pending[i/0x20] |=
266                        ((cpu->cd.sh.intc_intpri08 >> 16) & 0xf);
267            }
268    }
269    
270    
271    /*
272     *  sh_cpu_interrupt_assert():
273     */
274    void sh_cpu_interrupt_assert(struct interrupt *interrupt)
275    {
276            struct cpu *cpu = interrupt->extra;
277            unsigned int irq_nr = interrupt->line;
278            unsigned int index = irq_nr / 0x20;
279            unsigned int prio;
280    
281            /*  Assert the interrupt, and check its priority level:  */
282            cpu->cd.sh.int_prio_and_pending[index] |= SH_INT_ASSERTED;
283            prio = cpu->cd.sh.int_prio_and_pending[index] & SH_INT_PRIO_MASK;
284    
285            if (prio == 0) {
286                    /*  Interrupt not implemented? Hm.  */
287                    fatal("[ SH interrupt 0x%x, prio 0 (?), aborting ]\n", irq_nr);
288                    exit(1);
289            }
290    
291            if (cpu->cd.sh.int_to_assert == 0 || prio > cpu->cd.sh.int_level) {
292                    cpu->cd.sh.int_to_assert = irq_nr;
293                    cpu->cd.sh.int_level = prio;
294            }
295    }
296    
297    
298    /*
299     *  sh_cpu_interrupt_deassert():
300     */
301    void sh_cpu_interrupt_deassert(struct interrupt *interrupt)
302    {
303            struct cpu *cpu = interrupt->extra;
304            int irq_nr = interrupt->line;
305            int index = irq_nr / 0x20;
306    
307            /*  Deassert the interrupt:  */
308            if (cpu->cd.sh.int_prio_and_pending[index] & SH_INT_ASSERTED) {
309                    cpu->cd.sh.int_prio_and_pending[index] &= ~SH_INT_ASSERTED;
310    
311                    /*  Calculate new interrupt assertion:  */
312                    cpu->cd.sh.int_to_assert = 0;
313                    cpu->cd.sh.int_level = 0;
314    
315                    /*  NOTE/TODO: This is slow, but should hopefully work:  */
316                    for (index=0; index<0x1000/0x20; index++) {
317                            uint8_t x = cpu->cd.sh.int_prio_and_pending[index];
318                            uint8_t prio = x & SH_INT_PRIO_MASK;
319                            if (x & SH_INT_ASSERTED &&
320                                prio > cpu->cd.sh.int_level) {
321                                    cpu->cd.sh.int_to_assert = index * 0x20;
322                                    cpu->cd.sh.int_level = prio;
323                            }
324                    }
325            }
326    }
327    
328    
329    /*
330   *  sh_cpu_list_available_types():   *  sh_cpu_list_available_types():
331   *   *
332   *  Print a list of available SH CPU types.   *  Print a list of available SH CPU types.
# Line 313  void sh_cpu_register_dump(struct cpu *cp Line 465  void sh_cpu_register_dump(struct cpu *cp
465    
466          if (coprocs & 1) {          if (coprocs & 1) {
467                  /*  Floating point:  */                  /*  Floating point:  */
468                  debug("cpu%i: fpscr = 0x%08"PRIx32"  fpul = 0x%08"PRIx32                  debug("cpu%i: fpscr = 0x%08"PRIx32" (%s,%s,%s)  fpul = 0x%08"
469                      "\n", x, cpu->cd.sh.fpscr, cpu->cd.sh.fpul);                      PRIx32"\n", x, cpu->cd.sh.fpscr,
470                        cpu->cd.sh.fpscr & SH_FPSCR_PR? "PR" : "!pr",
471                        cpu->cd.sh.fpscr & SH_FPSCR_SZ? "SZ" : "!sz",
472                        cpu->cd.sh.fpscr & SH_FPSCR_FR? "FR" : "!fr",
473                        cpu->cd.sh.fpul);
474    
475                  for (i=0; i<SH_N_FPRS; i++) {                  for (i=0; i<SH_N_FPRS; i++) {
476                          if ((i % 4) == 0)                          if ((i % 4) == 0)
# Line 389  void sh_cpu_tlbdump(struct machine *m, i Line 545  void sh_cpu_tlbdump(struct machine *m, i
545    
546    
547  /*  /*
  *  sh_cpu_gdb_stub():  
  *  
  *  Execute a "remote GDB" command. Returns a newly allocated response string  
  *  on success, NULL on failure.  
  */  
 char *sh_cpu_gdb_stub(struct cpu *cpu, char *cmd)  
 {  
         fatal("sh_cpu_gdb_stub(): TODO\n");  
         return NULL;  
 }  
   
   
 /*  
  *  sh_cpu_interrupt():  
  *  
  *  Note: This gives higher interrupt priority to lower number interrupts.  
  *        Hopefully this is correct.  
  */  
 int sh_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)  
 {  
         int word_index, bit_index;  
   
         if (cpu->cd.sh.int_to_assert == 0 || irq_nr < cpu->cd.sh.int_to_assert)  
                 cpu->cd.sh.int_to_assert = irq_nr;  
   
         /*  
          *  TODO: Keep track of all pending interrupts at multiple levels...  
          *  
          *  This is just a quick hack:  
          */  
         cpu->cd.sh.int_level = 1;  
         if (irq_nr == SH_INTEVT_TMU0_TUNI0)  
                 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 12) & 0xf;  
         if (irq_nr == SH_INTEVT_TMU1_TUNI1)  
                 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 8) & 0xf;  
         if (irq_nr == SH_INTEVT_TMU2_TUNI2)  
                 cpu->cd.sh.int_level = (cpu->cd.sh.intc_ipra >> 4) & 0xf;  
         if (irq_nr >= SH4_INTEVT_SCIF_ERI &&  
             irq_nr <= SH4_INTEVT_SCIF_TXI)  
                 cpu->cd.sh.int_level = (cpu->cd.sh.intc_iprc >> 4) & 0xf;  
   
         irq_nr /= 0x20;  
         word_index = irq_nr / (sizeof(uint32_t)*8);  
         bit_index = irq_nr & ((sizeof(uint32_t)*8) - 1);  
   
         cpu->cd.sh.int_pending[word_index] |= (1 << bit_index);  
   
         return 0;  
 }  
   
   
 /*  
  *  sh_cpu_interrupt_ack():  
  */  
 int sh_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)  
 {  
         int word_index, bit_index;  
   
         if (cpu->cd.sh.int_to_assert == irq_nr) {  
                 /*  
                  *  Rescan all interrupts to see if any are still asserted.  
                  *  
                  *  Note: The scan only has to go from irq_nr + 0x20 to the max  
                  *        index, since any lower interrupt cannot be asserted  
                  *        at this time.  
                  */  
                 int i, max = 0x1000;  
                 cpu->cd.sh.int_to_assert = 0;  
   
                 for (i=irq_nr+0x20; i<max; i+=0x20) {  
                         int j = i / 0x20;  
                         int word_index = j / (sizeof(uint32_t)*8);  
                         int bit_index = j & ((sizeof(uint32_t)*8) - 1);  
   
                         /*  Skip entire word if no bits are set:  */  
                         if (bit_index == 0 &&  
                             cpu->cd.sh.int_pending[word_index] == 0)  
                                 i += (sizeof(uint32_t)*8 - 1) * 0x20;  
                         else if (cpu->cd.sh.int_pending[word_index]  
                             & (1 << bit_index)) {  
                                 cpu->cd.sh.int_to_assert = i;  
                                 break;  
                         }  
                 }  
         }  
   
         irq_nr /= 0x20;  
         word_index = irq_nr / (sizeof(uint32_t)*8);  
         bit_index = irq_nr & ((sizeof(uint32_t)*8) - 1);  
   
         cpu->cd.sh.int_pending[word_index] &= ~(1 << bit_index);  
   
         return 0;  
 }  
   
   
 /*  
548   *  sh_update_sr():   *  sh_update_sr():
549   *   *
550   *  Writes a new value to the status register.   *  Writes a new value to the status register.
# Line 534  void sh_update_fpscr(struct cpu *cpu, ui Line 593  void sh_update_fpscr(struct cpu *cpu, ui
593   *   *
594   *  Causes a transfer of control to an exception or interrupt handler.   *  Causes a transfer of control to an exception or interrupt handler.
595   *  If intevt > 0, then it is an interrupt, otherwise an exception.   *  If intevt > 0, then it is an interrupt, otherwise an exception.
596     *
597     *  vaddr contains the faulting address, on TLB exceptions.
598   */   */
599  void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)  void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
600  {  {
# Line 545  void sh_exception(struct cpu *cpu, int e Line 606  void sh_exception(struct cpu *cpu, int e
606                  else                  else
607                          debug("[ exception 0x%03x", expevt);                          debug("[ exception 0x%03x", expevt);
608    
609                  debug(", pc=0x%08"PRIx32" ", (uint32_t)vaddr);                  debug(", pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
610                  if (intevt == 0)                  if (intevt == 0)
611                          debug("vaddr=0x%08"PRIx32" ", vaddr);                          debug("vaddr=0x%08"PRIx32" ", vaddr);
612    
# Line 553  void sh_exception(struct cpu *cpu, int e Line 614  void sh_exception(struct cpu *cpu, int e
614          }          }
615    
616          if (cpu->cd.sh.sr & SH_SR_BL) {          if (cpu->cd.sh.sr & SH_SR_BL) {
617                  fatal("sh_exception(): BL bit already set. TODO\n");                  fatal("[ sh_exception(): BL bit already set. ]\n");
618    
619                  /*  This is actually OK in two cases: a User Break,                  /*  This is actually OK in two cases: a User Break,
620                      or on NMI interrupts if a special flag is set?  */                      or on NMI interrupts if a special flag is set?  */
# Line 578  void sh_exception(struct cpu *cpu, int e Line 639  void sh_exception(struct cpu *cpu, int e
639                  cpu->pc -= sizeof(uint16_t);                  cpu->pc -= sizeof(uint16_t);
640          }          }
641    
642          /*  Stuff common to all exceptions:  */  
643            /*
644             *  Stuff common to all exceptions:
645             */
646    
647          cpu->cd.sh.spc = cpu->pc;          cpu->cd.sh.spc = cpu->pc;
648          cpu->cd.sh.ssr = cpu->cd.sh.sr;          cpu->cd.sh.ssr = cpu->cd.sh.sr;
649          cpu->cd.sh.sgr = cpu->cd.sh.r[15];          cpu->cd.sh.sgr = cpu->cd.sh.r[15];
650    
651          if (intevt > 0) {          if (intevt > 0) {
652                  cpu->cd.sh.intevt = intevt;                  cpu->cd.sh.intevt = intevt;
653                  expevt = -1;                  expevt = -1;
654          } else          } else {
655                  cpu->cd.sh.expevt = expevt;                  cpu->cd.sh.expevt = expevt;
656            }
657    
658          sh_update_sr(cpu, cpu->cd.sh.sr | SH_SR_MD | SH_SR_RB | SH_SR_BL);          sh_update_sr(cpu, cpu->cd.sh.sr | SH_SR_MD | SH_SR_RB | SH_SR_BL);
659    
660          /*  Most exceptions set PC to VBR + 0x100.  */          /*  Most exceptions set PC to VBR + 0x100.  */
661          cpu->pc = vbr + 0x100;          cpu->pc = vbr + 0x100;
662    
663    
664          /*  Specific cases:  */          /*  Specific cases:  */
665          switch (expevt) {          switch (expevt) {
666    
# Line 618  void sh_exception(struct cpu *cpu, int e Line 687  void sh_exception(struct cpu *cpu, int e
687                  break;                  break;
688    
689          case EXPEVT_TRAPA:          case EXPEVT_TRAPA:
690                  /*  Note: The TRA register is already set by the                  /*
691                      implementation of the trapa instruction. See                   *  Note: The TRA register is already set by the implementation
692                      cpu_sh_instr.c.  */                   *  of the trapa instruction. See cpu_sh_instr.c for details.
693                     *  Here, spc is incremented, so that a return from the trap
694                     *  handler transfers control to the instruction _following_
695                     *  the trapa.
696                     */
697                  cpu->cd.sh.spc += sizeof(uint16_t);                  cpu->cd.sh.spc += sizeof(uint16_t);
698                  break;                  break;
699    
700            case EXPEVT_RES_INST:
701                    /*
702                     *  Note: Having this code here makes it possible to catch
703                     *  reserved instructions; during normal instruction execution,
704                     *  these are not very common.
705                     */
706    #if 1
707                    printf("\nRESERVED SuperH instruction at spc=%08"PRIx32"\n",
708                        cpu->cd.sh.spc);
709                    exit(1);
710    #else
711                    break;
712    #endif
713    
714            case EXPEVT_FPU_DISABLE:
715                    break;
716    
717          default:fatal("sh_exception(): exception 0x%x is not yet "          default:fatal("sh_exception(): exception 0x%x is not yet "
718                      "implemented.\n", expevt);                      "implemented.\n", expevt);
719                  exit(1);                  exit(1);
# Line 643  void sh_exception(struct cpu *cpu, int e Line 733  void sh_exception(struct cpu *cpu, int e
733  int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr,  int sh_cpu_disassemble_instr_compact(struct cpu *cpu, unsigned char *instr,
734          int running, uint64_t dumpaddr)          int running, uint64_t dumpaddr)
735  {  {
736          uint64_t addr;          char *symbol;
737            uint64_t offset, addr;
738          uint16_t iword;          uint16_t iword;
739          int hi4, lo4, lo8, r8, r4;          int hi4, lo4, lo8, r8, r4;
740    
# Line 666  int sh_cpu_disassemble_instr_compact(str Line 757  int sh_cpu_disassemble_instr_compact(str
757                          debug("stc\tsr,r%i\n", r8);                          debug("stc\tsr,r%i\n", r8);
758                  else if (lo8 == 0x03)                  else if (lo8 == 0x03)
759                          debug("bsrf\tr%i\n", r8);                          debug("bsrf\tr%i\n", r8);
760                  else if (lo4 == 0x4)                  else if (lo4 >= 4 && lo4 <= 6) {
761                          debug("mov.b\tr%i,@(r0,r%i)\n", r4, r8);                          if (lo4 == 0x4)
762                  else if (lo4 == 0x5)                                  debug("mov.b\tr%i,@(r0,r%i)", r4, r8);
763                          debug("mov.w\tr%i,@(r0,r%i)\n", r4, r8);                          else if (lo4 == 0x5)
764                  else if (lo4 == 0x6)                                  debug("mov.w\tr%i,@(r0,r%i)", r4, r8);
765                          debug("mov.l\tr%i,@(r0,r%i)\n", r4, r8);                          else if (lo4 == 0x6)
766                  else if (lo4 == 0x7)                                  debug("mov.l\tr%i,@(r0,r%i)", r4, r8);
767                            if (running) {
768                                    uint32_t addr = cpu->cd.sh.r[0] +
769                                        cpu->cd.sh.r[r8];
770                                    debug("\t; r0+r%i = ", r8);
771                                    symbol = get_symbol_name(
772                                        &cpu->machine->symbol_context,
773                                        addr, &offset);
774                                    if (symbol != NULL)
775                                            debug("<%s>", symbol);
776                                    else
777                                            debug("0x%08"PRIx32, addr);
778                            }
779                            debug("\n");
780                    } else if (lo4 == 0x7)
781                          debug("mul.l\tr%i,r%i\n", r4, r8);                          debug("mul.l\tr%i,r%i\n", r4, r8);
782                  else if (iword == 0x0008)                  else if (iword == 0x0008)
783                          debug("clrt\n");                          debug("clrt\n");
# Line 682  int sh_cpu_disassemble_instr_compact(str Line 787  int sh_cpu_disassemble_instr_compact(str
787                          debug("sts\tmach,r%i\n", r8);                          debug("sts\tmach,r%i\n", r8);
788                  else if (iword == 0x000b)                  else if (iword == 0x000b)
789                          debug("rts\n");                          debug("rts\n");
790                  else if (lo4 == 0xc)                  else if (lo4 >= 0xc && lo4 <= 0xe) {
791                          debug("mov.b\t@(r0,r%i),r%i\n", r4, r8);                          if (lo4 == 0xc)
792                  else if (lo4 == 0xd)                                  debug("mov.b\t@(r0,r%i),r%i", r4, r8);
793                          debug("mov.w\t@(r0,r%i),r%i\n", r4, r8);                          else if (lo4 == 0xd)
794                  else if (lo4 == 0xe)                                  debug("mov.w\t@(r0,r%i),r%i", r4, r8);
795                          debug("mov.l\t@(r0,r%i),r%i\n", r4, r8);                          else if (lo4 == 0xe)
796                  else if (lo8 == 0x12)                                  debug("mov.l\t@(r0,r%i),r%i", r4, r8);
797                            if (running) {
798                                    uint32_t addr = cpu->cd.sh.r[0] +
799                                        cpu->cd.sh.r[r4];
800                                    debug("\t; r0+r%i = ", r4);
801                                    symbol = get_symbol_name(
802                                        &cpu->machine->symbol_context,
803                                        addr, &offset);
804                                    if (symbol != NULL)
805                                            debug("<%s>", symbol);
806                                    else
807                                            debug("0x%08"PRIx32, addr);
808                            }
809                            debug("\n");
810                    } else if (lo8 == 0x12)
811                          debug("stc\tgbr,r%i\n", r8);                          debug("stc\tgbr,r%i\n", r8);
812                  else if (iword == 0x0018)                  else if (iword == 0x0018)
813                          debug("sett\n");                          debug("sett\n");
# Line 740  int sh_cpu_disassemble_instr_compact(str Line 859  int sh_cpu_disassemble_instr_compact(str
859                          debug("movca.l\tr0,@r%i\n", r8);                          debug("movca.l\tr0,@r%i\n", r8);
860                  else if (lo8 == 0xfa)                  else if (lo8 == 0xfa)
861                          debug("stc\tdbr,r%i\n", r8);                          debug("stc\tdbr,r%i\n", r8);
862                  else if (iword == 0x00ff)                  else if (iword == SH_INVALID_INSTR)
863                          debug("gxemul_dreamcast_prom_emul\n");                          debug("gxemul_dreamcast_prom_emul\n");
864                  else                  else
865                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
866                  break;                  break;
867          case 0x1:          case 0x1:
868                  debug("mov.l\tr%i,@(%i,r%i)\n", r4, lo4 * 4, r8);                  debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8);
869                    if (running) {
870                            uint32_t addr = cpu->cd.sh.r[r8] + lo4 * 4;
871                            debug("\t; r%i+%i = ", r8, lo4 * 4);
872                            symbol = get_symbol_name(&cpu->machine->symbol_context,
873                                addr, &offset);
874                            if (symbol != NULL)
875                                    debug("<%s>", symbol);
876                            else
877                                    debug("0x%08"PRIx32, addr);
878                    }
879                    debug("\n");
880                  break;                  break;
881          case 0x2:          case 0x2:
882                  if (lo4 == 0x0)                  if (lo4 == 0x0)
# Line 891  int sh_cpu_disassemble_instr_compact(str Line 1021  int sh_cpu_disassemble_instr_compact(str
1021                          debug("shlr16\tr%i\n", r8);                          debug("shlr16\tr%i\n", r8);
1022                  else if (lo8 == 0x2a)                  else if (lo8 == 0x2a)
1023                          debug("lds\tr%i,pr\n", r8);                          debug("lds\tr%i,pr\n", r8);
1024                  else if (lo8 == 0x2b)                  else if (lo8 == 0x2b) {
1025                          debug("jmp\t@r%i\n", r8);                          debug("jmp\t@r%i", r8);
1026                  else if (lo8 == 0x2e)                          if (running) {
1027                                    symbol = get_symbol_name(
1028                                        &cpu->machine->symbol_context,
1029                                        cpu->cd.sh.r[r8], &offset);
1030                                    if (symbol != NULL)
1031                                            debug("\t\t; <%s>", symbol);
1032                            }
1033                            debug("\n");
1034                    } else if (lo8 == 0x2e)
1035                          debug("ldc\tr%i,vbr\n", r8);                          debug("ldc\tr%i,vbr\n", r8);
1036                  else if (lo8 == 0x33)                  else if (lo8 == 0x33)
1037                          debug("stc.l\tssr,@-r%i\n", r8);                          debug("stc.l\tssr,@-r%i\n", r8);
# Line 931  int sh_cpu_disassemble_instr_compact(str Line 1069  int sh_cpu_disassemble_instr_compact(str
1069                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1070                  break;                  break;
1071          case 0x5:          case 0x5:
1072                  debug("mov.l\t@(%i,r%i),r%i\n", lo4 * 4, r4, r8);                  debug("mov.l\t@(%i,r%i),r%i", lo4 * 4, r4, r8);
1073                    if (running) {
1074                            debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 4,
1075                                cpu->cd.sh.r[r4] + lo4 * 4);
1076                    }
1077                    debug("\n");
1078                  break;                  break;
1079          case 0x6:          case 0x6:
1080                  if (lo4 == 0x0)                  if (lo4 == 0x0)
# Line 973  int sh_cpu_disassemble_instr_compact(str Line 1116  int sh_cpu_disassemble_instr_compact(str
1116                  debug("add\t#%i,r%i\n", (int8_t)lo8, r8);                  debug("add\t#%i,r%i\n", (int8_t)lo8, r8);
1117                  break;                  break;
1118          case 0x8:          case 0x8:
1119                  if (r8 == 0x0) {                  if (r8 == 0 || r8 == 4) {
1120                          debug("mov.b\tr0,@(%i,r%i)\n", lo4, r4);                          if (r8 == 0x0)
1121                  } else if (r8 == 0x1) {                                  debug("mov.b\tr0,@(%i,r%i)", lo4, r4);
1122                          debug("mov.w\tr0,@(%i,r%i)\n", lo4 * 2, r4);                          else if (r8 == 0x4)
1123                  } else if (r8 == 0x4) {                                  debug("mov.b\t@(%i,r%i),r0", lo4, r4);
1124                          debug("mov.b\t@(%i,r%i),r0\n", lo4, r4);                          if (running) {
1125                  } else if (r8 == 0x5) {                                  debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4,
1126                          debug("mov.w\t@(%i,r%i),r0\n", lo4 * 2, r4);                                      cpu->cd.sh.r[r4] + lo4);
1127                            }
1128                            debug("\n");
1129                    } else if (r8 == 1 || r8 == 5) {
1130                            if (r8 == 0x1)
1131                                    debug("mov.w\tr0,@(%i,r%i)", lo4 * 2, r4);
1132                            else if (r8 == 0x5)
1133                                    debug("mov.w\t@(%i,r%i),r0", lo4 * 2, r4);
1134                            if (running) {
1135                                    debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 2,
1136                                        cpu->cd.sh.r[r4] + lo4 * 2);
1137                            }
1138                            debug("\n");
1139                  } else if (r8 == 0x8) {                  } else if (r8 == 0x8) {
1140                          debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);                          debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1141                  } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {                  } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1142                          addr = (int8_t)lo8;                          addr = (int8_t)lo8;
1143                          addr = dumpaddr + 4 + (addr << 1);                          addr = dumpaddr + 4 + (addr << 1);
1144                          debug("b%s%s\t0x%x\n",                          debug("b%s%s\t0x%x",
1145                              (r8 == 0x9 || r8 == 0xd)? "t" : "f",                              (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1146                              (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);                              (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1147                            symbol = get_symbol_name(&cpu->machine->symbol_context,
1148                                addr, &offset);
1149                            if (symbol != NULL)
1150                                    debug("\t; <%s>", symbol);
1151                            debug("\n");
1152                  } else                  } else
1153                          debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);                          debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1154                  break;                  break;
# Line 996  int sh_cpu_disassemble_instr_compact(str Line 1156  int sh_cpu_disassemble_instr_compact(str
1156          case 0xd:          case 0xd:
1157                  addr = lo8 * (hi4==9? 2 : 4);                  addr = lo8 * (hi4==9? 2 : 4);
1158                  addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;                  addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1159                  debug("mov.%s\t0x%x,r%i\n", hi4==9? "w":"l", (int)addr, r8);                  debug("mov.%s\t0x%x,r%i", hi4==9? "w":"l", (int)addr, r8);
1160                    symbol = get_symbol_name(&cpu->machine->symbol_context,
1161                        addr, &offset);
1162                    if (symbol != NULL)
1163                            debug("\t; <%s>", symbol);
1164                    debug("\n");
1165                  break;                  break;
1166          case 0xa:          case 0xa:
1167          case 0xb:          case 0xb:
1168                  addr = (int32_t)(int16_t)((iword & 0xfff) << 4);                  addr = (int32_t)(int16_t)((iword & 0xfff) << 4);
1169                  addr = ((int32_t)addr >> 3);                  addr = ((int32_t)addr >> 3);
1170                  addr += dumpaddr + 4;                  addr += dumpaddr + 4;
1171                  debug("%s\t0x%x\n", hi4==0xa? "bra":"bsr", (int)addr);                  debug("%s\t0x%x", hi4==0xa? "bra":"bsr", (int)addr);
1172    
1173                    symbol = get_symbol_name(&cpu->machine->symbol_context,
1174                        addr, &offset);
1175                    if (symbol != NULL)
1176                            debug("\t; <%s>", symbol);
1177                    debug("\n");
1178                  break;                  break;
1179          case 0xc:          case 0xc:
1180                  if (r8 == 0x0)                  if (r8 == 0x0)
# Line 1143  int sh_cpu_disassemble_instr_compact(str Line 1314  int sh_cpu_disassemble_instr_compact(str
1314                          debug("fldi0\tfr%i\n", r8);                          debug("fldi0\tfr%i\n", r8);
1315                  else if (lo8 == 0x9d)                  else if (lo8 == 0x9d)
1316                          debug("fldi1\tfr%i\n", r8);                          debug("fldi1\tfr%i\n", r8);
1317                    else if (lo8 == 0xad)
1318                            debug("fcnvsd\tfpul,dr%i\n", r8);
1319                    else if (lo8 == 0xbd)
1320                            debug("fcnvds\tdr%i,fpul\n", r8);
1321                  else if ((iword & 0x01ff) == 0x00fd)                  else if ((iword & 0x01ff) == 0x00fd)
1322                          debug("fsca\tfpul,dr%i\n", r8);                          debug("fsca\tfpul,dr%i\n", r8);
1323                  else if (iword == 0xf3fd)                  else if (iword == 0xf3fd)

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

  ViewVC Help
Powered by ViewVC 1.1.26