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

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

revision 41 by dpavlin, Mon Oct 8 16:22:11 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_m88k.c,v 1.7 2007/04/28 09:19:51 debug Exp $   *  $Id: cpu_m88k.c,v 1.38 2007/06/07 15:36:24 debug Exp $
29   *   *
30   *  M88K CPU emulation.   *  Motorola M881x0 CPU emulation.
31   */   */
32    
33  #include <stdio.h>  #include <stdio.h>
# Line 40  Line 40 
40  #include "machine.h"  #include "machine.h"
41  #include "memory.h"  #include "memory.h"
42  #include "misc.h"  #include "misc.h"
43    #include "mvmeprom.h"
44  #include "settings.h"  #include "settings.h"
45  #include "symbol.h"  #include "symbol.h"
46    #include "timer.h"
47    
48    #include "m8820x_pte.h"
49    #include "m88k_dmt.h"
50    
51  #define DYNTRANS_32  #define DYNTRANS_32
52  #define DYNTRANS_DELAYSLOT  #define DYNTRANS_DELAYSLOT
53  #include "tmp_m88k_head.c"  #include "tmp_m88k_head.c"
54    
55    
56    extern int native_code_translation_enabled;
57    
58    void m88k_pc_to_pointers(struct cpu *);
59    
60  static char *memop[4] = { ".d", "", ".h", ".b" };  static char *memop[4] = { ".d", "", ".h", ".b" };
61    
62  void m88k_irq_interrupt_assert(struct interrupt *interrupt);  void m88k_irq_interrupt_assert(struct interrupt *interrupt);
63  void m88k_irq_interrupt_deassert(struct interrupt *interrupt);  void m88k_irq_interrupt_deassert(struct interrupt *interrupt);
64    
65    
66    static char *m88k_cr_names[] = M88K_CR_NAMES;
67    static char *m88k_cr_197_names[] = M88K_CR_NAMES_197;
68    
69    static char *m88k_cr_name(struct cpu *cpu, int i)
70    {
71            char **cr_names = m88k_cr_names;
72    
73            /*  Hm. Is this really MVME197 specific? TODO  */
74            if (cpu->machine->machine_subtype == MACHINE_MVME88K_197)
75                    cr_names = m88k_cr_197_names;
76    
77            return cr_names[i];
78    }
79    
80    static char *m88k_fcr_name(struct cpu *cpu, int fi)
81    {
82            /*  TODO  */
83            static char fcr_name[10];
84            snprintf(fcr_name, sizeof(fcr_name), "FCR%i", fi);
85            return fcr_name;
86    }
87    
88    
89    
90  /*  /*
91   *  m88k_cpu_new():   *  m88k_cpu_new():
92   *   *
# Line 84  int m88k_cpu_new(struct cpu *cpu, struct Line 117  int m88k_cpu_new(struct cpu *cpu, struct
117          cpu->invalidate_translation_caches =          cpu->invalidate_translation_caches =
118              m88k_invalidate_translation_caches;              m88k_invalidate_translation_caches;
119          cpu->invalidate_code_translation = m88k_invalidate_code_translation;          cpu->invalidate_code_translation = m88k_invalidate_code_translation;
120          /*  cpu->translate_v2p = m88k_translate_v2p;  */          cpu->translate_v2p = m88k_translate_v2p;
121    
122          cpu->cd.m88k.cpu_type = cpu_type_defs[found];          cpu->cd.m88k.cpu_type = cpu_type_defs[found];
123          cpu->name            = cpu->cd.m88k.cpu_type.name;          cpu->name            = cpu->cd.m88k.cpu_type.name;
# Line 98  int m88k_cpu_new(struct cpu *cpu, struct Line 131  int m88k_cpu_new(struct cpu *cpu, struct
131                  debug("%s", cpu->name);                  debug("%s", cpu->name);
132          }          }
133    
134    
135            /*
136             *  Add register names as settings:
137             */
138    
139          CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);          CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
140          for (i=0; i<N_M88K_REGS - 1; i++) {  
141            for (i=0; i<N_M88K_REGS; i++) {
142                  char name[10];                  char name[10];
143                  snprintf(name, sizeof(name), "r%i", i);                  snprintf(name, sizeof(name), "r%i", i);
144                  CPU_SETTINGS_ADD_REGISTER32(name, cpu->cd.m88k.r[i]);                  CPU_SETTINGS_ADD_REGISTER32(name, cpu->cd.m88k.r[i]);
145          }          }
146    
147            for (i=0; i<N_M88K_CONTROL_REGS; i++) {
148                    char name[10];
149                    snprintf(name, sizeof(name), "%s", m88k_cr_name(cpu, i));
150                    CPU_SETTINGS_ADD_REGISTER32(name, cpu->cd.m88k.cr[i]);
151            }
152    
153            for (i=0; i<N_M88K_FPU_CONTROL_REGS; i++) {
154                    char name[10];
155                    snprintf(name, sizeof(name), "%s", m88k_fcr_name(cpu, i));
156                    CPU_SETTINGS_ADD_REGISTER32(name, cpu->cd.m88k.fcr[i]);
157            }
158    
159    
160          /*  Register the CPU interrupt pin:  */          /*  Register the CPU interrupt pin:  */
161          {          {
162                  struct interrupt template;                  struct interrupt template;
163                  char name[50];                  char name[50];
164                  snprintf(name, sizeof(name), "%s.irq", cpu->path);                  snprintf(name, sizeof(name), "%s", cpu->path);
165    
166                    memset(&template, 0, sizeof(template));
167                    template.line = 0;
168                    template.name = name;
169                    template.extra = cpu;
170                    template.interrupt_assert = m88k_irq_interrupt_assert;
171                    template.interrupt_deassert = m88k_irq_interrupt_deassert;
172                    interrupt_handler_register(&template);
173            }
174    
175                  memset(&template, 0, sizeof(template));          /*  Set the Processor ID:  */
176                  template.line = 0;          cpu->cd.m88k.cr[M88K_CR_PID] = cpu->cd.m88k.cpu_type.pid | M88K_PID_MC;
                 template.name = name;  
                 template.extra = cpu;  
                 template.interrupt_assert = m88k_irq_interrupt_assert;  
                 template.interrupt_deassert = m88k_irq_interrupt_deassert;  
                 interrupt_handler_register(&template);  
         }  
