mirror of
				https://github.com/RaySollium99/picodrive.git
				synced 2025-10-28 05:48:52 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			2173 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2173 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*****************************************************************************
 | |
|  *
 | |
|  *   sh2.c
 | |
|  *   Portable Hitachi SH-2 (SH7600 family) emulator
 | |
|  *
 | |
|  *   Copyright Juergen Buchmueller <pullmoll@t-online.de>,
 | |
|  *   all rights reserved.
 | |
|  *
 | |
|  *   - This source code is released as freeware for non-commercial purposes.
 | |
|  *   - You are free to use and redistribute this code in modified or
 | |
|  *     unmodified form, provided you list me in the credits.
 | |
|  *   - If you modify this source code, you must add a notice to each modified
 | |
|  *     source file that it has been changed.  If you're a nice person, you
 | |
|  *     will clearly mark each change too.  :)
 | |
|  *   - If you wish to use this for commercial purposes, please contact me at
 | |
|  *     pullmoll@t-online.de
 | |
|  *   - The author of this copywritten work reserves the right to change the
 | |
|  *     terms of its usage and license at any time, including retroactively
 | |
|  *   - This entire notice must remain in the source code.
 | |
|  *
 | |
|  *  This work is based on <tiraniddo@hotmail.com> C/C++ implementation of
 | |
|  *  the SH-2 CPU core and was adapted to the MAME CPU core requirements.
 | |
|  *  Thanks also go to Chuck Mason <chukjr@sundail.net> and Olivier Galibert
 | |
|  *  <galibert@pobox.com> for letting me peek into their SEMU code :-)
 | |
|  *
 | |
|  *****************************************************************************/
 | |
| 
 | |
| /*****************************************************************************
 | |
|     Changes
 | |
|     20130129 Angelo Salese
 | |
|     - added illegal opcode exception handling, side effect of some Saturn games
 | |
|       on loading like Feda or Falcom Classics Vol. 1
 | |
|       (i.e. Master CPU Incautiously transfers memory from CD to work RAM H, and
 | |
|             wipes out Slave CPU program code too while at it).
 | |
| 
 | |
|     20051129 Mariusz Wojcieszek
 | |
|     - introduced memory_decrypted_read_word() for opcode fetching
 | |
| 
 | |
|     20050813 Mariusz Wojcieszek
 | |
|     - fixed 64 bit / 32 bit division in division unit
 | |
| 
 | |
|     20031015 O. Galibert
 | |
|     - dma fixes, thanks to sthief
 | |
| 
 | |
|     20031013 O. Galibert, A. Giles
 | |
|     - timer fixes
 | |
|     - multi-cpu simplifications
 | |
| 
 | |
|     20030915 O. Galibert
 | |
|     - fix DMA1 irq vector
 | |
|     - ignore writes to DRCRx
 | |
|     - fix cpu number issues
 | |
|     - fix slave/master recognition
 | |
|     - fix wrong-cpu-in-context problem with the timers
 | |
| 
 | |
|     20021020 O. Galibert
 | |
|     - DMA implementation, lightly tested
 | |
|     - delay slot in debugger fixed
 | |
|     - add divide box mirrors
 | |
|     - Nicola-ify the indentation
 | |
|     - Uncrapify sh2_internal_*
 | |
|     - Put back nmi support that had been lost somehow
 | |
| 
 | |
|     20020914 R. Belmont
 | |
|     - Initial SH2 internal timers implementation, based on code by O. Galibert.
 | |
|       Makes music work in galspanic4/s/s2, panic street, cyvern, other SKNS games.
 | |
|     - Fix to external division, thanks to "spice" on the E2J board.
 | |
|       Corrects behavior of s1945ii turret boss.
 | |
| 
 | |
|     20020302 Olivier Galibert (galibert@mame.net)
 | |
|     - Fixed interrupt in delay slot
 | |
|     - Fixed rotcr
 | |
|     - Fixed div1
 | |
|     - Fixed mulu
 | |
|     - Fixed negc
 | |
| 
 | |
|     20020301 R. Belmont
 | |
|     - Fixed external division
 | |
| 
 | |
|     20020225 Olivier Galibert (galibert@mame.net)
 | |
|     - Fixed interrupt handling
 | |
| 
 | |
|     20010207 Sylvain Glaize (mokona@puupuu.org)
 | |
| 
 | |
|     - Bug fix in INLINE void MOVBM(UINT32 m, UINT32 n) (see comment)
 | |
|     - Support of full 32 bit addressing (RB, RW, RL and WB, WW, WL functions)
 | |
|         reason : when the two high bits of the address are set, access is
 | |
|         done directly in the cache data array. The SUPER KANEKO NOVA SYSTEM
 | |
|         sets the stack pointer here, using these addresses as usual RAM access.
 | |
| 
 | |
|         No real cache support has been added.
 | |
|     - Read/Write memory format correction (_bew to _bedw) (see also SH2
 | |
|         definition in cpuintrf.c and DasmSH2(..) in sh2dasm.c )
 | |
| 
 | |
|     20010623 James Forshaw (TyRaNiD@totalise.net)
 | |
| 
 | |
|     - Modified operation of sh2_exception. Done cause mame irq system is stupid, and
 | |
|       doesnt really seem designed for any more than 8 interrupt lines.
 | |
| 
 | |
|     20010701 James Forshaw (TyRaNiD@totalise.net)
 | |
| 
 | |
|     - Fixed DIV1 operation. Q bit now correctly generated
 | |
| 
 | |
|     20020218 Added save states (mokona@puupuu.org)
 | |
| 
 | |
|  *****************************************************************************/
 | |
| 
 | |
| //#include "debugger.h"
 | |
| //#include "sh2.h"
 | |
| //#include "sh2comn.h"
 | |
| #define INLINE static
 | |
| 
 | |
| //CPU_DISASSEMBLE( sh2 );
 | |
| 
 | |
| #ifndef USE_SH2DRC
 | |
| 
 | |
| /* speed up delay loops, bail out of tight loops */
 | |
| //#define BUSY_LOOP_HACKS 	1
 | |
| 
 | |
| #define VERBOSE 0
 | |
| 
 | |
| #define LOG(x)	do { if (VERBOSE) logerror x; } while (0)
 | |
| 
 | |
| #if 0
 | |
| INLINE UINT8 RB(sh2_state *sh2, offs_t A)
 | |
| {
 | |
| 	if (A >= 0xe0000000)
 | |
| 		return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xff << (((~A) & 3)*8)) >> (((~A) & 3)*8);
 | |
| 
 | |
| 	if (A >= 0xc0000000)
 | |
| 		return sh2->program->read_byte(A);
 | |
| 
 | |
| 	if (A >= 0x40000000)
 | |
| 		return 0xa5;
 | |
| 
 | |
| 	return sh2->program->read_byte(A & AM);
 | |
| }
 | |
| 
 | |
| INLINE UINT16 RW(sh2_state *sh2, offs_t A)
 | |
| {
 | |
| 	if (A >= 0xe0000000)
 | |
| 		return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8);
 | |
| 
 | |
| 	if (A >= 0xc0000000)
 | |
| 		return sh2->program->read_word(A);
 | |
| 
 | |
| 	if (A >= 0x40000000)
 | |
| 		return 0xa5a5;
 | |
| 
 | |
| 	return sh2->program->read_word(A & AM);
 | |
| }
 | |
| 
 | |
| INLINE UINT32 RL(sh2_state *sh2, offs_t A)
 | |
| {
 | |
| 	if (A >= 0xe0000000)
 | |
| 		return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffffffff);
 | |
| 
 | |
| 	if (A >= 0xc0000000)
 | |
| 		return sh2->program->read_dword(A);
 | |
| 
 | |
| 	if (A >= 0x40000000)
 | |
| 		return 0xa5a5a5a5;
 | |
| 
 | |
| 	return sh2->program->read_dword(A & AM);
 | |
| }
 | |
| 
 | |
| INLINE void WB(sh2_state *sh2, offs_t A, UINT8 V)
 | |
| {
 | |
| 	if (A >= 0xe0000000)
 | |
| 	{
 | |
| 		sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 3)*8), 0xff << (((~A) & 3)*8));
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (A >= 0xc0000000)
 | |
| 	{
 | |
| 		sh2->program->write_byte(A,V);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (A >= 0x40000000)
 | |
| 		return;
 | |
| 
 | |
| 	sh2->program->write_byte(A & AM,V);
 | |
| }
 | |
| 
 | |
| INLINE void WW(sh2_state *sh2, offs_t A, UINT16 V)
 | |
| {
 | |
| 	if (A >= 0xe0000000)
 | |
| 	{
 | |
| 		sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 2)*8), 0xffff << (((~A) & 2)*8));
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (A >= 0xc0000000)
 | |
| 	{
 | |
| 		sh2->program->write_word(A,V);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (A >= 0x40000000)
 | |
| 		return;
 | |
| 
 | |
| 	sh2->program->write_word(A & AM,V);
 | |
| }
 | |
| 
 | |
| INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V)
 | |
