/[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 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  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.9 2006/02/17 18:38:30 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   *  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.
34     *
35     *  TODO: This actually only works or SH4 so far, not SH3.
36   */   */
37    
38  #include <stdio.h>  #include <stdio.h>
39  #include <stdlib.h>  #include <stdlib.h>
40  #include <string.h>  #include <string.h>
41  #include <ctype.h>  #include <ctype.h>
42    #include <unistd.h>
43    
44  #include "cpu.h"  #include "cpu.h"
45    #include "device.h"
46    #include "float_emul.h"
47    #include "interrupt.h"
48  #include "machine.h"  #include "machine.h"
49  #include "memory.h"  #include "memory.h"
50  #include "misc.h"  #include "misc.h"
51    #include "settings.h"
52  #include "symbol.h"  #include "symbol.h"
53    #include "timer.h"
54    
55    #include "sh4_exception.h"
56    #include "sh4_mmu.h"
57    
58    
59  #define DYNTRANS_DUALMODE_32  #define DYNTRANS_32
60    #define DYNTRANS_DELAYSLOT
61  #include "tmp_sh_head.c"  #include "tmp_sh_head.c"
62    
63    
64    extern int quiet_mode;
65    extern int native_code_translation_enabled;
66    
67    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():
75   *   *
# Line 59  Line 81 
81  int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,  int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
82          int cpu_id, char *cpu_type_name)          int cpu_id, char *cpu_type_name)
83  {  {
84          if (strcasecmp(cpu_type_name, "SH") != 0)          int i = 0;
85            struct sh_cpu_type_def cpu_type_defs[] = SH_CPU_TYPE_DEFS;
86    
87            /*  Scan the cpu_type_defs list for this cpu type:  */
88            while (cpu_type_defs[i].name != NULL) {
89                    if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
90                            break;
91                    }
92                    i++;
93            }
94            if (cpu_type_defs[i].name == NULL)
95                  return 0;                  return 0;
96    
97          cpu->memory_rw = sh_memory_rw;          cpu->memory_rw = sh_memory_rw;
98    
99          /*  TODO: per CPU type?  */          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 = 1;          cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
102          cpu->cd.sh.bits = 32;  
103          cpu->cd.sh.compact = 1;          if (!cpu->is_32bit) {
104                    fatal("SH64 emulation not implemented. Sorry.\n");
105          if (cpu->is_32bit) {                  exit(1);
                 cpu->update_translation_table = sh32_update_translation_table;  
                 cpu->invalidate_translation_caches =  
                     sh32_invalidate_translation_caches;  
                 cpu->invalidate_code_translation =  
                     sh32_invalidate_code_translation;  
         } else {  
                 cpu->update_translation_table = sh_update_translation_table;  
                 cpu->invalidate_translation_caches =  
                     sh_invalidate_translation_caches;  
                 cpu->invalidate_code_translation =  
                     sh_invalidate_code_translation;  
106          }          }
107    
108            cpu->instruction_has_delayslot = sh_cpu_instruction_has_delayslot;
109    
110            cpu->translate_v2p = sh_translate_v2p;
111    
112            cpu->run_instr = sh_run_instr;
113            cpu->update_translation_table = sh_update_translation_table;
114            cpu->invalidate_translation_caches =
115                sh_invalidate_translation_caches;
116            cpu->invalidate_code_translation =
117                sh_invalidate_code_translation;
118    
119          /*  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):  */
120          if (cpu_id == 0) {          if (cpu_id == 0) {
121                  debug("%s", cpu->name);                  debug("%s", cpu->name);
122          }          }
123    
124            /*  Initial value of FPSCR (according to the SH4 manual):  */
125            cpu->cd.sh.fpscr = 0x00040001;
126    
127            /*  (Initial value of the program counter on reboot is 0xA0000000.)  */
128    
129            /*  Start in Privileged Mode:  */
130            cpu->cd.sh.sr = SH_SR_MD | SH_SR_IMASK;
131    
132            /*  Stack pointer at end of physical RAM:  */
133            cpu->cd.sh.r[15] = cpu->machine->physical_ram_in_mb * 1048576 - 64;
134    
135            CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
136            CPU_SETTINGS_ADD_REGISTER32("sr", cpu->cd.sh.sr);
137            CPU_SETTINGS_ADD_REGISTER32("pr", cpu->cd.sh.pr);
138            CPU_SETTINGS_ADD_REGISTER32("vbr", cpu->cd.sh.vbr);
139            CPU_SETTINGS_ADD_REGISTER32("gbr", cpu->cd.sh.gbr);
140            CPU_SETTINGS_ADD_REGISTER32("macl", cpu->cd.sh.macl);
141            CPU_SETTINGS_ADD_REGISTER32("mach", cpu->cd.sh.mach);
142            CPU_SETTINGS_ADD_REGISTER32("expevt", cpu->cd.sh.expevt);
143            CPU_SETTINGS_ADD_REGISTER32("intevt", cpu->cd.sh.intevt);
144            CPU_SETTINGS_ADD_REGISTER32("tra", cpu->cd.sh.tra);
145            CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.sh.fpscr);
146            CPU_SETTINGS_ADD_REGISTER32("fpul", cpu->cd.sh.fpul);
147            for (i=0; i<SH_N_GPRS; i++) {
148                    char tmpstr[5];
149                    snprintf(tmpstr, sizeof(tmpstr), "r%i", i);
150                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r[i]);
151            }
152            for (i=0; i<SH_N_GPRS_BANKED; i++) {
153                    char tmpstr[15];
154                    snprintf(tmpstr, sizeof(tmpstr), "r%i_bank", i);
155                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r_bank[i]);
156            }
157            for (i=0; i<SH_N_FPRS; i++) {
158                    char tmpstr[6];
159                    snprintf(tmpstr, sizeof(tmpstr), "fr%i", i);
160                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.fr[i]);
161                    snprintf(tmpstr, sizeof(tmpstr), "xf%i", i);
162                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.xf[i]);
163            }
164            for (i=0; i<SH_N_ITLB_ENTRIES; i++) {
165                    char tmpstr[15];
166                    snprintf(tmpstr, sizeof(tmpstr), "itlb_hi_%i", i);
167                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_hi[i]);
168                    snprintf(tmpstr, sizeof(tmpstr), "itlb_lo_%i", i);
169                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_lo[i]);
170            }
171            for (i=0; i<SH_N_UTLB_ENTRIES; i++) {
172                    char tmpstr[15];
173                    snprintf(tmpstr, sizeof(tmpstr), "utlb_hi_%i", i);
174                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_hi[i]);
175                    snprintf(tmpstr, sizeof(tmpstr), "utlb_lo_%i", i);
176                    CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_lo[i]);
177            }
178    
179            /*  Register the CPU's interrupts:  */
180            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;
196                    memset(&template, 0, sizeof(template));
197                    template.line = i;
198                    template.name = cpu->path;
199                    template.extra = cpu;
200                    template.interrupt_assert = sh3_cpu_interrupt_assert;
201                    template.interrupt_deassert = sh3_cpu_interrupt_deassert;
202                    interrupt_handler_register(&template);
203            }
204    
205            /*  SH4-specific memory mapped registers, TLBs, caches, etc:  */
206            if (cpu->cd.sh.cpu_type.arch == 4) {
207                    cpu->cd.sh.pcic_pcibus = device_add(machine, "sh4");
208    
209                    /*
210                     *  Interrupt Controller initial values, according to the
211                     *  SH7760 manual:
212                     */
213                    cpu->cd.sh.intc_iprd = 0xda74;
214                    cpu->cd.sh.intc_intmsk00 = 0xf3ff7fff;
215                    cpu->cd.sh.intc_intmsk04 = 0x00ffffff;
216                    /*  All others are zero.  */
217    
218                    /*  TODO: Initial priorities?  */
219                    cpu->cd.sh.intc_intpri00 = 0x33333333;
220                    cpu->cd.sh.intc_intpri04 = 0x33333333;
221                    cpu->cd.sh.intc_intpri08 = 0x33333333;
222                    cpu->cd.sh.intc_intpri0c = 0x33333333;
223            }
224    
225            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    
234    
235  /*  /*
236     *  sh_update_interrupt_priorities():
237     *
238     *  SH interrupts are a bit complicated; there are several intc registers
239     *  controlling priorities for various peripherals:
240     *
241     *  Register:  Bits 15..12  11..8  7..4      3..0
242     *  ---------  -----------  -----  ----      ----
243     *  ipra       TMU0         TMU1   TMU2      Reserved
244     *  iprb       WDT          REF    Reserved  Reserved
245     *  iprc       GPIO         DMAC   Reserved  H-UDI
246     *  iprd       IRL0         IRL1   IRL2      IRL3
247     *
248     *  Register:  31..28  27..24  23..20  19..16  15..12  11..8   7..4   3..0
249     *  ---------  ------  ------  ------  ------  ------  -----   ----   ----
250     *  intpri00   IRQ4    IRQ5    IRQ6    IRQ7    Rsrvd.  Rsrvd.  Rsrvd. Reserved
251     *  intpri04   HCAN2,0 HCAN2,1 SSI(0)  SSI(1)  HAC(0)  HAC(1)  I2C(0) I2C(1)
252     *  intpri08   USB     LCDC    DMABRG  SCIF(0) SCIF(1) SCIF(2) SIM    HSPI
253     *  intpri0c   Reserv. Reserv. MMCIF   Reserv. MFI     Rsrvd.  ADC    CMT
254     */
255    void sh_update_interrupt_priorities(struct cpu *cpu)
256    {
257            int i;
258    
259            /*
260             *  Set priorities of known interrupts, without affecting the
261             *  SH_INT_ASSERTED bit:
262             */
263    
264            for (i=SH4_INTEVT_IRQ0; i<=SH4_INTEVT_IRQ14; i+=0x20) {
265                    cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
266                    cpu->cd.sh.int_prio_and_pending[i/0x20] |= (15 - ((i -
267                        SH4_INTEVT_IRQ0) / 0x20));
268            }
269    
270            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU0_TUNI0 / 0x20] &=
271                ~SH_INT_PRIO_MASK;
272            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU0_TUNI0 / 0x20] |=
273                (cpu->cd.sh.intc_ipra >> 12) & 0xf;
274    
275            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU1_TUNI1 / 0x20] &=
276                ~SH_INT_PRIO_MASK;
277            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU1_TUNI1 / 0x20] |=
278                (cpu->cd.sh.intc_ipra >> 8) & 0xf;
279    
280            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU2_TUNI2 / 0x20] &=
281                ~SH_INT_PRIO_MASK;
282            cpu->cd.sh.int_prio_and_pending[SH_INTEVT_TMU2_TUNI2 / 0x20] |=
283                (cpu->cd.sh.intc_ipra >> 4) & 0xf;
284    
285            for (i=SH4_INTEVT_SCIF_ERI; i<=SH4_INTEVT_SCIF_TXI; i+=0x20) {
286                    cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
287                    cpu->cd.sh.int_prio_and_pending[i/0x20] |=
288                        ((cpu->cd.sh.intc_intpri08 >> 16) & 0xf);
289            }
290    }
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():
309     */
310    void sh_cpu_interrupt_assert(struct interrupt *interrupt)
311    {
312            struct cpu *cpu = interrupt->extra;
313            unsigned int irq_nr = interrupt->line;
314            unsigned int index = irq_nr / 0x20;
315            unsigned int prio;
316    
317            /*  Assert the interrupt, and check its priority level:  */
318            cpu->cd.sh.int_prio_and_pending[index] |= SH_INT_ASSERTED;
319            prio = cpu->cd.sh.int_prio_and_pending[index] & SH_INT_PRIO_MASK;
320    
321            if (prio == 0) {
322                    /*  Interrupt not implemented? Hm.  */
323                    fatal("[ SH interrupt 0x%x, prio 0 (?), aborting ]\n", irq_nr);
324                    exit(1);
325            }
326    
327            if (cpu->cd.sh.int_to_assert == 0 || prio > cpu->cd.sh.int_level) {
328                    cpu->cd.sh.int_to_assert = irq_nr;
329                    cpu->cd.sh.int_level = prio;
330            }
331    }
332    
333    
334    /*
335     *  sh_cpu_interrupt_deassert():
336     */
337    void sh_cpu_interrupt_deassert(struct interrupt *interrupt)
338    {
339            struct cpu *cpu = interrupt->extra;
340            int irq_nr = interrupt->line;
341            int index = irq_nr / 0x20;
342    
343            /*  Deassert the interrupt:  */
344            if (cpu->cd.sh.int_prio_and_pending[index] & SH_INT_ASSERTED) {
345                    cpu->cd.sh.int_prio_and_pending[index] &= ~SH_INT_ASSERTED;
346    
347                    /*  Calculate new interrupt assertion:  */
348                    cpu->cd.sh.int_to_assert = 0;
349                    cpu->cd.sh.int_level = 0;
350    
351                    /*  NOTE/TODO: This is slow, but should hopefully work:  */
352                    for (index=0; index<0x1000/0x20; index++) {
353                            uint8_t x = cpu->cd.sh.int_prio_and_pending[index];
354                            uint8_t prio = x & SH_INT_PRIO_MASK;
355                            if (x & SH_INT_ASSERTED &&
356                                prio > cpu->cd.sh.int_level) {
357                                    cpu->cd.sh.int_to_assert = index * 0x20;
358                                    cpu->cd.sh.int_level = prio;
359                            }
360                    }
361            }
362    }
363    
364    
365    /*
366   *  sh_cpu_list_available_types():   *  sh_cpu_list_available_types():
367   *   *
368   *  Print a list of available SH CPU types.   *  Print a list of available SH CPU types.
369   */   */
370  void sh_cpu_list_available_types(void)  void sh_cpu_list_available_types(void)
371  {  {
372          debug("SH\n");          int i = 0, j;
373          /*  TODO  */          struct sh_cpu_type_def tdefs[] = SH_CPU_TYPE_DEFS;
374    
375            while (tdefs[i].name != NULL) {
376                    debug("%s", tdefs[i].name);
377                    for (j=10 - strlen(tdefs[i].name); j>0; j--)
378                            debug(" ");
379                    i ++;
380                    if ((i % 6) == 0 || tdefs[i].name == NULL)
381                            debug("\n");
382            }
383  }  }
384    
385    
# Line 110  void sh_cpu_list_available_types(void) Line 388  void sh_cpu_list_available_types(void)
388   */   */
389  void sh_cpu_dumpinfo(struct cpu *cpu)  void sh_cpu_dumpinfo(struct cpu *cpu)
390  {  {
391          debug("\n");          debug(" (%s-endian)\n",
392          /*  TODO  */              cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
393    }
394    
395    
396    /*
397     *  sh_cpu_instruction_has_delayslot():
398     *
399     *  Return 1 if an opcode is a branch, 0 otherwise.
400     */
401    int sh_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
402    {
403            uint16_t iword = *((uint16_t *)&ib[0]);
404            int hi4, lo4, lo8;
405    
406            if (!cpu->is_32bit)
407                    return 0;
408    
409            if (cpu->byte_order == EMUL_BIG_ENDIAN)
410                    iword = BE16_TO_HOST(iword);
411            else
412                    iword = LE16_TO_HOST(iword);
413    
414            hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
415    
416            switch (hi4) {
417            case 0x0:
418                    if (iword == 0x000b)    /*  rts  */
419                            return 1;
420                    if (iword == 0x002b)    /*  rte  */
421                            return 1;
422                    if (lo8 == 0x03)        /*  bsrf  */
423                            return 1;
424                    if (lo8 == 0x23)        /*  braf  */
425                            return 1;
426                    break;
427            case 0x4:
428                    switch (lo8) {
429                    case 0x0b:      /*  jsr  */
430                    case 0x2b:      /*  jmp  */
431                            return 1;
432                    }
433                    break;
434            case 0x8:
435                    switch ((iword >> 8) & 0xf) {
436                    case 0xd:       /*  bt/s  */
437                    case 0xf:       /*  bf/s  */
438                            return 1;
439                    }
440                    break;
441            case 0xa:       /*  bra  */
442            case 0xb:       /*  bsr  */
443                    return 1;
444            }
445    
446            return 0;
447  }  }
448    
449    
# Line 127  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;
         int bits32 = cpu->cd.sh.bits == 32;  
463    
464          if (gprs) {          if (gprs) {
465                  /*  Special registers (pc, ...) first:  */                  /*  Special registers (pc, ...) first:  */
466                  symbol = get_symbol_name(&cpu->machine->symbol_context,                  symbol = get_symbol_name(&cpu->machine->symbol_context,
467                      cpu->pc, &offset);                      cpu->pc, &offset);
468    
469                  debug("cpu%i: pc  = 0x", x);                  debug("cpu%i: pc  = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
                 if (bits32)  
                         debug("%08x", (int)cpu->pc);  
                 else  
                         debug("%016llx", (long long)cpu->pc);  
470                  debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");                  debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");
471    
472                  if (bits32) {                  debug("cpu%i: sr  = 0x%08"PRIx32"  (%s, %s, %s, %s, %s, %s,"
473                          /*  32-bit:  */                      " imask=0x%x, %s, %s)\n", x, (int32_t)cpu->cd.sh.sr,
474                          for (i=0; i<nregs; i++) {                      (cpu->cd.sh.sr & SH_SR_MD)? "MD" : "!md",
475                                  if ((i % 4) == 0)                      (cpu->cd.sh.sr & SH_SR_RB)? "RB" : "!rb",
476                                          debug("cpu%i:", x);                      (cpu->cd.sh.sr & SH_SR_BL)? "BL" : "!bl",
477                                  debug(" r%02i = 0x%08x ", i,                      (cpu->cd.sh.sr & SH_SR_FD)? "FD" : "!fd",
478                                      (int)cpu->cd.sh.r[i]);                      (cpu->cd.sh.sr & SH_SR_M)? "M" : "!m",
479                                  if ((i % 4) == 3)                      (cpu->cd.sh.sr & SH_SR_Q)? "Q" : "!q",
480                                          debug("\n");                      (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT,
481                          }                      (cpu->cd.sh.sr & SH_SR_S)? "S" : "!s",
482                  } else {                      (cpu->cd.sh.sr & SH_SR_T)? "T" : "!t");
483                          /*  64-bit:  */  
484                          for (i=0; i<nregs; i++) {                  symbol = get_symbol_name(&cpu->machine->symbol_context,
485                                  int r = (i >> 1) + ((i & 1) << 4);                      cpu->cd.sh.pr, &offset);
486                                  if ((i % 2) == 0)                  debug("cpu%i: pr  = 0x%08"PRIx32, x, (uint32_t)cpu->cd.sh.pr);
487                                          debug("cpu%i:", x);                  debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");
488                                  debug(" r%02i = 0x%016llx ", r,  
489                                      (long long)cpu->cd.sh.r[r]);                  debug("cpu%i: mach = 0x%08"PRIx32"  macl = 0x%08"PRIx32
490                                  if ((i % 2) == 1)                      "  gbr = 0x%08"PRIx32"\n", x, (uint32_t)cpu->cd.sh.mach,
491                                          debug("\n");                      (uint32_t)cpu->cd.sh.macl, (uint32_t)cpu->cd.sh.gbr);
492                          }  
493                    for (i=0; i<SH_N_GPRS; i++) {
494                            if ((i % 4) == 0)
495                                    debug("cpu%i:", x);
496                            debug(" r%-2i = 0x%08x ", i, (int)cpu->cd.sh.r[i]);
497                            if ((i % 4) == 3)
498                                    debug("\n");
499                    }
500            }
501    
502            if (coprocs & 1) {
503                    /*  Floating point:  */
504                    debug("cpu%i: fpscr = 0x%08"PRIx32" (%s,%s,%s)  fpul = 0x%08"
505                        PRIx32"\n", x, cpu->cd.sh.fpscr,
506                        cpu->cd.sh.fpscr & SH_FPSCR_PR? "PR" : "!pr",
507                        cpu->cd.sh.fpscr & SH_FPSCR_SZ? "SZ" : "!sz",
508                        cpu->cd.sh.fpscr & SH_FPSCR_FR? "FR" : "!fr",
509                        cpu->cd.sh.fpul);
510    
511                    for (i=0; i<SH_N_FPRS; i++) {
512                            if ((i % 4) == 0)
513                                    debug("cpu%i:", x);
514                            debug(" fr%-2i=0x%08x ", i, (int)cpu->cd.sh.fr[i]);
515                            if ((i % 4) == 3)
516                                    debug("\n");
517                    }
518    
519                    for (i=0; i<SH_N_FPRS; i++) {
520                            if ((i % 4) == 0)
521                                    debug("cpu%i:", x);
522                            debug(" xf%-2i=0x%08x ", i, (int)cpu->cd.sh.xf[i]);
523                            if ((i % 4) == 3)
524                                    debug("\n");
525                    }
526            }
527    
528            if (coprocs & 2) {
529                    /*  System registers, etc:  */
530                    debug("cpu%i: vbr = 0x%08"PRIx32"  sgr = 0x%08"PRIx32
531                        "\n", x, cpu->cd.sh.vbr, cpu->cd.sh.sgr);
532                    debug("cpu%i: spc = 0x%08"PRIx32"  ssr = 0x%08"PRIx32"\n",
533                        x, cpu->cd.sh.spc, cpu->cd.sh.ssr);
534                    debug("cpu%i: expevt = 0x%"PRIx32"  intevt = 0x%"PRIx32
535                        "  tra = 0x%"PRIx32"\n", x, cpu->cd.sh.expevt,
536                        cpu->cd.sh.intevt, cpu->cd.sh.tra);
537    
538                    for (i=0; i<SH_N_GPRS_BANKED; i++) {
539                            if ((i % 2) == 0)
540                                    debug("cpu%i:", x);
541                            debug(" r%i_bank = 0x%08x ", i,
542                                (int)cpu->cd.sh.r_bank[i]);
543                            if ((i % 2) == 1)
544                                    debug("\n");
545                  }                  }
546          }          }
547  }  }
548    
549    
550  /*  /*
551   *  sh_cpu_register_match():   *  sh_cpu_tlbdump():
552     *
553     *  Called from the debugger to dump the TLB in a readable format.
554     *  x is the cpu number to dump, or -1 to dump all CPUs.
555     *
556     *  If rawflag is nonzero, then the TLB contents isn't formated nicely,
557     *  just dumped.
558   */   */
559  void sh_cpu_register_match(struct machine *m, char *name,  void sh_cpu_tlbdump(struct machine *m, int x, int rawflag)
         int writeflag, uint64_t *valuep, int *match_register)  