177    
178            /*  Start in supervisor mode, with interrupts disabled.  */
179            cpu->cd.m88k.cr[M88K_CR_PSR] = M88K_PSR_MODE | M88K_PSR_IND;
180            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
181                    cpu->cd.m88k.cr[M88K_CR_PSR] |= M88K_PSR_BO;
182    
183            /*  Initial stack pointer:  */
184            cpu->cd.m88k.r[31] = 1048576 * cpu->machine->physical_ram_in_mb - 1024;
185    
186            if (native_code_translation_enabled)
187                    cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ,
188                        m88k_timer_sample_tick, cpu);
189    
190          return 1;          return 1;
191  }  }
# Line 164  void m88k_cpu_list_available_types(void) Line 230  void m88k_cpu_list_available_types(void)
230  /*  /*
231   *  m88k_cpu_instruction_has_delayslot():   *  m88k_cpu_instruction_has_delayslot():
232   *   *
233   *  Return 1 if an opcode is a branch, 0 otherwise.   *  Returns 1 if an opcode has a delay slot after it, 0 otherwise.
234   */   */
235  int m88k_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)  int m88k_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
236  {  {
# Line 180  int m88k_cpu_instruction_has_delayslot(s Line 246  int m88k_cpu_instruction_has_delayslot(s
246          case 0x33:      /*  bsr.n  */          case 0x33:      /*  bsr.n  */
247          case 0x35:      /*  bb0.n  */          case 0x35:      /*  bb0.n  */
248          case 0x37:      /*  bb1.n  */          case 0x37:      /*  bb1.n  */
249            case 0x3b:      /*  bcnd.n  */
250                  return 1;                  return 1;
251            case 0x3d:
252          /*  TODO: jsr.n, jmp.n  */                  switch ((iword >> 8) & 0xff) {
253                    case 0xc4:      /*  jmp.n  */
254                    case 0xcc:      /*  jsr.n  */
255                            return 1;
256                    }
257          }          }
258    
259          return 0;          return 0;
# Line 215  void m88k_cpu_register_dump(struct cpu * Line 286  void m88k_cpu_register_dump(struct cpu *
286                          if (i == 0)                          if (i == 0)
287                                  debug("                  ");                                  debug("                  ");
288                          else                          else
289                                  debug("  r%-2i = 0x%08x", i,                                  debug("  r%-2i = 0x%08"PRIx32,
290                                      (int)cpu->cd.m88k.r[i]);                                      i, cpu->cd.m88k.r[i]);
291                            if ((i % 4) == 3)
292                                    debug("\n");
293                    }
294            }
295    
296            if (coprocs & 1) {
297                    int n_control_regs = 32;
298    
299                    /*  Hm. Is this really MVME197 specific? TODO  */
300                    if (cpu->machine->machine_subtype == MACHINE_MVME88K_197)
301                            n_control_regs = 64;
302    
303                    for (i=0; i<n_control_regs; i++) {
304                            if ((i % 4) == 0)
305                                    debug("cpu%i:", x);
306                            debug("  %4s=0x%08"PRIx32,
307                                m88k_cr_name(cpu, i), cpu->cd.m88k.cr[i]);
308                            if ((i % 4) == 3)
309                                    debug("\n");
310                    }
311            }
312    
313            if (coprocs & 2) {
314                    int n_fpu_control_regs = 64;
315    
316                    for (i=0; i<n_fpu_control_regs; i++) {
317                            if ((i % 4) == 0)
318                                    debug("cpu%i:", x);
319                            debug("  %5s=0x%08"PRIx32,
320                                m88k_fcr_name(cpu, i), cpu->cd.m88k.fcr[i]);
321                          if ((i % 4) == 3)                          if ((i % 4) == 3)
322                                  debug("\n");                                  debug("\n");
323                  }                  }
# Line 235  void m88k_cpu_register_dump(struct cpu * Line 336  void m88k_cpu_register_dump(struct cpu *
336   */   */
337  void m88k_cpu_tlbdump(struct machine *m, int x, int rawflag)  void m88k_cpu_tlbdump(struct machine *m, int x, int rawflag)
338  {  {
339            int cpu_nr, cmmu_nr, i;
340    
341            for (cpu_nr = 0; cpu_nr < m->ncpus; cpu_nr++) {
342                    struct cpu *cpu = m->cpus[cpu_nr];
343    
344                    if (x != -1 && cpu_nr != x)
345                            continue;
346    
347                    for (cmmu_nr = 0; cmmu_nr < MAX_M8820X_CMMUS; cmmu_nr++) {
348                            struct m8820x_cmmu *cmmu = cpu->cd.m88k.cmmu[cmmu_nr];
349                            if (cmmu == NULL)
350                                    continue;
351    
352                            printf("cpu%i: CMMU %i (%s)\n", cpu_nr, cmmu_nr,
353                                cmmu_nr & 1? "data" : "instruction");
354    
355                            /*  BATC:  */
356                            for (i = 0; i < N_M88200_BATC_REGS; i++) {
357                                    uint32_t b = cmmu->batc[i];
358                                    printf("cpu%i: BATC[%2i]: ", cpu_nr, i);
359                                    printf("v=0x%08"PRIx32, b & 0xfff80000);
360                                    printf(", p=0x%08"PRIx32,
361                                        (b << 13) & 0xfff80000);
362                                    printf(", %s %s %s %s %s %s\n",
363                                        b & BATC_SO? "SP " : "!sp",
364                                        b & BATC_WT? "WT " : "!wt",
365                                        b & BATC_GLOBAL? "G  " : "!g ",
366                                        b & BATC_INH? "CI " : "!ci",
367                                        b & BATC_PROT? "WP " : "!wp",
368                                        b & BATC_SO? "V " : "!v");
369                            }
370    
371                            /*  PATC:  */
372                            for (i = 0; i < N_M88200_PATC_ENTRIES; i++) {
373                                    uint32_t v = cmmu->patc_v_and_control[i];
374                                    uint32_t p = cmmu->patc_p_and_supervisorbit[i];
375    
376                                    printf("cpu%i: patc[%2i]: ", cpu_nr, i);
377                                    if (p & M8820X_PATC_SUPERVISOR_BIT)
378                                            printf("superv");
379                                    else
380                                            printf("user  ");
381                                    printf(" v=0x%08"PRIx32, v & 0xfffff000);
382                                    printf(", p=0x%08"PRIx32, p & 0xfffff000);
383    
384                                    printf("  %s %s %s %s %s %s %s",
385                                        v & PG_U1?   "U1 " : "!u1",
386                                        v & PG_U0?   "U0 " : "!u0",
387                                        v & PG_SO?   "SP " : "!sp",
388                                        v & PG_M?    "M "  : "!m",
389                                        v & PG_U?    "U "  : "!u",
390                                        v & PG_PROT? "WP " : "!wp",
391                                        v & PG_V?    "V "  : "!v");
392    
393                                    if (i == cmmu->patc_update_index)
394                                            printf(" <--");
395                                    printf("\n");
396                            }
397                    }
398            }
399  }  }
400    
401    
# Line 255  void m88k_irq_interrupt_deassert(struct Line 416  void m88k_irq_interrupt_deassert(struct
416    
417    
418  /*  /*
419     *  m88k_ldcr():
420     *
421     *  Read from a control register. Store the resulting value in a register
422     *  (pointed to by r32ptr).
423     */
424    void m88k_ldcr(struct cpu *cpu, uint32_t *r32ptr, int cr)
425    {
426            uint32_t retval = cpu->cd.m88k.cr[cr];
427    
428            switch (cr) {
429    
430            case M88K_CR_PID:
431            case M88K_CR_PSR:
432            case M88K_CR_EPSR:
433            case M88K_CR_SSBR:
434            case M88K_CR_SXIP:
435            case M88K_CR_SNIP:
436            case M88K_CR_SFIP:
437            case M88K_CR_VBR:
438            case M88K_CR_DMD0:
439            case M88K_CR_DMD1:
440            case M88K_CR_DMD2:
441            case M88K_CR_SR0:
442            case M88K_CR_SR1:
443            case M88K_CR_SR2:
444            case M88K_CR_SR3:
445                    break;
446    
447            case M88K_CR_DMT0:
448            case M88K_CR_DMT1:
449            case M88K_CR_DMT2:
450                    /*
451                     *  Catch some possible internal errors in the emulator:
452                     *
453                     *  For valid memory Load transactions, the Destination Register
454                     *  should not be zero.
455                     *
456                     *  The Byte Order bit should be the same as the CPU's.
457                     */
458                    if (retval & DMT_VALID && !(retval & DMT_WRITE)) {
459                            if (DMT_DREGBITS(retval) == M88K_ZERO_REG) {
460                                    fatal("DMT DREG = zero? Internal error.\n");
461                                    exit(1);
462                            }
463                    }
464                    if (!!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_BO)
465                        != !!(retval & DMT_BO) && retval & DMT_VALID) {
466                            fatal("DMT byte order not same as CPUs?\n");
467                            exit(1);
468                    }
469    
470                    break;
471    
472            case M88K_CR_DMA0:
473            case M88K_CR_DMA1:
474            case M88K_CR_DMA2:
475                    /*
476                     *  Catch some possible internal errors in the emulator:
477                     *  The lowest 2 bits of the transaction address registers
478                     *  should always be zero.
479                     */
480                    if (retval & 3) {
481                            fatal("DMAx not word-aligned? Internal error.\n");
482                            exit(1);
483                    }
484    
485                    break;
486    
487            default:fatal("m88k_ldcr: UNIMPLEMENTED cr = 0x%02x (%s)\n",
488                        cr, m88k_cr_name(cpu, cr));
489                    exit(1);
490            }
491    
492            *r32ptr = retval;
493    }
494    
495    
496    /*
497     *  m88k_stcr():
498     *
499     *  Write to a control register.
500     *  (Used by both the stcr and rte instructions.)
501     */
502    void m88k_stcr(struct cpu *cpu, uint32_t value, int cr, int rte)
503    {
504            uint32_t old = cpu->cd.m88k.cr[cr];
505    
506            switch (cr) {
507    
508            case M88K_CR_PSR:       /*  Processor Status Regoster  */
509                    if ((cpu->byte_order == EMUL_LITTLE_ENDIAN
510                        && !(value & M88K_PSR_BO)) ||
511                        (cpu->byte_order == EMUL_BIG_ENDIAN
512                        && (value & M88K_PSR_BO))) {
513                            fatal("TODO: attempt to change endianness by flipping"
514                                " the endianness bit in the PSR. How should this"
515                                " be handled? Aborting.\n");
516                            exit(1);
517                    }
518    
519                    if (!rte && old & M88K_PSR_MODE && !(value & M88K_PSR_MODE))
520                            fatal("[ m88k_stcr: WARNING! the PSR_MODE bit is being"
521                                " cleared; this should be done using the RTE "
522                                "instruction only, according to the M88100 "
523                                "manual! Continuing anyway. ]\n");
524    
525                    if (value & M88K_PSR_MXM) {
526                            fatal("m88k_stcr: TODO: MXM support\n");
527                            exit(1);
528                    }
529    
530                    if ((old & M88K_PSR_MODE) != (value & M88K_PSR_MODE))
531                            cpu->invalidate_translation_caches(
532                                cpu, 0, INVALIDATE_ALL);
533    
534                    cpu->cd.m88k.cr[cr] = value;
535                    break;
536    
537            case M88K_CR_EPSR:
538                    cpu->cd.m88k.cr[cr] = value;
539                    break;
540    
541            case M88K_CR_SXIP:
542            case M88K_CR_SNIP:
543            case M88K_CR_SFIP:
544                    cpu->cd.m88k.cr[cr] = value;
545                    break;
546    
547            case M88K_CR_SSBR:      /*  Shadow ScoreBoard Register  */
548                    if (value & 1)
549                            fatal("[ m88k_stcr: WARNING! bit 0 non-zero when"
550                                " writing to SSBR (?) ]\n");
551                    cpu->cd.m88k.cr[cr] = value;
552                    break;
553    
554            case M88K_CR_VBR:
555                    if (value & 0x00000fff)
556                            fatal("[ m88k_stcr: WARNING! bits 0..11 non-zero when"
557                                " writing to VBR (?) ]\n");
558                    cpu->cd.m88k.cr[cr] = value;
559                    break;
560    
561            case M88K_CR_DMT0:
562            case M88K_CR_DMT1:
563            case M88K_CR_DMT2:
564                    cpu->cd.m88k.cr[cr] = value;
565                    break;
566    
567            case M88K_CR_SR0:       /*  Supervisor Storage Registers 0..3  */
568            case M88K_CR_SR1:
569            case M88K_CR_SR2:
570            case M88K_CR_SR3:
571                    cpu->cd.m88k.cr[cr] = value;
572                    break;
573    
574            default:fatal("m88k_stcr: UNIMPLEMENTED cr = 0x%02x (%s)\n",
575                        cr, m88k_cr_name(cpu, cr));
576                    exit(1);
577            }
578    }
579    
580    
581    /*
582     *  m88k_fstcr():
583     *
584     *  Write to a floating-point control register.
585     */
586    void m88k_fstcr(struct cpu *cpu, uint32_t value, int fcr)
587    {
588    #if 0
589            /*  TODO (?)  */
590            uint32_t old = cpu->cd.m88k.cr[fcr];
591    
592            switch (fcr) {
593            default:fatal("m88k_fstcr: UNIMPLEMENTED fcr = 0x%02x (%s)\n",
594                        fcr, m88k_fcr_name(cpu, fcr));
595                    exit(1);
596            }
597    #else
598            cpu->cd.m88k.cr[fcr] = value;
599    #endif
600    }
601    
602    
603    /*
604     *  m88k_memory_transaction_debug_dump():
605     *
606     *  Debug dump of the memory transaction registers of a cpu.
607     */
608    static void m88k_memory_transaction_debug_dump(struct cpu *cpu, int n)
609    {
610            uint32_t dmt = cpu->cd.m88k.dmt[n];
611    
612            debug("[ DMT%i: ", n);
613            if (dmt & DMT_VALID) {
614                    if (dmt & DMT_BO)
615                            debug("Little-Endian, ");
616                    else
617                            debug("Big-Endian, ");
618                    if (dmt & DMT_DAS)
619                            debug("Supervisor, ");
620                    else
621                            debug("User, ");
622                    if (dmt & DMT_DOUB1)
623                            debug("DOUB1, ");
624                    if (dmt & DMT_LOCKBAR)
625                            debug("LOCKBAR, ");
626                    if (dmt & DMT_WRITE)
627                            debug("store, ");
628                    else {
629                            debug("load.%c(r%i), ",
630                                dmt & DMT_SIGNED? 's' : 'u',
631                                DMT_DREGBITS(dmt));
632                    }
633                    debug("bytebits=0x%x ]\n", DMT_ENBITS(dmt));
634    
635                    debug("[ DMD%i: 0x%08"PRIx32"; ", n, cpu->cd.m88k.dmd[n]);
636                    debug("DMA%i: 0x%08"PRIx32" ]\n", n, cpu->cd.m88k.dma[n]);
637            } else
638                    debug("not valid ]\n");
639    }
640    
641    
642    /*
643     *  m88k_exception():
644     *
645     *  Cause an exception.
646     */
647    void m88k_exception(struct cpu *cpu, int vector, int is_trap)
648    {
649            int update_shadow_regs = 1;
650    
651            debug("[ EXCEPTION 0x%03x: ", vector);
652            switch (vector) {
653            case M88K_EXCEPTION_RESET:
654                    debug("RESET"); break;
655            case M88K_EXCEPTION_INTERRUPT:
656                    debug("INTERRUPT"); break;
657            case M88K_EXCEPTION_INSTRUCTION_ACCESS:
658                    debug("INSTRUCTION_ACCESS"); break;
659            case M88K_EXCEPTION_DATA_ACCESS:
660                    debug("DATA_ACCESS"); break;
661            case M88K_EXCEPTION_MISALIGNED_ACCESS:
662                    debug("MISALIGNED_ACCESS"); break;
663            case M88K_EXCEPTION_UNIMPLEMENTED_OPCODE:
664                    debug("UNIMPLEMENTED_OPCODE"); break;
665            case M88K_EXCEPTION_PRIVILEGE_VIOLATION:
666                    debug("PRIVILEGE_VIOLATION"); break;
667            case M88K_EXCEPTION_BOUNDS_CHECK_VIOLATION:
668                    debug("BOUNDS_CHECK_VIOLATION"); break;
669            case M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE:
670                    debug("ILLEGAL_INTEGER_DIVIDE"); break;
671            case M88K_EXCEPTION_INTEGER_OVERFLOW:
672                    debug("INTEGER_OVERFLOW"); break;
673            case M88K_EXCEPTION_ERROR:
674                    debug("ERROR"); break;
675            case M88K_EXCEPTION_SFU1_PRECISE:
676                    debug("SFU1_PRECISE"); break;
677            case M88K_EXCEPTION_SFU1_IMPRECISE:
678                    debug("SFU1_IMPRECISE"); break;
679            case 0x80:
680                    debug("syscall, r13=%i", cpu->cd.m88k.r[13]); break;
681            case MVMEPROM_VECTOR:
682                    debug("MVMEPROM_VECTOR"); break;
683            default:debug("unknown"); break;
684            }
685            debug(" ]\n");
686    
687            /*  Stuff common for all exceptions:  */
688            if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFRZ) {
689                    /*
690                     *  Non-trap exceptions when the shadow freeze bit is already
691                     *  set result in an Error exception:
692                     */
693                    if (!is_trap) {
694                            vector = M88K_EXCEPTION_ERROR;
695                            fatal("[ SFRZ already set in PSR => ERROR ]\n");
696                    }
697    
698                    update_shadow_regs = 0;
699            } else {
700                    /*  Freeze shadow registers, and save the PSR:  */
701    
702                    /*  TODO: Shadow registers!  */
703    
704                    cpu->cd.m88k.cr[M88K_CR_EPSR] = cpu->cd.m88k.cr[M88K_CR_PSR];
705            }
706    
707    
708            m88k_stcr(cpu, cpu->cd.m88k.cr[M88K_CR_PSR]
709                | M88K_PSR_SFRZ     /*  Freeze shadow registers,          */
710                | M88K_PSR_IND      /*  disable interrupts,               */
711                | M88K_PSR_SFD1     /*  disable the floating point unit,  */
712                | M88K_PSR_MODE,    /*  and switch to supervisor mode.    */
713                M88K_CR_PSR, 0);
714    
715            if (update_shadow_regs) {
716                    cpu->cd.m88k.cr[M88K_CR_SSBR] = 0;
717    
718                    /*  SNIP is the address to return to, when executing rte:  */
719                    cpu->cd.m88k.cr[M88K_CR_SXIP] = cpu->pc | M88K_XIP_V;
720    
721                    if (cpu->delay_slot) {
722                            cpu->cd.m88k.cr[M88K_CR_SXIP] += 4;
723                            cpu->cd.m88k.cr[M88K_CR_SNIP] =
724                                cpu->cd.m88k.delay_target | M88K_NIP_V;
725                    } else {
726                            cpu->cd.m88k.cr[M88K_CR_SNIP] =
727                                (cpu->pc + 4) | M88K_NIP_V;
728                    }
729    
730                    cpu->cd.m88k.cr[M88K_CR_SFIP] = cpu->cd.m88k.cr[M88K_CR_SNIP]+4;
731    
732                    if (vector == M88K_EXCEPTION_INSTRUCTION_ACCESS)
733                            cpu->cd.m88k.cr[M88K_CR_SXIP] |= M88K_XIP_E;
734            }
735    
736            cpu->pc = cpu->cd.m88k.cr[M88K_CR_VBR] + 8 * vector;
737    
738            if (cpu->delay_slot)
739                    cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
740            else
741                    cpu->delay_slot = NOT_DELAYED;
742    
743            /*  Vector-specific handling:  */
744            if (vector < M88K_EXCEPTION_USER_TRAPS_START) {
745                    switch (vector) {
746    
747                    case M88K_EXCEPTION_RESET:
748                            fatal("[ m88k_exception: reset ]\n");
749                            exit(1);
750    
751                    case M88K_EXCEPTION_INSTRUCTION_ACCESS:
752                            break;
753    
754                    case M88K_EXCEPTION_DATA_ACCESS:
755                            /*  Update the memory transaction registers:  */
756                            cpu->cd.m88k.cr[M88K_CR_DMT0] = cpu->cd.m88k.dmt[0];
757                            cpu->cd.m88k.cr[M88K_CR_DMD0] = cpu->cd.m88k.dmd[0];
758                            cpu->cd.m88k.cr[M88K_CR_DMA0] = cpu->cd.m88k.dma[0];
759                            cpu->cd.m88k.cr[M88K_CR_DMT1] = cpu->cd.m88k.dmt[1];
760                            cpu->cd.m88k.cr[M88K_CR_DMD1] = cpu->cd.m88k.dmd[1];
761                            cpu->cd.m88k.cr[M88K_CR_DMA1] = cpu->cd.m88k.dma[1];
762                            cpu->cd.m88k.cr[M88K_CR_DMT2] = 0;
763                            cpu->cd.m88k.cr[M88K_CR_DMD2] = 0;
764                            cpu->cd.m88k.cr[M88K_CR_DMA2] = 0;
765                            m88k_memory_transaction_debug_dump(cpu, 0);
766                            m88k_memory_transaction_debug_dump(cpu, 1);
767                            break;
768    
769                    default:fatal("m88k_exception(): 0x%x: TODO\n", vector);
770                            exit(1);
771                    }
772            }
773    
774            m88k_pc_to_pointers(cpu);
775    }
776    
777    
778    /*
779   *  m88k_cpu_disassemble_instr():   *  m88k_cpu_disassemble_instr():
780   *   *
781   *  Convert an instruction word into human readable format, for instruction   *  Convert an instruction word into human readable format, for instruction
# Line 263  void m88k_irq_interrupt_deassert(struct Line 784  void m88k_irq_interrupt_deassert(struct
784   *  If running is 1, cpu->pc should be the address of the instruction.   *  If running is 1, cpu->pc should be the address of the instruction.
785   *   *
786   *  If running is 0, things that depend on the runtime environment (eg.   *  If running is 0, things that depend on the runtime environment (eg.
787   *  register contents) will not be shown, and addr will be used instead of   *  register contents) will not be shown, and dumpaddr will be used instead of
788   *  cpu->pc for relative addresses.   *  cpu->pc for relative addresses.
789   */                       */                    
790  int m88k_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,  int m88k_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
791          int running, uint64_t dumpaddr)          int running, uint64_t dumpaddr)
792  {  {
793            int supervisor = cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE;
794          uint32_t iw;          uint32_t iw;
795          char *symbol, *mnem = NULL;          char *symbol, *mnem = NULL;
796          uint64_t offset;          uint64_t offset;
797          uint32_t op26, op10, op11, d, s1, s2, w5, imm16;          uint32_t op26, op10, op11, d, s1, s2, w5, cr6, imm16;
798          int32_t d16, d26, simm16;          int32_t d16, d26, simm16;
799    
800          if (running)          if (running)
# Line 280  int m88k_cpu_disassemble_instr(struct cp Line 802  int m88k_cpu_disassemble_instr(struct cp
802    
803          symbol = get_symbol_name(&cpu->machine->symbol_context,          symbol = get_symbol_name(&cpu->machine->symbol_context,
804              dumpaddr, &offset);              dumpaddr, &offset);
805          if (symbol != NULL && offset == 0)          if (symbol != NULL && offset == 0 && supervisor)
806                  debug("<%s>\n", symbol);                  debug("<%s>\n", symbol);
807    
808          if (cpu->machine->ncpus > 1 && running)          if (cpu->machine->ncpus > 1 && running)
809                  debug("cpu%i:\t", cpu->cpu_id);                  debug("cpu%i:\t", cpu->cpu_id);
810    
811          debug("%08x:  ", (int)dumpaddr);          debug("%c%08"PRIx32": ",
812                cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE? 's' : 'u',
813                (uint32_t) dumpaddr);
814    
815          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
816                  iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);                  iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
# Line 309  int m88k_cpu_disassemble_instr(struct cp Line 833  int m88k_cpu_disassemble_instr(struct cp
833          imm16  = iw & 0xffff;          imm16  = iw & 0xffff;
834          simm16 = (int16_t) (iw & 0xffff);          simm16 = (int16_t) (iw & 0xffff);
835          w5     = (iw >>  5) & 0x1f;          w5     = (iw >>  5) & 0x1f;
836            cr6    = (iw >>  5) & 0x3f;
837          d16    = ((int16_t) (iw & 0xffff)) * 4;          d16    = ((int16_t) (iw & 0xffff)) * 4;
838          d26    = ((int32_t)((iw & 0x03ffffff) << 6)) >> 4;          d26    = ((int32_t)((iw & 0x03ffffff) << 6)) >> 4;
839    
840          switch (op26) {          switch (op26) {
841    
842          case 0x04:      /*  ld.d  */          case 0x00:      /*  xmem.bu  */
843          case 0x05:      /*  ld    */          case 0x01:      /*  xmem     */
844          case 0x06:      /*  ld.h  */          case 0x02:      /*  ld.hu    */
845          case 0x07:      /*  ld.b  */          case 0x03:      /*  ld.bu    */
846          case 0x08:      /*  st.d  */          case 0x04:      /*  ld.d     */
847          case 0x09:      /*  st    */          case 0x05:      /*  ld       */
848          case 0x0a:      /*  st.h  */          case 0x06:      /*  ld.h     */
849          case 0x0b:      /*  st.b  */          case 0x07:      /*  ld.b     */
850                  debug("%s%s\tr%i,r%i,%i",          case 0x08:      /*  st.d     */
851                      op26 >= 0x08? "st" : "ld",          case 0x09:      /*  st       */
852                      memop[op26 & 3], d, s1, imm16);          case 0x0a:      /*  st.h     */
853            case 0x0b:      /*  st.b     */
854                    if (iw == 0x00000000) {
855                            debug("-\n");
856                            break;
857                    }
858                    switch (op26) {
859                    case 0x00:  debug("xmem.bu"); break;
860                    case 0x01:  debug("xmem"); break;
861                    case 0x02:  debug("ld.hu"); break;
862                    case 0x03:  debug("ld.bu"); break;
863                    default:    debug("%s%s", op26 >= 0x08? "st" : "ld",
864                                    memop[op26 & 3]);
865                    }
866                    debug("\tr%i,r%i,0x%x", d, s1, imm16);
867                  if (running) {                  if (running) {
868                          uint32_t tmpaddr = cpu->cd.m88k.r[s1] + imm16;                          uint32_t tmpaddr = cpu->cd.m88k.r[s1] + imm16;
869                          symbol = get_symbol_name(&cpu->machine->symbol_context,                          symbol = get_symbol_name(&cpu->machine->symbol_context,
870                              tmpaddr, &offset);                              tmpaddr, &offset);
871                          if (symbol != NULL)                          if (symbol != NULL && supervisor)
872                                  debug("\t; [<%s>]", symbol);                                  debug("\t; [<%s>]", symbol);
873                          else                          else
874                                  debug("\t; [0x%08"PRIx32"]", tmpaddr);                                  debug("\t; [0x%08"PRIx32"]", tmpaddr);
# Line 337  int m88k_cpu_disassemble_instr(struct cp Line 876  int m88k_cpu_disassemble_instr(struct cp
876                                  /*  Store:  */                                  /*  Store:  */
877                                  debug(" = ");                                  debug(" = ");
878                                  switch (op26 & 3) {                                  switch (op26 & 3) {
879                                  case 0: /*  TODO: Endianness!!!  */                                  case 0: debug("0x%016"PRIx64, (uint64_t)
                                         debug("0x%016"PRIx64, (uint64_t)  
880                                              ((((uint64_t) cpu->cd.m88k.r[d])                                              ((((uint64_t) cpu->cd.m88k.r[d])
881                                              << 32) + ((uint64_t)                                              << 32) + ((uint64_t)
882                                              cpu->cd.m88k.r[d+1])) );                                              cpu->cd.m88k.r[d+1])) );
# Line 346  int m88k_cpu_disassemble_instr(struct cp Line 884  int m88k_cpu_disassemble_instr(struct cp
884                                  case 1: debug("0x%08"PRIx32,                                  case 1: debug("0x%08"PRIx32,
885                                              (uint32_t) cpu->cd.m88k.r[d]);                                              (uint32_t) cpu->cd.m88k.r[d]);
886                                          break;                                          break;
887                                  case 2: debug("0x%08"PRIx16,                                  case 2: debug("0x%04"PRIx16,
888                                              (uint16_t) cpu->cd.m88k.r[d]);                                              (uint16_t) cpu->cd.m88k.r[d]);
889                                          break;                                          break;
890                                  case 3: debug("0x%08"PRIx8,                                  case 3: debug("0x%02"PRIx8,
891                                              (uint8_t) cpu->cd.m88k.r[d]);                                              (uint8_t) cpu->cd.m88k.r[d]);
892                                          break;                                          break;
893                                  }                                  }
# Line 363  int m88k_cpu_disassemble_instr(struct cp Line 901  int m88k_cpu_disassemble_instr(struct cp
901                           *  sequence is quite common:                           *  sequence is quite common:
902                           *                           *
903                           *  or.u      rX,r0,A                           *  or.u      rX,r0,A
904                           *  st_or_st  rY,rX,B                           *  st_or_ld  rY,rX,B
905                           */                           */
906    
907                          /*  Try loading the instruction before the                          /*  Try loading the instruction before the
# Line 383  int m88k_cpu_disassemble_instr(struct cp Line 921  int m88k_cpu_disassemble_instr(struct cp
921                                  symbol = get_symbol_name(                                  symbol = get_symbol_name(
922                                      &cpu->machine->symbol_context,                                      &cpu->machine->symbol_context,
923                                      tmpaddr, &offset);                                      tmpaddr, &offset);
924                                  if (symbol != NULL)                                  if (symbol != NULL && supervisor)
925                                          debug("\t; [<%s>]", symbol);                                          debug("\t; [<%s>]", symbol);
926                                  else                                  else
927                                          debug("\t; [0x%08"PRIx32"]", tmpaddr);                                          debug("\t; [0x%08"PRIx32"]", tmpaddr);
# Line 411  int m88k_cpu_disassemble_instr(struct cp Line 949  int m88k_cpu_disassemble_instr(struct cp
949                  case 0x17:      mnem = "or"; break;                  case 0x17:      mnem = "or"; break;
950                  }                  }
951                  debug("%s%s\t", mnem, op26 & 1? ".u" : "");                  debug("%s%s\t", mnem, op26 & 1? ".u" : "");
952                  debug("r%i,r%i,0x%x\n", d, s1, imm16);                  debug("r%i,r%i,0x%x", d, s1, imm16);
953    
954                    if (op26 == 0x16 && d != M88K_ZERO_REG) {
955                            /*
956                             *  The following instruction sequence is common:
957                             *
958                             *  or.u   rX,r0,A
959                             *  or     rY,rX,B      ; rY = AAAABBBB
960                             */
961    
962                            /*  Try loading the instruction before the
963                                current one.  */
964                            uint32_t iw2 = 0;
965                            cpu->memory_rw(cpu, cpu->mem,
966                                dumpaddr - sizeof(uint32_t), (unsigned char *)&iw2,
967                                sizeof(iw2), MEM_READ, CACHE_INSTRUCTION
968                                | NO_EXCEPTIONS);
969                            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
970                                     iw2 = LE32_TO_HOST(iw2);
971                            else
972                                     iw2 = BE32_TO_HOST(iw2);
973                            if ((iw2 >> 26) == 0x17 &&      /*  or.u  */
974                                ((iw2 >> 21) & 0x1f) == s1) {
975                                    uint32_t tmpaddr = (iw2 << 16) + imm16;
976                                    symbol = get_symbol_name(
977                                        &cpu->machine->symbol_context,
978                                        tmpaddr, &offset);
979                                    debug("\t; ");
980                                    if (symbol != NULL && supervisor)
981                                            debug("<%s>", symbol);
982                                    else
983                                            debug("0x%08"PRIx32, tmpaddr);
984                            }
985                    }
986    
987                    debug("\n");
988                  break;                  break;
989    
990          case 0x18:      /*  addu    */          case 0x18:      /*  addu    */
991          case 0x19:      /*  subu    */          case 0x19:      /*  subu    */
992          case 0x1a:      /*  divu    */          case 0x1a:      /*  divu    */
993          case 0x1b:      /*  mulu    */          case 0x1b:      /*  mulu    */
                 switch (op26) {  
                 case 0x18:      mnem = "addu"; break;  
                 case 0x19:      mnem = "subu"; break;  
                 case 0x1a:      mnem = "divu"; break;  
                 case 0x1b:      mnem = "mulu"; break;  
                 }  
                 debug("%s\tr%i,r%i,%i\n", mnem, d, s1, imm16);  
                 break;  
   
994          case 0x1c:      /*  add    */          case 0x1c:      /*  add    */
995          case 0x1d:      /*  sub    */          case 0x1d:      /*  sub    */
996          case 0x1e:      /*  div    */          case 0x1e:      /*  div    */
997          case 0x1f:      /*  cmp    */          case 0x1f:      /*  cmp    */
998                  switch (op26) {                  switch (op26) {
999                    case 0x18:      mnem = "addu"; break;
1000                    case 0x19:      mnem = "subu"; break;
1001                    case 0x1a:      mnem = "divu"; break;
1002                    case 0x1b:      mnem = "mulu"; break;
1003                  case 0x1c:      mnem = "add"; break;                  case 0x1c:      mnem = "add"; break;
1004                  case 0x1d:      mnem = "sub"; break;                  case 0x1d:      mnem = "sub"; break;
1005                  case 0x1e:      mnem = "div"; break;                  case 0x1e:      mnem = "div"; break;
1006                  case 0x1f:      mnem = "cmp"; break;                  case 0x1f:      mnem = "cmp"; break;
1007                  }                  }
1008                  debug("%s\tr%i,r%i,%i\n", mnem, d, s1, simm16);                  debug("%s\tr%i,r%i,%i\n", mnem, d, s1, imm16);
1009                    break;
1010    
1011            case 0x20:
1012                    if ((iw & 0x001ff81f) == 0x00004000) {
1013                            debug("ldcr\tr%i,%s\n", d,
1014                                m88k_cr_name(cpu, cr6));
1015                    } else if ((iw & 0x001ff81f) == 0x00004800) {
1016                            debug("fldcr\tr%i,%s\n", d,
1017                                m88k_fcr_name(cpu, cr6));
1018                    } else if ((iw & 0x03e0f800) == 0x00008000) {
1019                            debug("stcr\tr%i,%s", s1,
1020                                m88k_cr_name(cpu, cr6));
1021                            if (s1 != s2)
1022                                    debug("\t\t; NOTE: weird encoding: "
1023                                        "low 5 bits = 0x%02x", s2);
1024                            debug("\n");
1025                    } else if ((iw & 0x03e0f800) == 0x00008800) {
1026                            debug("fstcr\tr%i,%s", s1,
1027                                m88k_fcr_name(cpu, cr6));
1028                            if (s1 != s2)
1029                                    debug("\t\t; NOTE: weird encoding: "
1030                                        "low 5 bits = 0x%02x", s2);
1031                            debug("\n");
1032                    } else if ((iw & 0x0000f800) == 0x0000c000) {
1033                            debug("xcr\tr%i,r%i,%s", d, s1,
1034                                m88k_cr_name(cpu, cr6));
1035                            if (s1 != s2)
1036                                    debug("\t\t; NOTE: weird encoding: "
1037                                        "low 5 bits = 0x%02x", s2);
1038                            debug("\n");
1039                    } else if ((iw & 0x0000f800) == 0x0000c800) {
1040                            debug("fxcr\tr%i,r%i,%s", d, s1,
1041                                m88k_fcr_name(cpu, cr6));
1042                            if (s1 != s2)
1043                                    debug("\t\t; NOTE: weird encoding: "
1044                                        "low 5 bits = 0x%02x", s2);
1045                            debug("\n");
1046                    } else {
1047                            debug("UNIMPLEMENTED 0x20\n");
1048                    }
1049                  break;                  break;
1050    
1051          case 0x30:          case 0x30:
# Line 450  int m88k_cpu_disassemble_instr(struct cp Line 1058  int m88k_cpu_disassemble_instr(struct cp
1058                  debug("0x%08"PRIx32, (uint32_t) (dumpaddr + d26));                  debug("0x%08"PRIx32, (uint32_t) (dumpaddr + d26));
1059                  symbol = get_symbol_name(&cpu->machine->symbol_context,                  symbol = get_symbol_name(&cpu->machine->symbol_context,
1060                      dumpaddr + d26, &offset);                      dumpaddr + d26, &offset);
1061                  if (symbol != NULL)                  if (symbol != NULL && supervisor)
1062                          debug("\t; <%s>", symbol);                          debug("\t; <%s>", symbol);
1063                  debug("\n");                  debug("\n");
1064                  break;                  break;
# Line 459  int m88k_cpu_disassemble_instr(struct cp Line 1067  int m88k_cpu_disassemble_instr(struct cp
1067          case 0x35:      /*  bb0.n  */          case 0x35:      /*  bb0.n  */
1068          case 0x36:      /*  bb1    */          case 0x36:      /*  bb1    */
1069          case 0x37:      /*  bb1.n  */          case 0x37:      /*  bb1.n  */
1070                  debug("bb%s%s\t",          case 0x3a:      /*  bcnd    */
1071                      op26 >= 0x36? "1" : "0",          case 0x3b:      /*  bcnd.n  */
1072                      op26 & 1? ".n" : "");                  switch (op26) {
1073                  debug("%i,r%i,0x%08"PRIx32, d, s1, (uint32_t) (dumpaddr + d16));                  case 0x34:
1074                    case 0x35: mnem = "bb0"; break;
1075                    case 0x36:
1076                    case 0x37: mnem = "bb1"; break;
1077                    case 0x3a:
1078                    case 0x3b: mnem = "bcnd"; break;
1079                    }
1080                    debug("%s%s\t", mnem, op26 & 1? ".n" : "");
1081                    if (op26 == 0x3a || op26 == 0x3b) {
1082                            /*  Attempt to decode bcnd condition:  */
1083                            switch (d) {
1084                            case 0x1: debug("gt0"); break;
1085                            case 0x2: debug("eq0"); break;
1086                            case 0x3: debug("ge0"); break;
1087                            case 0xc: debug("lt0"); break;
1088                            case 0xd: debug("ne0"); break;
1089                            case 0xe: debug("le0"); break;
1090                            default:  debug("%i", d);
1091                            }
1092                    } else {
1093                            debug("%i", d);
1094                    }
1095                    debug(",r%i,0x%08"PRIx32, s1, (uint32_t) (dumpaddr + d16));
1096                  symbol = get_symbol_name(&cpu->machine->symbol_context,                  symbol = get_symbol_name(&cpu->machine->symbol_context,
1097                      dumpaddr + d16, &offset);                      dumpaddr + d16, &offset);
1098                  if (symbol != NULL)                  if (symbol != NULL && supervisor)
1099                          debug("\t; <%s>", symbol);                          debug("\t; <%s>", symbol);
1100                  debug("\n");                  debug("\n");
1101                  break;                  break;
1102    
1103            case 0x3c:
1104                    if ((iw & 0x0000f000)==0x1000 || (iw & 0x0000f000)==0x2000) {
1105                            int scale = 0;
1106    
1107                            /*  Load/store:  */
1108                            debug("%s", (iw & 0x0000f000) == 0x1000? "ld" : "st");
1109                            switch (iw & 0x00000c00) {
1110                            case 0x000: scale = 8; debug(".d"); break;
1111                            case 0x400: scale = 4; break;
1112                            case 0x800: debug(".x"); break;
1113                            default: debug(".UNIMPLEMENTED");
1114                            }
1115                            if (iw & 0x100)
1116                                    debug(".usr");
1117                            if (iw & 0x80)
1118                                    debug(".wt");
1119                            debug("\tr%i,r%i", d, s1);
1120                            if (iw & 0x200)
1121                                    debug("[r%i]", s2);
1122                            else
1123                                    debug(",r%i", s2);
1124    
1125                            if (running && scale >= 1) {
1126                                    uint32_t tmpaddr = cpu->cd.m88k.r[s1];
1127                                    if (iw & 0x200)
1128                                            tmpaddr += scale * cpu->cd.m88k.r[s2];
1129                                    else
1130                                            tmpaddr += cpu->cd.m88k.r[s2];
1131                                    symbol = get_symbol_name(&cpu->machine->
1132                                        symbol_context, tmpaddr, &offset);
1133                                    if (symbol != NULL && supervisor)
1134                                            debug("\t; [<%s>]", symbol);
1135                                    else
1136                                            debug("\t; [0x%08"PRIx32"]", tmpaddr);
1137                            }
1138    
1139                            debug("\n");
1140                    } else switch (op10) {
1141                    case 0x20:      /*  clr  */
1142                    case 0x22:      /*  set  */
1143                    case 0x24:      /*  ext  */
1144                    case 0x26:      /*  extu  */
1145                    case 0x28:      /*  mak  */
1146                    case 0x2a:      /*  rot  */
1147                            switch (op10) {
1148                            case 0x20: mnem = "clr"; break;
1149                            case 0x22: mnem = "set"; break;
1150                            case 0x24: mnem = "ext"; break;
1151                            case 0x26: mnem = "extu"; break;
1152                            case 0x28: mnem = "mak"; break;
1153                            case 0x2a: mnem = "rot"; break;
1154                            }
1155                            debug("%s\tr%i,r%i,", mnem, d, s1);
1156                            /*  Don't include w5 for the rot instruction:  */
1157                            if (op10 != 0x2a)
1158                                    debug("%i", w5);
1159                            /*  Note: o5 = s2:  */
1160                            debug("<%i>\n", s2);
1161                            break;
1162                    case 0x34:      /*  tb0  */
1163                    case 0x36:      /*  tb1  */
1164                            switch (op10) {
1165                            case 0x34: mnem = "tb0"; break;
1166                            case 0x36: mnem = "tb1"; break;
1167                            }
1168                            debug("%s\t%i,r%i,0x%x\n", mnem, d, s1, iw & 0x1ff);
1169                            break;
1170                    default:debug("UNIMPLEMENTED 0x3c, op10=0x%02x\n", op10);
1171                    }
1172                    break;
1173    
1174          case 0x3d:          case 0x3d:
1175                  if ((iw & 0x03fff3e0) == 0x0000c000) {                  if ((iw & 0xf000) <= 0x3fff) {
1176                          debug("%s%s\t(r%i)\n",                          int scale = 0;
1177    
1178                            /*  Load, Store, xmem, and lda:  */
1179                            switch (iw & 0xf000) {
1180                            case 0x2000: debug("st"); break;
1181                            case 0x3000: debug("lda"); break;
1182                            default:     if ((iw & 0xf800) >= 0x0800)
1183                                              debug("ld");
1184                                         else
1185                                              debug("xmem");
1186                            }
1187                            if ((iw & 0xf000) >= 0x1000) {
1188                                    /*  ld, st, lda  */
1189                                    scale = 1 << (3 - ((iw >> 10) & 3));
1190                                    debug("%s", memop[(iw >> 10) & 3]);
1191                            } else if ((iw & 0xf800) == 0x0000) {
1192                                    /*  xmem  */
1193                                    if (iw & 0x400)
1194                                            scale = 4;
1195                                    else
1196                                            debug(".bu"), scale = 1;
1197                            } else {
1198                                    /*  ld  */
1199                                    if ((iw & 0xf00) < 0xc00)
1200                                            debug(".hu"), scale = 2;
1201                                    else
1202                                            debug(".bu"), scale = 1;
1203                            }
1204                            if (iw & 0x100)
1205                                    debug(".usr");
1206                            if (iw & 0x80)
1207                                    debug(".wt");
1208                            debug("\tr%i,r%i", d, s1);
1209                            if (iw & 0x200)
1210                                    debug("[r%i]", s2);
1211                            else
1212                                    debug(",r%i", s2);
1213    
1214                            if (running && scale >= 1) {
1215                                    uint32_t tmpaddr = cpu->cd.m88k.r[s1];
1216                                    if (iw & 0x200)
1217                                            tmpaddr += scale * cpu->cd.m88k.r[s2];
1218                                    else
1219                                            tmpaddr += cpu->cd.m88k.r[s2];
1220                                    symbol = get_symbol_name(&cpu->machine->
1221                                        symbol_context, tmpaddr, &offset);
1222                                    if (symbol != NULL && supervisor)
1223                                            debug("\t; [<%s>]", symbol);
1224                                    else
1225                                            debug("\t; [0x%08"PRIx32"]", tmpaddr);
1226                            }
1227    
1228                            debug("\n");
1229                    } else switch ((iw >> 8) & 0xff) {
1230                    case 0x40:      /*  and  */
1231                    case 0x44:      /*  and.c  */
1232                    case 0x50:      /*  xor  */
1233                    case 0x54:      /*  xor.c  */
1234                    case 0x58:      /*  or  */
1235                    case 0x5c:      /*  or.c  */
1236                    case 0x60:      /*  addu  */
1237                    case 0x61:      /*  addu.co  */
1238                    case 0x62:      /*  addu.ci  */
1239                    case 0x63:      /*  addu.cio  */
1240                    case 0x64:      /*  subu  */
1241                    case 0x65:      /*  subu.co  */
1242                    case 0x66:      /*  subu.ci  */
1243                    case 0x67:      /*  subu.cio  */
1244                    case 0x68:      /*  divu  */
1245                    case 0x69:      /*  divu.d  */
1246                    case 0x6c:      /*  mul  */
1247                    case 0x6d:      /*  mulu.d  */
1248                    case 0x6e:      /*  muls  */
1249                    case 0x70:      /*  add  */
1250                    case 0x71:      /*  add.co  */
1251                    case 0x72:      /*  add.ci  */
1252                    case 0x73:      /*  add.cio  */
1253                    case 0x74:      /*  sub  */
1254                    case 0x75:      /*  sub.co  */
1255                    case 0x76:      /*  sub.ci  */
1256                    case 0x77:      /*  sub.cio  */
1257                    case 0x78:      /*  div  */
1258                    case 0x7c:      /*  cmp  */
1259                    case 0x80:      /*  clr  */
1260                    case 0x88:      /*  set  */
1261                    case 0x90:      /*  ext  */
1262                    case 0x98:      /*  extu  */
1263                    case 0xa0:      /*  mak  */
1264                    case 0xa8:      /*  rot  */
1265                            /*  Three-register opcodes:  */
1266                            switch ((iw >> 8) & 0xff) {
1267                            case 0x40: mnem = "and"; break;
1268                            case 0x44: mnem = "and.c"; break;
1269                            case 0x50: mnem = "xor"; break;
1270                            case 0x54: mnem = "xor.c"; break;
1271                            case 0x58: mnem = "or"; break;
1272                            case 0x5c: mnem = "or.c"; break;
1273                            case 0x60: mnem = "addu"; break;
1274                            case 0x61: mnem = "addu.co"; break;
1275                            case 0x62: mnem = "addu.ci"; break;
1276                            case 0x63: mnem = "addu.cio"; break;
1277                            case 0x64: mnem = "subu"; break;
1278                            case 0x65: mnem = "subu.co"; break;
1279                            case 0x66: mnem = "subu.ci"; break;
1280                            case 0x67: mnem = "subu.cio"; break;
1281                            case 0x68: mnem = "divu"; break;
1282                            case 0x69: mnem = "divu.d"; break;
1283                            case 0x6c: mnem = "mul"; break;
1284                            case 0x6d: mnem = "mulu.d"; break;
1285                            case 0x6e: mnem = "muls"; break;
1286                            case 0x70: mnem = "add"; break;
1287                            case 0x71: mnem = "add.co"; break;
1288                            case 0x72: mnem = "add.ci"; break;
1289                            case 0x73: mnem = "add.cio"; break;
1290                            case 0x74: mnem = "sub"; break;
1291                            case 0x75: mnem = "sub.co"; break;
1292                            case 0x76: mnem = "sub.ci"; break;
1293                            case 0x77: mnem = "sub.cio"; break;
1294                            case 0x78: mnem = "div"; break;
1295                            case 0x7c: mnem = "cmp"; break;
1296                            case 0x80: mnem = "clr"; break;
1297                            case 0x88: mnem = "set"; break;
1298                            case 0x90: mnem = "ext"; break;
1299                            case 0x98: mnem = "extu"; break;
1300                            case 0xa0: mnem = "mak"; break;
1301                            case 0xa8: mnem = "rot"; break;
1302                            }
1303                            debug("%s\tr%i,r%i,r%i\n", mnem, d, s1, s2);
1304                            break;
1305                    case 0xc0:      /*  jmp  */
1306                    case 0xc4:      /*  jmp.n  */
1307                    case 0xc8:      /*  jsr  */
1308                    case 0xcc:      /*  jsr.n  */
1309                            debug("%s%s\t(r%i)",
1310                              op11 & 1? "jsr" : "jmp",                              op11 & 1? "jsr" : "jmp",
1311                              iw & 0x400? ".n" : "",                              iw & 0x400? ".n" : "",
1312                              s2);                              s2);
# Line 480  int m88k_cpu_disassemble_instr(struct cp Line 1314  int m88k_cpu_disassemble_instr(struct cp
1314                                  uint32_t tmpaddr = cpu->cd.m88k.r[s2];                                  uint32_t tmpaddr = cpu->cd.m88k.r[s2];
1315                                  symbol = get_symbol_name(&cpu->machine->                                  symbol = get_symbol_name(&cpu->machine->
1316                                      symbol_context, tmpaddr, &offset);                                      symbol_context, tmpaddr, &offset);
1317                                  debug("\t; ");                                  debug("\t\t; ");
1318                                  if (symbol != NULL)                                  if (symbol != NULL && supervisor)
1319                                          debug("<%s>", symbol);                                          debug("<%s>", symbol);
1320                                  else                                  else
1321                                          debug("0x%08"PRIx32, tmpaddr);                                          debug("0x%08"PRIx32, tmpaddr);
1322                          }                          }
1323                  } else if ((iw & 0x0000ffe0) == 0x00000000) {                          debug("\n");
1324                          debug("xmem\tr%i,r%i,r%i\n", d, s1, s2);                          break;
1325                  } else {                  case 0xe8:      /*  ff1  */
1326                          debug("UNIMPLEMENTED 0x3d\n");                  case 0xec:      /*  ff0  */
1327                            debug("%s\tr%i,r%i\n",
1328                                ((iw >> 8) & 0xff) == 0xe8 ? "ff1" : "ff0", d, s2);
1329                            break;
1330                    case 0xf8:      /*  tbnd  */
1331                            debug("tbnd\tr%i,r%i\n", s1, s2);
1332                            break;
1333                    case 0xfc:
1334                            switch (iw & 0xff) {
1335                            case 0x00:
1336                                    debug("rte\n");
1337                                    break;
1338                            case 0x01:
1339                            case 0x02:
1340                            case 0x03:
1341                                    debug("illop%i\n", iw & 0xff);
1342                                    break;
1343                            case (M88K_PROM_INSTR & 0xff):
1344                                    debug("gxemul_prom_call\n");
1345                                    break;
1346                            default:debug("UNIMPLEMENTED 0x3d,0xfc: 0x%02x\n",
1347                                        iw & 0xff);
1348                            }
1349                            break;
1350                    default:debug("UNIMPLEMENTED 0x3d, opbyte = 0x%02x\n",
1351                                (iw >> 8) & 0xff);
1352                  }                  }
1353                  break;                  break;
1354    
1355          default:debug("UNIMPLEMENTED\n");          case 0x3e:
1356                    debug("tbnd\tr%i,0x%x\n", s1, imm16);
1357                    break;
1358    
1359            default:debug("UNIMPLEMENTED op26=0x%02x\n", op26);
1360          }          }
1361    
1362          return sizeof(uint32_t);          return sizeof(uint32_t);

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

  ViewVC Help
Powered by ViewVC 1.1.26