| | 1 | /* |
| | 2 | * PicoDrive |
| | 3 | * (C) notaz, 2007 |
| | 4 | * |
| | 5 | * This work is licensed under the terms of MAME license. |
| | 6 | * See COPYING file in the top-level directory. |
| | 7 | */ |
| | 8 | |
| | 9 | #include "../pico_int.h" |
| | 10 | |
| | 11 | |
| | 12 | unsigned int SekCycleCntS68k; |
| | 13 | unsigned int SekCycleAimS68k; |
| | 14 | |
| | 15 | |
| | 16 | /* context */ |
| | 17 | // Cyclone 68000 |
| | 18 | #ifdef EMU_C68K |
| | 19 | struct Cyclone PicoCpuCS68k; |
| | 20 | #endif |
| | 21 | // MUSASHI 68000 |
| | 22 | #ifdef EMU_M68K |
| | 23 | m68ki_cpu_core PicoCpuMS68k; |
| | 24 | #endif |
| | 25 | // FAME 68000 |
| | 26 | #ifdef EMU_F68K |
| | 27 | M68K_CONTEXT PicoCpuFS68k; |
| | 28 | #endif |
| | 29 | |
| | 30 | |
| | 31 | static int new_irq_level(int level) |
| | 32 | { |
| | 33 | int level_new = 0, irqs; |
| | 34 | Pico_mcd->m.s68k_pend_ints &= ~(1 << level); |
| | 35 | if (level == 2) // clear pending bit |
| | 36 | Pico_mcd->m.state_flags &= ~PCD_ST_S68K_IFL2; |
| | 37 | irqs = Pico_mcd->m.s68k_pend_ints; |
| | 38 | irqs &= Pico_mcd->s68k_regs[0x33]; |
| | 39 | while ((irqs >>= 1)) level_new++; |
| | 40 | |
| | 41 | return level_new; |
| | 42 | } |
| | 43 | |
| | 44 | #ifdef EMU_C68K |
| | 45 | // interrupt acknowledgement |
| | 46 | static int SekIntAckS68k(int level) |
| | 47 | { |
| | 48 | int level_new = new_irq_level(level); |
| | 49 | |
| | 50 | elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new); |
| | 51 | PicoCpuCS68k.irq = level_new; |
| | 52 | return CYCLONE_INT_ACK_AUTOVECTOR; |
| | 53 | } |
| | 54 | |
| | 55 | static void SekResetAckS68k(void) |
| | 56 | { |
| | 57 | elprintf(EL_ANOMALY, "s68k: Reset encountered @ %06x", SekPcS68k); |
| | 58 | } |
| | 59 | |
| | 60 | static int SekUnrecognizedOpcodeS68k(void) |
| | 61 | { |
| | 62 | elprintf(EL_ANOMALY, "Unrecognized Opcode @ %06x", SekPcS68k); |
| | 63 | //exit(1); |
| | 64 | return 0; |
| | 65 | } |
| | 66 | #endif |
| | 67 | |
| | 68 | #ifdef EMU_M68K |
| | 69 | static int SekIntAckMS68k(int level) |
| | 70 | { |
| | 71 | #ifndef EMU_CORE_DEBUG |
| | 72 | int level_new = new_irq_level(level); |
| | 73 | elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new); |
| | 74 | CPU_INT_LEVEL = level_new << 8; |
| | 75 | #else |
| | 76 | CPU_INT_LEVEL = 0; |
| | 77 | #endif |
| | 78 | return M68K_INT_ACK_AUTOVECTOR; |
| | 79 | } |
| | 80 | #endif |
| | 81 | |
| | 82 | #ifdef EMU_F68K |
| | 83 | static void SekIntAckFS68k(unsigned level) |
| | 84 | { |
| | 85 | int level_new = new_irq_level(level); |
| | 86 | elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new); |
| | 87 | #ifndef EMU_CORE_DEBUG |
| | 88 | PicoCpuFS68k.interrupts[0] = level_new; |
| | 89 | #else |
| | 90 | { |
| | 91 | extern int dbg_irq_level_sub; |
| | 92 | dbg_irq_level_sub = level_new; |
| | 93 | PicoCpuFS68k.interrupts[0] = 0; |
| | 94 | } |
| | 95 | #endif |
| | 96 | } |
| | 97 | #endif |
| | 98 | |
| | 99 | |
| | 100 | PICO_INTERNAL void SekInitS68k(void) |
| | 101 | { |
| | 102 | #ifdef EMU_C68K |
| | 103 | // CycloneInit(); |
| | 104 | memset(&PicoCpuCS68k,0,sizeof(PicoCpuCS68k)); |
| | 105 | PicoCpuCS68k.IrqCallback=SekIntAckS68k; |
| | 106 | PicoCpuCS68k.ResetCallback=SekResetAckS68k; |
| | 107 | PicoCpuCS68k.UnrecognizedCallback=SekUnrecognizedOpcodeS68k; |
| | 108 | #endif |
| | 109 | #ifdef EMU_M68K |
| | 110 | { |
| | 111 | // Musashi is not very context friendly.. |
| | 112 | void *oldcontext = m68ki_cpu_p; |
| | 113 | m68k_set_context(&PicoCpuMS68k); |
| | 114 | m68k_set_cpu_type(M68K_CPU_TYPE_68000); |
| | 115 | m68k_init(); |
| | 116 | m68k_set_int_ack_callback(SekIntAckMS68k); |
| | 117 | // m68k_pulse_reset(); // not yet, memmap is not set up |
| | 118 | m68k_set_context(oldcontext); |
| | 119 | } |
| | 120 | #endif |
| | 121 | #ifdef EMU_F68K |
| | 122 | memset(&PicoCpuFS68k, 0, sizeof(PicoCpuFS68k)); |
| | 123 | fm68k_init(); |
| | 124 | PicoCpuFS68k.iack_handler = SekIntAckFS68k; |
| | 125 | PicoCpuFS68k.sr = 0x2704; // Z flag |
| | 126 | #endif |
| | 127 | } |
| | 128 | |
| | 129 | // Reset the 68000: |
| | 130 | PICO_INTERNAL int SekResetS68k(void) |
| | 131 | { |
| | 132 | #ifdef EMU_C68K |
| | 133 | CycloneReset(&PicoCpuCS68k); |
| | 134 | #endif |
| | 135 | #ifdef EMU_M68K |
| | 136 | { |
| | 137 | void *oldcontext = m68ki_cpu_p; |
| | 138 | |
| | 139 | m68k_set_context(&PicoCpuMS68k); |
| | 140 | m68ki_cpu.sp[0]=0; |
| | 141 | m68k_set_irq(0); |
| | 142 | m68k_pulse_reset(); |
| | 143 | m68k_set_context(oldcontext); |
| | 144 | } |
| | 145 | #endif |
| | 146 | #ifdef EMU_F68K |
| | 147 | fm68k_reset(&PicoCpuFS68k); |
| | 148 | #endif |
| | 149 | |
| | 150 | return 0; |
| | 151 | } |
| | 152 | |
| | 153 | PICO_INTERNAL int SekInterruptS68k(int irq) |
| | 154 | { |
| | 155 | int irqs, real_irq = 1; |
| | 156 | Pico_mcd->m.s68k_pend_ints |= 1 << irq; |
| | 157 | irqs = Pico_mcd->m.s68k_pend_ints >> 1; |
| | 158 | while ((irqs >>= 1)) real_irq++; |
| | 159 | |
| | 160 | #ifdef EMU_CORE_DEBUG |
| | 161 | { |
| | 162 | extern int dbg_irq_level_sub; |
| | 163 | dbg_irq_level_sub=real_irq; |
| | 164 | return 0; |
| | 165 | } |
| | 166 | #endif |
| | 167 | #ifdef EMU_C68K |
| | 168 | PicoCpuCS68k.irq=real_irq; |
| | 169 | #endif |
| | 170 | #ifdef EMU_M68K |
| | 171 | // avoid m68k_set_irq() for delaying to work |
| | 172 | PicoCpuMS68k.int_level = real_irq << 8; |
| | 173 | #endif |
| | 174 | #ifdef EMU_F68K |
| | 175 | PicoCpuFS68k.interrupts[0]=real_irq; |
| | 176 | #endif |
| | 177 | return 0; |
| | 178 | } |
| | 179 | |
| | 180 | void SekInterruptClearS68k(int irq) |
| | 181 | { |
| | 182 | int level_new = new_irq_level(irq); |
| | 183 | |
| | 184 | #ifdef EMU_C68K |
| | 185 | PicoCpuCS68k.irq = level_new; |
| | 186 | #endif |
| | 187 | #ifdef EMU_M68K |
| | 188 | CPU_INT_LEVEL = level_new << 8; |
| | 189 | #endif |
| | 190 | #ifdef EMU_F68K |
| | 191 | PicoCpuFS68k.interrupts[0] = level_new; |
| | 192 | #endif |
| | 193 | } |