| {
 | |
| 	if (A >= 0xe0000000)
 | |
| 	{
 | |
| 		sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V, 0xffffffff);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (A >= 0xc0000000)
 | |
| 	{
 | |
| 		sh2->program->write_dword(A,V);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (A >= 0x40000000)
 | |
| 		return;
 | |
| 
 | |
| 	sh2->program->write_dword(A & AM,V);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 1100  1       -
 | |
|  *  ADD     Rm,Rn
 | |
|  */
 | |
| INLINE void ADD(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] += sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0111 nnnn iiii iiii  1       -
 | |
|  *  ADD     #imm,Rn
 | |
|  */
 | |
| INLINE void ADDI(sh2_state *sh2, UINT32 i, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] += (INT32)(INT16)(INT8)i;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 1110  1       carry
 | |
|  *  ADDC    Rm,Rn
 | |
|  */
 | |
| INLINE void ADDC(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 tmp0, tmp1;
 | |
| 
 | |
| 	tmp1 = sh2->r[n] + sh2->r[m];
 | |
| 	tmp0 = sh2->r[n];
 | |
| 	sh2->r[n] = tmp1 + (sh2->sr & T);
 | |
| 	if (tmp0 > tmp1)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| 	if (tmp1 > sh2->r[n])
 | |
| 		sh2->sr |= T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 1111  1       overflow
 | |
|  *  ADDV    Rm,Rn
 | |
|  */
 | |
| INLINE void ADDV(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	INT32 dest, src, ans;
 | |
| 
 | |
| 	if ((INT32) sh2->r[n] >= 0)
 | |
| 		dest = 0;
 | |
| 	else
 | |
| 		dest = 1;
 | |
| 	if ((INT32) sh2->r[m] >= 0)
 | |
| 		src = 0;
 | |
| 	else
 | |
| 		src = 1;
 | |
| 	src += dest;
 | |
| 	sh2->r[n] += sh2->r[m];
 | |
| 	if ((INT32) sh2->r[n] >= 0)
 | |
| 		ans = 0;
 | |
| 	else
 | |
| 		ans = 1;
 | |
| 	ans += dest;
 | |
| 	if (src == 0 || src == 2)
 | |
| 	{
 | |
| 		if (ans == 1)
 | |
| 			sh2->sr |= T;
 | |
| 		else
 | |
| 			sh2->sr &= ~T;
 | |
| 	}
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0010 nnnn mmmm 1001  1       -
 | |
|  *  AND     Rm,Rn
 | |
|  */
 | |
| INLINE void AND(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] &= sh2->r[m];
 | |
| }
 | |
| 
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1100 1001 iiii iiii  1       -
 | |
|  *  AND     #imm,R0
 | |
|  */
 | |
| INLINE void ANDI(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	sh2->r[0] &= i;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1100 1101 iiii iiii  1       -
 | |
|  *  AND.B   #imm,@(R0,GBR)
 | |
|  */
 | |
| INLINE void ANDM(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 
 | |
| 	sh2->ea = sh2->gbr + sh2->r[0];
 | |
| 	temp = i & RB( sh2, sh2->ea );
 | |
| 	WB( sh2, sh2->ea, temp );
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1000 1011 dddd dddd  3/1     -
 | |
|  *  BF      disp8
 | |
|  */
 | |
| INLINE void BF(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	if ((sh2->sr & T) == 0)
 | |
| 	{
 | |
| 		INT32 disp = ((INT32)d << 24) >> 24;
 | |
| 		sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
 | |
| 		sh2->icount -= 2;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1000 1111 dddd dddd  3/1     -
 | |
|  *  BFS     disp8
 | |
|  */
 | |
| INLINE void BFS(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc += 2;
 | |
| 
 | |
| 	if ((sh2->sr & T) == 0)
 | |
| 	{
 | |
| 		INT32 disp = ((INT32)d << 24) >> 24;
 | |
| 		sh2->pc = sh2->ea = sh2->pc + disp * 2;
 | |
| 		sh2->icount--;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1010 dddd dddd dddd  2       -
 | |
|  *  BRA     disp12
 | |
|  */
 | |
| INLINE void BRA(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	INT32 disp = ((INT32)d << 20) >> 20;
 | |
| 
 | |
| #if BUSY_LOOP_HACKS
 | |
| 	if (disp == -2)
 | |
| 	{
 | |
| 		UINT32 next_opcode = RW( sh2, sh2->ppc & AM );
 | |
| 		/* BRA  $
 | |
| 		 * NOP
 | |
| 		 */
 | |
| 		if (next_opcode == 0x0009)
 | |
| 			sh2->icount %= 3;   /* cycles for BRA $ and NOP taken (3) */
 | |
| 	}
 | |
| #endif
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0000 mmmm 0010 0011  2       -
 | |
|  *  BRAF    Rm
 | |
|  */
 | |
| INLINE void BRAF(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc += sh2->r[m] + 2;
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1011 dddd dddd dddd  2       -
 | |
|  *  BSR     disp12
 | |
|  */
 | |
| INLINE void BSR(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	INT32 disp = ((INT32)d << 20) >> 20;
 | |
| 
 | |
| 	sh2->pr = sh2->pc + 2;
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0000 mmmm 0000 0011  2       -
 | |
|  *  BSRF    Rm
 | |
|  */
 | |
| INLINE void BSRF(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->pr = sh2->pc + 2;
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc += sh2->r[m] + 2;
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1000 1001 dddd dddd  3/1     -
 | |
|  *  BT      disp8
 | |
|  */
 | |
| INLINE void BT(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	if ((sh2->sr & T) != 0)
 | |
| 	{
 | |
| 		INT32 disp = ((INT32)d << 24) >> 24;
 | |
| 		sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2;
 | |
| 		sh2->icount -= 2;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1000 1101 dddd dddd  2/1     -
 | |
|  *  BTS     disp8
 | |
|  */
 | |
| INLINE void BTS(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc += 2;
 | |
| 
 | |
| 	if ((sh2->sr & T) != 0)
 | |
| 	{
 | |
| 		INT32 disp = ((INT32)d << 24) >> 24;
 | |
| 		sh2->pc = sh2->ea = sh2->pc + disp * 2;
 | |
| 		sh2->icount--;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0000 0000 0010 1000  1       -
 | |
|  *  CLRMAC
 | |
|  */
 | |
| INLINE void CLRMAC(sh2_state *sh2)
 | |
| {
 | |
| 	sh2->mach = 0;
 | |
| 	sh2->macl = 0;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0000 0000 0000 1000  1       -
 | |
|  *  CLRT
 | |
|  */
 | |
| INLINE void CLRT(sh2_state *sh2)
 | |
| {
 | |
| 	sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 0000  1       comparison result
 | |
|  *  CMP_EQ  Rm,Rn
 | |
|  */
 | |
| INLINE void CMPEQ(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	if (sh2->r[n] == sh2->r[m])
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 0011  1       comparison result
 | |
|  *  CMP_GE  Rm,Rn
 | |
|  */
 | |
| INLINE void CMPGE(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	if ((INT32) sh2->r[n] >= (INT32) sh2->r[m])
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 0111  1       comparison result
 | |
|  *  CMP_GT  Rm,Rn
 | |
|  */
 | |
| INLINE void CMPGT(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	if ((INT32) sh2->r[n] > (INT32) sh2->r[m])
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 0110  1       comparison result
 | |
|  *  CMP_HI  Rm,Rn
 | |
|  */
 | |
| INLINE void CMPHI(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	if ((UINT32) sh2->r[n] > (UINT32) sh2->r[m])
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 0010  1       comparison result
 | |
|  *  CMP_HS  Rm,Rn
 | |
|  */
 | |
| INLINE void CMPHS(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	if ((UINT32) sh2->r[n] >= (UINT32) sh2->r[m])
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0100 nnnn 0001 0101  1       comparison result
 | |
|  *  CMP_PL  Rn
 | |
|  */
 | |
| INLINE void CMPPL(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	if ((INT32) sh2->r[n] > 0)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0100 nnnn 0001 0001  1       comparison result
 | |
|  *  CMP_PZ  Rn
 | |
|  */
 | |
| INLINE void CMPPZ(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	if ((INT32) sh2->r[n] >= 0)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0010 nnnn mmmm 1100  1       comparison result
 | |
|  * CMP_STR  Rm,Rn
 | |
|  */
 | |
| INLINE void CMPSTR(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| 	{
 | |
| 	UINT32 temp;
 | |
| 	INT32 HH, HL, LH, LL;
 | |
| 	temp = sh2->r[n] ^ sh2->r[m];
 | |
| 	HH = (temp >> 24) & 0xff;
 | |
| 	HL = (temp >> 16) & 0xff;
 | |
| 	LH = (temp >> 8) & 0xff;
 | |
| 	LL = temp & 0xff;
 | |
| 	if (HH && HL && LH && LL)
 | |
| 	sh2->sr &= ~T;
 | |
| 	else
 | |
| 	sh2->sr |= T;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  1000 1000 iiii iiii  1       comparison result
 | |
|  *  CMP/EQ #imm,R0
 | |
|  */
 | |
| INLINE void CMPIM(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i;
 | |
| 
 | |
| 	if (sh2->r[0] == imm)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0010 nnnn mmmm 0111  1       calculation result
 | |
|  *  DIV0S   Rm,Rn
 | |
|  */
 | |
| INLINE void DIV0S(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	if ((sh2->r[n] & 0x80000000) == 0)
 | |
| 		sh2->sr &= ~Q;
 | |
| 	else
 | |
| 		sh2->sr |= Q;
 | |
| 	if ((sh2->r[m] & 0x80000000) == 0)
 | |
| 		sh2->sr &= ~M;
 | |
| 	else
 | |
| 		sh2->sr |= M;
 | |
| 	if ((sh2->r[m] ^ sh2->r[n]) & 0x80000000)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0000 0000 0001 1001  1       0
 | |
|  *  DIV0U
 | |
|  */
 | |
| INLINE void DIV0U(sh2_state *sh2)
 | |
| {
 | |
| 	sh2->sr &= ~(M | Q | T);
 | |
| }
 | |
| 
 | |
| /*  code                 cycles  t-bit
 | |
|  *  0011 nnnn mmmm 0100  1       calculation result
 | |
|  *  DIV1 Rm,Rn
 | |
|  */
 | |
| INLINE void DIV1(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 tmp0;
 | |
| 	UINT32 old_q;
 | |
| 
 | |
| 	old_q = sh2->sr & Q;
 | |
| 	if (0x80000000 & sh2->r[n])
 | |
| 		sh2->sr |= Q;
 | |
| 	else
 | |
| 		sh2->sr &= ~Q;
 | |
| 
 | |
| 	sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T);
 | |
| 
 | |
| 	if (!old_q)
 | |
| 	{
 | |
| 		if (!(sh2->sr & M))
 | |
| 		{
 | |
| 			tmp0 = sh2->r[n];
 | |
| 			sh2->r[n] -= sh2->r[m];
 | |
| 			if(!(sh2->sr & Q))
 | |
| 				if(sh2->r[n] > tmp0)
 | |
| 					sh2->sr |= Q;
 | |
| 				else
 | |
| 					sh2->sr &= ~Q;
 | |
| 			else
 | |
| 				if(sh2->r[n] > tmp0)
 | |
| 					sh2->sr &= ~Q;
 | |
| 				else
 | |
| 					sh2->sr |= Q;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			tmp0 = sh2->r[n];
 | |
| 			sh2->r[n] += sh2->r[m];
 | |
| 			if(!(sh2->sr & Q))
 | |
| 			{
 | |
| 				if(sh2->r[n] < tmp0)
 | |
| 					sh2->sr &= ~Q;
 | |
| 				else
 | |
| 					sh2->sr |= Q;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				if(sh2->r[n] < tmp0)
 | |
| 					sh2->sr |= Q;
 | |
| 				else
 | |
| 					sh2->sr &= ~Q;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		if (!(sh2->sr & M))
 | |
| 		{
 | |
| 			tmp0 = sh2->r[n];
 | |
| 			sh2->r[n] += sh2->r[m];
 | |
| 			if(!(sh2->sr & Q))
 | |
| 				if(sh2->r[n] < tmp0)
 | |
| 					sh2->sr |= Q;
 | |
| 				else
 | |
| 					sh2->sr &= ~Q;
 | |
| 			else
 | |
| 				if(sh2->r[n] < tmp0)
 | |
| 					sh2->sr &= ~Q;
 | |
| 				else
 | |
| 					sh2->sr |= Q;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			tmp0 = sh2->r[n];
 | |
| 			sh2->r[n] -= sh2->r[m];
 | |
| 			if(!(sh2->sr & Q))
 | |
| 				if(sh2->r[n] > tmp0)
 | |
| 					sh2->sr &= ~Q;
 | |
| 				else
 | |
| 					sh2->sr |= Q;
 | |
| 			else
 | |
| 				if(sh2->r[n] > tmp0)
 | |
| 					sh2->sr |= Q;
 | |
| 				else
 | |
| 					sh2->sr &= ~Q;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	tmp0 = (sh2->sr & (Q | M));
 | |
| 	if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  DMULS.L Rm,Rn */
 | |
| INLINE void DMULS(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
 | |
| 	UINT32 temp0, temp1, temp2, temp3;
 | |
| 	INT32 tempm, tempn, fnLmL;
 | |
| 
 | |
| 	tempn = (INT32) sh2->r[n];
 | |
| 	tempm = (INT32) sh2->r[m];
 | |
| 	if (tempn < 0)
 | |
| 		tempn = 0 - tempn;
 | |
| 	if (tempm < 0)
 | |
| 		tempm = 0 - tempm;
 | |
| 	if ((INT32) (sh2->r[n] ^ sh2->r[m]) < 0)
 | |
| 		fnLmL = -1;
 | |
| 	else
 | |
| 		fnLmL = 0;
 | |
| 	temp1 = (UINT32) tempn;
 | |
| 	temp2 = (UINT32) tempm;
 | |
| 	RnL = temp1 & 0x0000ffff;
 | |
| 	RnH = (temp1 >> 16) & 0x0000ffff;
 | |
| 	RmL = temp2 & 0x0000ffff;
 | |
| 	RmH = (temp2 >> 16) & 0x0000ffff;
 | |
| 	temp0 = RmL * RnL;
 | |
| 	temp1 = RmH * RnL;
 | |
| 	temp2 = RmL * RnH;
 | |
| 	temp3 = RmH * RnH;
 | |
| 	Res2 = 0;
 | |
| 	Res1 = temp1 + temp2;
 | |
| 	if (Res1 < temp1)
 | |
| 		Res2 += 0x00010000;
 | |
| 	temp1 = (Res1 << 16) & 0xffff0000;
 | |
| 	Res0 = temp0 + temp1;
 | |
| 	if (Res0 < temp0)
 | |
| 		Res2++;
 | |
| 	Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
 | |
| 	if (fnLmL < 0)
 | |
| 	{
 | |
| 		Res2 = ~Res2;
 | |
| 		if (Res0 == 0)
 | |
| 			Res2++;
 | |
| 		else
 | |
| 			Res0 = (~Res0) + 1;
 | |
| 	}
 | |
| 	sh2->mach = Res2;
 | |
| 	sh2->macl = Res0;
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  DMULU.L Rm,Rn */
 | |
| INLINE void DMULU(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
 | |
| 	UINT32 temp0, temp1, temp2, temp3;
 | |
| 
 | |
| 	RnL = sh2->r[n] & 0x0000ffff;
 | |
| 	RnH = (sh2->r[n] >> 16) & 0x0000ffff;
 | |
| 	RmL = sh2->r[m] & 0x0000ffff;
 | |
| 	RmH = (sh2->r[m] >> 16) & 0x0000ffff;
 | |
| 	temp0 = RmL * RnL;
 | |
| 	temp1 = RmH * RnL;
 | |
| 	temp2 = RmL * RnH;
 | |
| 	temp3 = RmH * RnH;
 | |
| 	Res2 = 0;
 | |
| 	Res1 = temp1 + temp2;
 | |
| 	if (Res1 < temp1)
 | |
| 		Res2 += 0x00010000;
 | |
| 	temp1 = (Res1 << 16) & 0xffff0000;
 | |
| 	Res0 = temp0 + temp1;
 | |
| 	if (Res0 < temp0)
 | |
| 		Res2++;
 | |
| 	Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
 | |
| 	sh2->mach = Res2;
 | |
| 	sh2->macl = Res0;
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  DT      Rn */
 | |
| INLINE void DT(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n]--;
 | |
| 	if (sh2->r[n] == 0)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| #if BUSY_LOOP_HACKS
 | |
| 	{
 | |
| 		UINT32 next_opcode = RW( sh2, sh2->ppc & AM );
 | |
| 		/* DT   Rn
 | |
| 		 * BF   $-2
 | |
| 		 */
 | |
| 		if (next_opcode == 0x8bfd)
 | |
| 		{
 | |
| 			while (sh2->r[n] > 1 && sh2->icount > 4)
 | |
| 			{
 | |
| 				sh2->r[n]--;
 | |
| 				sh2->icount -= 4;   /* cycles for DT (1) and BF taken (3) */
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*  EXTS.B  Rm,Rn */
 | |
| INLINE void EXTSB(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = ((INT32)sh2->r[m] << 24) >> 24;
 | |
| }
 | |
| 
 | |
| /*  EXTS.W  Rm,Rn */
 | |
| INLINE void EXTSW(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = ((INT32)sh2->r[m] << 16) >> 16;
 | |
| }
 | |
| 
 | |
| /*  EXTU.B  Rm,Rn */
 | |
| INLINE void EXTUB(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->r[m] & 0x000000ff;
 | |
| }
 | |
| 
 | |
| /*  EXTU.W  Rm,Rn */
 | |
| INLINE void EXTUW(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->r[m] & 0x0000ffff;
 | |
| }
 | |
| 
 | |
| /*  ILLEGAL */
 | |
| INLINE void ILLEGAL(sh2_state *sh2)
 | |
| {
 | |
| 	logerror("SH2: Illegal opcode at %08x\n", sh2->pc - 2);
 | |
| 	sh2->r[15] -= 4;
 | |
| 	WL( sh2, sh2->r[15], sh2->sr );     /* push SR onto stack */
 | |
| 	sh2->r[15] -= 4;
 | |
| 	WL( sh2, sh2->r[15], sh2->pc - 2 ); /* push PC onto stack */
 | |
| 
 | |
| 	/* fetch PC */
 | |
| 	sh2->pc = RL( sh2, sh2->vbr + 4 * 4 );
 | |
| 
 | |
| 	/* TODO: timing is a guess */
 | |
| 	sh2->icount -= 5;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*  JMP     @Rm */
 | |
| INLINE void JMP(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc = sh2->ea = sh2->r[m];
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  JSR     @Rm */
 | |
| INLINE void JSR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pr = sh2->pc + 2;
 | |
| 	sh2->pc = sh2->ea = sh2->r[m];
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*  LDC     Rm,SR */
 | |
| INLINE void LDCSR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->sr = sh2->r[m] & FLAGS;
 | |
| 	sh2->test_irq = 1;
 | |
| }
 | |
| 
 | |
| /*  LDC     Rm,GBR */
 | |
| INLINE void LDCGBR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->gbr = sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  LDC     Rm,VBR */
 | |
| INLINE void LDCVBR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->vbr = sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  LDC.L   @Rm+,SR */
 | |
| INLINE void LDCMSR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->sr = RL( sh2, sh2->ea ) & FLAGS;
 | |
| 	sh2->r[m] += 4;
 | |
| 	sh2->icount -= 2;
 | |
| 	sh2->test_irq = 1;
 | |
| }
 | |
| 
 | |
| /*  LDC.L   @Rm+,GBR */
 | |
| INLINE void LDCMGBR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->gbr = RL( sh2, sh2->ea );
 | |
| 	sh2->r[m] += 4;
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  LDC.L   @Rm+,VBR */
 | |
| INLINE void LDCMVBR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->vbr = RL( sh2, sh2->ea );
 | |
| 	sh2->r[m] += 4;
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  LDS     Rm,MACH */
 | |
| INLINE void LDSMACH(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->mach = sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  LDS     Rm,MACL */
 | |
| INLINE void LDSMACL(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->macl = sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  LDS     Rm,PR */
 | |
| INLINE void LDSPR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->pr = sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  LDS.L   @Rm+,MACH */
 | |
| INLINE void LDSMMACH(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->mach = RL( sh2, sh2->ea );
 | |
| 	sh2->r[m] += 4;
 | |
| }
 | |
| 
 | |
| /*  LDS.L   @Rm+,MACL */
 | |
| INLINE void LDSMMACL(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->macl = RL( sh2, sh2->ea );
 | |
| 	sh2->r[m] += 4;
 | |
| }
 | |
| 
 | |
| /*  LDS.L   @Rm+,PR */
 | |
| INLINE void LDSMPR(sh2_state *sh2, UINT32 m)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->pr = RL( sh2, sh2->ea );
 | |
| 	sh2->r[m] += 4;
 | |
| }
 | |
| 
 | |
| /*  MAC.L   @Rm+,@Rn+ */
 | |
| INLINE void MAC_L(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
 | |
| 	UINT32 temp0, temp1, temp2, temp3;
 | |
| 	INT32 tempm, tempn, fnLmL;
 | |
| 
 | |
| 	tempn = (INT32) RL( sh2, sh2->r[n] );
 | |
| 	sh2->r[n] += 4;
 | |
| 	tempm = (INT32) RL( sh2, sh2->r[m] );
 | |
| 	sh2->r[m] += 4;
 | |
| 	if ((INT32) (tempn ^ tempm) < 0)
 | |
| 		fnLmL = -1;
 | |
| 	else
 | |
| 		fnLmL = 0;
 | |
| 	if (tempn < 0)
 | |
| 		tempn = 0 - tempn;
 | |
| 	if (tempm < 0)
 | |
| 		tempm = 0 - tempm;
 | |
| 	temp1 = (UINT32) tempn;
 | |
| 	temp2 = (UINT32) tempm;
 | |
| 	RnL = temp1 & 0x0000ffff;
 | |
| 	RnH = (temp1 >> 16) & 0x0000ffff;
 | |
| 	RmL = temp2 & 0x0000ffff;
 | |
| 	RmH = (temp2 >> 16) & 0x0000ffff;
 | |
| 	temp0 = RmL * RnL;
 | |
| 	temp1 = RmH * RnL;
 | |
| 	temp2 = RmL * RnH;
 | |
| 	temp3 = RmH * RnH;
 | |
| 	Res2 = 0;
 | |
| 	Res1 = temp1 + temp2;
 | |
| 	if (Res1 < temp1)
 | |
| 		Res2 += 0x00010000;
 | |
| 	temp1 = (Res1 << 16) & 0xffff0000;
 | |
| 	Res0 = temp0 + temp1;
 | |
| 	if (Res0 < temp0)
 | |
| 		Res2++;
 | |
| 	Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
 | |
| 	if (fnLmL < 0)
 | |
| 	{
 | |
| 		Res2 = ~Res2;
 | |
| 		if (Res0 == 0)
 | |
| 			Res2++;
 | |
| 		else
 | |
| 			Res0 = (~Res0) + 1;
 | |
| 	}
 | |
| 	if (sh2->sr & S)
 | |
| 	{
 | |
| 		Res0 = sh2->macl + Res0;
 | |
| 		if (sh2->macl > Res0)
 | |
| 			Res2++;
 | |
| 		Res2 += (sh2->mach & 0x0000ffff);
 | |
| 		if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
 | |
| 		{
 | |
| 			Res2 = 0x00008000;
 | |
| 			Res0 = 0x00000000;
 | |
| 		}
 | |
| 		else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
 | |
| 		{
 | |
| 			Res2 = 0x00007fff;
 | |
| 			Res0 = 0xffffffff;
 | |
| 		}
 | |
| 		sh2->mach = Res2;
 | |
| 		sh2->macl = Res0;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		Res0 = sh2->macl + Res0;
 | |
| 		if (sh2->macl > Res0)
 | |
| 			Res2++;
 | |
| 		Res2 += sh2->mach;
 | |
| 		sh2->mach = Res2;
 | |
| 		sh2->macl = Res0;
 | |
| 	}
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  MAC.W   @Rm+,@Rn+ */
 | |
| INLINE void MAC_W(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	INT32 tempm, tempn, dest, src, ans;
 | |
| 	UINT32 templ;
 | |
| 
 | |
| 	tempn = (INT32) RW( sh2, sh2->r[n] );
 | |
| 	sh2->r[n] += 2;
 | |
| 	tempm = (INT32) RW( sh2, sh2->r[m] );
 | |
| 	sh2->r[m] += 2;
 | |
| 	templ = sh2->macl;
 | |
| 	tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
 | |
| 	if ((INT32) sh2->macl >= 0)
 | |
| 		dest = 0;
 | |
| 	else
 | |
| 		dest = 1;
 | |
| 	if ((INT32) tempm >= 0)
 | |
| 	{
 | |
| 		src = 0;
 | |
| 		tempn = 0;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		src = 1;
 | |
| 		tempn = 0xffffffff;
 | |
| 	}
 | |
| 	src += dest;
 | |
| 	sh2->macl += tempm;
 | |
| 	if ((INT32) sh2->macl >= 0)
 | |
| 		ans = 0;
 | |
| 	else
 | |
| 		ans = 1;
 | |
| 	ans += dest;
 | |
| 	if (sh2->sr & S)
 | |
| 	{
 | |
| 		if (ans == 1)
 | |
| 			{
 | |
| 				if (src == 0)
 | |
| 					sh2->macl = 0x7fffffff;
 | |
| 				if (src == 2)
 | |
| 					sh2->macl = 0x80000000;
 | |
| 			}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		sh2->mach += tempn;
 | |
| 		if (templ > sh2->macl)
 | |
| 			sh2->mach += 1;
 | |
| 	}
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  MOV     Rm,Rn */
 | |
| INLINE void MOV(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  MOV.B   Rm,@Rn */
 | |
| INLINE void MOVBS(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff);
 | |
| }
 | |
| 
 | |
| /*  MOV.W   Rm,@Rn */
 | |
| INLINE void MOVWS(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff);
 | |
| }
 | |
| 
 | |
| /*  MOV.L   Rm,@Rn */
 | |
| INLINE void MOVLS(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WL( sh2, sh2->ea, sh2->r[m] );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   @Rm,Rn */
 | |
| INLINE void MOVBL(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   @Rm,Rn */
 | |
| INLINE void MOVWL(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   @Rm,Rn */
 | |
| INLINE void MOVLL(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m];
 | |
| 	sh2->r[n] = RL( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   Rm,@-Rn */
 | |
| INLINE void MOVBM(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	/* SMG : bug fix, was reading sh2->r[n] */
 | |
| 	UINT32 data = sh2->r[m] & 0x000000ff;
 | |
| 
 | |
| 	sh2->r[n] -= 1;
 | |
| 	WB( sh2, sh2->r[n], data );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   Rm,@-Rn */
 | |
| INLINE void MOVWM(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 data = sh2->r[m] & 0x0000ffff;
 | |
| 
 | |
| 	sh2->r[n] -= 2;
 | |
| 	WW( sh2, sh2->r[n], data );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   Rm,@-Rn */
 | |
| INLINE void MOVLM(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 data = sh2->r[m];
 | |
| 
 | |
| 	sh2->r[n] -= 4;
 | |
| 	WL( sh2, sh2->r[n], data );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   @Rm+,Rn */
 | |
| INLINE void MOVBP(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->r[m] );
 | |
| 	if (n != m)
 | |
| 		sh2->r[m] += 1;
 | |
| }
 | |
| 
 | |
| /*  MOV.W   @Rm+,Rn */
 | |
| INLINE void MOVWP(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->r[m] );
 | |
| 	if (n != m)
 | |
| 		sh2->r[m] += 2;
 | |
| }
 | |
| 
 | |
| /*  MOV.L   @Rm+,Rn */
 | |
| INLINE void MOVLP(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = RL( sh2, sh2->r[m] );
 | |
| 	if (n != m)
 | |
| 		sh2->r[m] += 4;
 | |
| }
 | |
| 
 | |
| /*  MOV.B   Rm,@(R0,Rn) */
 | |
| INLINE void MOVBS0(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[n] + sh2->r[0];
 | |
| 	WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   Rm,@(R0,Rn) */
 | |
| INLINE void MOVWS0(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[n] + sh2->r[0];
 | |
| 	WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   Rm,@(R0,Rn) */
 | |
| INLINE void MOVLS0(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[n] + sh2->r[0];
 | |
| 	WL( sh2, sh2->ea, sh2->r[m] );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   @(R0,Rm),Rn */
 | |
| INLINE void MOVBL0(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m] + sh2->r[0];
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   @(R0,Rm),Rn */
 | |
| INLINE void MOVWL0(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m] + sh2->r[0];
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   @(R0,Rm),Rn */
 | |
| INLINE void MOVLL0(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->ea = sh2->r[m] + sh2->r[0];
 | |
| 	sh2->r[n] = RL( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV     #imm,Rn */
 | |
| INLINE void MOVI(sh2_state *sh2, UINT32 i, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) i;
 | |
| }
 | |
| 
 | |
| /*  MOV.W   @(disp8,PC),Rn */
 | |
| INLINE void MOVWI(sh2_state *sh2, UINT32 d, UINT32 n)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = sh2->pc + disp * 2 + 2;
 | |
| 	sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   @(disp8,PC),Rn */
 | |
| INLINE void MOVLI(sh2_state *sh2, UINT32 d, UINT32 n)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4;
 | |
| 	sh2->r[n] = RL( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   @(disp8,GBR),R0 */
 | |
| INLINE void MOVBLG(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = sh2->gbr + disp;
 | |
| 	sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   @(disp8,GBR),R0 */
 | |
| INLINE void MOVWLG(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = sh2->gbr + disp * 2;
 | |
| 	sh2->r[0] = (INT32)(INT16) RW( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   @(disp8,GBR),R0 */
 | |
| INLINE void MOVLLG(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = sh2->gbr + disp * 4;
 | |
| 	sh2->r[0] = RL( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   R0,@(disp8,GBR) */
 | |
| INLINE void MOVBSG(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = sh2->gbr + disp;
 | |
| 	WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   R0,@(disp8,GBR) */
 | |
| INLINE void MOVWSG(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = sh2->gbr + disp * 2;
 | |
| 	WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   R0,@(disp8,GBR) */
 | |
| INLINE void MOVLSG(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = sh2->gbr + disp * 4;
 | |
| 	WL( sh2, sh2->ea, sh2->r[0] );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   R0,@(disp4,Rn) */
 | |
| INLINE void MOVBS4(sh2_state *sh2, UINT32 d, UINT32 n)
 | |
| {
 | |
| 	UINT32 disp = d & 0x0f;
 | |
| 	sh2->ea = sh2->r[n] + disp;
 | |
| 	WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   R0,@(disp4,Rn) */
 | |
| INLINE void MOVWS4(sh2_state *sh2, UINT32 d, UINT32 n)
 | |
| {
 | |
| 	UINT32 disp = d & 0x0f;
 | |
| 	sh2->ea = sh2->r[n] + disp * 2;
 | |
| 	WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff );
 | |
| }
 | |
| 
 | |
| /* MOV.L Rm,@(disp4,Rn) */
 | |
| INLINE void MOVLS4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n)
 | |
| {
 | |
| 	UINT32 disp = d & 0x0f;
 | |
| 	sh2->ea = sh2->r[n] + disp * 4;
 | |
| 	WL( sh2, sh2->ea, sh2->r[m] );
 | |
| }
 | |
| 
 | |
| /*  MOV.B   @(disp4,Rm),R0 */
 | |
| INLINE void MOVBL4(sh2_state *sh2, UINT32 m, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0x0f;
 | |
| 	sh2->ea = sh2->r[m] + disp;
 | |
| 	sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.W   @(disp4,Rm),R0 */
 | |
| INLINE void MOVWL4(sh2_state *sh2, UINT32 m, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0x0f;
 | |
| 	sh2->ea = sh2->r[m] + disp * 2;
 | |
| 	sh2->r[0] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOV.L   @(disp4,Rm),Rn */
 | |
| INLINE void MOVLL4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n)
 | |
| {
 | |
| 	UINT32 disp = d & 0x0f;
 | |
| 	sh2->ea = sh2->r[m] + disp * 4;
 | |
| 	sh2->r[n] = RL( sh2, sh2->ea );
 | |
| }
 | |
| 
 | |
| /*  MOVA    @(disp8,PC),R0 */
 | |
| INLINE void MOVA(sh2_state *sh2, UINT32 d)
 | |
| {
 | |
| 	UINT32 disp = d & 0xff;
 | |
| 	sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4;
 | |
| 	sh2->r[0] = sh2->ea;
 | |
| }
 | |
| 
 | |
| /*  MOVT    Rn */
 | |
| INLINE void MOVT(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->sr & T;
 | |
| }
 | |
| 
 | |
| /*  MUL.L   Rm,Rn */
 | |
| INLINE void MULL(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->macl = sh2->r[n] * sh2->r[m];
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  MULS    Rm,Rn */
 | |
| INLINE void MULS(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->macl = (INT16) sh2->r[n] * (INT16) sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  MULU    Rm,Rn */
 | |
| INLINE void MULU(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->macl = (UINT16) sh2->r[n] * (UINT16) sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  NEG     Rm,Rn */
 | |
| INLINE void NEG(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = 0 - sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  NEGC    Rm,Rn */
 | |
| INLINE void NEGC(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 
 | |
| 	temp = sh2->r[m];
 | |
| 	sh2->r[n] = -temp - (sh2->sr & T);
 | |
| 	if (temp || (sh2->sr & T))
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  NOP */
 | |
| INLINE void NOP(void)
 | |
| {
 | |
| }
 | |
| 
 | |
| /*  NOT     Rm,Rn */
 | |
| INLINE void NOT(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = ~sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  OR      Rm,Rn */
 | |
| INLINE void OR(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] |= sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  OR      #imm,R0 */
 | |
| INLINE void ORI(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	sh2->r[0] |= i;
 | |
| }
 | |
| 
 | |
| /*  OR.B    #imm,@(R0,GBR) */
 | |
| INLINE void ORM(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 
 | |
| 	sh2->ea = sh2->gbr + sh2->r[0];
 | |
| 	temp = RB( sh2, sh2->ea );
 | |
| 	temp |= i;
 | |
| 	WB( sh2, sh2->ea, temp );
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  ROTCL   Rn */
 | |
| INLINE void ROTCL(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 
 | |
| 	temp = (sh2->r[n] >> 31) & T;
 | |
| 	sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T);
 | |
| 	sh2->sr = (sh2->sr & ~T) | temp;
 | |
| }
 | |
| 
 | |
| /*  ROTCR   Rn */
 | |
| INLINE void ROTCR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 	temp = (sh2->sr & T) << 31;
 | |
| 	if (sh2->r[n] & T)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| 	sh2->r[n] = (sh2->r[n] >> 1) | temp;
 | |
| }
 | |
| 
 | |
| /*  ROTL    Rn */
 | |
| INLINE void ROTL(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T);
 | |
| 	sh2->r[n] = (sh2->r[n] << 1) | (sh2->r[n] >> 31);
 | |
| }
 | |
| 
 | |
| /*  ROTR    Rn */
 | |
| INLINE void ROTR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T);
 | |
| 	sh2->r[n] = (sh2->r[n] >> 1) | (sh2->r[n] << 31);
 | |
| }
 | |
| 
 | |
| /*  RTE */
 | |
| INLINE void RTE(sh2_state *sh2)
 | |
| {
 | |
| 	sh2->ea = sh2->r[15];
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc = RL( sh2, sh2->ea );
 | |
| 	sh2->r[15] += 4;
 | |
| 	sh2->ea = sh2->r[15];
 | |
| 	sh2->sr = RL( sh2, sh2->ea ) & FLAGS;
 | |
| 	sh2->r[15] += 4;
 | |
| 	sh2->icount -= 3;
 | |
| 	sh2->test_irq = 1;
 | |
| }
 | |
| 
 | |
| /*  RTS */
 | |
| INLINE void RTS(sh2_state *sh2)
 | |
| {
 | |
| 	sh2->delay = sh2->pc;
 | |
| 	sh2->pc = sh2->ea = sh2->pr;
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  SETT */
 | |
| INLINE void SETT(sh2_state *sh2)
 | |
| {
 | |
| 	sh2->sr |= T;
 | |
| }
 | |
| 
 | |
| /*  SHAL    Rn      (same as SHLL) */
 | |
| INLINE void SHAL(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T);
 | |
| 	sh2->r[n] <<= 1;
 | |
| }
 | |
| 
 | |
| /*  SHAR    Rn */
 | |
| INLINE void SHAR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T);
 | |
| 	sh2->r[n] = (UINT32)((INT32)sh2->r[n] >> 1);
 | |
| }
 | |
| 
 | |
| /*  SHLL    Rn      (same as SHAL) */
 | |
| INLINE void SHLL(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T);
 | |
| 	sh2->r[n] <<= 1;
 | |
| }
 | |
| 
 | |
| /*  SHLL2   Rn */
 | |
| INLINE void SHLL2(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] <<= 2;
 | |
| }
 | |
| 
 | |
| /*  SHLL8   Rn */
 | |
| INLINE void SHLL8(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] <<= 8;
 | |
| }
 | |
| 
 | |
| /*  SHLL16  Rn */
 | |
| INLINE void SHLL16(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] <<= 16;
 | |
| }
 | |
| 
 | |
| /*  SHLR    Rn */
 | |
| INLINE void SHLR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T);
 | |
| 	sh2->r[n] >>= 1;
 | |
| }
 | |
| 
 | |
| /*  SHLR2   Rn */
 | |
| INLINE void SHLR2(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] >>= 2;
 | |
| }
 | |
| 
 | |
| /*  SHLR8   Rn */
 | |
| INLINE void SHLR8(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] >>= 8;
 | |
| }
 | |
| 
 | |
| /*  SHLR16  Rn */
 | |
| INLINE void SHLR16(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] >>= 16;
 | |
| }
 | |
| 
 | |
| /*  SLEEP */
 | |
| INLINE void SLEEP(sh2_state *sh2)
 | |
| {
 | |
| 	//if(sh2->sleep_mode != 2)
 | |
| 		sh2->pc -= 2;
 | |
| 	sh2->icount -= 2;
 | |
| 	/* Wait_for_exception; */
 | |
| 	/*if(sh2->sleep_mode == 0)
 | |
| 		sh2->sleep_mode = 1;
 | |
| 	else if(sh2->sleep_mode == 2)
 | |
| 		sh2->sleep_mode = 0;*/
 | |
| }
 | |
| 
 | |
| /*  STC     SR,Rn */
 | |
| INLINE void STCSR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->sr;
 | |
| }
 | |
| 
 | |
| /*  STC     GBR,Rn */
 | |
| INLINE void STCGBR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->gbr;
 | |
| }
 | |
| 
 | |
| /*  STC     VBR,Rn */
 | |
| INLINE void STCVBR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->vbr;
 | |
| }
 | |
| 
 | |
| /*  STC.L   SR,@-Rn */
 | |
| INLINE void STCMSR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] -= 4;
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WL( sh2, sh2->ea, sh2->sr );
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  STC.L   GBR,@-Rn */
 | |
| INLINE void STCMGBR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] -= 4;
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WL( sh2, sh2->ea, sh2->gbr );
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  STC.L   VBR,@-Rn */
 | |
| INLINE void STCMVBR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] -= 4;
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WL( sh2, sh2->ea, sh2->vbr );
 | |
| 	sh2->icount--;
 | |
| }
 | |
| 
 | |
| /*  STS     MACH,Rn */
 | |
| INLINE void STSMACH(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->mach;
 | |
| }
 | |
| 
 | |
| /*  STS     MACL,Rn */
 | |
| INLINE void STSMACL(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->macl;
 | |
| }
 | |
| 
 | |
| /*  STS     PR,Rn */
 | |
| INLINE void STSPR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] = sh2->pr;
 | |
| }
 | |
| 
 | |
| /*  STS.L   MACH,@-Rn */
 | |
| INLINE void STSMMACH(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] -= 4;
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WL( sh2, sh2->ea, sh2->mach );
 | |
| }
 | |
| 
 | |
| /*  STS.L   MACL,@-Rn */
 | |
| INLINE void STSMMACL(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] -= 4;
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WL( sh2, sh2->ea, sh2->macl );
 | |
| }
 | |
| 
 | |
| /*  STS.L   PR,@-Rn */
 | |
| INLINE void STSMPR(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] -= 4;
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	WL( sh2, sh2->ea, sh2->pr );
 | |
| }
 | |
| 
 | |
| /*  SUB     Rm,Rn */
 | |
| INLINE void SUB(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] -= sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  SUBC    Rm,Rn */
 | |
| INLINE void SUBC(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 tmp0, tmp1;
 | |
| 
 | |
| 	tmp1 = sh2->r[n] - sh2->r[m];
 | |
| 	tmp0 = sh2->r[n];
 | |
| 	sh2->r[n] = tmp1 - (sh2->sr & T);
 | |
| 	if (tmp0 < tmp1)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| 	if (tmp1 < sh2->r[n])
 | |
| 		sh2->sr |= T;
 | |
| }
 | |
| 
 | |
| /*  SUBV    Rm,Rn */
 | |
| INLINE void SUBV(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	INT32 dest, src, ans;
 | |
| 
 | |
| 	if ((INT32) sh2->r[n] >= 0)
 | |
| 		dest = 0;
 | |
| 	else
 | |
| 		dest = 1;
 | |
| 	if ((INT32) sh2->r[m] >= 0)
 | |
| 		src = 0;
 | |
| 	else
 | |
| 		src = 1;
 | |
| 	src += dest;
 | |
| 	sh2->r[n] -= sh2->r[m];
 | |
| 	if ((INT32) sh2->r[n] >= 0)
 | |
| 		ans = 0;
 | |
| 	else
 | |
| 		ans = 1;
 | |
| 	ans += dest;
 | |
| 	if (src == 1)
 | |
| 	{
 | |
| 		if (ans == 1)
 | |
| 			sh2->sr |= T;
 | |
| 		else
 | |
| 			sh2->sr &= ~T;
 | |
| 	}
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  SWAP.B  Rm,Rn */
 | |
| INLINE void SWAPB(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 temp0, temp1;
 | |
| 
 | |
| 	temp0 = sh2->r[m] & 0xffff0000;
 | |
| 	temp1 = (sh2->r[m] & 0x000000ff) << 8;
 | |
| 	sh2->r[n] = (sh2->r[m] >> 8) & 0x000000ff;
 | |
| 	sh2->r[n] = sh2->r[n] | temp1 | temp0;
 | |
| }
 | |
| 
 | |
| /*  SWAP.W  Rm,Rn */
 | |
| INLINE void SWAPW(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 
 | |
| 	temp = (sh2->r[m] >> 16) & 0x0000ffff;
 | |
| 	sh2->r[n] = (sh2->r[m] << 16) | temp;
 | |
| }
 | |
| 
 | |
| /*  TAS.B   @Rn */
 | |
| INLINE void TAS(sh2_state *sh2, UINT32 n)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 	sh2->ea = sh2->r[n];
 | |
| 	/* Bus Lock enable */
 | |
| 	temp = RB( sh2, sh2->ea );
 | |
| 	if (temp == 0)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| 	temp |= 0x80;
 | |
| 	/* Bus Lock disable */
 | |
| 	WB( sh2, sh2->ea, temp );
 | |
| 	sh2->icount -= 3;
 | |
| }
 | |
| 
 | |
| /*  TRAPA   #imm */
 | |
| INLINE void TRAPA(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 imm = i & 0xff;
 | |
| 
 | |
| 	sh2->ea = sh2->vbr + imm * 4;
 | |
| 
 | |
| 	sh2->r[15] -= 4;
 | |
| 	WL( sh2, sh2->r[15], sh2->sr );
 | |
| 	sh2->r[15] -= 4;
 | |
| 	WL( sh2, sh2->r[15], sh2->pc );
 | |
| 
 | |
| 	sh2->pc = RL( sh2, sh2->ea );
 | |
| 
 | |
| 	sh2->icount -= 7;
 | |
| }
 | |
| 
 | |
| /*  TST     Rm,Rn */
 | |
| INLINE void TST(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	if ((sh2->r[n] & sh2->r[m]) == 0)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  TST     #imm,R0 */
 | |
| INLINE void TSTI(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 imm = i & 0xff;
 | |
| 
 | |
| 	if ((imm & sh2->r[0]) == 0)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| }
 | |
| 
 | |
| /*  TST.B   #imm,@(R0,GBR) */
 | |
| INLINE void TSTM(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 imm = i & 0xff;
 | |
| 
 | |
| 	sh2->ea = sh2->gbr + sh2->r[0];
 | |
| 	if ((imm & RB( sh2, sh2->ea )) == 0)
 | |
| 		sh2->sr |= T;
 | |
| 	else
 | |
| 		sh2->sr &= ~T;
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  XOR     Rm,Rn */
 | |
| INLINE void XOR(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	sh2->r[n] ^= sh2->r[m];
 | |
| }
 | |
| 
 | |
| /*  XOR     #imm,R0 */
 | |
| INLINE void XORI(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 imm = i & 0xff;
 | |
| 	sh2->r[0] ^= imm;
 | |
| }
 | |
| 
 | |
| /*  XOR.B   #imm,@(R0,GBR) */
 | |
| INLINE void XORM(sh2_state *sh2, UINT32 i)
 | |
| {
 | |
| 	UINT32 imm = i & 0xff;
 | |
| 	UINT32 temp;
 | |
| 
 | |
| 	sh2->ea = sh2->gbr + sh2->r[0];
 | |
| 	temp = RB( sh2, sh2->ea );
 | |
| 	temp ^= imm;
 | |
| 	WB( sh2, sh2->ea, temp );
 | |
| 	sh2->icount -= 2;
 | |
| }
 | |
| 
 | |
| /*  XTRCT   Rm,Rn */
 | |
| INLINE void XTRCT(sh2_state *sh2, UINT32 m, UINT32 n)
 | |
| {
 | |
| 	UINT32 temp;
 | |
| 
 | |
| 	temp = (sh2->r[m] << 16) & 0xffff0000;
 | |
| 	sh2->r[n] = (sh2->r[n] >> 16) & 0x0000ffff;
 | |
| 	sh2->r[n] |= temp;
 | |
| }
 | |
| 
 | |
| /*****************************************************************************
 | |
|  *  OPCODE DISPATCHERS
 | |
|  *****************************************************************************/
 | |
| 
 | |
| INLINE void op0000(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	switch (opcode & 0x3F)
 | |
| 	{
 | |
| 	case 0x00: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x01: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x02: STCSR(sh2, Rn);	rlog(LRN); 			break;
 | |
| 	case 0x03: BSRF(sh2, Rn);	rlog(LRN); 			break;
 | |
| 	case 0x04: MOVBS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x05: MOVWS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x06: MOVLS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x07: MULL(sh2, Rm, Rn);	rlog(LRNM); rlog1(SHR_MACL);	break;
 | |
| 	case 0x08: CLRT(sh2);		rlog(0);			break;
 | |
| 	case 0x09: NOP();		rlog(0);			break;
 | |
| 	case 0x0a: STSMACH(sh2, Rn); 	rlog(LRN);  rlog1(SHR_MACH); 	break;
 | |
| 	case 0x0b: RTS(sh2);		rlog(0);    rlog1(SHR_PR);	break;
 | |
| 	case 0x0c: MOVBL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x0d: MOVWL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x0e: MOVLL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x0f: MAC_L(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 
 | |
| 	case 0x10: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x11: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x12: STCGBR(sh2, Rn);	rlog(LRN);  rlog1(SHR_GBR);	break;
 | |
| 	case 0x13: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x14: MOVBS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x15: MOVWS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x16: MOVLS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x17: MULL(sh2, Rm, Rn);	rlog(LRNM); rlog1(SHR_MACL);	break;
 | |
| 	case 0x18: SETT(sh2);		rlog(0);			break;
 | |
| 	case 0x19: DIV0U(sh2); 		rlog(0);			break;
 | |
| 	case 0x1a: STSMACL(sh2, Rn); 	rlog(LRN);  rlog1(SHR_MACL);	break;
 | |
| 	case 0x1b: SLEEP(sh2); 		rlog(0);			break;
 | |
| 	case 0x1c: MOVBL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x1d: MOVWL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x1e: MOVLL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x1f: MAC_L(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 
 | |
| 	case 0x20: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x21: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x22: STCVBR(sh2, Rn);	rlog(LRN);  rlog1(SHR_VBR);	break;
 | |
| 	case 0x23: BRAF(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x24: MOVBS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x25: MOVWS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x26: MOVLS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x27: MULL(sh2, Rm, Rn);	rlog(LRNM); rlog1(SHR_MACL);	break;
 | |
| 	case 0x28: CLRMAC(sh2);		rlog(0);    rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 	case 0x29: MOVT(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x2a: STSPR(sh2, Rn);	rlog(LRN);  rlog1(SHR_PR);	break;
 | |
| 	case 0x2b: RTE(sh2);		rlog(0);			break;
 | |
| 	case 0x2c: MOVBL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x2d: MOVWL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x2e: MOVLL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x2f: MAC_L(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 
 | |
| 	case 0x30: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x31: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x32: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x33: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x34: MOVBS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x35: MOVWS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x36: MOVLS0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x37: MULL(sh2, Rm, Rn);	rlog(LRNM); rlog1(SHR_MACL);	break;
 | |
| 	case 0x38: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x39: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x3c: MOVBL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x3d: MOVWL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x3e: MOVLL0(sh2, Rm, Rn);	rlog(LRNM); rlog1(0);		break;
 | |
| 	case 0x3f: MAC_L(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 	case 0x3a: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x3b: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| INLINE void op0001(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	MOVLS4(sh2, Rm, opcode & 0x0f, Rn);
 | |
| 	rlog(LRNM);
 | |
| }
 | |
| 
 | |
| INLINE void op0010(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	switch (opcode & 15)
 | |
| 	{
 | |
| 	case  0: MOVBS(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  1: MOVWS(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  2: MOVLS(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  3: ILLEGAL(sh2);		rlog(0);			break;
 | |
| 	case  4: MOVBM(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  5: MOVWM(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  6: MOVLM(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  7: DIV0S(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  8: TST(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case  9: AND(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 10: XOR(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 11: OR(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 12: CMPSTR(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 13: XTRCT(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case 14: MULU(sh2, Rm, Rn);	rlog(LRNM); rlog1(SHR_MACL);	break;
 | |
| 	case 15: MULS(sh2, Rm, Rn);	rlog(LRNM); rlog1(SHR_MACL);	break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| INLINE void op0011(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	switch (opcode & 15)
 | |
| 	{
 | |
| 	case  0: CMPEQ(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  1: ILLEGAL(sh2);		rlog(0);			break;
 | |
| 	case  2: CMPHS(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  3: CMPGE(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  4: DIV1(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case  5: DMULU(sh2, Rm, Rn); 	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 	case  6: CMPHI(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  7: CMPGT(sh2, Rm, Rn); 	rlog(LRNM);			break;
 | |
| 	case  8: SUB(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case  9: ILLEGAL(sh2);		rlog(0);			break;
 | |
| 	case 10: SUBC(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 11: SUBV(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 12: ADD(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 13: DMULS(sh2, Rm, Rn); 	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 	case 14: ADDC(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	case 15: ADDV(sh2, Rm, Rn);	rlog(LRNM);			break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| INLINE void op0100(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	switch (opcode & 0x3F)
 | |
| 	{
 | |
| 	case 0x00: SHLL(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x01: SHLR(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x02: STSMMACH(sh2, Rn);	rlog(LRN); rlog1(SHR_MACH);	break;
 | |
| 	case 0x03: STCMSR(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x04: ROTL(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x05: ROTR(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x06: LDSMMACH(sh2, Rn);	rlog(LRN); rlog1(SHR_MACH);	break;
 | |
| 	case 0x07: LDCMSR(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x08: SHLL2(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x09: SHLR2(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x0a: LDSMACH(sh2, Rn); 	rlog(LRN); rlog1(SHR_MACH);	break;
 | |
| 	case 0x0b: JSR(sh2, Rn); 	rlog(LRN); rlog1(SHR_PR);	break;
 | |
| 	case 0x0c: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x0d: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x0e: LDCSR(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x0f: MAC_W(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 
 | |
| 	case 0x10: DT(sh2, Rn);		rlog(LRN);			break;
 | |
| 	case 0x11: CMPPZ(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x12: STSMMACL(sh2, Rn);	rlog(LRN); rlog1(SHR_MACL);	break;
 | |
| 	case 0x13: STCMGBR(sh2, Rn); 	rlog(LRN); rlog1(SHR_GBR);	break;
 | |
| 	case 0x14: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x15: CMPPL(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x16: LDSMMACL(sh2, Rn);	rlog(LRN); rlog1(SHR_MACL);	break;
 | |
| 	case 0x17: LDCMGBR(sh2, Rn); 	rlog(LRN); rlog1(SHR_GBR);	break;
 | |
| 	case 0x18: SHLL8(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x19: SHLR8(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x1a: LDSMACL(sh2, Rn); 	rlog(LRN); rlog1(SHR_MACL);	break;
 | |
| 	case 0x1b: TAS(sh2, Rn); 	rlog(LRN);			break;
 | |
| 	case 0x1c: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x1d: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x1e: LDCGBR(sh2, Rn);	rlog(LRN); rlog1(SHR_GBR);	break;
 | |
| 	case 0x1f: MAC_W(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 
 | |
| 	case 0x20: SHAL(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x21: SHAR(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x22: STSMPR(sh2, Rn);	rlog(LRN); rlog1(SHR_PR);	break;
 | |
| 	case 0x23: STCMVBR(sh2, Rn); 	rlog(LRN); rlog1(SHR_VBR);	break;
 | |
| 	case 0x24: ROTCL(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x25: ROTCR(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x26: LDSMPR(sh2, Rn);	rlog(LRN); rlog1(SHR_PR);	break;
 | |
| 	case 0x27: LDCMVBR(sh2, Rn); 	rlog(LRN); rlog1(SHR_VBR);	break;
 | |
| 	case 0x28: SHLL16(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x29: SHLR16(sh2, Rn);	rlog(LRN);			break;
 | |
| 	case 0x2a: LDSPR(sh2, Rn);	rlog(LRN); rlog1(SHR_PR);	break;
 | |
| 	case 0x2b: JMP(sh2, Rn); 	rlog(LRN);			break;
 | |
| 	case 0x2c: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x2d: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x2e: LDCVBR(sh2, Rn);	rlog(LRN); rlog1(SHR_VBR);	break;
 | |
| 	case 0x2f: MAC_W(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 
 | |
| 	case 0x30:
 | |
| 	case 0x31:
 | |
| 	case 0x32:
 | |
| 	case 0x33:
 | |
| 	case 0x34:
 | |
| 	case 0x35:
 | |
| 	case 0x36:
 | |
| 	case 0x37:
 | |
| 	case 0x38:
 | |
| 	case 0x39:
 | |
| 	case 0x3a:
 | |
| 	case 0x3b:
 | |
| 	case 0x3c:
 | |
| 	case 0x3d:
 | |
| 	case 0x3e: ILLEGAL(sh2);	rlog(0);			break;
 | |
| 	case 0x3f: MAC_W(sh2, Rm, Rn);	rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| INLINE void op0101(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	MOVLL4(sh2, Rm, opcode & 0x0f, Rn);
 | |
| 	rlog(LRNM);
 | |
| }
 | |
| 
 | |
| INLINE void op0110(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	switch (opcode & 15)
 | |
| 	{
 | |
| 	case  0: MOVBL(sh2, Rm, Rn); 				break;
 | |
| 	case  1: MOVWL(sh2, Rm, Rn); 				break;
 | |
| 	case  2: MOVLL(sh2, Rm, Rn); 				break;
 | |
| 	case  3: MOV(sh2, Rm, Rn);				break;
 | |
| 	case  4: MOVBP(sh2, Rm, Rn); 				break;
 | |
| 	case  5: MOVWP(sh2, Rm, Rn); 				break;
 | |
| 	case  6: MOVLP(sh2, Rm, Rn); 				break;
 | |
| 	case  7: NOT(sh2, Rm, Rn);				break;
 | |
| 	case  8: SWAPB(sh2, Rm, Rn); 				break;
 | |
| 	case  9: SWAPW(sh2, Rm, Rn); 				break;
 | |
| 	case 10: NEGC(sh2, Rm, Rn);				break;
 | |
| 	case 11: NEG(sh2, Rm, Rn);				break;
 | |
| 	case 12: EXTUB(sh2, Rm, Rn); 				break;
 | |
| 	case 13: EXTUW(sh2, Rm, Rn); 				break;
 | |
| 	case 14: EXTSB(sh2, Rm, Rn); 				break;
 | |
| 	case 15: EXTSW(sh2, Rm, Rn); 				break;
 | |
| 	}
 | |
| 	rlog(LRNM);
 | |
| }
 | |
| 
 | |
| INLINE void op0111(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	ADDI(sh2, opcode & 0xff, Rn);
 | |
| 	rlog(LRN);
 | |
| }
 | |
| 
 | |
| INLINE void op1000(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	switch ( opcode  & (15<<8) )
 | |
| 	{
 | |
| 	case  0<< 8: MOVBS4(sh2, opcode & 0x0f, Rm);	rlog(LRM); rlog1(0);	break;
 | |
| 	case  1<< 8: MOVWS4(sh2, opcode & 0x0f, Rm);	rlog(LRM); rlog1(0);	break;
 | |
| 	case  2<< 8: ILLEGAL(sh2); 			rlog(0);		break;
 | |
| 	case  3<< 8: ILLEGAL(sh2); 			rlog(0);		break;
 | |
| 	case  4<< 8: MOVBL4(sh2, Rm, opcode & 0x0f);	rlog(LRM); rlog1(0);	break;
 | |
| 	case  5<< 8: MOVWL4(sh2, Rm, opcode & 0x0f);	rlog(LRM); rlog1(0);	break;
 | |
| 	case  6<< 8: ILLEGAL(sh2); 			rlog(0);		break;
 | |
| 	case  7<< 8: ILLEGAL(sh2); 			rlog(0);		break;
 | |
| 	case  8<< 8: CMPIM(sh2, opcode & 0xff);		rlog(0);   rlog1(0);	break;
 | |
| 	case  9<< 8: BT(sh2, opcode & 0xff); 		rlog(0);	break;
 | |
| 	case 10<< 8: ILLEGAL(sh2); 			rlog(0);	break;
 | |
| 	case 11<< 8: BF(sh2, opcode & 0xff); 		rlog(0);	break;
 | |
| 	case 12<< 8: ILLEGAL(sh2); 			rlog(0);	break;
 | |
| 	case 13<< 8: BTS(sh2, opcode & 0xff);		rlog(0);	break;
 | |
| 	case 14<< 8: ILLEGAL(sh2); 			rlog(0);	break;
 | |
| 	case 15<< 8: BFS(sh2, opcode & 0xff);		rlog(0);	break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| INLINE void op1001(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	MOVWI(sh2, opcode & 0xff, Rn);
 | |
| 	rlog(LRN);
 | |
| }
 | |
| 
 | |
| INLINE void op1010(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	BRA(sh2, opcode & 0xfff);
 | |
| 	rlog(0);
 | |
| }
 | |
| 
 | |
| INLINE void op1011(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	BSR(sh2, opcode & 0xfff);
 | |
| 	rlog(0);
 | |
| 	rlog1(SHR_PR);
 | |
| }
 | |
| 
 | |
| INLINE void op1100(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	switch (opcode & (15<<8))
 | |
| 	{
 | |
| 	case  0<<8: MOVBSG(sh2, opcode & 0xff); rlog2(0, SHR_GBR);	break;
 | |
| 	case  1<<8: MOVWSG(sh2, opcode & 0xff); rlog2(0, SHR_GBR);	break;
 | |
| 	case  2<<8: MOVLSG(sh2, opcode & 0xff); rlog2(0, SHR_GBR);	break;
 | |
| 	case  3<<8: TRAPA(sh2, opcode & 0xff);	rlog1(SHR_VBR);		break;
 | |
| 	case  4<<8: MOVBLG(sh2, opcode & 0xff); rlog2(0, SHR_GBR);	break;
 | |
| 	case  5<<8: MOVWLG(sh2, opcode & 0xff); rlog2(0, SHR_GBR);	break;
 | |
| 	case  6<<8: MOVLLG(sh2, opcode & 0xff); rlog2(0, SHR_GBR);	break;
 | |
| 	case  7<<8: MOVA(sh2, opcode & 0xff);	rlog1(0);		break;
 | |
| 	case  8<<8: TSTI(sh2, opcode & 0xff);	rlog1(0);		break;
 | |
| 	case  9<<8: ANDI(sh2, opcode & 0xff);	rlog1(0);		break;
 | |
| 	case 10<<8: XORI(sh2, opcode & 0xff);	rlog1(0);		break;
 | |
| 	case 11<<8: ORI(sh2, opcode & 0xff);	rlog1(0);		break;
 | |
| 	case 12<<8: TSTM(sh2, opcode & 0xff);	rlog2(0, SHR_GBR);	break;
 | |
| 	case 13<<8: ANDM(sh2, opcode & 0xff);	rlog2(0, SHR_GBR);	break;
 | |
| 	case 14<<8: XORM(sh2, opcode & 0xff);	rlog2(0, SHR_GBR);	break;
 | |
| 	case 15<<8: ORM(sh2, opcode & 0xff);	rlog2(0, SHR_GBR);	break;
 | |
| 	}
 | |
| 	rlog(0);
 | |
| }
 | |
| 
 | |
| INLINE void op1101(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	MOVLI(sh2, opcode & 0xff, Rn);
 | |
| 	rlog(LRN);
 | |
| }
 | |
| 
 | |
| INLINE void op1110(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	MOVI(sh2, opcode & 0xff, Rn);
 | |
| 	rlog(LRN);
 | |
| }
 | |
| 
 | |
| INLINE void op1111(sh2_state *sh2, UINT16 opcode)
 | |
| {
 | |
| 	ILLEGAL(sh2);
 | |
| 	rlog(0);
 | |
| }
 | |
| 
 | |
| #endif
 | 
