1 /*****************************************************************************
2 *
3 * sh2.c
4 * Portable Hitachi SH-2 (SH7600 family) emulator
5 *
6 * Copyright (c) 2000 Juergen Buchmueller <pullmoll@t-online.de>,
7 * all rights reserved.
8 *
9 * - This source code is released as freeware for non-commercial purposes.
10 * - You are free to use and redistribute this code in modified or
11 * unmodified form, provided you list me in the credits.
12 * - If you modify this source code, you must add a notice to each modified
13 * source file that it has been changed. If you're a nice person, you
14 * will clearly mark each change too. :)
15 * - If you wish to use this for commercial purposes, please contact me at
16 * pullmoll@t-online.de
17 * - The author of this copywritten work reserves the right to change the
18 * terms of its usage and license at any time, including retroactively
19 * - This entire notice must remain in the source code.
20 *
21 * This work is based on <tiraniddo@hotmail.com> C/C++ implementation of
22 * the SH-2 CPU core and was adapted to the MAME CPU core requirements.
23 * Thanks also go to Chuck Mason <chukjr@sundail.net> and Olivier Galibert
24 * <galibert@pobox.com> for letting me peek into their SEMU code :-)
25 *
26 *****************************************************************************/
27
28 /*****************************************************************************
29 Changes
30 20031015 O. Galibert
31 - dma fixes, thanks to sthief
32
33 20031013 O. Galibert, A. Giles
34 - timer fixes
35 - multi-cpu simplifications
36
37 20030915 O. Galibert
38 - fix DMA1 irq vector
39 - ignore writes to DRCRx
40 - fix cpu number issues
41 - fix slave/master recognition
42 - fix wrong-cpu-in-context problem with the timers
43
44 20021020 O. Galibert
45 - DMA implementation, lightly tested
46 - change_pc() crap fixed
47 - delay slot in debugger fixed
48 - add divide box mirrors
49 - Nicola-ify the indentation
50 - Uncrapify sh2_internal_*
51 - Put back nmi support that had been lost somehow
52
53 20020914 R. Belmont
54 - Initial SH2 internal timers implementation, based on code by O. Galibert.
55 Makes music work in galspanic4/s/s2, panic street, cyvern, other SKNS games.
56 - Fix to external division, thanks to "spice" on the E2J board.
57 Corrects behavior of s1945ii turret boss.
58
59 20020302 Olivier Galibert (galibert@mame.net)
60 - Fixed interrupt in delay slot
61 - Fixed rotcr
62 - Fixed div1
63 - Fixed mulu
64 - Fixed negc
65
66 20020301 R. Belmont
67 - Fixed external division
68
69 20020225 Olivier Galibert (galibert@mame.net)
70 - Fixed interrupt handling
71
72 20010207 Sylvain Glaize (mokona@puupuu.org)
73
74 - Bug fix in INLINE void MOVBM(UINT32 m, UINT32 n) (see comment)
75 - Support of full 32 bit addressing (RB, RW, RL and WB, WW, WL functions)
76 reason : when the two high bits of the address are set, access is
77 done directly in the cache data array. The SUPER KANEKO NOVA SYSTEM
78 sets the stack pointer here, using these addresses as usual RAM access.
79
80 No real cache support has been added.
81 - Read/Write memory format correction (_bew to _bedw) (see also SH2
82 definition in cpuintrf.c and DasmSH2(..) in sh2dasm.c )
83
84 20010623 James Forshaw (TyRaNiD@totalise.net)
85
86 - Modified operation of sh2_exception. Done cause mame irq system is stupid, and
87 doesnt really seem designed for any more than 8 interrupt lines.
88
89 20010701 James Forshaw (TyRaNiD@totalise.net)
90
91 - Fixed DIV1 operation. Q bit now correctly generated
92
93 20020218 Added save states (mokona@puupuu.org)
94
95 *****************************************************************************/
96
97 #include <stdio.h>
98 #include "driver.h"
99 #include "state.h"
100 #include "mamedbg.h"
101 #include "sh2.h"
102 #include "memory.h"
103
104 /* speed up delay loops, bail out of tight loops */
105 #define BUSY_LOOP_HACKS 1
106
107 typedef struct
108 {
109 int irq_vector;
110 int irq_priority;
111 } irq_entry;
112
113 typedef struct
114 {
115 UINT32 ppc;
116 UINT32 pc;
117 UINT32 pr;
118 UINT32 sr;
119 UINT32 gbr, vbr;
120 UINT32 mach, macl;
121 UINT32 r[16];
122 UINT32 ea;
123 UINT32 delay;
124 UINT32 cpu_off;
125 UINT32 dvsr, dvdnth, dvdntl, dvcr;
126 UINT32 pending_irq;
127 UINT32 test_irq;
128 irq_entry irq_queue[16];
129
130 INT8 irq_line_state[16];
131 int (*irq_callback)(int irqline);
132 UINT32 *m;
133 INT8 nmi_line_state;
134
135 UINT16 frc;
136 UINT16 ocra, ocrb, icr;
137 UINT32 frc_base;
138
139 int frt_input;
140 int internal_irq_level;
141 int internal_irq_vector;
142
143 void *timer;
144 void *dma_timer[2];
145 int dma_timer_active[2];
146
147 int is_slave, cpu_number;
148 } SH2;
149
150 int sh2_icount;
151 static SH2 sh2;
152
153 /* Atrocious hack that makes the soldivid music correct*/
154
155 /*static const int div_tab[4] = { 3, 5, 7, 0 };*/
156 static const int div_tab[4] = { 3, 5, 3, 0 };
157
158 enum {
159 ICF = 0x00800000,
160 OCFA = 0x00080000,
161 OCFB = 0x00040000,
162 OVF = 0x00020000
163 };
164
165 static void sh2_timer_callback(int data);
166
167 #define T 0x00000001
168 #define S 0x00000002
169 #define I 0x000000f0
170 #define Q 0x00000100
171 #define M 0x00000200
172
173 #define AM 0x07ffffff
174
175 #define FLAGS (M|Q|I|S|T)
176
177 #define Rn ((opcode>>8)&15)
178 #define Rm ((opcode>>4)&15)
179
RB(offs_t A)180 static INLINE data8_t RB(offs_t A)
181 {
182 if (A >= 0xe0000000)
183 return sh2_internal_r((A & 0x1fc)>>2, ~(0xff << (((~A) & 3)*8))) >> (((~A) & 3)*8);
184
185 if (A >= 0xc0000000)
186 return cpu_readmem32bedw(A);
187
188 if (A >= 0x40000000)
189 return 0xa5;
190
191 return cpu_readmem32bedw(A & AM);
192 }
193
RW(offs_t A)194 static INLINE data16_t RW(offs_t A)
195 {
196 if (A >= 0xe0000000)
197 return sh2_internal_r((A & 0x1fc)>>2, ~(0xffff << (((~A) & 2)*8))) >> (((~A) & 2)*8);
198
199 if (A >= 0xc0000000)
200 return cpu_readmem32bedw_word(A);
201
202 if (A >= 0x40000000)
203 return 0xa5a5;
204
205 return cpu_readmem32bedw_word(A & AM);
206 }
207
RL(offs_t A)208 static INLINE data32_t RL(offs_t A)
209 {
210 if (A >= 0xe0000000)
211 return sh2_internal_r((A & 0x1fc)>>2, 0);
212
213 if (A >= 0xc0000000)
214 return cpu_readmem32bedw_dword(A);
215
216 if (A >= 0x40000000)
217 return 0xa5a5a5a5;
218
219 return cpu_readmem32bedw_dword(A & AM);
220 }
221
WB(offs_t A,data8_t V)222 static INLINE void WB(offs_t A, data8_t V)
223 {
224
225 if (A >= 0xe0000000)
226 {
227 sh2_internal_w((A & 0x1fc)>>2, V << (((~A) & 3)*8), ~(0xff << (((~A) & 3)*8)));
228 return;
229 }
230
231 if (A >= 0xc0000000)
232 {
233 cpu_writemem32bedw(A,V);
234 return;
235 }
236
237 if (A >= 0x40000000)
238 return;
239
240 cpu_writemem32bedw(A & AM,V);
241 }
242
WW(offs_t A,data16_t V)243 static INLINE void WW(offs_t A, data16_t V)
244 {
245 if (A >= 0xe0000000)
246 {
247 sh2_internal_w((A & 0x1fc)>>2, V << (((~A) & 2)*8), ~(0xffff << (((~A) & 2)*8)));
248 return;
249 }
250
251 if (A >= 0xc0000000)
252 {
253 cpu_writemem32bedw_word(A,V);
254 return;
255 }
256
257 if (A >= 0x40000000)
258 return;
259
260 cpu_writemem32bedw_word(A & AM,V);
261 }
262
WL(offs_t A,data32_t V)263 static INLINE void WL(offs_t A, data32_t V)
264 {
265 if (A >= 0xe0000000)
266 {
267 sh2_internal_w((A & 0x1fc)>>2, V, 0);
268 return;
269 }
270
271 if (A >= 0xc0000000)
272 {
273 cpu_writemem32bedw_dword(A,V);
274 return;
275 }
276
277 if (A >= 0x40000000)
278 return;
279
280 cpu_writemem32bedw_dword(A & AM,V);
281 }
282
sh2_exception(const char * message,int irqline)283 static INLINE void sh2_exception(const char *message, int irqline)
284 {
285 int vector;
286
287 if (irqline != 16)
288 {
289 if (irqline <= ((sh2.sr >> 4) & 15)) /* If the cpu forbids this interrupt */
290 return;
291
292 /* if this is an sh2 internal irq, use its vector*/
293 if (sh2.internal_irq_level == irqline)
294 {
295 vector = sh2.internal_irq_vector;
296 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d exception #%d (internal vector: $%x) after [%s]\n", cpu_getactivecpu(), irqline, vector, message);
297 }
298 else
299 {
300 if(sh2.m[0x38] & 0x00010000)
301 {
302 vector = sh2.irq_callback(irqline);
303 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d exception #%d (external vector: $%x) after [%s]\n", cpu_getactivecpu(), irqline, vector, message);
304 }
305 else
306 {
307 sh2.irq_callback(irqline);
308 vector = 64 + irqline/2;
309 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d exception #%d (autovector: $%x) after [%s]\n", cpu_getactivecpu(), irqline, vector, message);
310 }
311 }
312 }
313 else
314 {
315 vector = 11;
316 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d nmi exception (autovector: $%x) after [%s]\n", cpu_getactivecpu(), vector, message);
317 }
318
319 sh2.r[15] -= 4;
320 WL( sh2.r[15], sh2.sr ); /* push SR onto stack */
321 sh2.r[15] -= 4;
322 WL( sh2.r[15], sh2.pc ); /* push PC onto stack */
323
324 /* set I flags in SR */
325 if (irqline > SH2_INT_15)
326 sh2.sr = sh2.sr | I;
327 else
328 sh2.sr = (sh2.sr & ~I) | (irqline << 4);
329
330 /* fetch PC */
331 sh2.pc = RL( sh2.vbr + vector * 4 );
332 change_pc32bedw(sh2.pc & AM);
333 }
334
335 #define CHECK_PENDING_IRQ(message) \
336 do { \
337 int irq = -1; \
338 if (sh2.pending_irq & (1 << 0)) irq = 0; \
339 if (sh2.pending_irq & (1 << 1)) irq = 1; \
340 if (sh2.pending_irq & (1 << 2)) irq = 2; \
341 if (sh2.pending_irq & (1 << 3)) irq = 3; \
342 if (sh2.pending_irq & (1 << 4)) irq = 4; \
343 if (sh2.pending_irq & (1 << 5)) irq = 5; \
344 if (sh2.pending_irq & (1 << 6)) irq = 6; \
345 if (sh2.pending_irq & (1 << 7)) irq = 7; \
346 if (sh2.pending_irq & (1 << 8)) irq = 8; \
347 if (sh2.pending_irq & (1 << 9)) irq = 9; \
348 if (sh2.pending_irq & (1 << 10)) irq = 10; \
349 if (sh2.pending_irq & (1 << 11)) irq = 11; \
350 if (sh2.pending_irq & (1 << 12)) irq = 12; \
351 if (sh2.pending_irq & (1 << 13)) irq = 13; \
352 if (sh2.pending_irq & (1 << 14)) irq = 14; \
353 if (sh2.pending_irq & (1 << 15)) irq = 15; \
354 if ((sh2.internal_irq_level != -1) && (sh2.internal_irq_level > irq)) irq = sh2.internal_irq_level; \
355 if (irq >= 0) \
356 sh2_exception(message,irq); \
357 } while(0)
358
359 /* Layout of the registers in the debugger */
360 static UINT8 sh2_reg_layout[] = {
361 SH2_PC, SH2_R15, SH2_SR, SH2_PR, -1,
362 SH2_GBR, SH2_VBR, SH2_MACH, SH2_MACL,-1,
363 SH2_R0, SH2_R1, SH2_R2, SH2_R3, -1,
364 SH2_R4, SH2_R5, SH2_R6, SH2_R7, -1,
365 SH2_R8, SH2_R9, SH2_R10, SH2_R11, -1,
366 SH2_R12, SH2_R13, SH2_R14, SH2_EA, 0
367 };
368
369 /* Layout of the debugger windows x,y,w,h */
370 static UINT8 sh2_win_layout[] = {
371 0, 0,80, 6, /* register window (top rows) */
372 0, 7,39,15, /* disassembler window */
373 40, 7,39, 7, /* memory #1 window (left) */
374 40,15,39, 7, /* memory #2 window (right) */
375 0,23,80, 1, /* command line window (bottom rows) */
376 };
377
378 /* code cycles t-bit
379 * 0011 nnnn mmmm 1100 1 -
380 * ADD Rm,Rn
381 */
ADD(UINT32 m,UINT32 n)382 static INLINE void ADD(UINT32 m, UINT32 n)
383 {
384 sh2.r[n] += sh2.r[m];
385 }
386
387 /* code cycles t-bit
388 * 0111 nnnn iiii iiii 1 -
389 * ADD #imm,Rn
390 */
ADDI(UINT32 i,UINT32 n)391 static INLINE void ADDI(UINT32 i, UINT32 n)
392 {
393 sh2.r[n] += (INT32)(INT16)(INT8)i;
394 }
395
396 /* code cycles t-bit
397 * 0011 nnnn mmmm 1110 1 carry
398 * ADDC Rm,Rn
399 */
ADDC(UINT32 m,UINT32 n)400 static INLINE void ADDC(UINT32 m, UINT32 n)
401 {
402 UINT32 tmp0, tmp1;
403
404 tmp1 = sh2.r[n] + sh2.r[m];
405 tmp0 = sh2.r[n];
406 sh2.r[n] = tmp1 + (sh2.sr & T);
407 if (tmp0 > tmp1)
408 sh2.sr |= T;
409 else
410 sh2.sr &= ~T;
411 if (tmp1 > sh2.r[n])
412 sh2.sr |= T;
413 }
414
415 /* code cycles t-bit
416 * 0011 nnnn mmmm 1111 1 overflow
417 * ADDV Rm,Rn
418 */
ADDV(UINT32 m,UINT32 n)419 static INLINE void ADDV(UINT32 m, UINT32 n)
420 {
421 INT32 dest, src, ans;
422
423 if ((INT32) sh2.r[n] >= 0)
424 dest = 0;
425 else
426 dest = 1;
427 if ((INT32) sh2.r[m] >= 0)
428 src = 0;
429 else
430 src = 1;
431 src += dest;
432 sh2.r[n] += sh2.r[m];
433 if ((INT32) sh2.r[n] >= 0)
434 ans = 0;
435 else
436 ans = 1;
437 ans += dest;
438 if (src == 0 || src == 2)
439 {
440 if (ans == 1)
441 sh2.sr |= T;
442 else
443 sh2.sr &= ~T;
444 }
445 else
446 sh2.sr &= ~T;
447 }
448
449 /* code cycles t-bit
450 * 0010 nnnn mmmm 1001 1 -
451 * AND Rm,Rn
452 */
AND(UINT32 m,UINT32 n)453 static INLINE void AND(UINT32 m, UINT32 n)
454 {
455 sh2.r[n] &= sh2.r[m];
456 }
457
458
459 /* code cycles t-bit
460 * 1100 1001 iiii iiii 1 -
461 * AND #imm,R0
462 */
ANDI(UINT32 i)463 static INLINE void ANDI(UINT32 i)
464 {
465 sh2.r[0] &= i;
466 }
467
468 /* code cycles t-bit
469 * 1100 1101 iiii iiii 1 -
470 * AND.B #imm,@(R0,GBR)
471 */
ANDM(UINT32 i)472 static INLINE void ANDM(UINT32 i)
473 {
474 UINT32 temp;
475
476 sh2.ea = sh2.gbr + sh2.r[0];
477 temp = i & RB( sh2.ea );
478 WB( sh2.ea, temp );
479 sh2_icount -= 2;
480 }
481
482 /* code cycles t-bit
483 * 1000 1011 dddd dddd 3/1 -
484 * BF disp8
485 */
BF(UINT32 d)486 static INLINE void BF(UINT32 d)
487 {
488 if ((sh2.sr & T) == 0)
489 {
490 INT32 disp = ((INT32)d << 24) >> 24;
491 sh2.pc = sh2.ea = sh2.pc + disp * 2 + 2;
492 change_pc32bedw(sh2.pc & AM);
493 sh2_icount -= 2;
494 }
495 }
496
497 /* code cycles t-bit
498 * 1000 1111 dddd dddd 3/1 -
499 * BFS disp8
500 */
BFS(UINT32 d)501 static INLINE void BFS(UINT32 d)
502 {
503 if ((sh2.sr & T) == 0)
504 {
505 INT32 disp = ((INT32)d << 24) >> 24;
506 sh2.delay = sh2.pc;
507 sh2.pc = sh2.ea = sh2.pc + disp * 2 + 2;
508 sh2_icount--;
509 }
510 }
511
512 /* code cycles t-bit
513 * 1010 dddd dddd dddd 2 -
514 * BRA disp12
515 */
BRA(UINT32 d)516 static INLINE void BRA(UINT32 d)
517 {
518 INT32 disp = ((INT32)d << 20) >> 20;
519
520 #if BUSY_LOOP_HACKS
521 if (disp == -2)
522 {
523 UINT32 next_opcode = RW(sh2.ppc & AM);
524 /* BRA $
525 * NOP
526 */
527 if (next_opcode == 0x0009)
528 sh2_icount %= 3; /* cycles for BRA $ and NOP taken (3) */
529 }
530 #endif
531 sh2.delay = sh2.pc;
532 sh2.pc = sh2.ea = sh2.pc + disp * 2 + 2;
533 sh2_icount--;
534 }
535
536 /* code cycles t-bit
537 * 0000 mmmm 0010 0011 2 -
538 * BRAF Rm
539 */
BRAF(UINT32 m)540 static INLINE void BRAF(UINT32 m)
541 {
542 sh2.delay = sh2.pc;
543 sh2.pc += sh2.r[m] + 2;
544 sh2_icount--;
545 }
546
547 /* code cycles t-bit
548 * 1011 dddd dddd dddd 2 -
549 * BSR disp12
550 */
BSR(UINT32 d)551 static INLINE void BSR(UINT32 d)
552 {
553 INT32 disp = ((INT32)d << 20) >> 20;
554
555 sh2.pr = sh2.pc + 2;
556 sh2.delay = sh2.pc;
557 sh2.pc = sh2.ea = sh2.pc + disp * 2 + 2;
558 sh2_icount--;
559 }
560
561 /* code cycles t-bit
562 * 0000 mmmm 0000 0011 2 -
563 * BSRF Rm
564 */
BSRF(UINT32 m)565 static INLINE void BSRF(UINT32 m)
566 {
567 sh2.pr = sh2.pc + 2;
568 sh2.delay = sh2.pc;
569 sh2.pc += sh2.r[m] + 2;
570 sh2_icount--;
571 }
572
573 /* code cycles t-bit
574 * 1000 1001 dddd dddd 3/1 -
575 * BT disp8
576 */
BT(UINT32 d)577 static INLINE void BT(UINT32 d)
578 {
579 if ((sh2.sr & T) != 0)
580 {
581 INT32 disp = ((INT32)d << 24) >> 24;
582 sh2.pc = sh2.ea = sh2.pc + disp * 2 + 2;
583 change_pc32bedw(sh2.pc & AM);
584 sh2_icount -= 2;
585 }
586 }
587
588 /* code cycles t-bit
589 * 1000 1101 dddd dddd 2/1 -
590 * BTS disp8
591 */
BTS(UINT32 d)592 static INLINE void BTS(UINT32 d)
593 {
594 if ((sh2.sr & T) != 0)
595 {
596 INT32 disp = ((INT32)d << 24) >> 24;
597 sh2.delay = sh2.pc;
598 sh2.pc = sh2.ea = sh2.pc + disp * 2 + 2;
599 sh2_icount--;
600 }
601 }
602
603 /* code cycles t-bit
604 * 0000 0000 0010 1000 1 -
605 * CLRMAC
606 */
CLRMAC(void)607 static INLINE void CLRMAC(void)
608 {
609 sh2.mach = 0;
610 sh2.macl = 0;
611 }
612
613 /* code cycles t-bit
614 * 0000 0000 0000 1000 1 -
615 * CLRT
616 */
CLRT(void)617 static INLINE void CLRT(void)
618 {
619 sh2.sr &= ~T;
620 }
621
622 /* code cycles t-bit
623 * 0011 nnnn mmmm 0000 1 comparison result
624 * CMP_EQ Rm,Rn
625 */
CMPEQ(UINT32 m,UINT32 n)626 static INLINE void CMPEQ(UINT32 m, UINT32 n)
627 {
628 if (sh2.r[n] == sh2.r[m])
629 sh2.sr |= T;
630 else
631 sh2.sr &= ~T;
632 }
633
634 /* code cycles t-bit
635 * 0011 nnnn mmmm 0011 1 comparison result
636 * CMP_GE Rm,Rn
637 */
CMPGE(UINT32 m,UINT32 n)638 static INLINE void CMPGE(UINT32 m, UINT32 n)
639 {
640 if ((INT32) sh2.r[n] >= (INT32) sh2.r[m])
641 sh2.sr |= T;
642 else
643 sh2.sr &= ~T;
644 }
645
646 /* code cycles t-bit
647 * 0011 nnnn mmmm 0111 1 comparison result
648 * CMP_GT Rm,Rn
649 */
CMPGT(UINT32 m,UINT32 n)650 static INLINE void CMPGT(UINT32 m, UINT32 n)
651 {
652 if ((INT32) sh2.r[n] > (INT32) sh2.r[m])
653 sh2.sr |= T;
654 else
655 sh2.sr &= ~T;
656 }
657
658 /* code cycles t-bit
659 * 0011 nnnn mmmm 0110 1 comparison result
660 * CMP_HI Rm,Rn
661 */
CMPHI(UINT32 m,UINT32 n)662 static INLINE void CMPHI(UINT32 m, UINT32 n)
663 {
664 if ((UINT32) sh2.r[n] > (UINT32) sh2.r[m])
665 sh2.sr |= T;
666 else
667 sh2.sr &= ~T;
668 }
669
670 /* code cycles t-bit
671 * 0011 nnnn mmmm 0010 1 comparison result
672 * CMP_HS Rm,Rn
673 */
CMPHS(UINT32 m,UINT32 n)674 static INLINE void CMPHS(UINT32 m, UINT32 n)
675 {
676 if ((UINT32) sh2.r[n] >= (UINT32) sh2.r[m])
677 sh2.sr |= T;
678 else
679 sh2.sr &= ~T;
680 }
681
682
683 /* code cycles t-bit
684 * 0100 nnnn 0001 0101 1 comparison result
685 * CMP_PL Rn
686 */
CMPPL(UINT32 n)687 static INLINE void CMPPL(UINT32 n)
688 {
689 if ((INT32) sh2.r[n] > 0)
690 sh2.sr |= T;
691 else
692 sh2.sr &= ~T;
693 }
694
695 /* code cycles t-bit
696 * 0100 nnnn 0001 0001 1 comparison result
697 * CMP_PZ Rn
698 */
CMPPZ(UINT32 n)699 static INLINE void CMPPZ(UINT32 n)
700 {
701 if ((INT32) sh2.r[n] >= 0)
702 sh2.sr |= T;
703 else
704 sh2.sr &= ~T;
705 }
706
707 /* code cycles t-bit
708 * 0010 nnnn mmmm 1100 1 comparison result
709 * CMP_STR Rm,Rn
710 */
CMPSTR(UINT32 m,UINT32 n)711 static INLINE void CMPSTR(UINT32 m, UINT32 n)
712 {
713 UINT32 temp;
714 INT32 HH, HL, LH, LL;
715 temp = sh2.r[n] ^ sh2.r[m];
716 HH = (temp >> 24) & 0xff;
717 HL = (temp >> 16) & 0xff;
718 LH = (temp >> 8) & 0xff;
719 LL = temp & 0xff;
720 if (HH && HL && LH && LL)
721 sh2.sr &= ~T;
722 else
723 sh2.sr |= T;
724 }
725
726
727 /* code cycles t-bit
728 * 1000 1000 iiii iiii 1 comparison result
729 * CMP/EQ #imm,R0
730 */
CMPIM(UINT32 i)731 static INLINE void CMPIM(UINT32 i)
732 {
733 UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i;
734
735 if (sh2.r[0] == imm)
736 sh2.sr |= T;
737 else
738 sh2.sr &= ~T;
739 }
740
741 /* code cycles t-bit
742 * 0010 nnnn mmmm 0111 1 calculation result
743 * DIV0S Rm,Rn
744 */
DIV0S(UINT32 m,UINT32 n)745 static INLINE void DIV0S(UINT32 m, UINT32 n)
746 {
747 if ((sh2.r[n] & 0x80000000) == 0)
748 sh2.sr &= ~Q;
749 else
750 sh2.sr |= Q;
751 if ((sh2.r[m] & 0x80000000) == 0)
752 sh2.sr &= ~M;
753 else
754 sh2.sr |= M;
755 if ((sh2.r[m] ^ sh2.r[n]) & 0x80000000)
756 sh2.sr |= T;
757 else
758 sh2.sr &= ~T;
759 }
760
761 /* code cycles t-bit
762 * 0000 0000 0001 1001 1 0
763 * DIV0U
764 */
DIV0U(void)765 static INLINE void DIV0U(void)
766 {
767 sh2.sr &= ~(M | Q | T);
768 }
769
770 /* code cycles t-bit
771 * 0011 nnnn mmmm 0100 1 calculation result
772 * DIV1 Rm,Rn
773 */
DIV1(UINT32 m,UINT32 n)774 static INLINE void DIV1(UINT32 m, UINT32 n)
775 {
776 UINT32 tmp0;
777 UINT32 old_q;
778
779 old_q = sh2.sr & Q;
780 if (0x80000000 & sh2.r[n])
781 sh2.sr |= Q;
782 else
783 sh2.sr &= ~Q;
784
785 sh2.r[n] = (sh2.r[n] << 1) | (sh2.sr & T);
786
787 if (!old_q)
788 {
789 if (!(sh2.sr & M))
790 {
791 tmp0 = sh2.r[n];
792 sh2.r[n] -= sh2.r[m];
793 if(!(sh2.sr & Q))
794 if(sh2.r[n] > tmp0)
795 sh2.sr |= Q;
796 else
797 sh2.sr &= ~Q;
798 else
799 if(sh2.r[n] > tmp0)
800 sh2.sr &= ~Q;
801 else
802 sh2.sr |= Q;
803 }
804 else
805 {
806 tmp0 = sh2.r[n];
807 sh2.r[n] += sh2.r[m];
808 if(!(sh2.sr & Q))
809 {
810 if(sh2.r[n] < tmp0)
811 sh2.sr &= ~Q;
812 else
813 sh2.sr |= Q;
814 }
815 else
816 {
817 if(sh2.r[n] < tmp0)
818 sh2.sr |= Q;
819 else
820 sh2.sr &= ~Q;
821 }
822 }
823 }
824 else
825 {
826 if (!(sh2.sr & M))
827 {
828 tmp0 = sh2.r[n];
829 sh2.r[n] += sh2.r[m];
830 if(!(sh2.sr & Q))
831 if(sh2.r[n] < tmp0)
832 sh2.sr |= Q;
833 else
834 sh2.sr &= ~Q;
835 else
836 if(sh2.r[n] < tmp0)
837 sh2.sr &= ~Q;
838 else
839 sh2.sr |= Q;
840 }
841 else
842 {
843 tmp0 = sh2.r[n];
844 sh2.r[n] -= sh2.r[m];
845 if(!(sh2.sr & Q))
846 if(sh2.r[n] > tmp0)
847 sh2.sr &= ~Q;
848 else
849 sh2.sr |= Q;
850 else
851 if(sh2.r[n] > tmp0)
852 sh2.sr |= Q;
853 else
854 sh2.sr &= ~Q;
855 }
856 }
857
858 tmp0 = (sh2.sr & (Q | M));
859 if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
860 sh2.sr |= T;
861 else
862 sh2.sr &= ~T;
863 }
864
865 /* DMULS.L Rm,Rn */
DMULS(UINT32 m,UINT32 n)866 static INLINE void DMULS(UINT32 m, UINT32 n)
867 {
868 UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
869 UINT32 temp0, temp1, temp2, temp3;
870 INT32 tempm, tempn, fnLmL;
871
872 tempn = (INT32) sh2.r[n];
873 tempm = (INT32) sh2.r[m];
874 if (tempn < 0)
875 tempn = 0 - tempn;
876 if (tempm < 0)
877 tempm = 0 - tempm;
878 if ((INT32) (sh2.r[n] ^ sh2.r[m]) < 0)
879 fnLmL = -1;
880 else
881 fnLmL = 0;
882 temp1 = (UINT32) tempn;
883 temp2 = (UINT32) tempm;
884 RnL = temp1 & 0x0000ffff;
885 RnH = (temp1 >> 16) & 0x0000ffff;
886 RmL = temp2 & 0x0000ffff;
887 RmH = (temp2 >> 16) & 0x0000ffff;
888 temp0 = RmL * RnL;
889 temp1 = RmH * RnL;
890 temp2 = RmL * RnH;
891 temp3 = RmH * RnH;
892 Res2 = 0;
893 Res1 = temp1 + temp2;
894 if (Res1 < temp1)
895 Res2 += 0x00010000;
896 temp1 = (Res1 << 16) & 0xffff0000;
897 Res0 = temp0 + temp1;
898 if (Res0 < temp0)
899 Res2++;
900 Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
901 if (fnLmL < 0)
902 {
903 Res2 = ~Res2;
904 if (Res0 == 0)
905 Res2++;
906 else
907 Res0 = (~Res0) + 1;
908 }
909 sh2.mach = Res2;
910 sh2.macl = Res0;
911 sh2_icount--;
912 }
913
914 /* DMULU.L Rm,Rn */
DMULU(UINT32 m,UINT32 n)915 static INLINE void DMULU(UINT32 m, UINT32 n)
916 {
917 UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
918 UINT32 temp0, temp1, temp2, temp3;
919
920 RnL = sh2.r[n] & 0x0000ffff;
921 RnH = (sh2.r[n] >> 16) & 0x0000ffff;
922 RmL = sh2.r[m] & 0x0000ffff;
923 RmH = (sh2.r[m] >> 16) & 0x0000ffff;
924 temp0 = RmL * RnL;
925 temp1 = RmH * RnL;
926 temp2 = RmL * RnH;
927 temp3 = RmH * RnH;
928 Res2 = 0;
929 Res1 = temp1 + temp2;
930 if (Res1 < temp1)
931 Res2 += 0x00010000;
932 temp1 = (Res1 << 16) & 0xffff0000;
933 Res0 = temp0 + temp1;
934 if (Res0 < temp0)
935 Res2++;
936 Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
937 sh2.mach = Res2;
938 sh2.macl = Res0;
939 sh2_icount--;
940 }
941
942 /* DT Rn */
DT(UINT32 n)943 static INLINE void DT(UINT32 n)
944 {
945 sh2.r[n]--;
946 if (sh2.r[n] == 0)
947 sh2.sr |= T;
948 else
949 sh2.sr &= ~T;
950 #if BUSY_LOOP_HACKS
951 {
952 UINT32 next_opcode = RW(sh2.ppc & AM);
953 /* DT Rn
954 * BF $-2
955 */
956 if (next_opcode == 0x8bfd)
957 {
958 while (sh2.r[n] > 1 && sh2_icount > 4)
959 {
960 sh2.r[n]--;
961 sh2_icount -= 4; /* cycles for DT (1) and BF taken (3) */
962 }
963 }
964 }
965 #endif
966 }
967
968 /* EXTS.B Rm,Rn */
EXTSB(UINT32 m,UINT32 n)969 static INLINE void EXTSB(UINT32 m, UINT32 n)
970 {
971 sh2.r[n] = ((INT32)sh2.r[m] << 24) >> 24;
972 }
973
974 /* EXTS.W Rm,Rn */
EXTSW(UINT32 m,UINT32 n)975 static INLINE void EXTSW(UINT32 m, UINT32 n)
976 {
977 sh2.r[n] = ((INT32)sh2.r[m] << 16) >> 16;
978 }
979
980 /* EXTU.B Rm,Rn */
EXTUB(UINT32 m,UINT32 n)981 static INLINE void EXTUB(UINT32 m, UINT32 n)
982 {
983 sh2.r[n] = sh2.r[m] & 0x000000ff;
984 }
985
986 /* EXTU.W Rm,Rn */
EXTUW(UINT32 m,UINT32 n)987 static INLINE void EXTUW(UINT32 m, UINT32 n)
988 {
989 sh2.r[n] = sh2.r[m] & 0x0000ffff;
990 }
991
992 /* JMP @Rm */
JMP(UINT32 m)993 static INLINE void JMP(UINT32 m)
994 {
995 sh2.delay = sh2.pc;
996 sh2.pc = sh2.ea = sh2.r[m];
997 }
998
999 /* JSR @Rm */
JSR(UINT32 m)1000 static INLINE void JSR(UINT32 m)
1001 {
1002 sh2.delay = sh2.pc;
1003 sh2.pr = sh2.pc + 2;
1004 sh2.pc = sh2.ea = sh2.r[m];
1005 sh2_icount--;
1006 }
1007
1008
1009 /* LDC Rm,SR */
LDCSR(UINT32 m)1010 static INLINE void LDCSR(UINT32 m)
1011 {
1012 sh2.sr = sh2.r[m] & FLAGS;
1013 sh2.test_irq = 1;
1014 }
1015
1016 /* LDC Rm,GBR */
LDCGBR(UINT32 m)1017 static INLINE void LDCGBR(UINT32 m)
1018 {
1019 sh2.gbr = sh2.r[m];
1020 }
1021
1022 /* LDC Rm,VBR */
LDCVBR(UINT32 m)1023 static INLINE void LDCVBR(UINT32 m)
1024 {
1025 sh2.vbr = sh2.r[m];
1026 }
1027
1028 /* LDC.L @Rm+,SR */
LDCMSR(UINT32 m)1029 static INLINE void LDCMSR(UINT32 m)
1030 {
1031 sh2.ea = sh2.r[m];
1032 sh2.sr = RL( sh2.ea ) & FLAGS;
1033 sh2.r[m] += 4;
1034 sh2_icount -= 2;
1035 sh2.test_irq = 1;
1036 }
1037
1038 /* LDC.L @Rm+,GBR */
LDCMGBR(UINT32 m)1039 static INLINE void LDCMGBR(UINT32 m)
1040 {
1041 sh2.ea = sh2.r[m];
1042 sh2.gbr = RL( sh2.ea );
1043 sh2.r[m] += 4;
1044 sh2_icount -= 2;
1045 }
1046
1047 /* LDC.L @Rm+,VBR */
LDCMVBR(UINT32 m)1048 static INLINE void LDCMVBR(UINT32 m)
1049 {
1050 sh2.ea = sh2.r[m];
1051 sh2.vbr = RL( sh2.ea );
1052 sh2.r[m] += 4;
1053 sh2_icount -= 2;
1054 }
1055
1056 /* LDS Rm,MACH */
LDSMACH(UINT32 m)1057 static INLINE void LDSMACH(UINT32 m)
1058 {
1059 sh2.mach = sh2.r[m];
1060 }
1061
1062 /* LDS Rm,MACL */
LDSMACL(UINT32 m)1063 static INLINE void LDSMACL(UINT32 m)
1064 {
1065 sh2.macl = sh2.r[m];
1066 }
1067
1068 /* LDS Rm,PR */
LDSPR(UINT32 m)1069 static INLINE void LDSPR(UINT32 m)
1070 {
1071 sh2.pr = sh2.r[m];
1072 }
1073
1074 /* LDS.L @Rm+,MACH */
LDSMMACH(UINT32 m)1075 static INLINE void LDSMMACH(UINT32 m)
1076 {
1077 sh2.ea = sh2.r[m];
1078 sh2.mach = RL( sh2.ea );
1079 sh2.r[m] += 4;
1080 }
1081
1082 /* LDS.L @Rm+,MACL */
LDSMMACL(UINT32 m)1083 static INLINE void LDSMMACL(UINT32 m)
1084 {
1085 sh2.ea = sh2.r[m];
1086 sh2.macl = RL( sh2.ea );
1087 sh2.r[m] += 4;
1088 }
1089
1090 /* LDS.L @Rm+,PR */
LDSMPR(UINT32 m)1091 static INLINE void LDSMPR(UINT32 m)
1092 {
1093 sh2.ea = sh2.r[m];
1094 sh2.pr = RL( sh2.ea );
1095 sh2.r[m] += 4;
1096 }
1097
1098 /* MAC.L @Rm+,@Rn+ */
MAC_L(UINT32 m,UINT32 n)1099 static INLINE void MAC_L(UINT32 m, UINT32 n)
1100 {
1101 UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
1102 UINT32 temp0, temp1, temp2, temp3;
1103 INT32 tempm, tempn, fnLmL;
1104
1105 tempn = (INT32) RL( sh2.r[n] );
1106 sh2.r[n] += 4;
1107 tempm = (INT32) RL( sh2.r[m] );
1108 sh2.r[m] += 4;
1109 if ((INT32) (tempn ^ tempm) < 0)
1110 fnLmL = -1;
1111 else
1112 fnLmL = 0;
1113 if (tempn < 0)
1114 tempn = 0 - tempn;
1115 if (tempm < 0)
1116 tempm = 0 - tempm;
1117 temp1 = (UINT32) tempn;
1118 temp2 = (UINT32) tempm;
1119 RnL = temp1 & 0x0000ffff;
1120 RnH = (temp1 >> 16) & 0x0000ffff;
1121 RmL = temp2 & 0x0000ffff;
1122 RmH = (temp2 >> 16) & 0x0000ffff;
1123 temp0 = RmL * RnL;
1124 temp1 = RmH * RnL;
1125 temp2 = RmL * RnH;
1126 temp3 = RmH * RnH;
1127 Res2 = 0;
1128 Res1 = temp1 + temp2;
1129 if (Res1 < temp1)
1130 Res2 += 0x00010000;
1131 temp1 = (Res1 << 16) & 0xffff0000;
1132 Res0 = temp0 + temp1;
1133 if (Res0 < temp0)
1134 Res2++;
1135 Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
1136 if (fnLmL < 0)
1137 {
1138 Res2 = ~Res2;
1139 if (Res0 == 0)
1140 Res2++;
1141 else
1142 Res0 = (~Res0) + 1;
1143 }
1144 if (sh2.sr & S)
1145 {
1146 Res0 = sh2.macl + Res0;
1147 if (sh2.macl > Res0)
1148 Res2++;
1149 Res2 += (sh2.mach & 0x0000ffff);
1150 if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
1151 {
1152 Res2 = 0x00008000;
1153 Res0 = 0x00000000;
1154 }
1155 else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
1156 {
1157 Res2 = 0x00007fff;
1158 Res0 = 0xffffffff;
1159 }
1160 sh2.mach = Res2;
1161 sh2.macl = Res0;
1162 }
1163 else
1164 {
1165 Res0 = sh2.macl + Res0;
1166 if (sh2.macl > Res0)
1167 Res2++;
1168 Res2 += sh2.mach;
1169 sh2.mach = Res2;
1170 sh2.macl = Res0;
1171 }
1172 sh2_icount -= 2;
1173 }
1174
1175 /* MAC.W @Rm+,@Rn+ */
MAC_W(UINT32 m,UINT32 n)1176 static INLINE void MAC_W(UINT32 m, UINT32 n)
1177 {
1178 INT32 tempm, tempn, dest, src, ans;
1179 UINT32 templ;
1180
1181 tempn = (INT32) RW( sh2.r[n] );
1182 sh2.r[n] += 2;
1183 tempm = (INT32) RW( sh2.r[m] );
1184 sh2.r[m] += 2;
1185 templ = sh2.macl;
1186 tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
1187 if ((INT32) sh2.macl >= 0)
1188 dest = 0;
1189 else
1190 dest = 1;
1191 if ((INT32) tempm >= 0)
1192 {
1193 src = 0;
1194 tempn = 0;
1195 }
1196 else
1197 {
1198 src = 1;
1199 tempn = 0xffffffff;
1200 }
1201 src += dest;
1202 sh2.macl += tempm;
1203 if ((INT32) sh2.macl >= 0)
1204 ans = 0;
1205 else
1206 ans = 1;
1207 ans += dest;
1208 if (sh2.sr & S)
1209 {
1210 if (ans == 1)
1211 {
1212 if (src == 0)
1213 sh2.macl = 0x7fffffff;
1214 if (src == 2)
1215 sh2.macl = 0x80000000;
1216 }
1217 }
1218 else
1219 {
1220 sh2.mach += tempn;
1221 if (templ > sh2.macl)
1222 sh2.mach += 1;
1223 }
1224 sh2_icount -= 2;
1225 }
1226
1227 /* MOV Rm,Rn */
MOV(UINT32 m,UINT32 n)1228 static INLINE void MOV(UINT32 m, UINT32 n)
1229 {
1230 sh2.r[n] = sh2.r[m];
1231 }
1232
1233 /* MOV.B Rm,@Rn */
MOVBS(UINT32 m,UINT32 n)1234 static INLINE void MOVBS(UINT32 m, UINT32 n)
1235 {
1236 sh2.ea = sh2.r[n];
1237 WB( sh2.ea, sh2.r[m] & 0x000000ff);
1238 }
1239
1240 /* MOV.W Rm,@Rn */
MOVWS(UINT32 m,UINT32 n)1241 static INLINE void MOVWS(UINT32 m, UINT32 n)
1242 {
1243 sh2.ea = sh2.r[n];
1244 WW( sh2.ea, sh2.r[m] & 0x0000ffff);
1245 }
1246
1247 /* MOV.L Rm,@Rn */
MOVLS(UINT32 m,UINT32 n)1248 static INLINE void MOVLS(UINT32 m, UINT32 n)
1249 {
1250 sh2.ea = sh2.r[n];
1251 WL( sh2.ea, sh2.r[m] );
1252 }
1253
1254 /* MOV.B @Rm,Rn */
MOVBL(UINT32 m,UINT32 n)1255 static INLINE void MOVBL(UINT32 m, UINT32 n)
1256 {
1257 sh2.ea = sh2.r[m];
1258 sh2.r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2.ea );
1259 }
1260
1261 /* MOV.W @Rm,Rn */
MOVWL(UINT32 m,UINT32 n)1262 static INLINE void MOVWL(UINT32 m, UINT32 n)
1263 {
1264 sh2.ea = sh2.r[m];
1265 sh2.r[n] = (UINT32)(INT32)(INT16) RW( sh2.ea );
1266 }
1267
1268 /* MOV.L @Rm,Rn */
MOVLL(UINT32 m,UINT32 n)1269 static INLINE void MOVLL(UINT32 m, UINT32 n)
1270 {
1271 sh2.ea = sh2.r[m];
1272 sh2.r[n] = RL( sh2.ea );
1273 }
1274
1275 /* MOV.B Rm,@-Rn */
MOVBM(UINT32 m,UINT32 n)1276 static INLINE void MOVBM(UINT32 m, UINT32 n)
1277 {
1278 /* SMG : bug fix, was reading sh2.r[n] */
1279 UINT32 data = sh2.r[m] & 0x000000ff;
1280
1281 sh2.r[n] -= 1;
1282 WB( sh2.r[n], data );
1283 }
1284
1285 /* MOV.W Rm,@-Rn */
MOVWM(UINT32 m,UINT32 n)1286 static INLINE void MOVWM(UINT32 m, UINT32 n)
1287 {
1288 UINT32 data = sh2.r[m] & 0x0000ffff;
1289
1290 sh2.r[n] -= 2;
1291 WW( sh2.r[n], data );
1292 }
1293
1294 /* MOV.L Rm,@-Rn */
MOVLM(UINT32 m,UINT32 n)1295 static INLINE void MOVLM(UINT32 m, UINT32 n)
1296 {
1297 UINT32 data = sh2.r[m];
1298
1299 sh2.r[n] -= 4;
1300 WL( sh2.r[n], data );
1301 }
1302
1303 /* MOV.B @Rm+,Rn */
MOVBP(UINT32 m,UINT32 n)1304 static INLINE void MOVBP(UINT32 m, UINT32 n)
1305 {
1306 sh2.r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2.r[m] );
1307 if (n != m)
1308 sh2.r[m] += 1;
1309 }
1310
1311 /* MOV.W @Rm+,Rn */
MOVWP(UINT32 m,UINT32 n)1312 static INLINE void MOVWP(UINT32 m, UINT32 n)
1313 {
1314 sh2.r[n] = (UINT32)(INT32)(INT16) RW( sh2.r[m] );
1315 if (n != m)
1316 sh2.r[m] += 2;
1317 }
1318
1319 /* MOV.L @Rm+,Rn */
MOVLP(UINT32 m,UINT32 n)1320 static INLINE void MOVLP(UINT32 m, UINT32 n)
1321 {
1322 sh2.r[n] = RL( sh2.r[m] );
1323 if (n != m)
1324 sh2.r[m] += 4;
1325 }
1326
1327 /* MOV.B Rm,@(R0,Rn) */
MOVBS0(UINT32 m,UINT32 n)1328 static INLINE void MOVBS0(UINT32 m, UINT32 n)
1329 {
1330 sh2.ea = sh2.r[n] + sh2.r[0];
1331 WB( sh2.ea, sh2.r[m] & 0x000000ff );
1332 }
1333
1334 /* MOV.W Rm,@(R0,Rn) */
MOVWS0(UINT32 m,UINT32 n)1335 static INLINE void MOVWS0(UINT32 m, UINT32 n)
1336 {
1337 sh2.ea = sh2.r[n] + sh2.r[0];
1338 WW( sh2.ea, sh2.r[m] & 0x0000ffff );
1339 }
1340
1341 /* MOV.L Rm,@(R0,Rn) */
MOVLS0(UINT32 m,UINT32 n)1342 static INLINE void MOVLS0(UINT32 m, UINT32 n)
1343 {
1344 sh2.ea = sh2.r[n] + sh2.r[0];
1345 WL( sh2.ea, sh2.r[m] );
1346 }
1347
1348 /* MOV.B @(R0,Rm),Rn */
MOVBL0(UINT32 m,UINT32 n)1349 static INLINE void MOVBL0(UINT32 m, UINT32 n)
1350 {
1351 sh2.ea = sh2.r[m] + sh2.r[0];
1352 sh2.r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2.ea );
1353 }
1354
1355 /* MOV.W @(R0,Rm),Rn */
MOVWL0(UINT32 m,UINT32 n)1356 static INLINE void MOVWL0(UINT32 m, UINT32 n)
1357 {
1358 sh2.ea = sh2.r[m] + sh2.r[0];
1359 sh2.r[n] = (UINT32)(INT32)(INT16) RW( sh2.ea );
1360 }
1361
1362 /* MOV.L @(R0,Rm),Rn */
MOVLL0(UINT32 m,UINT32 n)1363 static INLINE void MOVLL0(UINT32 m, UINT32 n)
1364 {
1365 sh2.ea = sh2.r[m] + sh2.r[0];
1366 sh2.r[n] = RL( sh2.ea );
1367 }
1368
1369 /* MOV #imm,Rn */
MOVI(UINT32 i,UINT32 n)1370 static INLINE void MOVI(UINT32 i, UINT32 n)
1371 {
1372 sh2.r[n] = (UINT32)(INT32)(INT16)(INT8) i;
1373 }
1374
1375 /* MOV.W @(disp8,PC),Rn */
MOVWI(UINT32 d,UINT32 n)1376 static INLINE void MOVWI(UINT32 d, UINT32 n)
1377 {
1378 UINT32 disp = d & 0xff;
1379 sh2.ea = sh2.pc + disp * 2 + 2;
1380 sh2.r[n] = (UINT32)(INT32)(INT16) RW( sh2.ea );
1381 }
1382
1383 /* MOV.L @(disp8,PC),Rn */
MOVLI(UINT32 d,UINT32 n)1384 static INLINE void MOVLI(UINT32 d, UINT32 n)
1385 {
1386 UINT32 disp = d & 0xff;
1387 sh2.ea = ((sh2.pc + 2) & ~3) + disp * 4;
1388 sh2.r[n] = RL( sh2.ea );
1389 }
1390
1391 /* MOV.B @(disp8,GBR),R0 */
MOVBLG(UINT32 d)1392 static INLINE void MOVBLG(UINT32 d)
1393 {
1394 UINT32 disp = d & 0xff;
1395 sh2.ea = sh2.gbr + disp;
1396 sh2.r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2.ea );
1397 }
1398
1399 /* MOV.W @(disp8,GBR),R0 */
MOVWLG(UINT32 d)1400 static INLINE void MOVWLG(UINT32 d)
1401 {
1402 UINT32 disp = d & 0xff;
1403 sh2.ea = sh2.gbr + disp * 2;
1404 sh2.r[0] = (INT32)(INT16) RW( sh2.ea );
1405 }
1406
1407 /* MOV.L @(disp8,GBR),R0 */
MOVLLG(UINT32 d)1408 static INLINE void MOVLLG(UINT32 d)
1409 {
1410 UINT32 disp = d & 0xff;
1411 sh2.ea = sh2.gbr + disp * 4;
1412 sh2.r[0] = RL( sh2.ea );
1413 }
1414
1415 /* MOV.B R0,@(disp8,GBR) */
MOVBSG(UINT32 d)1416 static INLINE void MOVBSG(UINT32 d)
1417 {
1418 UINT32 disp = d & 0xff;
1419 sh2.ea = sh2.gbr + disp;
1420 WB( sh2.ea, sh2.r[0] & 0x000000ff );
1421 }
1422
1423 /* MOV.W R0,@(disp8,GBR) */
MOVWSG(UINT32 d)1424 static INLINE void MOVWSG(UINT32 d)
1425 {
1426 UINT32 disp = d & 0xff;
1427 sh2.ea = sh2.gbr + disp * 2;
1428 WW( sh2.ea, sh2.r[0] & 0x0000ffff );
1429 }
1430
1431 /* MOV.L R0,@(disp8,GBR) */
MOVLSG(UINT32 d)1432 static INLINE void MOVLSG(UINT32 d)
1433 {
1434 UINT32 disp = d & 0xff;
1435 sh2.ea = sh2.gbr + disp * 4;
1436 WL( sh2.ea, sh2.r[0] );
1437 }
1438
1439 /* MOV.B R0,@(disp4,Rn) */
MOVBS4(UINT32 d,UINT32 n)1440 static INLINE void MOVBS4(UINT32 d, UINT32 n)
1441 {
1442 UINT32 disp = d & 0x0f;
1443 sh2.ea = sh2.r[n] + disp;
1444 WB( sh2.ea, sh2.r[0] & 0x000000ff );
1445 }
1446
1447 /* MOV.W R0,@(disp4,Rn) */
MOVWS4(UINT32 d,UINT32 n)1448 static INLINE void MOVWS4(UINT32 d, UINT32 n)
1449 {
1450 UINT32 disp = d & 0x0f;
1451 sh2.ea = sh2.r[n] + disp * 2;
1452 WW( sh2.ea, sh2.r[0] & 0x0000ffff );
1453 }
1454
1455 /* MOV.L Rm,@(disp4,Rn) */
MOVLS4(UINT32 m,UINT32 d,UINT32 n)1456 static INLINE void MOVLS4(UINT32 m, UINT32 d, UINT32 n)
1457 {
1458 UINT32 disp = d & 0x0f;
1459 sh2.ea = sh2.r[n] + disp * 4;
1460 WL( sh2.ea, sh2.r[m] );
1461 }
1462
1463 /* MOV.B @(disp4,Rm),R0 */
MOVBL4(UINT32 m,UINT32 d)1464 static INLINE void MOVBL4(UINT32 m, UINT32 d)
1465 {
1466 UINT32 disp = d & 0x0f;
1467 sh2.ea = sh2.r[m] + disp;
1468 sh2.r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2.ea );
1469 }
1470
1471 /* MOV.W @(disp4,Rm),R0 */
MOVWL4(UINT32 m,UINT32 d)1472 static INLINE void MOVWL4(UINT32 m, UINT32 d)
1473 {
1474 UINT32 disp = d & 0x0f;
1475 sh2.ea = sh2.r[m] + disp * 2;
1476 sh2.r[0] = (UINT32)(INT32)(INT16) RW( sh2.ea );
1477 }
1478
1479 /* MOV.L @(disp4,Rm),Rn */
MOVLL4(UINT32 m,UINT32 d,UINT32 n)1480 static INLINE void MOVLL4(UINT32 m, UINT32 d, UINT32 n)
1481 {
1482 UINT32 disp = d & 0x0f;
1483 sh2.ea = sh2.r[m] + disp * 4;
1484 sh2.r[n] = RL( sh2.ea );
1485 }
1486
1487 /* MOVA @(disp8,PC),R0 */
MOVA(UINT32 d)1488 static INLINE void MOVA(UINT32 d)
1489 {
1490 UINT32 disp = d & 0xff;
1491 sh2.ea = ((sh2.pc + 2) & ~3) + disp * 4;
1492 sh2.r[0] = sh2.ea;
1493 }
1494
1495 /* MOVT Rn */
MOVT(UINT32 n)1496 static INLINE void MOVT(UINT32 n)
1497 {
1498 sh2.r[n] = sh2.sr & T;
1499 }
1500
1501 /* MUL.L Rm,Rn */
MULL(UINT32 m,UINT32 n)1502 static INLINE void MULL(UINT32 m, UINT32 n)
1503 {
1504 sh2.macl = sh2.r[n] * sh2.r[m];
1505 sh2_icount--;
1506 }
1507
1508 /* MULS Rm,Rn */
MULS(UINT32 m,UINT32 n)1509 static INLINE void MULS(UINT32 m, UINT32 n)
1510 {
1511 sh2.macl = (INT16) sh2.r[n] * (INT16) sh2.r[m];
1512 }
1513
1514 /* MULU Rm,Rn */
MULU(UINT32 m,UINT32 n)1515 static INLINE void MULU(UINT32 m, UINT32 n)
1516 {
1517 sh2.macl = (UINT16) sh2.r[n] * (UINT16) sh2.r[m];
1518 }
1519
1520 /* NEG Rm,Rn */
NEG(UINT32 m,UINT32 n)1521 static INLINE void NEG(UINT32 m, UINT32 n)
1522 {
1523 sh2.r[n] = 0 - sh2.r[m];
1524 }
1525
1526 /* NEGC Rm,Rn */
NEGC(UINT32 m,UINT32 n)1527 static INLINE void NEGC(UINT32 m, UINT32 n)
1528 {
1529 UINT32 temp;
1530
1531 temp = sh2.r[m];
1532 sh2.r[n] = -temp - (sh2.sr & T);
1533 if (temp || (sh2.sr & T))
1534 sh2.sr |= T;
1535 else
1536 sh2.sr &= ~T;
1537 }
1538
1539 /* NOP */
NOP(void)1540 static INLINE void NOP(void)
1541 {
1542 }
1543
1544 /* NOT Rm,Rn */
NOT(UINT32 m,UINT32 n)1545 static INLINE void NOT(UINT32 m, UINT32 n)
1546 {
1547 sh2.r[n] = ~sh2.r[m];
1548 }
1549
1550 /* OR Rm,Rn */
OR(UINT32 m,UINT32 n)1551 static INLINE void OR(UINT32 m, UINT32 n)
1552 {
1553 sh2.r[n] |= sh2.r[m];
1554 }
1555
1556 /* OR #imm,R0 */
ORI(UINT32 i)1557 static INLINE void ORI(UINT32 i)
1558 {
1559 sh2.r[0] |= i;
1560 sh2_icount -= 2;
1561 }
1562
1563 /* OR.B #imm,@(R0,GBR) */
ORM(UINT32 i)1564 static INLINE void ORM(UINT32 i)
1565 {
1566 UINT32 temp;
1567
1568 sh2.ea = sh2.gbr + sh2.r[0];
1569 temp = RB( sh2.ea );
1570 temp |= i;
1571 WB( sh2.ea, temp );
1572 }
1573
1574 /* ROTCL Rn */
ROTCL(UINT32 n)1575 static INLINE void ROTCL(UINT32 n)
1576 {
1577 UINT32 temp;
1578
1579 temp = (sh2.r[n] >> 31) & T;
1580 sh2.r[n] = (sh2.r[n] << 1) | (sh2.sr & T);
1581 sh2.sr = (sh2.sr & ~T) | temp;
1582 }
1583
1584 /* ROTCR Rn */
ROTCR(UINT32 n)1585 static INLINE void ROTCR(UINT32 n)
1586 {
1587 UINT32 temp;
1588 temp = (sh2.sr & T) << 31;
1589 if (sh2.r[n] & T)
1590 sh2.sr |= T;
1591 else
1592 sh2.sr &= ~T;
1593 sh2.r[n] = (sh2.r[n] >> 1) | temp;
1594 }
1595
1596 /* ROTL Rn */
ROTL(UINT32 n)1597 static INLINE void ROTL(UINT32 n)
1598 {
1599 sh2.sr = (sh2.sr & ~T) | ((sh2.r[n] >> 31) & T);
1600 sh2.r[n] = (sh2.r[n] << 1) | (sh2.r[n] >> 31);
1601 }
1602
1603 /* ROTR Rn */
ROTR(UINT32 n)1604 static INLINE void ROTR(UINT32 n)
1605 {
1606 sh2.sr = (sh2.sr & ~T) | (sh2.r[n] & T);
1607 sh2.r[n] = (sh2.r[n] >> 1) | (sh2.r[n] << 31);
1608 }
1609
1610 /* RTE */
RTE(void)1611 static INLINE void RTE(void)
1612 {
1613 sh2.ea = sh2.r[15];
1614 sh2.delay = sh2.pc;
1615 sh2.pc = RL( sh2.ea );
1616 sh2.r[15] += 4;
1617 sh2.ea = sh2.r[15];
1618 sh2.sr = RL( sh2.ea ) & FLAGS;
1619 sh2.r[15] += 4;
1620 sh2_icount -= 3;
1621 sh2.test_irq = 1;
1622 }
1623
1624 /* RTS */
RTS(void)1625 static INLINE void RTS(void)
1626 {
1627 sh2.delay = sh2.pc;
1628 sh2.pc = sh2.ea = sh2.pr;
1629 sh2_icount--;
1630 }
1631
1632 /* SETT */
SETT(void)1633 static INLINE void SETT(void)
1634 {
1635 sh2.sr |= T;
1636 }
1637
1638 /* SHAL Rn (same as SHLL) */
SHAL(UINT32 n)1639 static INLINE void SHAL(UINT32 n)
1640 {
1641 sh2.sr = (sh2.sr & ~T) | ((sh2.r[n] >> 31) & T);
1642 sh2.r[n] <<= 1;
1643 }
1644
1645 /* SHAR Rn */
SHAR(UINT32 n)1646 static INLINE void SHAR(UINT32 n)
1647 {
1648 sh2.sr = (sh2.sr & ~T) | (sh2.r[n] & T);
1649 sh2.r[n] = (UINT32)((INT32)sh2.r[n] >> 1);
1650 }
1651
1652 /* SHLL Rn (same as SHAL) */
SHLL(UINT32 n)1653 static INLINE void SHLL(UINT32 n)
1654 {
1655 sh2.sr = (sh2.sr & ~T) | ((sh2.r[n] >> 31) & T);
1656 sh2.r[n] <<= 1;
1657 }
1658
1659 /* SHLL2 Rn */
SHLL2(UINT32 n)1660 static INLINE void SHLL2(UINT32 n)
1661 {
1662 sh2.r[n] <<= 2;
1663 }
1664
1665 /* SHLL8 Rn */
SHLL8(UINT32 n)1666 static INLINE void SHLL8(UINT32 n)
1667 {
1668 sh2.r[n] <<= 8;
1669 }
1670
1671 /* SHLL16 Rn */
SHLL16(UINT32 n)1672 static INLINE void SHLL16(UINT32 n)
1673 {
1674 sh2.r[n] <<= 16;
1675 }
1676
1677 /* SHLR Rn */
SHLR(UINT32 n)1678 static INLINE void SHLR(UINT32 n)
1679 {
1680 sh2.sr = (sh2.sr & ~T) | (sh2.r[n] & T);
1681 sh2.r[n] >>= 1;
1682 }
1683
1684 /* SHLR2 Rn */
SHLR2(UINT32 n)1685 static INLINE void SHLR2(UINT32 n)
1686 {
1687 sh2.r[n] >>= 2;
1688 }
1689
1690 /* SHLR8 Rn */
SHLR8(UINT32 n)1691 static INLINE void SHLR8(UINT32 n)
1692 {
1693 sh2.r[n] >>= 8;
1694 }
1695
1696 /* SHLR16 Rn */
SHLR16(UINT32 n)1697 static INLINE void SHLR16(UINT32 n)
1698 {
1699 sh2.r[n] >>= 16;
1700 }
1701
1702 /* SLEEP */
SLEEP(void)1703 static INLINE void SLEEP(void)
1704 {
1705 sh2.pc -= 2;
1706 sh2_icount -= 2;
1707 /* Wait_for_exception; */
1708 }
1709
1710 /* STC SR,Rn */
STCSR(UINT32 n)1711 static INLINE void STCSR(UINT32 n)
1712 {
1713 sh2.r[n] = sh2.sr;
1714 }
1715
1716 /* STC GBR,Rn */
STCGBR(UINT32 n)1717 static INLINE void STCGBR(UINT32 n)
1718 {
1719 sh2.r[n] = sh2.gbr;
1720 }
1721
1722 /* STC VBR,Rn */
STCVBR(UINT32 n)1723 static INLINE void STCVBR(UINT32 n)
1724 {
1725 sh2.r[n] = sh2.vbr;
1726 }
1727
1728 /* STC.L SR,@-Rn */
STCMSR(UINT32 n)1729 static INLINE void STCMSR(UINT32 n)
1730 {
1731 sh2.r[n] -= 4;
1732 sh2.ea = sh2.r[n];
1733 WL( sh2.ea, sh2.sr );
1734 sh2_icount--;
1735 }
1736
1737 /* STC.L GBR,@-Rn */
STCMGBR(UINT32 n)1738 static INLINE void STCMGBR(UINT32 n)
1739 {
1740 sh2.r[n] -= 4;
1741 sh2.ea = sh2.r[n];
1742 WL( sh2.ea, sh2.gbr );
1743 sh2_icount--;
1744 }
1745
1746 /* STC.L VBR,@-Rn */
STCMVBR(UINT32 n)1747 static INLINE void STCMVBR(UINT32 n)
1748 {
1749 sh2.r[n] -= 4;
1750 sh2.ea = sh2.r[n];
1751 WL( sh2.ea, sh2.vbr );
1752 sh2_icount--;
1753 }
1754
1755 /* STS MACH,Rn */
STSMACH(UINT32 n)1756 static INLINE void STSMACH(UINT32 n)
1757 {
1758 sh2.r[n] = sh2.mach;
1759 }
1760
1761 /* STS MACL,Rn */
STSMACL(UINT32 n)1762 static INLINE void STSMACL(UINT32 n)
1763 {
1764 sh2.r[n] = sh2.macl;
1765 }
1766
1767 /* STS PR,Rn */
STSPR(UINT32 n)1768 static INLINE void STSPR(UINT32 n)
1769 {
1770 sh2.r[n] = sh2.pr;
1771 }
1772
1773 /* STS.L MACH,@-Rn */
STSMMACH(UINT32 n)1774 static INLINE void STSMMACH(UINT32 n)
1775 {
1776 sh2.r[n] -= 4;
1777 sh2.ea = sh2.r[n];
1778 WL( sh2.ea, sh2.mach );
1779 }
1780
1781 /* STS.L MACL,@-Rn */
STSMMACL(UINT32 n)1782 static INLINE void STSMMACL(UINT32 n)
1783 {
1784 sh2.r[n] -= 4;
1785 sh2.ea = sh2.r[n];
1786 WL( sh2.ea, sh2.macl );
1787 }
1788
1789 /* STS.L PR,@-Rn */
STSMPR(UINT32 n)1790 static INLINE void STSMPR(UINT32 n)
1791 {
1792 sh2.r[n] -= 4;
1793 sh2.ea = sh2.r[n];
1794 WL( sh2.ea, sh2.pr );
1795 }
1796
1797 /* SUB Rm,Rn */
SUB(UINT32 m,UINT32 n)1798 static INLINE void SUB(UINT32 m, UINT32 n)
1799 {
1800 sh2.r[n] -= sh2.r[m];
1801 }
1802
1803 /* SUBC Rm,Rn */
SUBC(UINT32 m,UINT32 n)1804 static INLINE void SUBC(UINT32 m, UINT32 n)
1805 {
1806 UINT32 tmp0, tmp1;
1807
1808 tmp1 = sh2.r[n] - sh2.r[m];
1809 tmp0 = sh2.r[n];
1810 sh2.r[n] = tmp1 - (sh2.sr & T);
1811 if (tmp0 < tmp1)
1812 sh2.sr |= T;
1813 else
1814 sh2.sr &= ~T;
1815 if (tmp1 < sh2.r[n])
1816 sh2.sr |= T;
1817 }
1818
1819 /* SUBV Rm,Rn */
SUBV(UINT32 m,UINT32 n)1820 static INLINE void SUBV(UINT32 m, UINT32 n)
1821 {
1822 INT32 dest, src, ans;
1823
1824 if ((INT32) sh2.r[n] >= 0)
1825 dest = 0;
1826 else
1827 dest = 1;
1828 if ((INT32) sh2.r[m] >= 0)
1829 src = 0;
1830 else
1831 src = 1;
1832 src += dest;
1833 sh2.r[n] -= sh2.r[m];
1834 if ((INT32) sh2.r[n] >= 0)
1835 ans = 0;
1836 else
1837 ans = 1;
1838 ans += dest;
1839 if (src == 1)
1840 {
1841 if (ans == 1)
1842 sh2.sr |= T;
1843 else
1844 sh2.sr &= ~T;
1845 }
1846 else
1847 sh2.sr &= ~T;
1848 }
1849
1850 /* SWAP.B Rm,Rn */
SWAPB(UINT32 m,UINT32 n)1851 static INLINE void SWAPB(UINT32 m, UINT32 n)
1852 {
1853 UINT32 temp0, temp1;
1854
1855 temp0 = sh2.r[m] & 0xffff0000;
1856 temp1 = (sh2.r[m] & 0x000000ff) << 8;
1857 sh2.r[n] = (sh2.r[m] >> 8) & 0x000000ff;
1858 sh2.r[n] = sh2.r[n] | temp1 | temp0;
1859 }
1860
1861 /* SWAP.W Rm,Rn */
SWAPW(UINT32 m,UINT32 n)1862 static INLINE void SWAPW(UINT32 m, UINT32 n)
1863 {
1864 UINT32 temp;
1865
1866 temp = (sh2.r[m] >> 16) & 0x0000ffff;
1867 sh2.r[n] = (sh2.r[m] << 16) | temp;
1868 }
1869
1870 /* TAS.B @Rn */
TAS(UINT32 n)1871 static INLINE void TAS(UINT32 n)
1872 {
1873 UINT32 temp;
1874 sh2.ea = sh2.r[n];
1875 /* Bus Lock enable */
1876 temp = RB( sh2.ea );
1877 if (temp == 0)
1878 sh2.sr |= T;
1879 else
1880 sh2.sr &= ~T;
1881 temp |= 0x80;
1882 /* Bus Lock disable */
1883 WB( sh2.ea, temp );
1884 sh2_icount -= 3;
1885 }
1886
1887 /* TRAPA #imm */
TRAPA(UINT32 i)1888 static INLINE void TRAPA(UINT32 i)
1889 {
1890 UINT32 imm = i & 0xff;
1891
1892 sh2.ea = sh2.vbr + imm * 4;
1893
1894 sh2.r[15] -= 4;
1895 WL( sh2.r[15], sh2.sr );
1896 sh2.r[15] -= 4;
1897 WL( sh2.r[15], sh2.pc );
1898
1899 sh2.pc = RL( sh2.ea );
1900 change_pc32bedw(sh2.pc & AM);
1901
1902 sh2_icount -= 7;
1903 }
1904
1905 /* TST Rm,Rn */
TST(UINT32 m,UINT32 n)1906 static INLINE void TST(UINT32 m, UINT32 n)
1907 {
1908 if ((sh2.r[n] & sh2.r[m]) == 0)
1909 sh2.sr |= T;
1910 else
1911 sh2.sr &= ~T;
1912 }
1913
1914 /* TST #imm,R0 */
TSTI(UINT32 i)1915 static INLINE void TSTI(UINT32 i)
1916 {
1917 UINT32 imm = i & 0xff;
1918
1919 if ((imm & sh2.r[0]) == 0)
1920 sh2.sr |= T;
1921 else
1922 sh2.sr &= ~T;
1923 }
1924
1925 /* TST.B #imm,@(R0,GBR) */
TSTM(UINT32 i)1926 static INLINE void TSTM(UINT32 i)
1927 {
1928 UINT32 imm = i & 0xff;
1929
1930 sh2.ea = sh2.gbr + sh2.r[0];
1931 if ((imm & RB( sh2.ea )) == 0)
1932 sh2.sr |= T;
1933 else
1934 sh2.sr &= ~T;
1935 sh2_icount -= 2;
1936 }
1937
1938 /* XOR Rm,Rn */
XOR(UINT32 m,UINT32 n)1939 static INLINE void XOR(UINT32 m, UINT32 n)
1940 {
1941 sh2.r[n] ^= sh2.r[m];
1942 }
1943
1944 /* XOR #imm,R0 */
XORI(UINT32 i)1945 static INLINE void XORI(UINT32 i)
1946 {
1947 UINT32 imm = i & 0xff;
1948 sh2.r[0] ^= imm;
1949 }
1950
1951 /* XOR.B #imm,@(R0,GBR) */
XORM(UINT32 i)1952 static INLINE void XORM(UINT32 i)
1953 {
1954 UINT32 imm = i & 0xff;
1955 UINT32 temp;
1956
1957 sh2.ea = sh2.gbr + sh2.r[0];
1958 temp = RB( sh2.ea );
1959 temp ^= imm;
1960 WB( sh2.ea, temp );
1961 sh2_icount -= 2;
1962 }
1963
1964 /* XTRCT Rm,Rn */
XTRCT(UINT32 m,UINT32 n)1965 static INLINE void XTRCT(UINT32 m, UINT32 n)
1966 {
1967 UINT32 temp;
1968
1969 temp = (sh2.r[m] << 16) & 0xffff0000;
1970 sh2.r[n] = (sh2.r[n] >> 16) & 0x0000ffff;
1971 sh2.r[n] |= temp;
1972 }
1973
1974 /*****************************************************************************
1975 * OPCODE DISPATCHERS
1976 *****************************************************************************/
1977
op0000(UINT16 opcode)1978 static INLINE void op0000(UINT16 opcode)
1979 {
1980 switch (opcode & 0x3F)
1981 {
1982 case 0x00: NOP(); break;
1983 case 0x01: NOP(); break;
1984 case 0x02: STCSR(Rn); break;
1985 case 0x03: BSRF(Rn); break;
1986 case 0x04: MOVBS0(Rm, Rn); break;
1987 case 0x05: MOVWS0(Rm, Rn); break;
1988 case 0x06: MOVLS0(Rm, Rn); break;
1989 case 0x07: MULL(Rm, Rn); break;
1990 case 0x08: CLRT(); break;
1991 case 0x09: NOP(); break;
1992 case 0x0a: STSMACH(Rn); break;
1993 case 0x0b: RTS(); break;
1994 case 0x0c: MOVBL0(Rm, Rn); break;
1995 case 0x0d: MOVWL0(Rm, Rn); break;
1996 case 0x0e: MOVLL0(Rm, Rn); break;
1997 case 0x0f: MAC_L(Rm, Rn); break;
1998
1999 case 0x10: NOP(); break;
2000 case 0x11: NOP(); break;
2001 case 0x12: STCGBR(Rn); break;
2002 case 0x13: NOP(); break;
2003 case 0x14: MOVBS0(Rm, Rn); break;
2004 case 0x15: MOVWS0(Rm, Rn); break;
2005 case 0x16: MOVLS0(Rm, Rn); break;
2006 case 0x17: MULL(Rm, Rn); break;
2007 case 0x18: SETT(); break;
2008 case 0x19: DIV0U(); break;
2009 case 0x1a: STSMACL(Rn); break;
2010 case 0x1b: SLEEP(); break;
2011 case 0x1c: MOVBL0(Rm, Rn); break;
2012 case 0x1d: MOVWL0(Rm, Rn); break;
2013 case 0x1e: MOVLL0(Rm, Rn); break;
2014 case 0x1f: MAC_L(Rm, Rn); break;
2015
2016 case 0x20: NOP(); break;
2017 case 0x21: NOP(); break;
2018 case 0x22: STCVBR(Rn); break;
2019 case 0x23: BRAF(Rn); break;
2020 case 0x24: MOVBS0(Rm, Rn); break;
2021 case 0x25: MOVWS0(Rm, Rn); break;
2022 case 0x26: MOVLS0(Rm, Rn); break;
2023 case 0x27: MULL(Rm, Rn); break;
2024 case 0x28: CLRMAC(); break;
2025 case 0x29: MOVT(Rn); break;
2026 case 0x2a: STSPR(Rn); break;
2027 case 0x2b: RTE(); break;
2028 case 0x2c: MOVBL0(Rm, Rn); break;
2029 case 0x2d: MOVWL0(Rm, Rn); break;
2030 case 0x2e: MOVLL0(Rm, Rn); break;
2031 case 0x2f: MAC_L(Rm, Rn); break;
2032
2033 case 0x30: NOP(); break;
2034 case 0x31: NOP(); break;
2035 case 0x32: NOP(); break;
2036 case 0x33: NOP(); break;
2037 case 0x34: MOVBS0(Rm, Rn); break;
2038 case 0x35: MOVWS0(Rm, Rn); break;
2039 case 0x36: MOVLS0(Rm, Rn); break;
2040 case 0x37: MULL(Rm, Rn); break;
2041 case 0x38: NOP(); break;
2042 case 0x39: NOP(); break;
2043 case 0x3c: MOVBL0(Rm, Rn); break;
2044 case 0x3d: MOVWL0(Rm, Rn); break;
2045 case 0x3e: MOVLL0(Rm, Rn); break;
2046 case 0x3f: MAC_L(Rm, Rn); break;
2047 case 0x3a: NOP(); break;
2048 case 0x3b: NOP(); break;
2049 }
2050 }
2051
op0001(UINT16 opcode)2052 static INLINE void op0001(UINT16 opcode)
2053 {
2054 MOVLS4(Rm, opcode & 0x0f, Rn);
2055 }
2056
op0010(UINT16 opcode)2057 static INLINE void op0010(UINT16 opcode)
2058 {
2059 switch (opcode & 15)
2060 {
2061 case 0: MOVBS(Rm, Rn); break;
2062 case 1: MOVWS(Rm, Rn); break;
2063 case 2: MOVLS(Rm, Rn); break;
2064 case 3: NOP(); break;
2065 case 4: MOVBM(Rm, Rn); break;
2066 case 5: MOVWM(Rm, Rn); break;
2067 case 6: MOVLM(Rm, Rn); break;
2068 case 7: DIV0S(Rm, Rn); break;
2069 case 8: TST(Rm, Rn); break;
2070 case 9: AND(Rm, Rn); break;
2071 case 10: XOR(Rm, Rn); break;
2072 case 11: OR(Rm, Rn); break;
2073 case 12: CMPSTR(Rm, Rn); break;
2074 case 13: XTRCT(Rm, Rn); break;
2075 case 14: MULU(Rm, Rn); break;
2076 case 15: MULS(Rm, Rn); break;
2077 }
2078 }
2079
op0011(UINT16 opcode)2080 static INLINE void op0011(UINT16 opcode)
2081 {
2082 switch (opcode & 15)
2083 {
2084 case 0: CMPEQ(Rm, Rn); break;
2085 case 1: NOP(); break;
2086 case 2: CMPHS(Rm, Rn); break;
2087 case 3: CMPGE(Rm, Rn); break;
2088 case 4: DIV1(Rm, Rn); break;
2089 case 5: DMULU(Rm, Rn); break;
2090 case 6: CMPHI(Rm, Rn); break;
2091 case 7: CMPGT(Rm, Rn); break;
2092 case 8: SUB(Rm, Rn); break;
2093 case 9: NOP(); break;
2094 case 10: SUBC(Rm, Rn); break;
2095 case 11: SUBV(Rm, Rn); break;
2096 case 12: ADD(Rm, Rn); break;
2097 case 13: DMULS(Rm, Rn); break;
2098 case 14: ADDC(Rm, Rn); break;
2099 case 15: ADDV(Rm, Rn); break;
2100 }
2101 }
2102
op0100(UINT16 opcode)2103 static INLINE void op0100(UINT16 opcode)
2104 {
2105 switch (opcode & 0x3F)
2106 {
2107 case 0x00: SHLL(Rn); break;
2108 case 0x01: SHLR(Rn); break;
2109 case 0x02: STSMMACH(Rn); break;
2110 case 0x03: STCMSR(Rn); break;
2111 case 0x04: ROTL(Rn); break;
2112 case 0x05: ROTR(Rn); break;
2113 case 0x06: LDSMMACH(Rn); break;
2114 case 0x07: LDCMSR(Rn); break;
2115 case 0x08: SHLL2(Rn); break;
2116 case 0x09: SHLR2(Rn); break;
2117 case 0x0a: LDSMACH(Rn); break;
2118 case 0x0b: JSR(Rn); break;
2119 case 0x0c: NOP(); break;
2120 case 0x0d: NOP(); break;
2121 case 0x0e: LDCSR(Rn); break;
2122 case 0x0f: MAC_W(Rm, Rn); break;
2123
2124 case 0x10: DT(Rn); break;
2125 case 0x11: CMPPZ(Rn); break;
2126 case 0x12: STSMMACL(Rn); break;
2127 case 0x13: STCMGBR(Rn); break;
2128 case 0x14: NOP(); break;
2129 case 0x15: CMPPL(Rn); break;
2130 case 0x16: LDSMMACL(Rn); break;
2131 case 0x17: LDCMGBR(Rn); break;
2132 case 0x18: SHLL8(Rn); break;
2133 case 0x19: SHLR8(Rn); break;
2134 case 0x1a: LDSMACL(Rn); break;
2135 case 0x1b: TAS(Rn); break;
2136 case 0x1c: NOP(); break;
2137 case 0x1d: NOP(); break;
2138 case 0x1e: LDCGBR(Rn); break;
2139 case 0x1f: MAC_W(Rm, Rn); break;
2140
2141 case 0x20: SHAL(Rn); break;
2142 case 0x21: SHAR(Rn); break;
2143 case 0x22: STSMPR(Rn); break;
2144 case 0x23: STCMVBR(Rn); break;
2145 case 0x24: ROTCL(Rn); break;
2146 case 0x25: ROTCR(Rn); break;
2147 case 0x26: LDSMPR(Rn); break;
2148 case 0x27: LDCMVBR(Rn); break;
2149 case 0x28: SHLL16(Rn); break;
2150 case 0x29: SHLR16(Rn); break;
2151 case 0x2a: LDSPR(Rn); break;
2152 case 0x2b: JMP(Rn); break;
2153 case 0x2c: NOP(); break;
2154 case 0x2d: NOP(); break;
2155 case 0x2e: LDCVBR(Rn); break;
2156 case 0x2f: MAC_W(Rm, Rn); break;
2157
2158 case 0x30: NOP(); break;
2159 case 0x31: NOP(); break;
2160 case 0x32: NOP(); break;
2161 case 0x33: NOP(); break;
2162 case 0x34: NOP(); break;
2163 case 0x35: NOP(); break;
2164 case 0x36: NOP(); break;
2165 case 0x37: NOP(); break;
2166 case 0x38: NOP(); break;
2167 case 0x39: NOP(); break;
2168 case 0x3a: NOP(); break;
2169 case 0x3b: NOP(); break;
2170 case 0x3c: NOP(); break;
2171 case 0x3d: NOP(); break;
2172 case 0x3e: NOP(); break;
2173 case 0x3f: MAC_W(Rm, Rn); break;
2174 }
2175 }
2176
op0101(UINT16 opcode)2177 static INLINE void op0101(UINT16 opcode)
2178 {
2179 MOVLL4(Rm, opcode & 0x0f, Rn);
2180 }
2181
op0110(UINT16 opcode)2182 static INLINE void op0110(UINT16 opcode)
2183 {
2184 switch (opcode & 15)
2185 {
2186 case 0: MOVBL(Rm, Rn); break;
2187 case 1: MOVWL(Rm, Rn); break;
2188 case 2: MOVLL(Rm, Rn); break;
2189 case 3: MOV(Rm, Rn); break;
2190 case 4: MOVBP(Rm, Rn); break;
2191 case 5: MOVWP(Rm, Rn); break;
2192 case 6: MOVLP(Rm, Rn); break;
2193 case 7: NOT(Rm, Rn); break;
2194 case 8: SWAPB(Rm, Rn); break;
2195 case 9: SWAPW(Rm, Rn); break;
2196 case 10: NEGC(Rm, Rn); break;
2197 case 11: NEG(Rm, Rn); break;
2198 case 12: EXTUB(Rm, Rn); break;
2199 case 13: EXTUW(Rm, Rn); break;
2200 case 14: EXTSB(Rm, Rn); break;
2201 case 15: EXTSW(Rm, Rn); break;
2202 }
2203 }
2204
op0111(UINT16 opcode)2205 static INLINE void op0111(UINT16 opcode)
2206 {
2207 ADDI(opcode & 0xff, Rn);
2208 }
2209
op1000(UINT16 opcode)2210 static INLINE void op1000(UINT16 opcode)
2211 {
2212 switch ((opcode >> 8) & 15)
2213 {
2214 case 0: MOVBS4(opcode & 0x0f, Rm); break;
2215 case 1: MOVWS4(opcode & 0x0f, Rm); break;
2216 case 2: NOP(); break;
2217 case 3: NOP(); break;
2218 case 4: MOVBL4(Rm, opcode & 0x0f); break;
2219 case 5: MOVWL4(Rm, opcode & 0x0f); break;
2220 case 6: NOP(); break;
2221 case 7: NOP(); break;
2222 case 8: CMPIM(opcode & 0xff); break;
2223 case 9: BT(opcode & 0xff); break;
2224 case 10: NOP(); break;
2225 case 11: BF(opcode & 0xff); break;
2226 case 12: NOP(); break;
2227 case 13: BTS(opcode & 0xff); break;
2228 case 14: NOP(); break;
2229 case 15: BFS(opcode & 0xff); break;
2230 }
2231 }
2232
2233
op1001(UINT16 opcode)2234 static INLINE void op1001(UINT16 opcode)
2235 {
2236 MOVWI(opcode & 0xff, Rn);
2237 }
2238
op1010(UINT16 opcode)2239 static INLINE void op1010(UINT16 opcode)
2240 {
2241 BRA(opcode & 0xfff);
2242 }
2243
op1011(UINT16 opcode)2244 static INLINE void op1011(UINT16 opcode)
2245 {
2246 BSR(opcode & 0xfff);
2247 }
2248
op1100(UINT16 opcode)2249 static INLINE void op1100(UINT16 opcode)
2250 {
2251 switch ((opcode >> 8) & 15)
2252 {
2253 case 0: MOVBSG(opcode & 0xff); break;
2254 case 1: MOVWSG(opcode & 0xff); break;
2255 case 2: MOVLSG(opcode & 0xff); break;
2256 case 3: TRAPA(opcode & 0xff); break;
2257 case 4: MOVBLG(opcode & 0xff); break;
2258 case 5: MOVWLG(opcode & 0xff); break;
2259 case 6: MOVLLG(opcode & 0xff); break;
2260 case 7: MOVA(opcode & 0xff); break;
2261 case 8: TSTI(opcode & 0xff); break;
2262 case 9: ANDI(opcode & 0xff); break;
2263 case 10: XORI(opcode & 0xff); break;
2264 case 11: ORI(opcode & 0xff); break;
2265 case 12: TSTM(opcode & 0xff); break;
2266 case 13: ANDM(opcode & 0xff); break;
2267 case 14: XORM(opcode & 0xff); break;
2268 case 15: ORM(opcode & 0xff); break;
2269 }
2270 }
2271
op1101(UINT16 opcode)2272 static INLINE void op1101(UINT16 opcode)
2273 {
2274 MOVLI(opcode & 0xff, Rn);
2275 }
2276
op1110(UINT16 opcode)2277 static INLINE void op1110(UINT16 opcode)
2278 {
2279 MOVI(opcode & 0xff, Rn);
2280 }
2281
op1111(UINT16 opcode)2282 static INLINE void op1111(UINT16 opcode)
2283 {
2284 NOP();
2285 }
2286
2287 /*****************************************************************************
2288 * MAME CPU INTERFACE
2289 *****************************************************************************/
2290
sh2_reset(void * param)2291 void sh2_reset(void *param)
2292 {
2293 void *tsave, *tsaved0, *tsaved1;
2294 UINT32 *m;
2295
2296 struct sh2_config *conf = param;
2297
2298 m = sh2.m;
2299 tsave = sh2.timer;
2300 tsaved0 = sh2.dma_timer[0];
2301 tsaved1 = sh2.dma_timer[1];
2302 memset(&sh2, 0, sizeof(SH2));
2303 sh2.timer = tsave;
2304 sh2.dma_timer[0] = tsaved0;
2305 sh2.dma_timer[1] = tsaved1;
2306 sh2.m = m;
2307 memset(sh2.m, 0, 0x200);
2308
2309 if(conf)
2310 sh2.is_slave = conf->is_slave;
2311 else
2312 sh2.is_slave = 0;
2313
2314 sh2.cpu_number = cpu_getactivecpu();
2315
2316 sh2.pc = RL(0);
2317 sh2.r[15] = RL(4);
2318 sh2.sr = I;
2319 change_pc32bedw(sh2.pc & AM);
2320
2321 sh2.internal_irq_level = -1;
2322 }
2323
2324 /* Shut down CPU core */
sh2_exit(void)2325 void sh2_exit(void)
2326 {
2327 if (sh2.m)
2328 free(sh2.m);
2329 sh2.m = NULL;
2330 }
2331
2332 /* Execute cycles - returns number of cycles actually run */
sh2_execute(int cycles)2333 int sh2_execute(int cycles)
2334 {
2335 sh2_icount = cycles;
2336
2337 if (sh2.cpu_off)
2338 return 0;
2339
2340 do
2341 {
2342 UINT32 opcode;
2343
2344 if (sh2.delay)
2345 {
2346 opcode = RW(sh2.delay & AM);
2347 change_pc32bedw(sh2.pc & AM);
2348 sh2.pc -= 2;
2349 }
2350 else
2351 opcode = RW(sh2.pc & AM);
2352
2353 CALL_MAME_DEBUG;
2354
2355 sh2.delay = 0;
2356 sh2.pc += 2;
2357 sh2.ppc = sh2.pc;
2358
2359 switch ((opcode >> 12) & 15)
2360 {
2361 case 0: op0000(opcode); break;
2362 case 1: op0001(opcode); break;
2363 case 2: op0010(opcode); break;
2364 case 3: op0011(opcode); break;
2365 case 4: op0100(opcode); break;
2366 case 5: op0101(opcode); break;
2367 case 6: op0110(opcode); break;
2368 case 7: op0111(opcode); break;
2369 case 8: op1000(opcode); break;
2370 case 9: op1001(opcode); break;
2371 case 10: op1010(opcode); break;
2372 case 11: op1011(opcode); break;
2373 case 12: op1100(opcode); break;
2374 case 13: op1101(opcode); break;
2375 case 14: op1110(opcode); break;
2376 default: op1111(opcode); break;
2377 }
2378
2379 if(sh2.test_irq && !sh2.delay)
2380 {
2381 CHECK_PENDING_IRQ("mame_sh2_execute");
2382 sh2.test_irq = 0;
2383 }
2384 sh2_icount--;
2385 } while( sh2_icount > 0 );
2386
2387 return cycles - sh2_icount;
2388 }
2389
2390 /* Get registers, return context size */
sh2_get_context(void * dst)2391 unsigned sh2_get_context(void *dst)
2392 {
2393 if( dst )
2394 memcpy(dst, &sh2, sizeof(SH2));
2395 return sizeof(SH2);
2396 }
2397
2398 /* Set registers */
sh2_set_context(void * src)2399 void sh2_set_context(void *src)
2400 {
2401 if( src )
2402 memcpy(&sh2, src, sizeof(SH2));
2403 }
2404
sh2_timer_resync(void)2405 static void sh2_timer_resync(void)
2406 {
2407 int divider = div_tab[(sh2.m[5] >> 8) & 3];
2408 UINT32 cur_time = cpunum_gettotalcycles(sh2.cpu_number);
2409
2410 if(divider)
2411 sh2.frc += (cur_time - sh2.frc_base) >> divider;
2412 sh2.frc_base = cur_time;
2413 }
2414
sh2_timer_activate(void)2415 static void sh2_timer_activate(void)
2416 {
2417 int max_delta = 0xfffff;
2418 UINT16 frc;
2419
2420 timer_adjust(sh2.timer, TIME_NEVER, 0, 0);
2421
2422 frc = sh2.frc;
2423 if(!(sh2.m[4] & OCFA)) {
2424 UINT16 delta = sh2.ocra - frc;
2425 if(delta < max_delta)
2426 max_delta = delta;
2427 }
2428
2429 if(!(sh2.m[4] & OCFB) && (sh2.ocra <= sh2.ocrb || !(sh2.m[4] & 0x010000))) {
2430 UINT16 delta = sh2.ocrb - frc;
2431 if(delta < max_delta)
2432 max_delta = delta;
2433 }
2434
2435 if(!(sh2.m[4] & OVF) && !(sh2.m[4] & 0x010000)) {
2436 int delta = 0x10000 - frc;
2437 if(delta < max_delta)
2438 max_delta = delta;
2439 }
2440
2441 if(max_delta != 0xfffff) {
2442 int divider = div_tab[(sh2.m[5] >> 8) & 3];
2443 if(divider) {
2444 max_delta <<= divider;
2445 sh2.frc_base = cpunum_gettotalcycles(sh2.cpu_number);
2446 timer_adjust(sh2.timer, TIME_IN_CYCLES(max_delta, sh2.cpu_number), sh2.cpu_number, 0);
2447 } else {
2448 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2.%d: Timer event in %d cycles of external clock", sh2.cpu_number, max_delta);
2449 }
2450 }
2451 }
2452
sh2_recalc_irq(void)2453 static void sh2_recalc_irq(void)
2454 {
2455 int irq = 0, vector = -1;
2456 int level;
2457
2458 /* Timer irqs*/
2459 if((sh2.m[4]>>8) & sh2.m[4] & (ICF|OCFA|OCFB|OVF))
2460 {
2461 level = (sh2.m[0x18] >> 24) & 15;
2462 if(level > irq)
2463 {
2464 int mask = (sh2.m[4]>>8) & sh2.m[4];
2465 irq = level;
2466 if(mask & ICF)
2467 vector = (sh2.m[0x19] >> 8) & 0x7f;
2468 else if(mask & (OCFA|OCFB))
2469 vector = sh2.m[0x19] & 0x7f;
2470 else
2471 vector = (sh2.m[0x1a] >> 24) & 0x7f;
2472 }
2473 }
2474
2475 /* DMA irqs*/
2476 if((sh2.m[0x63] & 6) == 6) {
2477 level = (sh2.m[0x38] >> 8) & 15;
2478 if(level > irq) {
2479 irq = level;
2480 vector = (sh2.m[0x68] >> 24) & 0x7f;
2481 }
2482 }
2483
2484 if((sh2.m[0x67] & 6) == 6) {
2485 level = (sh2.m[0x38] >> 8) & 15;
2486 if(level > irq) {
2487 irq = level;
2488 vector = (sh2.m[0x6a] >> 24) & 0x7f;
2489 }
2490 }
2491
2492 sh2.internal_irq_level = irq;
2493 sh2.internal_irq_vector = vector;
2494 sh2.test_irq = 1;
2495 }
2496
sh2_timer_callback(int cpunum)2497 static void sh2_timer_callback(int cpunum)
2498 {
2499 UINT16 frc;
2500
2501 cpuintrf_push_context(cpunum);
2502 sh2_timer_resync();
2503
2504 frc = sh2.frc;
2505
2506 if(frc == sh2.ocrb)
2507 sh2.m[4] |= OCFB;
2508
2509 if(frc == 0x0000)
2510 sh2.m[4] |= OVF;
2511
2512 if(frc == sh2.ocra)
2513 {
2514 sh2.m[4] |= OCFA;
2515
2516 if(sh2.m[4] & 0x010000)
2517 sh2.frc = 0;
2518 }
2519
2520 sh2_recalc_irq();
2521 sh2_timer_activate();
2522
2523 cpuintrf_pop_context();
2524 }
2525
sh2_dmac_callback(int dma)2526 static void sh2_dmac_callback(int dma)
2527 {
2528 int cpunum = dma >> 1;
2529 dma &= 1;
2530
2531 cpuintrf_push_context(cpunum);
2532 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2.%d: DMA %d complete\n", cpunum, dma);
2533 sh2.m[0x63+4*dma] |= 2;
2534 sh2.dma_timer_active[dma] = 0;
2535 sh2_recalc_irq();
2536 cpuintrf_pop_context();
2537 }
2538
sh2_dmac_check(int dma)2539 static void sh2_dmac_check(int dma)
2540 {
2541 if(sh2.m[0x63+4*dma] & sh2.m[0x6c] & 1)
2542 {
2543 if(!sh2.dma_timer_active[dma] && !(sh2.m[0x63+4*dma] & 2))
2544 {
2545 int incs, incd, size;
2546 UINT32 src, dst, count;
2547 incd = (sh2.m[0x63+4*dma] >> 14) & 3;
2548 incs = (sh2.m[0x63+4*dma] >> 12) & 3;
2549 size = (sh2.m[0x63+4*dma] >> 10) & 3;
2550 if(incd == 3 || incs == 3)
2551 {
2552 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, sh2.m[0x63+4*dma]);
2553 return;
2554 }
2555 src = sh2.m[0x60+4*dma];
2556 dst = sh2.m[0x61+4*dma];
2557 count = sh2.m[0x62+4*dma];
2558 if(!count)
2559 count = 0x1000000;
2560
2561 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, src, dst, count, sh2.m[0x63+4*dma], incs, incd, size);
2562
2563 sh2.dma_timer_active[dma] = 1;
2564 timer_adjust(sh2.dma_timer[dma], TIME_IN_CYCLES(2*count+1, sh2.cpu_number), (sh2.cpu_number<<1)|dma, 0);
2565
2566 src &= AM;
2567 dst &= AM;
2568
2569 switch(size)
2570 {
2571 case 0:
2572 for(;count > 0; count --)
2573 {
2574 if(incs == 2)
2575 src --;
2576 if(incd == 2)
2577 dst --;
2578 cpu_writemem32bedw(dst, cpu_readmem32bedw(src));
2579 if(incs == 1)
2580 src ++;
2581 if(incd == 1)
2582 dst ++;
2583 }
2584 break;
2585 case 1:
2586 src &= ~1;
2587 dst &= ~1;
2588 for(;count > 0; count --)
2589 {
2590 if(incs == 2)
2591 src -= 2;
2592 if(incd == 2)
2593 dst -= 2;
2594 cpu_writemem32bedw_word(dst, cpu_readmem32bedw_word(src));
2595 if(incs == 1)
2596 src += 2;
2597 if(incd == 1)
2598 dst += 2;
2599 }
2600 break;
2601 case 2:
2602 src &= ~3;
2603 dst &= ~3;
2604 for(;count > 0; count --)
2605 {
2606 if(incs == 2)
2607 src -= 4;
2608 if(incd == 2)
2609 dst -= 4;
2610 cpu_writemem32bedw_dword(dst, cpu_readmem32bedw_dword(src));
2611 if(incs == 1)
2612 src += 4;
2613 if(incd == 1)
2614 dst += 4;
2615 }
2616 break;
2617 case 3:
2618 src &= ~3;
2619 dst &= ~3;
2620 count &= ~3;
2621 for(;count > 0; count -= 4)
2622 {
2623 if(incd == 2)
2624 dst -= 16;
2625 cpu_writemem32bedw_dword(dst, cpu_readmem32bedw_dword(src));
2626 cpu_writemem32bedw_dword(dst+4, cpu_readmem32bedw_dword(src+4));
2627 cpu_writemem32bedw_dword(dst+8, cpu_readmem32bedw_dword(src+8));
2628 cpu_writemem32bedw_dword(dst+12, cpu_readmem32bedw_dword(src+12));
2629 src += 16;
2630 if(incd == 1)
2631 dst += 16;
2632 }
2633 break;
2634 }
2635 }
2636 }
2637 else
2638 {
2639 if(sh2.dma_timer_active[dma])
2640 {
2641 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2: DMA %d cancelled in-flight", dma);
2642 timer_adjust(sh2.dma_timer[dma], TIME_NEVER, 0, 0);
2643 sh2.dma_timer_active[dma] = 0;
2644 }
2645 }
2646 }
2647
WRITE32_HANDLER(sh2_internal_w)2648 WRITE32_HANDLER( sh2_internal_w )
2649 {
2650 UINT32 old = sh2.m[offset];
2651 COMBINE_DATA(sh2.m+offset);
2652
2653 /* if(offset != 0x20)*/
2654 /* log_cb(RETRO_LOG_DEBUG, LOGPRE "sh2_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfffffe00+offset*4, offset, data, mem_mask);*/
2655
2656 switch( offset )
2657 {
2658 /* Timers*/
2659 case 0x04: /* TIER, FTCSR, FRC*/
2660 if((mem_mask & 0x00ffffff) != 0xffffff)
2661 sh2_timer_resync();
2662 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2.%d: TIER write %04x @ %04x\n", sh2.cpu_number, data >> 16, mem_mask>>16);
2663 sh2.m[4] = (sh2.m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & sh2.m[4] & (ICF|OCFA|OCFB|OVF));
2664 COMBINE_DATA(&sh2.frc);
2665 if((mem_mask & 0x00ffffff) != 0xffffff)
2666 sh2_timer_activate();
2667 sh2_recalc_irq();
2668 break;
2669 case 0x05: /* OCRx, TCR, TOCR*/
2670 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2.%d: TCR write %08x @ %08x\n", sh2.cpu_number, data, mem_mask);
2671 sh2_timer_resync();
2672 if(sh2.m[5] & 0x10)
2673 sh2.ocrb = (sh2.ocrb & (mem_mask >> 16)) | ((data & ~mem_mask) >> 16);
2674 else
2675 sh2.ocra = (sh2.ocra & (mem_mask >> 16)) | ((data & ~mem_mask) >> 16);
2676 sh2_timer_activate();
2677 break;
2678
2679 case 0x06: /* ICR*/
2680 break;
2681
2682 /* Interrupt vectors*/
2683 case 0x18: /* IPRB, VCRA*/
2684 case 0x19: /* VCRB, VCRC*/
2685 case 0x1a: /* VCRD*/
2686 sh2_recalc_irq();
2687 break;
2688
2689 /* DMA*/
2690 case 0x1c: /* DRCR0, DRCR1*/
2691 break;
2692
2693 /* Watchdog*/
2694 case 0x20: /* WTCNT, RSTCSR*/
2695 break;
2696
2697 /* Standby and cache*/
2698 case 0x24: /* SBYCR, CCR*/
2699 break;
2700
2701 /* Interrupt vectors cont.*/
2702 case 0x38: /* ICR, IRPA*/
2703 break;
2704 case 0x39: /* VCRWDT*/
2705 break;
2706
2707 /* Division box*/
2708 case 0x40: /* DVSR*/
2709 break;
2710 case 0x41: /* DVDNT*/
2711 {
2712 INT32 a = sh2.m[0x41];
2713 INT32 b = sh2.m[0x40];
2714 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %d/%d\n", cpu_getactivecpu(), a, b);
2715 if (b)
2716 {
2717 sh2.m[0x45] = a / b;
2718 sh2.m[0x44] = a % b;
2719 }
2720 else
2721 {
2722 sh2.m[0x42] |= 0x00010000;
2723 sh2.m[0x45] = 0x7fffffff;
2724 sh2.m[0x44] = 0x7fffffff;
2725 sh2_recalc_irq();
2726 }
2727 break;
2728 }
2729 case 0x42: /* DVCR*/
2730 sh2.m[0x42] = (sh2.m[0x42] & ~0x00001000) | (old & sh2.m[0x42] & 0x00010000);
2731 sh2_recalc_irq();
2732 break;
2733 case 0x43: /* VCRDIV*/
2734 sh2_recalc_irq();
2735 break;
2736 case 0x44: /* DVDNTH*/
2737 break;
2738 case 0x45: /* DVDNTL*/
2739 {
2740 INT64 a = sh2.m[0x45] | ((UINT64)(sh2.m[0x44]) << 32);
2741 INT64 b = sh2.m[0x40];
2742 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %lld/%lld\n", cpu_getactivecpu(), a, b);
2743 if (b)
2744 {
2745 INT64 q = a / b;
2746 if (q != (INT32)q)
2747 {
2748 sh2.m[0x42] |= 0x00010000;
2749 sh2.m[0x45] = 0x7fffffff;
2750 sh2.m[0x44] = 0x7fffffff;
2751 sh2_recalc_irq();
2752 }
2753 else
2754 {
2755 sh2.m[0x45] = q;
2756 sh2.m[0x44] = a % b;
2757 }
2758 }
2759 else
2760 {
2761 sh2.m[0x42] |= 0x00010000;
2762 sh2.m[0x45] = 0x7fffffff;
2763 sh2.m[0x44] = 0x7fffffff;
2764 sh2_recalc_irq();
2765 }
2766 break;
2767 }
2768
2769 /* DMA controller*/
2770 case 0x60: /* SAR0*/
2771 case 0x61: /* DAR0*/
2772 break;
2773 case 0x62: /* DTCR0*/
2774 sh2.m[0x62] &= 0xffffff;
2775 break;
2776 case 0x63: /* CHCR0*/
2777 sh2.m[0x63] = (sh2.m[0x63] & ~2) | (old & sh2.m[0x63] & 2);
2778 sh2_dmac_check(0);
2779 break;
2780 case 0x64: /* SAR1*/
2781 case 0x65: /* DAR1*/
2782 break;
2783 case 0x66: /* DTCR1*/
2784 sh2.m[0x66] &= 0xffffff;
2785 break;
2786 case 0x67: /* CHCR1*/
2787 sh2.m[0x67] = (sh2.m[0x67] & ~2) | (old & sh2.m[0x67] & 2);
2788 sh2_dmac_check(1);
2789 break;
2790 case 0x68: /* VCRDMA0*/
2791 case 0x6a: /* VCRDMA1*/
2792 sh2_recalc_irq();
2793 break;
2794 case 0x6c: /* DMAOR*/
2795 sh2.m[0x6c] = (sh2.m[0x6c] & ~6) | (old & sh2.m[0x6c] & 6);
2796 sh2_dmac_check(0);
2797 sh2_dmac_check(1);
2798 break;
2799
2800 /* Bus controller*/
2801 case 0x78: /* BCR1*/
2802 case 0x79: /* BCR2*/
2803 case 0x7a: /* WCR*/
2804 case 0x7b: /* MCR*/
2805 case 0x7c: /* RTCSR*/
2806 case 0x7d: /* RTCNT*/
2807 case 0x7e: /* RTCOR*/
2808 break;
2809
2810 default:
2811 log_cb(RETRO_LOG_DEBUG, LOGPRE "sh2_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfffffe00+offset*4, data, mem_mask);
2812 break;
2813 }
2814 }
2815
READ32_HANDLER(sh2_internal_r)2816 READ32_HANDLER( sh2_internal_r )
2817 {
2818 /* log_cb(RETRO_LOG_DEBUG, LOGPRE "sh2_internal_r: Read %08x (%x) @ %08x\n", 0xfffffe00+offset*4, offset, mem_mask);*/
2819 switch( offset )
2820 {
2821 case 0x04: /* TIER, FTCSR, FRC*/
2822 sh2_timer_resync();
2823 return (sh2.m[4] & 0xffff0000) | sh2.frc;
2824 case 0x05: /* OCRx, TCR, TOCR*/
2825 if(sh2.m[5] & 0x10)
2826 return (sh2.ocrb << 16) | (sh2.m[5] & 0xffff);
2827 else
2828 return (sh2.ocra << 16) | (sh2.m[5] & 0xffff);
2829 case 0x06: /* ICR*/
2830 return sh2.icr << 16;
2831
2832 case 0x38: /* ICR, IPRA*/
2833 return (sh2.m[0x38] & 0x7fffffff) | (sh2.nmi_line_state == ASSERT_LINE ? 0 : 0x80000000);
2834
2835 case 0x78: /* BCR1*/
2836 return sh2.is_slave ? 0x00008000 : 0;
2837
2838 case 0x41: /* dvdntl mirrors*/
2839 case 0x47:
2840 return sh2.m[0x45];
2841
2842 case 0x46: /* dvdnth mirror*/
2843 return sh2.m[0x44];
2844 }
2845 return sh2.m[offset];
2846 }
2847
sh2_set_frt_input(int cpunum,int state)2848 void sh2_set_frt_input(int cpunum, int state)
2849 {
2850 if(state == PULSE_LINE)
2851 {
2852 sh2_set_frt_input(cpunum, ASSERT_LINE);
2853 sh2_set_frt_input(cpunum, CLEAR_LINE);
2854 return;
2855 }
2856
2857 cpuintrf_push_context(cpunum);
2858
2859 if(sh2.frt_input == state) {
2860 cpuintrf_pop_context();
2861 return;
2862 }
2863
2864 sh2.frt_input = state;
2865
2866 if(sh2.m[5] & 0x8000) {
2867 if(state == CLEAR_LINE) {
2868 cpuintrf_pop_context();
2869 return;
2870 }
2871 } else {
2872 if(state == ASSERT_LINE) {
2873 cpuintrf_pop_context();
2874 return;
2875 }
2876 }
2877
2878 sh2_timer_resync();
2879 sh2.icr = sh2.frc;
2880 sh2.m[4] |= ICF;
2881 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2.%d: ICF activated (%x)\n", sh2.cpu_number, sh2.pc & AM);
2882 sh2_recalc_irq();
2883 cpuintrf_pop_context();
2884 }
2885
sh2_get_reg(int regnum)2886 unsigned sh2_get_reg(int regnum)
2887 {
2888 switch( regnum )
2889 {
2890 case REG_PREVIOUSPC:
2891 return sh2.ppc;
2892 case REG_PC:
2893 case SH2_PC:
2894 if (sh2.delay)
2895 return sh2.delay & AM;
2896 return sh2.pc & AM;
2897 case REG_SP: return sh2.r[15];
2898 case SH2_PR: return sh2.pr;
2899 case SH2_SR: return sh2.sr;
2900 case SH2_GBR: return sh2.gbr;
2901 case SH2_VBR: return sh2.vbr;
2902 case SH2_MACH: return sh2.mach;
2903 case SH2_MACL: return sh2.macl;
2904 case SH2_R0: return sh2.r[ 0];
2905 case SH2_R1: return sh2.r[ 1];
2906 case SH2_R2: return sh2.r[ 2];
2907 case SH2_R3: return sh2.r[ 3];
2908 case SH2_R4: return sh2.r[ 4];
2909 case SH2_R5: return sh2.r[ 5];
2910 case SH2_R6: return sh2.r[ 6];
2911 case SH2_R7: return sh2.r[ 7];
2912 case SH2_R8: return sh2.r[ 8];
2913 case SH2_R9: return sh2.r[ 9];
2914 case SH2_R10: return sh2.r[10];
2915 case SH2_R11: return sh2.r[11];
2916 case SH2_R12: return sh2.r[12];
2917 case SH2_R13: return sh2.r[13];
2918 case SH2_R14: return sh2.r[14];
2919 case SH2_R15: return sh2.r[15];
2920 case SH2_EA: return sh2.ea;
2921 }
2922 return 0;
2923 }
2924
sh2_set_reg(int regnum,unsigned val)2925 void sh2_set_reg (int regnum, unsigned val)
2926 {
2927 switch( regnum )
2928 {
2929 case SH2_PC:
2930 case REG_PC:
2931 sh2.pc = val;
2932 sh2.delay = 0;
2933 break;
2934 case REG_SP: sh2.r[15] = val; break;
2935 case SH2_PR: sh2.pr = val; break;
2936 case SH2_SR:
2937 sh2.sr = val;
2938 CHECK_PENDING_IRQ("sh2_set_reg");
2939 break;
2940 case SH2_GBR: sh2.gbr = val; break;
2941 case SH2_VBR: sh2.vbr = val; break;
2942 case SH2_MACH: sh2.mach = val; break;
2943 case SH2_MACL: sh2.macl = val; break;
2944 case SH2_R0: sh2.r[ 0] = val; break;
2945 case SH2_R1: sh2.r[ 1] = val; break;
2946 case SH2_R2: sh2.r[ 2] = val; break;
2947 case SH2_R3: sh2.r[ 3] = val; break;
2948 case SH2_R4: sh2.r[ 4] = val; break;
2949 case SH2_R5: sh2.r[ 5] = val; break;
2950 case SH2_R6: sh2.r[ 6] = val; break;
2951 case SH2_R7: sh2.r[ 7] = val; break;
2952 case SH2_R8: sh2.r[ 8] = val; break;
2953 case SH2_R9: sh2.r[ 9] = val; break;
2954 case SH2_R10: sh2.r[10] = val; break;
2955 case SH2_R11: sh2.r[11] = val; break;
2956 case SH2_R12: sh2.r[12] = val; break;
2957 case SH2_R13: sh2.r[13] = val; break;
2958 case SH2_R14: sh2.r[14] = val; break;
2959 case SH2_R15: sh2.r[15] = val; break;
2960 case SH2_EA: sh2.ea = val; break;
2961 }
2962 }
2963
sh2_set_irq_line(int irqline,int state)2964 void sh2_set_irq_line(int irqline, int state)
2965 {
2966 if (irqline == IRQ_LINE_NMI)
2967 {
2968 if (sh2.nmi_line_state == state)
2969 return;
2970 sh2.nmi_line_state = state;
2971
2972 if( state == CLEAR_LINE )
2973 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d cleared nmi\n", cpu_getactivecpu());
2974 else
2975 {
2976 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d assert nmi\n", cpu_getactivecpu());
2977 sh2_exception("sh2_set_irq_line/nmi", 16);
2978 }
2979 }
2980 else
2981 {
2982 if (sh2.irq_line_state[irqline] == state)
2983 return;
2984 sh2.irq_line_state[irqline] = state;
2985
2986 if( state == CLEAR_LINE )
2987 {
2988 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d cleared irq #%d\n", cpu_getactivecpu(), irqline);
2989 sh2.pending_irq &= ~(1 << irqline);
2990 }
2991 else
2992 {
2993 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH-2 #%d assert irq #%d\n", cpu_getactivecpu(), irqline);
2994 sh2.pending_irq |= 1 << irqline;
2995 if(sh2.delay)
2996 sh2.test_irq = 1;
2997 else
2998 CHECK_PENDING_IRQ("sh2_set_irq_line");
2999 }
3000 }
3001 }
3002
sh2_set_irq_callback(int (* callback)(int irqline))3003 void sh2_set_irq_callback(int (*callback)(int irqline))
3004 {
3005 sh2.irq_callback = callback;
3006 }
3007
sh2_info(void * context,int regnum)3008 const char *sh2_info(void *context, int regnum)
3009 {
3010 static char buffer[8][15+1];
3011 static int which = 0;
3012 SH2 *r = context;
3013
3014 which = (which + 1) % 8;
3015 buffer[which][0] = '\0';
3016 if( !context )
3017 r = &sh2;
3018
3019 switch( regnum )
3020 {
3021 case CPU_INFO_REG+SH2_PC: sprintf(buffer[which], "PC :%08X", r->pc); break;
3022 case CPU_INFO_REG+SH2_SR: sprintf(buffer[which], "SR :%08X", r->sr); break;
3023 case CPU_INFO_REG+SH2_PR: sprintf(buffer[which], "PR :%08X", r->pr); break;
3024 case CPU_INFO_REG+SH2_GBR: sprintf(buffer[which], "GBR :%08X", r->gbr); break;
3025 case CPU_INFO_REG+SH2_VBR: sprintf(buffer[which], "VBR :%08X", r->vbr); break;
3026 case CPU_INFO_REG+SH2_MACH:sprintf(buffer[which], "MACH:%08X", r->mach); break;
3027 case CPU_INFO_REG+SH2_MACL:sprintf(buffer[which], "MACL:%08X", r->macl); break;
3028 case CPU_INFO_REG+SH2_R0: sprintf(buffer[which], "R0 :%08X", r->r[ 0]); break;
3029 case CPU_INFO_REG+SH2_R1: sprintf(buffer[which], "R1 :%08X", r->r[ 1]); break;
3030 case CPU_INFO_REG+SH2_R2: sprintf(buffer[which], "R2 :%08X", r->r[ 2]); break;
3031 case CPU_INFO_REG+SH2_R3: sprintf(buffer[which], "R3 :%08X", r->r[ 3]); break;
3032 case CPU_INFO_REG+SH2_R4: sprintf(buffer[which], "R4 :%08X", r->r[ 4]); break;
3033 case CPU_INFO_REG+SH2_R5: sprintf(buffer[which], "R5 :%08X", r->r[ 5]); break;
3034 case CPU_INFO_REG+SH2_R6: sprintf(buffer[which], "R6 :%08X", r->r[ 6]); break;
3035 case CPU_INFO_REG+SH2_R7: sprintf(buffer[which], "R7 :%08X", r->r[ 7]); break;
3036 case CPU_INFO_REG+SH2_R8: sprintf(buffer[which], "R8 :%08X", r->r[ 8]); break;
3037 case CPU_INFO_REG+SH2_R9: sprintf(buffer[which], "R9 :%08X", r->r[ 9]); break;
3038 case CPU_INFO_REG+SH2_R10: sprintf(buffer[which], "R10 :%08X", r->r[10]); break;
3039 case CPU_INFO_REG+SH2_R11: sprintf(buffer[which], "R11 :%08X", r->r[11]); break;
3040 case CPU_INFO_REG+SH2_R12: sprintf(buffer[which], "R12 :%08X", r->r[12]); break;
3041 case CPU_INFO_REG+SH2_R13: sprintf(buffer[which], "R13 :%08X", r->r[13]); break;
3042 case CPU_INFO_REG+SH2_R14: sprintf(buffer[which], "R14 :%08X", r->r[14]); break;
3043 case CPU_INFO_REG+SH2_R15: sprintf(buffer[which], "R15 :%08X", r->r[15]); break;
3044 case CPU_INFO_REG+SH2_EA: sprintf(buffer[which], "EA :%08X", r->ea); break;
3045 case CPU_INFO_FLAGS:
3046 sprintf(buffer[which], "%c%c%d%c%c",
3047 r->sr & M ? 'M':'.',
3048 r->sr & Q ? 'Q':'.',
3049 (r->sr & I) >> 4,
3050 r->sr & S ? 'S':'.',
3051 r->sr & T ? 'T':'.');
3052 break;
3053 case CPU_INFO_NAME: return "SH-2";
3054 case CPU_INFO_FAMILY: return "Hitachi SH7600";
3055 case CPU_INFO_VERSION: return "1.01";
3056 case CPU_INFO_FILE: return __FILE__;
3057 case CPU_INFO_CREDITS: return "Copyright (c) 2000 Juergen Buchmueller, all rights reserved.";
3058 case CPU_INFO_REG_LAYOUT: return (const char*)sh2_reg_layout;
3059 case CPU_INFO_WIN_LAYOUT: return (const char*)sh2_win_layout;
3060 }
3061 return buffer[which];
3062 }
3063
sh2_dasm(char * buffer,unsigned pc)3064 unsigned sh2_dasm(char *buffer, unsigned pc)
3065 {
3066 #ifdef MAME_DEBUG
3067 return DasmSH2( buffer, pc );
3068 #else
3069 sprintf( buffer, "$%02X", cpu_readop(pc) );
3070 return 1;
3071 #endif
3072 }
3073
sh2_init(void)3074 void sh2_init(void)
3075 {
3076 int cpu = cpu_getactivecpu();
3077
3078 sh2.timer = timer_alloc(sh2_timer_callback);
3079 timer_adjust(sh2.timer, TIME_NEVER, 0, 0);
3080
3081 sh2.dma_timer[0] = timer_alloc(sh2_dmac_callback);
3082 timer_adjust(sh2.dma_timer[0], TIME_NEVER, 0, 0);
3083
3084 sh2.dma_timer[1] = timer_alloc(sh2_dmac_callback);
3085 timer_adjust(sh2.dma_timer[1], TIME_NEVER, 0, 0);
3086
3087 sh2.m = malloc(0x200);
3088 if (!sh2.m)
3089 {
3090 log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 failed to malloc FREGS\n");
3091 /*raise( SIGABRT );*/
3092 }
3093
3094 state_save_register_UINT32("sh2", cpu, "PC", &sh2.pc, 1);
3095 state_save_register_UINT32("sh2", cpu, "SP", &sh2.r[15], 1);
3096 state_save_register_UINT32("sh2", cpu, "SR", &sh2.sr, 1);
3097 state_save_register_UINT32("sh2", cpu, "PR", &sh2.pr, 1);
3098 state_save_register_UINT32("sh2", cpu, "GBR", &sh2.gbr, 1);
3099 state_save_register_UINT32("sh2", cpu, "VBR", &sh2.vbr, 1);
3100 state_save_register_UINT32("sh2", cpu, "MACH",&sh2.mach, 1);
3101 state_save_register_UINT32("sh2", cpu, "MACL",&sh2.macl, 1);
3102 state_save_register_UINT32("sh2", cpu, "R0", &sh2.r[ 0], 1);
3103 state_save_register_UINT32("sh2", cpu, "R1", &sh2.r[ 1], 1);
3104 state_save_register_UINT32("sh2", cpu, "R2", &sh2.r[ 2], 1);
3105 state_save_register_UINT32("sh2", cpu, "R3", &sh2.r[ 3], 1);
3106 state_save_register_UINT32("sh2", cpu, "R4", &sh2.r[ 4], 1);
3107 state_save_register_UINT32("sh2", cpu, "R5", &sh2.r[ 5], 1);
3108 state_save_register_UINT32("sh2", cpu, "R6", &sh2.r[ 6], 1);
3109 state_save_register_UINT32("sh2", cpu, "R7", &sh2.r[ 7], 1);
3110 state_save_register_UINT32("sh2", cpu, "R8", &sh2.r[ 8], 1);
3111 state_save_register_UINT32("sh2", cpu, "R9", &sh2.r[ 9], 1);
3112 state_save_register_UINT32("sh2", cpu, "R10", &sh2.r[10], 1);
3113 state_save_register_UINT32("sh2", cpu, "R11", &sh2.r[11], 1);
3114 state_save_register_UINT32("sh2", cpu, "R12", &sh2.r[12], 1);
3115 state_save_register_UINT32("sh2", cpu, "R13", &sh2.r[13], 1);
3116 state_save_register_UINT32("sh2", cpu, "R14", &sh2.r[14], 1);
3117 state_save_register_UINT32("sh2", cpu, "EA", &sh2.ea, 1);
3118 return;
3119 }
3120