560  {  {
561          int cpunr = 0;          int i, j;
562    
563          /*  CPU number:  */          for (j=0; j<m->ncpus; j++) {
564                    struct cpu *cpu = m->cpus[j];
565    
566          /*  TODO  */                  if (x >= 0 && j != x)
567                            continue;
568    
569          /*  Register name:  */                  for (i=0; i<SH_N_ITLB_ENTRIES; i++)
570          if (strcasecmp(name, "pc") == 0) {                          printf("cpu%i: itlb_hi_%-2i = 0x%08"PRIx32"  "
571                  if (writeflag) {                              "itlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
572                          m->cpus[cpunr]->pc = *valuep;                              (uint32_t) cpu->cd.sh.itlb_hi[i], i,
573                  } else                              (uint32_t) cpu->cd.sh.itlb_lo[i]);
574                          *valuep = m->cpus[cpunr]->pc;                  for (i=0; i<SH_N_UTLB_ENTRIES; i++)
575                  *match_register = 1;                          printf("cpu%i: utlb_hi_%-2i = 0x%08"PRIx32"  "
576                                "utlb_lo_%-2i = 0x%08"PRIx32"\n", j, i,
577                                (uint32_t) cpu->cd.sh.utlb_hi[i], i,
578                                (uint32_t) cpu->cd.sh.utlb_lo[i]);
579          }          }
580  }  }
581    
582    
583  /*  /*
584   *  sh_cpu_interrupt():   *  sh_update_sr():
585     *
586     *  Writes a new value to the status register.
587   */   */
588  int sh_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)  void sh_update_sr(struct cpu *cpu, uint32_t new_sr)
589  {  {
590          fatal("sh_cpu_interrupt(): TODO\n");          uint32_t old_sr = cpu->cd.sh.sr;
591          return 0;  
592            if ((new_sr & SH_SR_RB) != (old_sr & SH_SR_RB)) {
593                    int i;
594                    for (i=0; i<SH_N_GPRS_BANKED; i++) {
595                            uint32_t tmp = cpu->cd.sh.r[i];
596                            cpu->cd.sh.r[i] = cpu->cd.sh.r_bank[i];
597                            cpu->cd.sh.r_bank[i] = tmp;
598                    }
599            }
600    
601            cpu->cd.sh.sr = new_sr;
602  }  }
603    
604    
605  /*  /*
606   *  sh_cpu_interrupt_ack():   *  sh_update_fpscr():
607     *
608     *  Writes a new value to the floating-point status/control register.
609   */   */
610  int sh_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)  void sh_update_fpscr(struct cpu *cpu, uint32_t new_fpscr)
611  {  {
612          /*  fatal("sh_cpu_interrupt_ack(): TODO\n");  */          uint32_t old_fpscr = cpu->cd.sh.fpscr;
613          return 0;  
614            if ((new_fpscr & SH_FPSCR_FR) != (old_fpscr & SH_FPSCR_FR)) {
615                    int i;
616                    for (i=0; i<SH_N_FPRS; i++) {
617                            uint32_t tmp = cpu->cd.sh.fr[i];
618                            cpu->cd.sh.fr[i] = cpu->cd.sh.xf[i];
619                            cpu->cd.sh.xf[i] = tmp;
620                    }
621            }
622    
623            cpu->cd.sh.fpscr = new_fpscr;
624  }  }
625    
626    
627  /*  /*
628   *  sh_cpu_disassemble_instr_compact():   *  sh_exception():
629     *
630     *  Causes a transfer of control to an exception or interrupt handler.
631     *  If intevt > 0, then it is an interrupt, otherwise an exception.
632     *
633     *  vaddr contains the faulting address, on TLB exceptions.
634     */
635    void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
636    {
637            uint32_t vbr = cpu->cd.sh.vbr;
638    
639            if (!quiet_mode) {
640                    if (intevt > 0)
641                            debug("[ interrupt 0x%03x", intevt);
642                    else
643                            debug("[ exception 0x%03x", expevt);
644    
645                    debug(", pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
646                    if (intevt == 0)
647                            debug("vaddr=0x%08"PRIx32" ", vaddr);
648    
649                    debug(" ]\n");
650            }
651    
652            if (cpu->cd.sh.sr & SH_SR_BL) {
653                    fatal("[ sh_exception(): BL bit already set. ]\n");
654    
655                    /*  This is actually OK in two cases: a User Break,
656                        or on NMI interrupts if a special flag is set?  */
657                    /*  TODO  */
658    
659                    expevt = EXPEVT_RESET_POWER;
660            }
661    
662            if (cpu->is_halted) {
663                    /*
664                     *  If the exception occurred on a 'sleep' instruction, then let
665                     *  the instruction following the sleep instruction be the one
666                     *  where execution resumes when the interrupt service routine
667                     *  returns.
668                     */
669                    cpu->is_halted = 0;
670                    cpu->pc += sizeof(uint16_t);
671            }
672    
673            if (cpu->delay_slot) {
674                    cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
675                    cpu->pc -= sizeof(uint16_t);
676            }
677    
678    
679            /*
680             *  Stuff common to all exceptions:
681             */
682    
683            cpu->cd.sh.spc = cpu->pc;
684            cpu->cd.sh.ssr = cpu->cd.sh.sr;
685            cpu->cd.sh.sgr = cpu->cd.sh.r[15];
686    
687            if (intevt > 0) {
688                    cpu->cd.sh.intevt = intevt;
689                    expevt = -1;
690            } else {
691                    cpu->cd.sh.expevt = expevt;
692            }
693    
694            sh_update_sr(cpu, cpu->cd.sh.sr | SH_SR_MD | SH_SR_RB | SH_SR_BL);
695    
696            /*  Most exceptions set PC to VBR + 0x100.  */
697            cpu->pc = vbr + 0x100;
698    
699    
700            /*  Specific cases:  */
701            switch (expevt) {
702    
703            case -1:        /*  Interrupt  */
704                    cpu->pc = vbr + 0x600;
705                    break;
706    
707            case EXPEVT_RESET_POWER:
708            case EXPEVT_RESET_MANUAL:
709                    cpu->pc = 0xa0000000;
710                    cpu->cd.sh.vbr = 0x00000000;
711                    sh_update_sr(cpu, (cpu->cd.sh.sr | SH_SR_IMASK) & ~SH_SR_FD);
712                    break;
713    
714            case EXPEVT_TLB_MISS_LD:
715            case EXPEVT_TLB_MISS_ST:
716                    cpu->pc = vbr + 0x400;
717            case EXPEVT_TLB_PROT_LD:
718            case EXPEVT_TLB_PROT_ST:
719            case EXPEVT_TLB_MOD:
720                    cpu->cd.sh.tea = vaddr;
721                    cpu->cd.sh.pteh &= ~SH4_PTEH_VPN_MASK;
722                    cpu->cd.sh.pteh |= (vaddr & SH4_PTEH_VPN_MASK);
723                    break;
724    
725            case EXPEVT_TRAPA:
726                    /*
727                     *  Note: The TRA register is already set by the implementation
728                     *  of the trapa instruction. See cpu_sh_instr.c for details.
729                     *  Here, spc is incremented, so that a return from the trap
730                     *  handler transfers control to the instruction _following_
731                     *  the trapa.
732                     */
733                    cpu->cd.sh.spc += sizeof(uint16_t);
734                    break;
735    
736            case EXPEVT_RES_INST:
737                    /*
738                     *  Note: Having this code here makes it possible to catch
739                     *  reserved instructions; during normal instruction execution,
740                     *  these are not very common.
741                     */
742    #if 1
743                    printf("\nRESERVED SuperH instruction at spc=%08"PRIx32"\n",
744                        cpu->cd.sh.spc);
745                    exit(1);
746    #else
747                    break;
748    #endif
749    
750            case EXPEVT_FPU_DISABLE:
751                    break;
752    
753            default:fatal("sh_exception(): exception 0x%x is not yet "
754                        "implemented.\n", expevt);
755                    exit(1);
756            }
757    
758            sh_pc_to_pointers(cpu);
759    }
760    
761    
762    /*
763     *  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 bintrans)          int running, uint64_t dumpaddr)
780  {  {
781          uint64_t addr;          char *symbol;
782            uint64_t offset, addr;
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
802                  iword = (instr[1] << 8) + instr[0];                  iword = (instr[1] << 8) + instr[0];
803    
804          debug(":  %04x \t", iword);          debug(":  %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
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 244  int sh_cpu_disassemble_instr_compact(str Line 816  int sh_cpu_disassemble_instr_compact(str
816                          debug("stc\tsr,r%i\n", r8);                          debug("stc\tsr,r%i\n", r8);
817                  else if (lo8 == 0x03)                  else if (lo8 == 0x03)
818                          debug("bsrf\tr%i\n", r8);                          debug("bsrf\tr%i\n", r8);
819                  else if (lo4 == 0x4)                  else if (lo4 >= 4 && lo4 <= 6) {
820                          debug("mov.b\tr%i,@(r0,r%i)\n", r4, r8);                          if (lo4 == 0x4)
821                  else if (lo4 == 0x5)                                  debug("mov.b\tr%i,@(r0,r%i)", r4, r8);
822                          debug("mov.w\tr%i,@(r0,r%i)\n", r4, r8);                          else if (lo4 == 0x5)
823                  else if (lo4 == 0x6)                                  debug("mov.w\tr%i,@(r0,r%i)", r4, r8);
824                          debug("mov.l\tr%i,@(r0,r%i)\n", r4, r8);                          else if (lo4 == 0x6)
825                  else if (lo4 == 0x7)                                  debug("mov.l\tr%i,@(r0,r%i)", r4, r8);
826                            if (running) {
827                                    uint32_t addr = cpu->cd.sh.r[0] +
828                                        cpu->cd.sh.r[r8];
829                                    debug("\t; r0+r%i = ", r8);
830                                    symbol = get_symbol_name(
831                                        &cpu->machine->symbol_context,
832                                        addr, &offset);
833                                    if (symbol != NULL)
834                                            debug("<%s>", symbol);
835                                    else
836                                            debug("0x%08"PRIx32, addr);
837                            }
838                            debug("\n");
839                    } else if (lo4 == 0x7)
840                          debug("mul.l\tr%i,r%i\n", r4, r8);                          debug("mul.l\tr%i,r%i\n", r4, r8);
841                  else if (iword == 0x0008)                  else if (iword == 0x0008)
842                          debug("clrt\n");                          debug("clrt\n");
# Line 260  int sh_cpu_disassemble_instr_compact(str Line 846  int sh_cpu_disassemble_instr_compact(str
846                          debug("sts\tmach,r%i\n", r8);                          debug("sts\tmach,r%i\n", r8);
847                  else if (iword == 0x000b)                  else if (iword == 0x000b)
848                          debug("rts\n");                          debug("rts\n");
849                  else if (lo4 == 0xc)                  else if (lo4 >= 0xc && lo4 <= 0xe) {
850                          debug("mov.b\t@(r0,r%i),r%i\n", r4, r8);                          if (lo4 == 0xc)
851                  else if (lo4 == 0xd)                                  debug("mov.b\t@(r0,r%i),r%i", r4, r8);
852                          debug("mov.w\t@(r0,r%i),r%i\n", r4, r8);                          else if (lo4 == 0xd)
853                  else if (lo4 == 0xe)                                  debug("mov.w\t@(r0,r%i),r%i", r4, r8);
854                          debug("mov.l\t@(r0,r%i),r%i\n", r4, r8);                          else if (lo4 == 0xe)
855                  else if (lo8 == 0x12)                                  debug("mov.l\t@(r0,r%i),r%i", r4, r8);
856                            if (running) {
857                                    uint32_t addr = cpu->cd.sh.r[0] +
858                                        cpu->cd.sh.r[r4];
859                                    debug("\t; r0+r%i = ", r4);
860                                    symbol = get_symbol_name(
861                                        &cpu->machine->symbol_context,
862                                        addr, &offset);
863                                    if (symbol != NULL)
864                                            debug("<%s>", symbol);
865                                    else
866                                            debug("0x%08"PRIx32, addr);
867                            }
868                            debug("\n");
869                    } else if (lo8 == 0x12)
870                          debug("stc\tgbr,r%i\n", r8);                          debug("stc\tgbr,r%i\n", r8);
871                  else if (iword == 0x0018)                  else if (iword == 0x0018)
872                          debug("sett\n");                          debug("sett\n");
# Line 274  int sh_cpu_disassemble_instr_compact(str Line 874  int sh_cpu_disassemble_instr_compact(str
874                          debug("div0u\n");                          debug("div0u\n");
875                  else if (lo8 == 0x1a)                  else if (lo8 == 0x1a)
876                          debug("sts\tmacl,r%i\n", r8);                          debug("sts\tmacl,r%i\n", r8);
877                    else if (iword == 0x001b)
878                            debug("sleep\n");
879                    else if (lo8 == 0x22)
880                            debug("stc\tvbr,r%i\n", r8);
881                  else if (lo8 == 0x23)                  else if (lo8 == 0x23)
882                          debug("braf\tr%i\n", r8);                          debug("braf\tr%i\n", r8);
883                  else if (iword == 0x0028)                  else if (iword == 0x0028)
884                          debug("clrmac\n");                          debug("clrmac\n");
885                  else if (lo8 == 0x29)                  else if (lo8 == 0x29)
886                          debug("movt\tr%i\n", r8);                          debug("movt\tr%i\n", r8);
887                    else if (lo8 == 0x2a)
888                            debug("sts\tpr,r%i\n", r8);
889                    else if (iword == 0x002b)
890                            debug("rte\n");
891                    else if (lo8 == 0x32)
892                            debug("stc\tssr,r%i\n", r8);
893                    else if (iword == 0x0038)
894                            debug("ldtlb\n");
895                  else if (iword == 0x003b)                  else if (iword == 0x003b)
896                          debug("brk\n");                          debug("brk\n");
897                    else if (lo8 == 0x42)
898                            debug("stc\tspc,r%i\n", r8);
899                  else if (iword == 0x0048)                  else if (iword == 0x0048)
900                          debug("clrs\n");                          debug("clrs\n");
901                  else if (iword == 0x0058)                  else if (iword == 0x0058)
902                          debug("sets\n");                          debug("sets\n");
903                    else if (lo8 == 0x5a)
904                            debug("sts\tfpul,r%i\n", r8);
905                    else if (lo8 == 0x6a)
906                            debug("sts\tfpscr,r%i\n", r8);
907                    else if ((lo8 & 0x8f) == 0x82)
908                            debug("stc\tr%i_bank,r%i\n", (lo8 >> 4) & 7, r8);
909                  else if (lo8 == 0x83)                  else if (lo8 == 0x83)
910                          debug("pref\t@r%i\n", r8);                          debug("pref\t@r%i\n", r8);
911                    else if (lo8 == 0x93)
912                            debug("ocbi\t@r%i\n", r8);
913                    else if (lo8 == 0xa3)
914                            debug("ocbp\t@r%i\n", r8);
915                    else if (lo8 == 0xb3)
916                            debug("ocbwb\t@r%i\n", r8);
917                    else if (lo8 == 0xc3)
918                            debug("movca.l\tr0,@r%i\n", r8);
919                    else if (lo8 == 0xfa)
920                            debug("stc\tdbr,r%i\n", r8);
921                    else if (iword == SH_INVALID_INSTR)
922                            debug("gxemul_dreamcast_prom_emul\n");
923                  else                  else
924                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
925                  break;                  break;
926          case 0x1:          case 0x1:
927                  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);
928                    if (running) {
929                            uint32_t addr = cpu->cd.sh.r[r8] + lo4 * 4;
930                            debug("\t; r%i+%i = ", r8, lo4 * 4);
931                            symbol = get_symbol_name(&cpu->machine->symbol_context,
932                                addr, &offset);
933                            if (symbol != NULL)
934                                    debug("<%s>", symbol);
935                            else
936                                    debug("0x%08"PRIx32, addr);
937                    }
938                    debug("\n");
939                  break;                  break;
940          case 0x2:          case 0x2:
941                  if (lo4 == 0x0)                  if (lo4 == 0x0)
# Line 365  int sh_cpu_disassemble_instr_compact(str Line 1008  int sh_cpu_disassemble_instr_compact(str
1008                          debug("shll\tr%i\n", r8);                          debug("shll\tr%i\n", r8);
1009                  else if (lo8 == 0x01)                  else if (lo8 == 0x01)
1010                          debug("shlr\tr%i\n", r8);                          debug("shlr\tr%i\n", r8);
1011                    else if (lo8 == 0x02)
1012                            debug("sts.l\tmach,@-r%i\n", r8);
1013                    else if (lo8 == 0x03)
1014                            debug("stc.l\tsr,@-r%i\n", r8);
1015                  else if (lo8 == 0x04)                  else if (lo8 == 0x04)
1016                          debug("rotl\tr%i\n", r8);                          debug("rotl\tr%i\n", r8);
1017                  else if (lo8 == 0x05)                  else if (lo8 == 0x05)
1018                          debug("rotr\tr%i\n", r8);                          debug("rotr\tr%i\n", r8);
1019                  else if (lo8 == 0x06)                  else if (lo8 == 0x06)
1020                          debug("lds.l\t@r%i+,mach\n", r8);                          debug("lds.l\t@r%i+,mach\n", r8);
1021                    else if (lo8 == 0x07)
1022                            debug("ldc.l\t@r%i+,sr\n", r8);
1023                  else if (lo8 == 0x08)                  else if (lo8 == 0x08)
1024                          debug("shll2\tr%i\n", r8);                          debug("shll2\tr%i\n", r8);
1025                  else if (lo8 == 0x09)                  else if (lo8 == 0x09)
# Line 389  int sh_cpu_disassemble_instr_compact(str Line 1038  int sh_cpu_disassemble_instr_compact(str
1038                          debug("dt\tr%i\n", r8);                          debug("dt\tr%i\n", r8);
1039                  else if (lo8 == 0x11)                  else if (lo8 == 0x11)
1040                          debug("cmp/pz\tr%i\n", r8);                          debug("cmp/pz\tr%i\n", r8);
1041                    else if (lo8 == 0x12)
1042                            debug("sts.l\tmacl,@-r%i\n", r8);
1043                    else if (lo8 == 0x13)
1044                            debug("stc.l\tgbr,@-r%i\n", r8);
1045                  else if (lo8 == 0x15)                  else if (lo8 == 0x15)
1046                          debug("cmp/pl\tr%i\n", r8);                          debug("cmp/pl\tr%i\n", r8);
1047                  else if (lo8 == 0x16)                  else if (lo8 == 0x16)
1048                          debug("lds.l\t@r%i+,macl\n", r8);                          debug("lds.l\t@r%i+,macl\n", r8);
1049                    else if (lo8 == 0x17)
1050                            debug("ldc.l\t@r%i+,gbr\n", r8);
1051                  else if (lo8 == 0x18)                  else if (lo8 == 0x18)
1052                          debug("shll8\tr%i\n", r8);                          debug("shll8\tr%i\n", r8);
1053                  else if (lo8 == 0x19)                  else if (lo8 == 0x19)
# Line 409  int sh_cpu_disassemble_instr_compact(str Line 1064  int sh_cpu_disassemble_instr_compact(str
1064                          debug("shar\tr%i\n", r8);                          debug("shar\tr%i\n", r8);
1065                  else if (lo8 == 0x22)                  else if (lo8 == 0x22)
1066                          debug("sts.l\tpr,@-r%i\n", r8);                          debug("sts.l\tpr,@-r%i\n", r8);
1067                    else if (lo8 == 0x23)
1068                            debug("stc.l\tvbr,@-r%i\n", r8);
1069                  else if (lo8 == 0x24)                  else if (lo8 == 0x24)
1070                          debug("rotcl\tr%i\n", r8);                          debug("rotcl\tr%i\n", r8);
1071                  else if (lo8 == 0x25)                  else if (lo8 == 0x25)
1072                          debug("rotcr\tr%i\n", r8);                          debug("rotcr\tr%i\n", r8);
1073                  else if (lo8 == 0x26)                  else if (lo8 == 0x26)
1074                          debug("lds.l\t@r%i+,pr\n", r8);                          debug("lds.l\t@r%i+,pr\n", r8);
1075                    else if (lo8 == 0x27)
1076                            debug("ldc.l\t@r%i+,vbr\n", r8);
1077                  else if (lo8 == 0x28)                  else if (lo8 == 0x28)
1078                          debug("shll16\tr%i\n", r8);                          debug("shll16\tr%i\n", r8);
1079                  else if (lo8 == 0x29)                  else if (lo8 == 0x29)
1080                          debug("shlr16\tr%i\n", r8);                          debug("shlr16\tr%i\n", r8);
1081                  else if (lo8 == 0x2a)                  else if (lo8 == 0x2a)
1082                          debug("lds\tr%i,pr\n", r8);                          debug("lds\tr%i,pr\n", r8);
1083                  else if (lo8 == 0x2b)                  else if (lo8 == 0x2b) {
1084                          debug("jmp\t@r%i\n", r8);                          debug("jmp\t@r%i", r8);
1085                            if (running) {
1086                                    symbol = get_symbol_name(
1087                                        &cpu->machine->symbol_context,
1088                                        cpu->cd.sh.r[r8], &offset);
1089                                    if (symbol != NULL)
1090                                            debug("\t\t; <%s>", symbol);
1091                            }
1092                            debug("\n");
1093                    } else if (lo8 == 0x2e)
1094                            debug("ldc\tr%i,vbr\n", r8);
1095                    else if (lo8 == 0x33)
1096                            debug("stc.l\tssr,@-r%i\n", r8);
1097                    else if (lo8 == 0x37)
1098                            debug("ldc.l\t@r%i+,ssr\n", r8);
1099                    else if (lo8 == 0x3e)
1100                            debug("ldc\tr%i,ssr\n", r8);
1101                    else if (lo8 == 0x43)
1102                            debug("stc.l\tspc,@-r%i\n", r8);
1103                    else if (lo8 == 0x47)
1104                            debug("ldc.l\t@r%i+,spc\n", r8);
1105                    else if (lo8 == 0x4e)
1106                            debug("ldc\tr%i,spc\n", r8);
1107                    else if (lo8 == 0x52)
1108                            debug("sts.l\tfpul,@-r%i\n", r8);
1109                  else if (lo8 == 0x56)                  else if (lo8 == 0x56)
1110                          debug("lds.l\t@r%i+,fpul\n", r8);                          debug("lds.l\t@r%i+,fpul\n", r8);
1111                  else if (lo8 == 0x5a)                  else if (lo8 == 0x5a)
1112                          debug("lds\tr%i,fpul\n", r8);                          debug("lds\tr%i,fpul\n", r8);
1113                    else if (lo8 == 0x62)
1114                            debug("sts.l\tfpscr,@-r%i\n", r8);
1115                    else if (lo8 == 0x66)
1116                            debug("lds.l\t@r%i+,fpscr\n", r8);
1117                  else if (lo8 == 0x6a)                  else if (lo8 == 0x6a)
1118                          debug("lds\tr%i,fpscr\n", r8);                          debug("lds\tr%i,fpscr\n", r8);
1119                    else if ((lo8 & 0x8f) == 0x83)
1120                            debug("stc.l\tr%i_bank,@-r%i\n", (lo8 >> 4) & 7, r8);
1121                    else if ((lo8 & 0x8f) == 0x87)
1122                            debug("ldc.l\t@r%i,r%i_bank\n", r8, (lo8 >> 4) & 7, r8);
1123                    else if ((lo8 & 0x8f) == 0x8e)
1124                            debug("ldc\tr%i,r%i_bank\n", r8, (lo8 >> 4) & 7);
1125                    else if (lo8 == 0xfa)
1126                            debug("ldc\tr%i,dbr\n", r8);
1127                  else                  else
1128                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);                          debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1129                  break;                  break;
1130          case 0x5:          case 0x5:
1131                  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);
1132                    if (running) {
1133                            debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 4,
1134                                cpu->cd.sh.r[r4] + lo4 * 4);
1135                    }
1136                    debug("\n");
1137                  break;                  break;
1138          case 0x6:          case 0x6:
1139                  if (lo4 == 0x0)                  if (lo4 == 0x0)
# Line 446  int sh_cpu_disassemble_instr_compact(str Line 1146  int sh_cpu_disassemble_instr_compact(str
1146                          debug("mov\tr%i,r%i\n", r4, r8);                          debug("mov\tr%i,r%i\n", r4, r8);
1147                  else if (lo4 == 0x4)                  else if (lo4 == 0x4)
1148                          debug("mov.b\t@r%i+,r%i\n", r4, r8);                          debug("mov.b\t@r%i+,r%i\n", r4, r8);
1149                    else if (lo4 == 0x5)
1150                            debug("mov.w\t@r%i+,r%i\n", r4, r8);
1151                  else if (lo4 == 0x6)                  else if (lo4 == 0x6)
1152                          debug("mov.l\t@r%i+,r%i\n", r4, r8);                          debug("mov.l\t@r%i+,r%i\n", r4, r8);
1153                  else if (lo4 == 0x7)                  else if (lo4 == 0x7)
# Line 473  int sh_cpu_disassemble_instr_compact(str Line 1175  int sh_cpu_disassemble_instr_compact(str
1175                  debug("add\t#%i,r%i\n", (int8_t)lo8, r8);                  debug("add\t#%i,r%i\n", (int8_t)lo8, r8);
1176                  break;                  break;
1177          case 0x8:          case 0x8:
1178                  if (r8 == 0x8)                  if (r8 == 0 || r8 == 4) {
1179                            if (r8 == 0x0)
1180                                    debug("mov.b\tr0,@(%i,r%i)", lo4, r4);
1181                            else if (r8 == 0x4)
1182                                    debug("mov.b\t@(%i,r%i),r0", lo4, r4);
1183                            if (running) {
1184                                    debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4,
1185                                        cpu->cd.sh.r[r4] + lo4);
1186                            }
1187                            debug("\n");
1188                    } else if (r8 == 1 || r8 == 5) {
1189                            if (r8 == 0x1)
1190                                    debug("mov.w\tr0,@(%i,r%i)", lo4 * 2, r4);
1191                            else if (r8 == 0x5)
1192                                    debug("mov.w\t@(%i,r%i),r0", lo4 * 2, r4);
1193                            if (running) {
1194                                    debug("\t; r%i+%i = 0x%08"PRIx32, r4, lo4 * 2,
1195                                        cpu->cd.sh.r[r4] + lo4 * 2);
1196                            }
1197                            debug("\n");
1198                    } else if (r8 == 0x8) {
1199                          debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);                          debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1200                  else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {                  } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1201                          addr = (int8_t)lo8;                          addr = (int8_t)lo8;
1202                          addr = dumpaddr + 4 + (addr << 1);                          addr = dumpaddr + 4 + (addr << 1);
1203                          debug("b%s%s\t0x%x\n",                          debug("b%s%s\t0x%x",
1204                              (r8 == 0x9 || r8 == 0xd)? "t" : "f",                              (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1205                              (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);                              (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1206                            symbol = get_symbol_name(&cpu->machine->symbol_context,
1207                                addr, &offset);
1208                            if (symbol != NULL)
1209                                    debug("\t; <%s>", symbol);
1210                            debug("\n");
1211                  } else                  } else
1212                          debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);                          debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1213                  break;                  break;
1214          case 0x9:          case 0x9:
1215          case 0xd:          case 0xd:
1216                  addr = ((int8_t)lo8) * (hi4==9? 2 : 4);                  addr = lo8 * (hi4==9? 2 : 4);
1217                  addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;                  addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1218                  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);
1219                    symbol = get_symbol_name(&cpu->machine->symbol_context,
1220                        addr, &offset);
1221                    if (symbol != NULL)
1222                            debug("\t; <%s>", symbol);
1223                    debug("\n");
1224                  break;                  break;
1225          case 0xa:          case 0xa:
1226          case 0xb:          case 0xb:
1227                  addr = (int32_t)(int16_t)((iword & 0xfff) << 4);                  addr = (int32_t)(int16_t)((iword & 0xfff) << 4);
1228                  addr = ((int32_t)addr >> 3);                  addr = ((int32_t)addr >> 3);
1229                  addr += dumpaddr + 4;                  addr += dumpaddr + 4;
1230                  debug("%s\t0x%x\n", hi4==0xa? "bra":"bsr", (int)addr);                  debug("%s\t0x%x", hi4==0xa? "bra":"bsr", (int)addr);
1231    
1232                    symbol = get_symbol_name(&cpu->machine->symbol_context,
1233                        addr, &offset);
1234                    if (symbol != NULL)
1235                            debug("\t; <%s>", symbol);
1236                    debug("\n");
1237                  break;                  break;
1238          case 0xc:          case 0xc:
1239                  if (r8 == 0x3)                  if (r8 == 0x0)
1240                            debug("mov.b\tr0,@(%i,gbr)\n", lo8);
1241                    else if (r8 == 0x1)
1242                            debug("mov.w\tr0,@(%i,gbr)\n", lo8 * 2);
1243                    else if (r8 == 0x2)
1244                            debug("mov.l\tr0,@(%i,gbr)\n", lo8 * 4);
1245                    else if (r8 == 0x3)
1246                          debug("trapa\t#%i\n", (uint8_t)lo8);                          debug("trapa\t#%i\n", (uint8_t)lo8);
1247                  else if (r8 == 0x8)                  else if (r8 == 0x4)
1248                            debug("mov.b\t(%i,gbr),r0\n", lo8);
1249                    else if (r8 == 0x5)
1250                            debug("mov.w\t(%i,gbr),r0\n", lo8 * 2);
1251                    else if (r8 == 0x6)
1252                            debug("mov.l\t(%i,gbr),r0\n", lo8 * 4);
1253                    else if (r8 == 0x7) {
1254                            addr = lo8 * 4 + (dumpaddr & ~3) + 4;
1255                            debug("mova\t0x%x,r0\n", (int)addr);
1256                    } else if (r8 == 0x8)
1257                          debug("tst\t#%i,r0\n", (uint8_t)lo8);                          debug("tst\t#%i,r0\n", (uint8_t)lo8);
1258                  else if (r8 == 0x9)                  else if (r8 == 0x9)
1259                          debug("and\t#%i,r0\n", (uint8_t)lo8);                          debug("and\t#%i,r0\n", (uint8_t)lo8);
# Line 522  int sh_cpu_disassemble_instr_compact(str Line 1275  int sh_cpu_disassemble_instr_compact(str
1275          case 0xe:          case 0xe:
1276                  debug("mov\t#%i,r%i\n", (int8_t)lo8, r8);                  debug("mov\t#%i,r%i\n", (int8_t)lo8, r8);
1277                  break;                  break;
1278            case 0xf:
1279                    if (lo4 == 0x0)
1280                            debug("fadd\t%sr%i,%sr%i\n",
1281                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1282                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1283                    else if (lo4 == 0x1)
1284                            debug("fsub\t%sr%i,%sr%i\n",
1285                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1286                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1287                    else if (lo4 == 0x2)
1288                            debug("fmul\t%sr%i,%sr%i\n",
1289                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1290                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1291                    else if (lo4 == 0x3)
1292                            debug("fdiv\t%sr%i,%sr%i\n",
1293                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1294                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1295                    else if (lo4 == 0x4)
1296                            debug("fcmp/eq\t%sr%i,%sr%i\n",
1297                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1298                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1299                    else if (lo4 == 0x5)
1300                            debug("fcmp/gt\t%sr%i,%sr%i\n",
1301                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1302                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1303                    else if (lo4 == 0x6) {
1304                            char *n = "fr";
1305                            if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1306                                    n = (r8 & 1)? "xd" : "dr";
1307                                    r8 &= ~1;
1308                            }
1309                            debug("fmov\t@(r0,r%i),%s%i\n", r4, n, r8);
1310                    } else if (lo4 == 0x7) {
1311                            char *n = "fr";
1312                            if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1313                                    n = (r4 & 1)? "xd" : "dr";
1314                                    r4 &= ~1;
1315                            }
1316                            debug("fmov\t%s%i,@(r0,r%i)\n", n, r4, r8);
1317                    } else if (lo4 == 0x8) {
1318                            char *n = "fr";
1319                            if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1320                                    n = (r8 & 1)? "xd" : "dr";
1321                                    r8 &= ~1;
1322                            }
1323                            debug("fmov\t@r%i,%s%i\n", r4, n, r8);
1324                    } else if (lo4 == 0x9) {
1325                            char *n = "fr";
1326                            if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1327                                    n = (r8 & 1)? "xd" : "dr";
1328                                    r8 &= ~1;
1329                            }
1330                            debug("fmov\t@r%i+,%s%i\n", r4, n, r8);
1331                    } else if (lo4 == 0xa) {
1332                            char *n = "fr";
1333                            if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1334                                    n = (r4 & 1)? "xd" : "dr";
1335                                    r4 &= ~1;
1336                            }
1337                            debug("fmov\t%s%i,@r%i\n", n, r4, r8);
1338                    } else if (lo4 == 0xb) {
1339                            char *n = "fr";
1340                            if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1341                                    n = (r4 & 1)? "xd" : "dr";
1342                                    r4 &= ~1;
1343                            }
1344                            debug("fmov\t%s%i,@-r%i\n", n, r4, r8);
1345                    } else if (lo4 == 0xc) {
1346                            char *n1 = "fr", *n2 = "fr";
1347                            if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1348                                    n1 = (r4 & 1)? "xd" : "dr";
1349                                    n2 = (r8 & 1)? "xd" : "dr";
1350                                    r4 &= ~1; r8 &= ~1;
1351                            }
1352                            debug("fmov\t%s%i,%s%i\n", n1, r4, n2, r8);
1353                    } else if (lo8 == 0x0d)
1354                            debug("fsts\tfpul,fr%i\n", r8);
1355                    else if (lo8 == 0x1d)
1356                            debug("flds\tfr%i,fpul\n", r8);
1357                    else if (lo8 == 0x2d)
1358                            debug("float\tfpul,%sr%i\n",
1359                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1360                    else if (lo8 == 0x3d)
1361                            debug("ftrc\t%sr%i,fpul\n",
1362                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1363                    else if (lo8 == 0x4d)
1364                            debug("fneg\t%sr%i\n",
1365                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1366                    else if (lo8 == 0x5d)
1367                            debug("fabs\t%sr%i\n",
1368                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1369                    else if (lo8 == 0x6d)
1370                            debug("fsqrt\t%sr%i\n",
1371                                cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1372                    else if (lo8 == 0x8d)
1373                            debug("fldi0\tfr%i\n", r8);
1374                    else if (lo8 == 0x9d)
1375                            debug("fldi1\tfr%i\n", r8);
1376                    else if (lo8 == 0xad)
1377                            debug("fcnvsd\tfpul,dr%i\n", r8);
1378                    else if (lo8 == 0xbd)
1379                            debug("fcnvds\tdr%i,fpul\n", r8);
1380                    else if ((iword & 0x01ff) == 0x00fd)
1381                            debug("fsca\tfpul,dr%i\n", r8);
1382                    else if (iword == 0xf3fd)
1383                            debug("fschg\n");
1384                    else if (iword == 0xfbfd)
1385                            debug("frchg\n");
1386                    else if ((iword & 0xf3ff) == 0xf1fd)
1387                            debug("ftrv\txmtrx,fv%i\n", r8 & 0xc);
1388                    else if (lo4 == 0xe)
1389                            debug("fmac\tfr0,fr%i,fr%i\n", r4, r8);
1390                    else
1391                            debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, lo8);
1392                    break;
1393          default:debug("UNIMPLEMENTED hi4=0x%x\n", hi4);          default:debug("UNIMPLEMENTED hi4=0x%x\n", hi4);
1394          }          }
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, int bintrans)  
 {  
         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.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, bintrans);  
   
         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.22  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26