5 * This work is licensed under the terms of MAME license.
6 * See COPYING file in the top-level directory.
17 int sh2_init(SH2 *sh2, int is_slave, SH2 *other_sh2)
20 unsigned int mult_m68k_to_sh2 = sh2->mult_m68k_to_sh2;
21 unsigned int mult_sh2_to_m68k = sh2->mult_sh2_to_m68k;
23 memset(sh2, 0, sizeof(*sh2));
24 sh2->is_slave = is_slave;
25 sh2->other_sh2 = other_sh2;
26 sh2->mult_m68k_to_sh2 = mult_m68k_to_sh2;
27 sh2->mult_sh2_to_m68k = mult_sh2_to_m68k;
29 pdb_register_cpu(sh2, PDBCT_SH2, is_slave ? "ssh2" : "msh2");
31 ret = sh2_drc_init(sh2);
36 void sh2_finish(SH2 *sh2)
43 void sh2_reset(SH2 *sh2)
45 sh2->pc = p32x_sh2_read32(0, sh2);
46 sh2->r[15] = p32x_sh2_read32(4, sh2);
49 sh2->pending_int_irq = 0;
52 void sh2_do_irq(SH2 *sh2, int level, int vector)
57 p32x_sh2_write32(sh2->r[15], sh2->sr, sh2); /* push SR onto stack */
59 p32x_sh2_write32(sh2->r[15], sh2->pc, sh2); /* push PC onto stack */
61 /* set I flags in SR */
62 sh2->sr = (sh2->sr & ~I) | (level << 4);
65 sh2->pc = p32x_sh2_read32(sh2->vbr + vector * 4, sh2);
67 /* 13 cycles at best */
71 int sh2_irl_irq(SH2 *sh2, int level, int nested_call)
75 sh2->pending_irl = level;
76 if (level < sh2->pending_int_irq)
77 level = sh2->pending_int_irq;
78 sh2->pending_level = level;
80 taken = (level > ((sh2->sr >> 4) & 0x0f));
83 // not in memhandler, so handle this now (recompiler friendly)
84 // do this to avoid missing irqs that other SH2 might clear
85 int vector = sh2->irq_callback(sh2, level);
86 sh2_do_irq(sh2, level, vector);
87 sh2->m68krcycles_done += C_SH2_TO_M68K(sh2, 13);
95 void sh2_internal_irq(SH2 *sh2, int level, int vector)
97 // FIXME: multiple internal irqs not handled..
98 // assuming internal irqs never clear until accepted
99 sh2->pending_int_irq = level;
100 sh2->pending_int_vector = vector;
101 if (level > sh2->pending_level)
102 sh2->pending_level = level;
107 #define SH2_REG_SIZE (offsetof(SH2, macl) + sizeof(sh2->macl))
109 void sh2_pack(const SH2 *sh2, unsigned char *buff)
113 memcpy(buff, sh2, SH2_REG_SIZE);
114 p = (void *)(buff + SH2_REG_SIZE);
116 p[0] = sh2->pending_int_irq;
117 p[1] = sh2->pending_int_vector;
118 p[2] = sh2->m68krcycles_done;
121 void sh2_unpack(SH2 *sh2, const unsigned char *buff)
125 memcpy(sh2, buff, SH2_REG_SIZE);
126 p = (void *)(buff + SH2_REG_SIZE);
128 sh2->pending_int_irq = p[0];
129 sh2->pending_int_vector = p[1];
131 sh2->m68krcycles_done = p[2];
139 #include <pico/memory.h>
140 #undef _USE_CZ80 // HACK
141 #include <pico/pico_int.h>
142 #include <pico/debug.h>
144 static SH2 sh2ref[2];
145 static unsigned int mem_val;
147 static unsigned int local_read32(SH2 *sh2, u32 a)
149 const sh2_memmap *sh2_map = sh2->read16_map;
153 sh2_map += (a >> 25);
155 if (!map_flag_set(p)) {
156 pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
157 return (pd[0] << 16) | pd[1];
160 if ((a & 0xfffff000) == 0xc0000000) {
162 pd = (u16 *)sh2->data_array + (a & 0xfff) / 2;
163 return (pd[0] << 16) | pd[1];
165 if ((a & 0xdfffffc0) == 0x4000) {
166 pd = &Pico32x.regs[(a & 0x3f) / 2];
167 return (pd[0] << 16) | pd[1];
169 if ((a & 0xdffffe00) == 0x4200) {
170 pd = &Pico32xMem->pal[(a & 0x1ff) / 2];
171 return (pd[0] << 16) | pd[1];
177 void do_sh2_trace(SH2 *current, int cycles)
179 static int current_slave = -1;
180 static u32 current_m68k_pc;
181 SH2 *sh2o = &sh2ref[current->is_slave];
182 u32 *regs_a = (void *)current;
183 u32 *regs_o = (void *)sh2o;
188 if (SekPc != current_m68k_pc) {
189 current_m68k_pc = SekPc;
190 tl_write_uint(CTL_M68KPC, current_m68k_pc);
193 if (current->is_slave != current_slave) {
194 current_slave = current->is_slave;
195 v = CTL_MASTERSLAVE | current->is_slave;
196 tl_write(&v, sizeof(v));
199 for (i = 0; i < offsetof(SH2, read8_map) / 4; i++) {
202 if (regs_a[i] != regs_o[i]) {
203 tl_write_uint(CTL_SH2_R + i, regs_a[i]);
204 regs_o[i] = regs_a[i];
208 if (current->ea != sh2o->ea) {
209 tl_write_uint(CTL_EA, current->ea);
210 sh2o->ea = current->ea;
212 val = local_read32(current, current->ea);
213 if (mem_val != val) {
214 tl_write_uint(CTL_EAVAL, val);
217 tl_write_uint(CTL_CYCLES, cycles);
220 static const char *regnames[] = {
221 "r0", "r1", "r2", "r3",
222 "r4", "r5", "r6", "r7",
223 "r8", "r9", "r10", "r11",
224 "r12", "r13", "r14", "r15",
225 "pc", "ppc", "pr", "sr",
226 "gbr", "vbr", "mach","macl",
229 static void dump_regs(SH2 *sh2)
234 csh2 = sh2->is_slave ? 's' : 'm';
235 for (i = 0; i < 16/2; i++)
236 printf("%csh2 r%d: %08x r%02d: %08x\n", csh2,
237 i, sh2->r[i], i+8, sh2->r[i+8]);
238 printf("%csh2 PC: %08x , %08x\n", csh2, sh2->pc, sh2->ppc);
239 printf("%csh2 SR: %03x PR: %08x\n", csh2, sh2->sr, sh2->pr);
242 void REGPARM(1) do_sh2_cmp(SH2 *current)
244 static int current_slave;
245 static u32 current_val;
246 SH2 *sh2o = &sh2ref[current->is_slave];
247 u32 *regs_a = (void *)current;
248 u32 *regs_o = (void *)sh2o;
258 current->sr &= 0x3f3;
259 do_sh2_trace(current, (signed int)sr >> 12);
263 sh2ref[1].is_slave = 1;
266 ret = tl_read(&code, 1);
269 if (code == CTL_CYCLES) {
270 tl_read(&cycles_o, 4);
275 case CTL_MASTERSLAVE:
276 case CTL_MASTERSLAVE + 1:
277 current_slave = code & 1;
280 tl_read_uint(&sh2o->ea);
283 tl_read_uint(¤t_val);
288 printf("m68k: %08x %08x\n", SekPc, val);
293 if (CTL_SH2_R <= code && code < CTL_SH2_R +
294 offsetof(SH2, read8_map) / 4)
296 tl_read_uint(regs_o + code - CTL_SH2_R);
300 printf("wrong code: %02x\n", code);
312 if (current->is_slave != current_slave) {
313 printf("bad slave: %d %d\n", current->is_slave,
318 for (i = 0; i < offsetof(SH2, read8_map) / 4; i++) {
319 if (i == 17 || i == 19) // ppc, sr
321 if (regs_a[i] != regs_o[i]) {
322 printf("bad %4s: %08x %08x\n",
323 regnames[i], regs_a[i], regs_o[i]);
328 sr = current->sr & 0x3f3;
329 cycles = (signed int)current->sr >> 12;
331 if (sr != sh2o->sr) {
332 printf("bad SR: %03x %03x\n", sr, sh2o->sr);
336 if (cycles != cycles_o) {
337 printf("bad cycles: %d %d\n", cycles, cycles_o);
341 val = local_read32(current, sh2o->ea);
342 if (val != current_val) {
343 printf("bad val @%08x: %08x %08x\n", sh2o->ea, val, current_val);
348 sh2o->ppc = current->pc;
355 if (current->is_slave != current_slave)
356 dump_regs(&sh2ref[current->is_slave ^ 1]);