famec.cpp
   1  /****************************************************************************/
   2  /* FAME (Fast and Accurate Motorola 68000 Emulation Library)                */
   3  /* Emulador de 68000 en C                                                   */
   4  /* Autor: Oscar Orallo Pelaez                                               */
   5  /* Fecha de comienzo: 03-10-2006                                            */
   6  /* Ultima actualizacion: 28-10-2009                                         */
   7  /* Based on the excellent FAMEC emulator by Stephane Dallongueville         */
   8  /****************************************************************************/
   9  
  10  #include <stdio.h>
  11  #include <stdlib.h>
  12  #include <string.h>
  13  #include <assert.h>
  14  
  15  #include "dcastaway.h"
  16  
  17  #ifdef _MSC_VER
  18  /* Ignore unary minus applied to unsigned type */
  19  #pragma warning( disable : 4146 )
  20  #endif
  21  
  22  /* Options */
  23  /*
  24   Do not use the following lines to enable/disable features
  25   They are here as a reference only
  26   Define them in your project as you need instead
  27  */
  28  /* #define FAME_INLINE_LOOP */
  29  /* #define FAME_IRQ_CLOCKING */
  30  /* #define FAME_CHECK_BRANCHES */
  31  /* #define FAME_DIRECT_MAPPING */
  32  /* #define FAME_EXTRA_INLINE */
  33  /* #define FAME_EMULATE_TRACE */
  34  /* #define FAME_BYPASS_TAS_WRITEBACK */
  35  /* #define FAME_ACCURATE_TIMING */
  36  /* #define FAME_GLOBAL_CONTEXT */
  37  /* #define FAME_DEBUG */
  38  /* #define FAME_GOTOS */
  39  /* #define FAME_BIG_ENDIAN */
  40  
  41  #define FAME_SECURE_ALL_BANKS
  42  
  43  #ifndef FAME_ADDR_BITS
  44  #define FAME_ADDR_BITS  24
  45  #endif
  46  
  47  #ifndef FAME_PC_BITS
  48  #define FAME_PC_BITS  24
  49  #endif
  50  
  51  #ifndef FAME_FETCHBITS
  52  #define FAME_FETCHBITS 12
  53  #endif
  54  
  55  #ifndef FAME_DATABITS
  56  #define FAME_DATABITS  12
  57  #endif
  58  
  59  #ifndef FAME_PREFIX
  60  #define FAME_PREFIX m68k
  61  #endif
  62  
  63  /* Options */
  64  
  65  #define CONCAT(P1,P2)  P1##P2
  66  #define FAME_FNT(P,F)  CONCAT(P,_##F)
  67  #define FAME_DT(P,D)   CONCAT(P,D)
  68  #define FAME_API(F)    FAME_FNT(FAME_PREFIX,F)
  69  #define FAME_CONTEXT   FAME_DT(FAME_PREFIX,context)
  70  
  71  
  72  #ifndef INLINE
  73  #define INLINE
  74  #endif
  75  
  76  #ifndef FAME_EXTRA_INLINE
  77  #define EXTRA_INLINE
  78  #else
  79  #define EXTRA_INLINE INLINE
  80  #endif
  81  
  82  /* Return codes */
  83  #define M68K_OK 0
  84  #define M68K_RUNNING 1
  85  #define M68K_NO_SUP_ADDR_SPACE 2
  86  #define M68K_INV_REG -1
  87  
  88  /* Hardware interrupt state */
  89  #define M68K_IRQ_LEVEL_ERROR -1
  90  #define M68K_IRQ_INV_PARAMS -2
  91  
  92  /* Defines to specify hardware interrupt type */
  93  #define M68K_AUTOVECTORED_IRQ -1
  94  #define M68K_SPURIOUS_IRQ -2
  95  
  96  /* Defines to specify address space */
  97  #define M68K_SUP_ADDR_SPACE 0
  98  #define M68K_USER_ADDR_SPACE 2
  99  #define M68K_PROG_ADDR_SPACE 0
 100  #define M68K_DATA_ADDR_SPACE 1
 101  
 102  /******************************/
 103  /* 68K core types definitions */
 104  /******************************/
 105  
 106  #if FAME_ADDR_BITS < 32
 107  #define M68K_ADDR_MASK  ((1 << FAME_ADDR_BITS)-1)
 108  #else
 109  #define M68K_ADDR_MASK  0xFFFFFFFF
 110  #endif
 111  
 112  #define M68K_FETCHSFT  (FAME_ADDR_BITS - FAME_FETCHBITS)
 113  #define M68K_FETCHBANK (1 << FAME_FETCHBITS)
 114  #define M68K_FETCHMASK (M68K_FETCHBANK - 1)
 115  
 116  #define M68K_DATASFT  (FAME_ADDR_BITS - FAME_DATABITS)
 117  #define M68K_DATABANK (1 << FAME_DATABITS)
 118  #define M68K_DATAMASK (M68K_DATABANK - 1)
 119  
 120  #define M68K_SR_C_SFT   8
 121  #define M68K_SR_V_SFT   7
 122  #define M68K_SR_Z_SFT   0
 123  #define M68K_SR_N_SFT   7
 124  #define M68K_SR_X_SFT   8
 125  
 126  #define M68K_SR_S_SFT   13
 127  #define M68K_SR_T_SFT   15
 128  
 129  #define M68K_SR_C       (1 << M68K_SR_C_SFT)
 130  #define M68K_SR_V       (1 << M68K_SR_V_SFT)
 131  #define M68K_SR_Z       0
 132  #define M68K_SR_N       (1 << M68K_SR_N_SFT)
 133  #define M68K_SR_X       (1 << M68K_SR_X_SFT)
 134  
 135  #define M68K_SR_S       (1 << M68K_SR_S_SFT)
 136  #define M68K_SR_T       (1 << M68K_SR_T_SFT)
 137  
 138  #define M68K_CCR_MASK   0x1F
 139  
 140  #ifdef FAME_IRQ_CLOCKING
 141  #define INT_TIMING 44
 142  #else
 143  #define INT_TIMING  0
 144  #endif
 145  
 146  #ifdef FAME_EMULATE_TRACE
 147  #define M68K_SR_MASK    (M68K_SR_T | M68K_SR_S | 0x0700 | M68K_CCR_MASK)
 148  #else
 149  #define M68K_SR_MASK    (M68K_SR_S | 0x0700 | M68K_CCR_MASK)
 150  #endif
 151  
 152  /* exception defines taken from musashi core */
 153  #define M68K_RESET_EX                   1
 154  #define M68K_BUS_ERROR_EX               2
 155  #define M68K_ADDRESS_ERROR_EX           3
 156  #define M68K_ILLEGAL_INSTRUCTION_EX     4
 157  #define M68K_ZERO_DIVIDE_EX             5
 158  #define M68K_CHK_EX                     6
 159  #define M68K_TRAPV_EX                   7
 160  #define M68K_PRIVILEGE_VIOLATION_EX     8
 161  #define M68K_TRACE_EX                   9
 162  #define M68K_1010_EX                    10
 163  #define M68K_1111_EX                    11
 164  #define M68K_FORMAT_ERROR_EX            14
 165  #define M68K_UNINITIALIZED_INTERRUPT_EX 15
 166  #define M68K_SPURIOUS_INTERRUPT_EX      24
 167  #define M68K_INTERRUPT_AUTOVECTOR_EX    24
 168  #define M68K_TRAP_BASE_EX               32
 169  
 170  #define M68K_INT_ACK_AUTOVECTOR         -1
 171  
 172  /*#define M68K_RUNNING    0x01 */
 173  #define M68K_HALTED     0x80
 174  #define M68K_WAITING    0x04
 175  #define M68K_DISABLE    0x20
 176  /* #define M68K_FAULTED    0x40 */
 177  #define M68K_EMULATE_GROUP_0  0x02
 178  #define M68K_EMULATE_TRACE    0x08
 179  #define M68K_DO_TRACE    0x10
 180  
 181  #ifdef FAME_LITTLE_ENDIAN
 182  #ifdef FAME_BIG_ENDIAN
 183  #undef FAME_BIG_ENDIAN
 184  #endif
 185  #else
 186  #ifndef FAME_BIG_ENDIAN
 187  #if defined(__hppa__) || \
 188      defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
 189      (defined(__MIPS__) && defined(__MISPEB__)) || \
 190      defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
 191      defined(__sparc__)
 192  #define FAME_BIG_ENDIAN
 193  #else
 194  #define FAME_LITTLE_ENDIAN
 195  #endif
 196  #endif
 197  #endif
 198  
 199  
 200  /*
 201   internals core macros
 202  */
 203  
 204  #define DREG(X)         (FAME_CONTEXT.dreg[(X)].D)
 205  #define DREGu32(X)      (FAME_CONTEXT.dreg[(X)].D)
 206  #define DREGs32(X)      (FAME_CONTEXT.dreg[(X)].SD)
 207  #define DREGu16(X)      (FAME_CONTEXT.dreg[(X)].w.W)
 208  #define DREGs16(X)      (FAME_CONTEXT.dreg[(X)].sw.SW)
 209  #define DREGu8(X)       (FAME_CONTEXT.dreg[(X)].b.B)
 210  #define DREGs8(X)       (FAME_CONTEXT.dreg[(X)].sb.SB)
 211  
 212  #define AREG(X)         (FAME_CONTEXT.areg[(X)].D)
 213  #define AREGu32(X)      (FAME_CONTEXT.areg[(X)].D)
 214  #define AREGs32(X)      (FAME_CONTEXT.areg[(X)].SD)
 215  #define AREGu16(X)      (FAME_CONTEXT.areg[(X)].w.W)
 216  #define AREGs16(X)      (FAME_CONTEXT.areg[(X)].sw.SW)
 217  
 218  #define ASP             (FAME_CONTEXT.asp)
 219  
 220  #define LSL(A, C)       ((A) << (C))
 221  #define LSR(A, C)       ((A) >> (C))
 222  
 223  #define LSR_32(A, C)    ((C) < 32 ? (A) >> (C) : 0)
 224  #define LSL_32(A, C)    ((C) < 32 ? (A) << (C) : 0)
 225  
 226  #define ROL_8(A, C)     (LSL(A, C) | LSR(A, 8-(C)))
 227  #define ROL_9(A, C)     (LSL(A, C) | LSR(A, 9-(C)))
 228  #define ROL_16(A, C)    (LSL(A, C) | LSR(A, 16-(C)))
 229  #define ROL_17(A, C)    (LSL(A, C) | LSR(A, 17-(C)))
 230  #define ROL_32(A, C)    (LSL_32(A, C) | LSR_32(A, 32-(C)))
 231  #define ROL_33(A, C)    (LSL_32(A, C) | LSR_32(A, 33-(C)))
 232  
 233  #define ROR_8(A, C)     (LSR(A, C) | LSL(A, 8-(C)))
 234  #define ROR_9(A, C)     (LSR(A, C) | LSL(A, 9-(C)))
 235  #define ROR_16(A, C)    (LSR(A, C) | LSL(A, 16-(C)))
 236  #define ROR_17(A, C)    (LSR(A, C) | LSL(A, 17-(C)))
 237  #define ROR_32(A, C)    (LSR_32(A, C) | LSL_32(A, 32-(C)))
 238  #define ROR_33(A, C)    (LSR_32(A, C) | LSL_32(A, 33-(C)))
 239  
 240  /* Flag setup */
 241  #define SET_FLAGS_Z_VC0 \
 242      flag_C = 0; \
 243      flag_V = 0; \
 244      flag_NotZ = res;
 245  
 246  #define SET_FLAGS_NZ_VC0 \
 247  	SET_FLAGS_Z_VC0 \
 248      flag_N = res;
 249  
 250  #define SET_FLAGS_DIV_ZERO \
 251  	flag_V = 0; \
 252  	flag_C = 0;
 253  
 254  #define SET_FLAGS_DIV_OVERFLOW \
 255  	flag_C = 0; \
 256  	flag_V = M68K_SR_V; \
 257  	flag_N = M68K_SR_N; \
 258  	/* Z flag is undefined on division overflow */ \
 259  	/* but is set here to match FAME versions */ \
 260  	flag_NotZ = 1; \
 261  
 262  
 263  #ifdef FAME_DEBUG
 264  #define DEBUG_OPCODE(OP) printf(":Opcode %.4X\n",Opcode);
 265  #else
 266  #define DEBUG_OPCODE(OP)
 267  #endif
 268  
 269  #ifdef FAME_GOTOS
 270  #define NEXT                    \
 271      FETCH_WORD(Opcode);         \
 272      DEBUG_OPCODE(Opcode) \
 273      goto *JumpTable[Opcode];
 274  
 275  #ifdef FAME_INLINE_LOOP
 276  #define RET(A)                                      \
 277      io_cycle_counter -= (A);                        \
 278      if (io_cycle_counter <= 0) goto famec_Exec_End;	\
 279      NEXT
 280  #else
 281  #define RET(A)                                      \
 282      io_cycle_counter -= (A);                        \
 283      if (io_cycle_counter <= 0) goto famec_Exec_End;	\
 284      goto famec_Exec;
 285  #endif
 286  
 287  #define RET_STOP(C) \
 288      io_cycle_counter -= (C);                        \
 289      if (io_cycle_counter > 0) io_cycle_counter = 0;	\
 290      goto famec_Exec_End;
 291  
 292  #else
 293  //printf("%8x",PC);
 294  //printf("=>%8x\n",Opcode);
 295  
 296  #define NEXT \
 297  	do { \
 298  		FETCH_WORD(Opcode); \
 299  		DEBUG_OPCODE(Opcode) \
 300  		JumpTable[Opcode](); \
 301  	} while(io_cycle_counter>0);
 302  
 303  #ifdef FAME_INLINE_LOOP
 304  #define RET(A) \
 305      io_cycle_counter -= (A);  \
 306      if (io_cycle_counter > 0) \
 307      { \
 308  	    FETCH_WORD(Opcode); \
 309  	    DEBUG_OPCODE(Opcode) \
 310  	    JumpTable[Opcode](); \
 311      } \
 312      return;
 313  
 314  #else
 315  
 316  #define RET(A) \
 317      io_cycle_counter -= (A);  \
 318      return;
 319  
 320  #endif
 321  
 322  #define RET_STOP(C) \
 323      io_cycle_counter -= (C);                        \
 324      if (io_cycle_counter > 0) io_cycle_counter = 0;	\
 325      return;
 326  
 327  #endif
 328  
 329  #define M68K_PPL (FAME_CONTEXT.sr >> 8) & 7
 330  
 331  #if FAME_PC_BITS == 32
 332  
 333  #define UNBASED_PC PC
 334  
 335  #define READ_BASED_PC BasePC[(PC & M68K_ADDR_MASK) >> 1]
 336  
 337  #define READ_BASED_PC_IDX(IDX) BasePC[((PC & M68K_ADDR_MASK) >> 1) + IDX]
 338  
 339  #define SET_PC(A)               \
 340      BasePC = (u16 *)Fetch[(((A) & M68K_ADDR_MASK) >> M68K_FETCHSFT) & M68K_FETCHMASK];    \
 341  	PC = A;
 342  
 343  #define INC_PC(I) (PC += I)
 344  
 345  #else
 346  
 347  #define UNBASED_PC ((u32)PC - BasePC)
 348  
 349  #define READ_BASED_PC (*PC)
 350  
 351  #define READ_BASED_PC_IDX(IDX) PC[IDX]
 352  
 353  #define SET_PC(A)               \
 354      BasePC = Fetch[((A) >> M68K_FETCHSFT) & M68K_FETCHMASK];    \
 355      PC = (u16*)(((A) & M68K_ADDR_MASK) + BasePC);
 356  
 357  #define INC_PC(I) (PC += (I) >> 1)
 358  
 359  #endif
 360  
 361  #define READ_BYTE_F(A, D)           \
 362  		D = Read_Byte(A) & 0xFF;
 363  
 364  #define READ_WORD_F(A, D)           \
 365  		D = Read_Word(A) & 0xFFFF;
 366  
 367  #define READ_LONG_F(A, D)               \
 368  		D = Read_Word((A)) << 16;          \
 369  		D |= Read_Word((A) + 2) & 0xFFFF;
 370  
 371  #define READ_LONG_DEC_F(A, D)           \
 372  		D = Read_Word((A) + 2) & 0xFFFF;   \
 373  		D |= Read_Word((A)) << 16;
 374  
 375  #define READSX_LONG_F(A, D)             \
 376  		D = Read_Word((A)) << 16;          \
 377  		D |= Read_Word((A) + 2) & 0xFFFF;
 378  
 379  #define WRITE_LONG_F(A, D)              \
 380  		Write_Word((A), (D) >> 16);        \
 381  		Write_Word((A) + 2, (D) & 0xFFFF);
 382  
 383  #define WRITE_LONG_DEC_F(A, D)         \
 384  		Write_Word((A) + 2, (D) & 0xFFFF); \
 385  		Write_Word((A), (D) >> 16);
 386  
 387  #define FETCH_LONG(A)               \
 388  		(A) = READ_BASED_PC_IDX(1) | (READ_BASED_PC_IDX(0) << 16);    \
 389  		INC_PC(4);
 390  
 391  #define PUSH_32_F(D)                            \
 392      	AREG(7) -= 4;                                   \
 393      	Write_Word(AREG(7), (D) >> 16);	\
 394      	Write_Word(AREG(7) + 2, (D) & 0xFFFF);
 395  
 396  #define POP_32_F(D)                         \
 397      	D = Read_Word(AREG(7)) << 16;          \
 398      	D |= Read_Word(AREG(7) + 2) & 0xFFFF;  \
 399      	AREG(7) += 4;
 400  
 401  #define GET_SWORD           \
 402  		((s16)READ_BASED_PC)
 403  
 404  #define FETCH_BYTE(A)       \
 405  		(A) = READ_BASED_PC & 0xFF; INC_PC(2);
 406  
 407  #define FETCH_SBYTE(A)      \
 408  		(A) = (s8)((READ_BASED_PC) & 0xFF); INC_PC(2);
 409  
 410  #define FETCH_WORD(A)       \
 411  		(A) = READ_BASED_PC; INC_PC(2);
 412  
 413  #define FETCH_SWORD(A)      \
 414  		(A) = (s16)READ_BASED_PC; INC_PC(2);
 415  
 416  #define DECODE_EXT_WORD     \
 417  	{                           \
 418  	    u32 ext = READ_BASED_PC; INC_PC(2);       \
 419  	    adr += (s8)(ext);                               \
 420  	    if (ext & 0x0800) adr += DREGs32(ext >> 12);    \
 421  	    else adr += DREGs16(ext >> 12);                 \
 422  	}
 423  
 424  #define READSX_BYTE_F(A, D)             \
 425      D = (s8)Read_Byte(A);
 426  
 427  #define READSX_WORD_F(A, D)             \
 428      D = (s16)Read_Word(A);
 429  
 430  
 431  #define WRITE_BYTE_F(A, D)      \
 432      Write_Byte(A, D);
 433  
 434  #define WRITE_WORD_F(A, D)      \
 435      Write_Word(A, D);
 436  
 437  #define PUSH_16_F(D)                    \
 438      Write_Word(AREG(7) -= 2, D);   \
 439  
 440  #define POP_16_F(D)                     \
 441      D = (u16)Read_Word(AREG(7));   \
 442      AREG(7) += 2;
 443  
 444  #define GET_CCR                                     \
 445      (((flag_C >> (M68K_SR_C_SFT - 0)) & 1) |   \
 446       ((flag_V >> (M68K_SR_V_SFT - 1)) & 2) |   \
 447       (((!flag_NotZ) & 1) << 2) |               \
 448       ((flag_N >> (M68K_SR_N_SFT - 3)) & 8) |   \
 449       ((flag_X >> (M68K_SR_X_SFT - 4)) & 0x10))
 450  
 451  #ifdef FAME_EMULATE_TRACE
 452  #define GET_SR                  \
 453      ((flag_S << 0)  |      \
 454       (flag_I << 8)  |      \
 455       (flag_T ) | \
 456       GET_CCR)
 457  #else
 458  #define GET_SR                  \
 459      ((flag_S << 0)  |      \
 460       (flag_I << 8)  |      \
 461       GET_CCR)
 462  #endif
 463  
 464  #define SET_CCR(A)                              \
 465      flag_C = (A) << (M68K_SR_C_SFT - 0);   \
 466      flag_V = (A) << (M68K_SR_V_SFT - 1);   \
 467      flag_NotZ = ~(A) & 4;                  \
 468      flag_N = (A) << (M68K_SR_N_SFT - 3);   \
 469      flag_X = (A) << (M68K_SR_X_SFT - 4);
 470  
 471  
 472  #ifdef FAME_EMULATE_TRACE
 473  #define SET_SR(A)                   \
 474      SET_CCR(A)                      \
 475      flag_T = (A) & M68K_SR_T; \
 476      flag_S = (A) & M68K_SR_S; \
 477      flag_I = ((A) >> 8) & 7;
 478  #else
 479  #define SET_SR(A)                   \
 480      SET_CCR(A)                      \
 481      flag_S = (A) & M68K_SR_S; \
 482      flag_I = ((A) >> 8) & 7;
 483  #endif
 484  
 485  #define CHECK_INT_TO_JUMP(CLK) \
 486  	if (interrupt_chk()) \
 487  	{ \
 488  		/* \
 489  		  si los ciclos restantes son menores o iguales \
 490  		  que los de la instruccion en curso, \
 491  		  no proceder a fijar el contador, pues cycles_needed \
 492  		  sera negativo, haciendo que el calculo de ciclos \
 493  		  ejecutados al final de emulate sea incorrecto \
 494  		*/ \
 495  		if(io_cycle_counter > (CLK)) \
 496  		{ \
 497  			cycles_needed=io_cycle_counter-(CLK); \
 498  			io_cycle_counter=0;  \
 499  		} \
 500  	}
 501  
 502  #define BANKEND_TAG ((u32)-1)
 503  
 504  #define SETUP_FETCH_BANK(FNT, BANK) \
 505  	{ \
 506  		u32 i = 0; \
 507  		while (BANK[i].low_addr != BANKEND_TAG) \
 508  		{ \
 509  			FNT(BANK[i].low_addr, BANK[i].high_addr, BANK[i].offset); \
 510  			i++; \
 511  		} \
 512  	}
 513  
 514  #define SETUP_DATA_BANK(FNT, BANK) \
 515  	{ \
 516  		u32 i = 0; \
 517  		while (BANK[i].low_addr != BANKEND_TAG) \
 518  		{ \
 519  			FNT(BANK[i].low_addr, BANK[i].high_addr, BANK[i].mem_handler, BANK[i].data); \
 520  			i++; \
 521  		} \
 522  	}
 523  
 524  
 525  #ifdef FAME_CHECK_BRANCHES
 526  
 527  #ifdef FAME_GOTOS
 528  #define CHECK_BRANCH_EXCEPTION_GOTO_END goto famec_Exec_End;
 529  #else
 530  #define CHECK_BRANCH_EXCEPTION_GOTO_END io_cycle_counter=0; return;
 531  #endif
 532  
 533  #define CHECK_BRANCH_EXCEPTION(_PC_) \
 534  	if ((_PC_)&1) \
 535  	{ \
 536  		u32 pr_PC=UNBASED_PC; \
 537  		FAME_CONTEXT.execinfo |= M68K_EMULATE_GROUP_0; \
 538  		execute_exception_group_0(M68K_ADDRESS_ERROR_EX, 0, pr_PC, 0x12 ); \
 539  		CHECK_BRANCH_EXCEPTION_GOTO_END \
 540  	}
 541  #else
 542  #define CHECK_BRANCH_EXCEPTION(_PC_)
 543  #endif
 544  
 545  
 546  
 547  typedef unsigned char  u8;
 548  typedef signed char    s8;
 549  typedef unsigned short u16;
 550  typedef signed short   s16;
 551  typedef unsigned int   u32;
 552  typedef signed int     s32;
 553  
 554  #ifdef FAME_EMULATE_TRACE
 555  static u32 flag_T;
 556  #endif
 557  static u32 flag_C;
 558  static u32 flag_V;
 559  static u32 flag_NotZ;
 560  static u32 flag_N;
 561  static u32 flag_X;         /* 16 bytes aligned */
 562  static u32 flag_S;
 563  static u32 flag_I;
 564  
 565  typedef union
 566  {
 567  #ifndef FAME_BIG_ENDIAN
 568      struct
 569      {
 570          u8 B,B1,B2,B3;
 571      } b;
 572      struct
 573      {
 574          s8 SB,SB1,SB2,SB3;
 575      } sb;
 576      struct
 577      {
 578          u16 W,W1;
 579      } w;
 580      struct
 581      {
 582          s16 SW,SW1;
 583      } sw;
 584  #else
 585      struct
 586      {
 587          u8 B3,B2,B1,B;
 588      } b;
 589      struct
 590      {
 591          s8 SB3,SB2,SB1,SB;
 592      } sb;
 593      struct
 594      {
 595          u16 W1,W;
 596      } w;
 597      struct
 598      {
 599          s16 SW1,SW;
 600      } sw;
 601  #endif
 602      u32 D;
 603      s32 SD;
 604  } famec_union32;
 605  
 606  /* M68K registers */
 607  typedef enum
 608  {
 609      M68K_REG_D0=0,
 610      M68K_REG_D1,
 611      M68K_REG_D2,
 612      M68K_REG_D3,
 613      M68K_REG_D4,
 614      M68K_REG_D5,
 615      M68K_REG_D6,
 616      M68K_REG_D7,
 617      M68K_REG_A0,
 618      M68K_REG_A1,
 619      M68K_REG_A2,
 620      M68K_REG_A3,
 621      M68K_REG_A4,
 622      M68K_REG_A5,
 623      M68K_REG_A6,
 624      M68K_REG_A7,
 625      M68K_REG_ASP,
 626      M68K_REG_PC,
 627      M68K_REG_SR
 628  } m68k_register;
 629  
 630  
 631  /* The memory blocks must be in native (Motorola) format */
 632  typedef struct
 633  {
 634      u32 low_addr;
 635      u32 high_addr;
 636      u32 offset;
 637  } M68K_PROGRAM;
 638  
 639  /* The memory blocks must be in native (Motorola) format */
 640  typedef struct
 641  {
 642      u32 low_addr;
 643      u32 high_addr;
 644      void    *mem_handler;
 645      void    *data;
 646  } M68K_DATA;
 647  
 648  /* M68K CPU CONTEXT */
 649  typedef struct
 650  {
 651      M68K_PROGRAM *fetch;
 652      M68K_DATA *read_byte;
 653      M68K_DATA *read_word;
 654      M68K_DATA *write_byte;
 655      M68K_DATA *write_word;
 656      M68K_PROGRAM *sv_fetch;
 657      M68K_DATA *sv_read_byte;
 658      M68K_DATA *sv_read_word;
 659      M68K_DATA *sv_write_byte;
 660      M68K_DATA *sv_write_word;
 661      M68K_PROGRAM *user_fetch;
 662      M68K_DATA *user_read_byte;
 663      M68K_DATA *user_read_word;
 664      M68K_DATA *user_write_byte;
 665      M68K_DATA *user_write_word;
 666      void           (*reset_handler)(void);
 667      void           (*iack_handler)(u32 level);
 668      u32 *icust_handler;
 669      famec_union32   dreg[8];
 670      famec_union32   areg[8];
 671      u32 asp;
 672      u32  pc;
 673      u32 cycles_counter;
 674      u8  interrupts[8];
 675      u16 sr;
 676      u16 execinfo;
 677  } M68K_CONTEXT;
 678  
 679  
 680  /* Custom function handler */
 681  typedef void (*icust_handler_func)(u32 vector);
 682  
 683  /*
 684   global variable
 685  */
 686  
 687  /* Main CPU context */
 688  #ifdef FAME_GLOBAL_CONTEXT
 689  M68K_CONTEXT FAME_CONTEXT;
 690  s32 io_cycle_counter;
 691  #else
 692  static M68K_CONTEXT FAME_CONTEXT;
 693  static s32 io_cycle_counter;
 694  #endif
 695  
 696  static s32 cycles_needed=0;
 697  static s32 cycles_to_do=0;
 698  #if FAME_PC_BITS == 32
 699  static u32 PC;
 700  static u16* BasePC;
 701  #else
 702  static u16 *PC;
 703  static u32 BasePC;
 704  #endif
 705  static u32 Fetch[M68K_FETCHBANK];
 706  
 707  
 708  #include <Arduino.h>
 709  /* Lookup IRQ level to attend */
 710  /* Indexed by interrupts[0] */
 711  PROGMEM static const u8 irq_level_lookup[256] =
 712  {
 713      0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
 714      5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
 715      6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
 716      6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
 717      7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
 718      7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
 719      7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
 720  };
 721  
 722  typedef u8 (*mem8_handler_func)(s32 address);
 723  typedef u16 (*mem16_handler_func)(s32 address);
 724  typedef u32 (*mem32_handler_func)(s32 address);
 725  typedef void (*memw_handler_func)(s32 address, s32 data);
 726  
 727  #ifdef FAME_SECURE_ALL_BANKS
 728  static unsigned char dummy_fetch[(1<<M68K_FETCHSFT)];
 729  #endif
 730  
 731  #ifdef FAME_DIRECT_MAPPING
 732  typedef struct
 733  {
 734      void    *mem_handler;
 735      void    *data;
 736  } M68K_INTERNAL_DATA;
 737  
 738  #ifdef FAME_SECURE_ALL_BANKS
 739  static void dummy_write(unsigned adr, unsigned btr){}
 740  static int dummy_read(unsigned adr)
 741  {
 742      return -1;
 743  }
 744  #endif
 745  
 746  static M68K_INTERNAL_DATA DataRB[M68K_DATABANK];
 747  static M68K_INTERNAL_DATA DataRW[M68K_DATABANK];
 748  static M68K_INTERNAL_DATA DataWB[M68K_DATABANK];
 749  static M68K_INTERNAL_DATA DataWW[M68K_DATABANK];
 750  
 751  #else
 752  
 753  #define DataRB FAME_CONTEXT.read_byte
 754  #define DataRW FAME_CONTEXT.read_word
 755  #define DataWB FAME_CONTEXT.write_byte
 756  #define DataWW FAME_CONTEXT.write_word
 757  
 758  #endif
 759  
 760  /* Custom function handler */
 761  typedef void (*opcode_func)(void);
 762  
 763  
 764  
 765  static u32 initialised = 0;
 766  
 767  /* exception cycle table (taken from musashi core) */
 768  PROGMEM static const s32 exception_cycle_table[256] =
 769  {
 770      4, /*  0: Reset - Initial Stack Pointer */
 771      4, /*  1: Reset - Initial Program Counter */
 772      50, /*  2: Bus Error */
 773      50, /*  3: Address Error */
 774      34, /*  4: Illegal Instruction */
 775      38, /*  5: Divide by Zero */
 776      40, /*  6: CHK */
 777      34, /*  7: TRAPV */
 778      34, /*  8: Privilege Violation */
 779      34, /*  9: Trace */
 780      4, /* 10: */
 781      4, /* 11: */
 782      4, /* 12: RESERVED */
 783      4, /* 13: Coprocessor Protocol Violation */
 784      4, /* 14: Format Error */
 785      44, /* 15: Uninitialized Interrupt */
 786      4, /* 16: RESERVED */
 787      4, /* 17: RESERVED */
 788      4, /* 18: RESERVED */
 789      4, /* 19: RESERVED */
 790      4, /* 20: RESERVED */
 791      4, /* 21: RESERVED */
 792      4, /* 22: RESERVED */
 793      4, /* 23: RESERVED */
 794      INT_TIMING, /* 24: Spurious Interrupt */
 795      INT_TIMING, /* 25: Level 1 Interrupt Autovector */
 796      INT_TIMING, /* 26: Level 2 Interrupt Autovector */
 797      INT_TIMING, /* 27: Level 3 Interrupt Autovector */
 798      INT_TIMING, /* 28: Level 4 Interrupt Autovector */
 799      INT_TIMING, /* 29: Level 5 Interrupt Autovector */
 800      INT_TIMING, /* 30: Level 6 Interrupt Autovector */
 801      INT_TIMING, /* 31: Level 7 Interrupt Autovector */
 802      34, /* 32: TRAP #0 */
 803      34, /* 33: TRAP #1 */
 804      34, /* 34: TRAP #2 */
 805      34, /* 35: TRAP #3 */
 806      34, /* 36: TRAP #4 */
 807      34, /* 37: TRAP #5 */
 808      34, /* 38: TRAP #6 */
 809      34, /* 39: TRAP #7 */
 810      34, /* 40: TRAP #8 */
 811      34, /* 41: TRAP #9 */
 812      34, /* 42: TRAP #10 */
 813      34, /* 43: TRAP #11 */
 814      34, /* 44: TRAP #12 */
 815      34, /* 45: TRAP #13 */
 816      34, /* 46: TRAP #14 */
 817      34, /* 47: TRAP #15 */
 818      4, /* 48: FP Branch or Set on Unknown Condition */
 819      4, /* 49: FP Inexact Result */
 820      4, /* 50: FP Divide by Zero */
 821      4, /* 51: FP Underflow */
 822      4, /* 52: FP Operand Error */
 823      4, /* 53: FP Overflow */
 824      4, /* 54: FP Signaling NAN */
 825      4, /* 55: FP Unimplemented Data Type */
 826      4, /* 56: MMU Configuration Error */
 827      4, /* 57: MMU Illegal Operation Error */
 828      4, /* 58: MMU Access Level Violation Error */
 829      4, /* 59: RESERVED */
 830      4, /* 60: RESERVED */
 831      4, /* 61: RESERVED */
 832      4, /* 62: RESERVED */
 833      4, /* 63: RESERVED */
 834      /* 64-255: User Defined */
 835      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
 836      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
 837      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
 838      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
 839      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
 840      4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
 841  };
 842  
 843  
 844  /*
 845   helper functions
 846  */
 847  
 848  static void famec_SetDummyFetch(void)
 849  {
 850  #ifdef FAME_SECURE_ALL_BANKS
 851      u32 i,j;
 852  
 853      i = (0 >> M68K_FETCHSFT) & M68K_FETCHMASK;
 854      j = (0xFFFFFFFF >> M68K_FETCHSFT) & M68K_FETCHMASK;
 855      while (i <= j)
 856      {
 857          Fetch[i] = ((u32)&dummy_fetch)-(i*(1<<M68K_FETCHSFT));
 858          i++;
 859      }
 860  #endif
 861  }
 862  
 863  static void famec_SetFetch(u32 low_adr, u32 high_adr, u32 fetch_adr)
 864  {
 865      u32 i, j;
 866  
 867      i = (low_adr >> M68K_FETCHSFT) & M68K_FETCHMASK;
 868      j = (high_adr >> M68K_FETCHSFT) & M68K_FETCHMASK;
 869  
 870      while (i <= j)
 871          Fetch[i++] = fetch_adr;
 872  }
 873  
 874  #ifdef FAME_DIRECT_MAPPING
 875  
 876  static void famec_SetDummyData(void)
 877  {
 878  #ifdef FAME_SECURE_ALL_BANKS
 879      u32 i, j;
 880  
 881      i = (0 >> M68K_DATASFT) & M68K_DATAMASK;
 882      j = (0xFFFFFFFF >> M68K_DATASFT) & M68K_DATAMASK;
 883  
 884      while (i <= j)
 885      {
 886          DataRB[i].mem_handler = DataRW[i].mem_handler = (void *)&dummy_read;
 887          DataWB[i].mem_handler = DataWW[i].mem_handler = (void *)&dummy_write;
 888          DataRB[i].data = DataRW[i].data = DataWB[i].data = DataWW[i].data = NULL;
 889          i++;
 890      }
 891  #endif
 892  }
 893  
 894  static void famec_SetDataRB(u32 low_adr, u32 high_adr, void *mh, void *dt)
 895  {
 896      u32 i, j;
 897  
 898      i = (low_adr >> M68K_DATASFT) & M68K_DATAMASK;
 899      j = (high_adr >> M68K_DATASFT) & M68K_DATAMASK;
 900  
 901      while (i <= j)
 902      {
 903          DataRB[i].mem_handler = mh;
 904          DataRB[i++].data = dt;
 905      }
 906  }
 907  
 908  static void famec_SetDataRW(u32 low_adr, u32 high_adr, void *mh, void *dt)
 909  {
 910      u32 i, j;
 911  
 912      i = (low_adr >> M68K_DATASFT) & M68K_DATAMASK;
 913      j = (high_adr >> M68K_DATASFT) & M68K_DATAMASK;
 914  
 915      while (i <= j)
 916      {
 917          DataRW[i].mem_handler = mh;
 918          DataRW[i++].data = dt;
 919      }
 920  }
 921  
 922  static void famec_SetDataWB(u32 low_adr, u32 high_adr, void *mh, void *dt)
 923  {
 924      u32 i, j;
 925  
 926      i = (low_adr >> M68K_DATASFT) & M68K_DATAMASK;
 927      j = (high_adr >> M68K_DATASFT) & M68K_DATAMASK;
 928  
 929      while (i <= j)
 930      {
 931          DataWB[i].mem_handler = mh;
 932          DataWB[i++].data = dt;
 933      }
 934  }
 935  
 936  static void famec_SetDataWW(u32 low_adr, u32 high_adr, void *mh, void *dt)
 937  {
 938      u32 i, j;
 939  
 940      i = (low_adr >> M68K_DATASFT) & M68K_DATAMASK;
 941      j = (high_adr >> M68K_DATASFT) & M68K_DATAMASK;
 942  
 943      while (i <= j)
 944      {
 945          DataWW[i].mem_handler = mh;
 946          DataWW[i++].data = dt;
 947      }
 948  }
 949  #endif
 950  
 951  static void famec_SetBanks(void)
 952  {
 953      famec_SetDummyFetch();
 954  
 955  	SETUP_FETCH_BANK(famec_SetFetch, FAME_CONTEXT.fetch)
 956  
 957  #ifdef FAME_DIRECT_MAPPING
 958      famec_SetDummyData();
 959  
 960  	SETUP_DATA_BANK(famec_SetDataRB, FAME_CONTEXT.read_byte)
 961  	SETUP_DATA_BANK(famec_SetDataRW, FAME_CONTEXT.read_word)
 962  	SETUP_DATA_BANK(famec_SetDataWB, FAME_CONTEXT.write_byte)
 963  	SETUP_DATA_BANK(famec_SetDataWW, FAME_CONTEXT.write_word)
 964  #endif
 965  }
 966  
 967  #ifdef FAME_ACCURATE_TIMING
 968  /*
 969   Functions used to compute accurate opcode timing (MUL/DIV)
 970  */
 971  
 972  static EXTRA_INLINE u8 bitset_count(u32 data)
 973  {
 974      unsigned int const MASK1  = 0x55555555;
 975      unsigned int const MASK2  = 0x33333333;
 976      unsigned int const MASK4  = 0x0f0f0f0f;
 977      unsigned int const MASK6 = 0x0000003f;
 978  
 979      unsigned int const w = (data & MASK1) + ((data >> 1) & MASK1);
 980      unsigned int const x = (w & MASK2) + ((w >> 2) & MASK2);
 981      unsigned int const y = ((x + (x >> 4)) & MASK4);
 982      unsigned int const z = (y + (y >> 8));
 983      unsigned int const c = (z + (z >> 16)) & MASK6;
 984  
 985      return c;
 986  }
 987  
 988  /*
 989   DIVU
 990   Unsigned division
 991  */
 992  static u32 getDivu68kCycles(u32 dividend, u16 divisor)
 993  {
 994      u32 mcycles;
 995      u32 hdivisor;
 996      int i;
 997  
 998      if ( (u16) divisor == 0)
 999          return 0;
1000  
1001      /* Overflow */
1002      if ( (dividend >> 16) >= divisor)
1003          return (mcycles = 5) * 2;
1004  
1005      mcycles = 38;
1006      hdivisor = ((u32) divisor) << 16;
1007  
1008      for ( i = 0; i < 15; i++)
1009      {
1010          u32 temp;
1011          temp = dividend;
1012  
1013          dividend <<= 1;
1014  
1015          /* If carry from shift */
1016          if ( (int) temp < 0)
1017          {
1018              dividend -= hdivisor;
1019          }
1020  
1021          else
1022          {
1023              mcycles += 2;
1024              if ( dividend >= hdivisor)
1025              {
1026                  dividend -= hdivisor;
1027                  mcycles--;
1028              }
1029          }
1030      }
1031  
1032      return mcycles * 2;
1033  }
1034  
1035  /*
1036   DIVS
1037   Signed division
1038  */
1039  static u32 getDivs68kCycles(s32 dividend, s16 divisor)
1040  {
1041      u32 mcycles;
1042      u32 aquot;
1043      int i;
1044  
1045      if ( (s16) divisor == 0)
1046          return 0;
1047  
1048      mcycles = 6;
1049  
1050      if ( dividend < 0)
1051          mcycles++;
1052  
1053      /*  Check for absolute overflow */
1054      if ( ((u32) abs( dividend) >> 16) >= (u16) abs( divisor))
1055      {
1056          return (mcycles + 2) * 2;
1057      }
1058  
1059      /* Absolute quotient */
1060      aquot = (u32) abs( dividend) / (u16) abs( divisor);
1061  
1062      mcycles += 55;
1063  
1064      if ( divisor >= 0)
1065      {
1066          if ( dividend >= 0)
1067              mcycles--;
1068          else
1069              mcycles++;
1070      }
1071  
1072      /* Count 15 msbits in absolute of quotient */
1073  
1074      for ( i = 0; i < 15; i++)
1075      {
1076          if ( (s16) aquot >= 0)
1077              mcycles++;
1078          aquot <<= 1;
1079      }
1080  
1081      return mcycles * 2;
1082  }
1083  #endif
1084  
1085  /*
1086   Read / Write functions
1087  */
1088  
1089  static EXTRA_INLINE u32 Read_Byte(u32 addr)
1090  {
1091      u32 i=0;
1092      s32 val;
1093  
1094      addr&=M68K_ADDR_MASK;
1095  #ifdef FAME_DEBUG
1096      printf("Reading byte from addr = 0x%08X\n",addr);
1097  #endif
1098  
1099  #ifndef FAME_DIRECT_MAPPING
1100      while ( ((FAME_CONTEXT.read_byte[i].low_addr > addr) || (FAME_CONTEXT.read_byte[i].high_addr < addr)) && (FAME_CONTEXT.read_byte[i].low_addr != BANKEND_TAG) )
1101          i++;
1102  
1103      if (FAME_CONTEXT.read_byte[i].low_addr == BANKEND_TAG)
1104          return (u32)-1;
1105  #else
1106      i=addr>>M68K_DATASFT;
1107  #endif
1108  
1109       if (DataRB[i].mem_handler)
1110          val= (*((mem8_handler_func *)&DataRB[i].mem_handler))(addr);
1111      else
1112  #ifndef FAME_BIG_ENDIAN
1113          val = *((u8 *)(((u32)DataRB[i].data) + (addr^1)));
1114  #else
1115          val = *((u8 *)(((u32)DataRB[i].data) + (addr)));
1116  #endif
1117  
1118  #ifdef FAME_DEBUG
1119      printf("Reading 0x%08X = 0x%04X...\n",addr,val);
1120  #endif
1121  
1122      return val;
1123  }
1124  
1125  static EXTRA_INLINE u32 Read_Word(u32 addr)
1126  {
1127      u32 i=0;
1128      s32 val;
1129  
1130      addr&=M68K_ADDR_MASK;
1131  #ifdef FAME_DEBUG
1132      printf("Reading from addr = 0x%08X\n",addr);
1133  #endif
1134  
1135  #ifndef FAME_DIRECT_MAPPING
1136      while ( ((FAME_CONTEXT.read_word[i].low_addr > addr) || (FAME_CONTEXT.read_word[i].high_addr < addr)) && (FAME_CONTEXT.read_word[i].low_addr != BANKEND_TAG) )
1137          i++;
1138  
1139      if (FAME_CONTEXT.read_word[i].low_addr == BANKEND_TAG)
1140          return (u32)-1;
1141  #else
1142      i=addr>>M68K_DATASFT;
1143  #endif
1144  
1145      if (DataRW[i].mem_handler)
1146          val= (*((mem16_handler_func *)&DataRW[i].mem_handler))(addr);
1147      else
1148          val = *((u16 *)(((u32)DataRW[i].data) + addr));
1149  
1150  #ifdef FAME_DEBUG
1151      printf("Reading 0x%08X = 0x%04X...\n",addr,val);
1152  #endif
1153  
1154      return val;
1155  }
1156  
1157  static EXTRA_INLINE void Write_Byte(u32 addr, u32 data)
1158  {
1159      u32 i=0;
1160  
1161      addr&=M68K_ADDR_MASK;
1162  #ifdef FAME_DEBUG
1163      printf("Writing byte 0x%08X = 0x%04X...\n",addr,data);
1164  #endif
1165  
1166  #ifndef FAME_DIRECT_MAPPING
1167      while ( ((FAME_CONTEXT.write_byte[i].low_addr > addr) || (FAME_CONTEXT.write_byte[i].high_addr < addr)) && (FAME_CONTEXT.write_byte[i].low_addr != BANKEND_TAG) )
1168          i++;
1169      if (FAME_CONTEXT.write_byte[i].low_addr == BANKEND_TAG)
1170          return;
1171  #else
1172      i=addr>>M68K_DATASFT;
1173  #endif
1174  
1175      if (DataWB[i].mem_handler != NULL)
1176          (*((memw_handler_func *)&DataWB[i].mem_handler))(addr,data);
1177      else
1178  #ifndef FAME_BIG_ENDIAN
1179          *((u8 *)(((u32)DataWB[i].data)+ (addr^1))) = data;
1180  #else
1181          *((u8 *)(((u32)DataWB[i].data)+ (addr))) = data;
1182  #endif
1183  }
1184  
1185  
1186  static EXTRA_INLINE void Write_Word(u32 addr, u32 data)
1187  {
1188      u32 i=0;
1189  
1190      addr&=M68K_ADDR_MASK;
1191  #ifdef FAME_DEBUG
1192      printf("Writing 0x%08X = 0x%04X...\n",addr,data);
1193  #endif
1194  
1195  #ifndef FAME_DIRECT_MAPPING
1196      while ( ((FAME_CONTEXT.write_word[i].low_addr > addr) || (FAME_CONTEXT.write_word[i].high_addr < addr)) && (FAME_CONTEXT.write_word[i].low_addr != BANKEND_TAG) )
1197          i++;
1198      if (FAME_CONTEXT.write_word[i].low_addr == BANKEND_TAG)
1199          return;
1200  #else
1201      i=addr>>M68K_DATASFT;
1202  #endif
1203  
1204      if (DataWW[i].mem_handler != NULL)
1205          (*((memw_handler_func *)&DataWW[i].mem_handler))(addr,data);
1206      else
1207          *((u16 *)(((u32)DataWW[i].data) + addr)) = data;
1208  }
1209  
1210  static u32 Opcode;
1211  
1212  /*
1213   Chequea las interrupciones y las inicia
1214  */
1215  static EXTRA_INLINE s32 interrupt_chk(void)
1216  {
1217      /* Bit 0 MUST be zero at all times */
1218      assert((FAME_CONTEXT.interrupts[0] & 1) == 0);
1219  
1220      if (FAME_CONTEXT.interrupts[0])
1221      {
1222          /* There is a pending IRQ */
1223          const u8 irql = irq_level_lookup[FAME_CONTEXT.interrupts[0]];
1224  
1225          if (irql == 7)		/* NMI */
1226              return irql;
1227          else if (irql > flag_I)
1228              return irql;
1229      }
1230  
1231  #ifdef FAME_EMULATE_TRACE
1232      if (flag_T)
1233      {
1234          /*
1235          		FAME_CONTEXT.execinfo |= M68K_EMULATE_TRACE;
1236          		cycles_needed= io_cycle_counter;
1237          		io_cycle_counter=0;
1238          */
1239          return -1;
1240      }
1241  #endif
1242      return 0;
1243  }
1244  
1245  
1246  static EXTRA_INLINE void execute_exception(s32 vect)
1247  {
1248  	/* comprobar si hay tabla funciones manejadoras */
1249      if (FAME_CONTEXT.icust_handler && FAME_CONTEXT.icust_handler[vect])
1250      {
1251          FAME_CONTEXT.sr = GET_SR;
1252          FAME_CONTEXT.pc = UNBASED_PC;
1253          (*(icust_handler_func*)&FAME_CONTEXT.icust_handler[vect])(vect);
1254      }
1255      else
1256      {
1257          u32 newPC;
1258          u32 oldPC;
1259          u32 oldSR = GET_SR;
1260  
1261          READ_LONG_F(vect * 4, newPC)
1262  
1263          /* swap A7 and USP */
1264          if (!flag_S)
1265          {
1266              u32 tmpSP;
1267  
1268              tmpSP = ASP;
1269              ASP = AREG(7);
1270              AREG(7) = tmpSP;
1271          }
1272  
1273          oldPC = UNBASED_PC;
1274          PUSH_32_F(oldPC)
1275          PUSH_16_F(oldSR)
1276  
1277          /* adjust SR */
1278          flag_S = M68K_SR_S;
1279  
1280          SET_PC(newPC)
1281      }
1282  
1283  	io_cycle_counter -= exception_cycle_table[vect];
1284  }
1285  
1286  static EXTRA_INLINE void interrupt_attend(s32 line)
1287  {
1288  	/* al atender la IRQ, la CPU sale del estado parado */
1289  	FAME_CONTEXT.execinfo &= ~M68K_HALTED;
1290  
1291  	/* Desactivar interrupcion */
1292  	FAME_CONTEXT.interrupts[0] &= ~(1 << ((u32)line));
1293  
1294  	execute_exception(FAME_CONTEXT.interrupts[(u32)line]);
1295  
1296  	/* comprobar si hay rutina de acknowledge */
1297  	if (FAME_CONTEXT.iack_handler != NULL)
1298  		FAME_CONTEXT.iack_handler(line);
1299  
1300  	flag_I = (u32)line;
1301  }
1302  
1303  /* Group 0 exceptions are not handled actually */
1304  static EXTRA_INLINE void execute_exception_group_0(s32 vect, u16 inst_reg, s32 addr, u16 spec_info)
1305  {
1306      execute_exception(vect);
1307      if (!(FAME_CONTEXT.icust_handler && FAME_CONTEXT.icust_handler[vect]))
1308      {
1309          PUSH_16_F(inst_reg);
1310          PUSH_32_F(addr);
1311          PUSH_16_F(spec_info);
1312      }
1313  }
1314  
1315  /* Performs the required actions to finish the emulate call */
1316  static EXTRA_INLINE void finish_emulate(const s32 cycles_to_add)
1317  {
1318      FAME_CONTEXT.sr = GET_SR;
1319      FAME_CONTEXT.pc = UNBASED_PC;
1320  
1321      FAME_CONTEXT.execinfo &= ~M68K_RUNNING;
1322  
1323      /* Actualizar contador de ciclos */
1324      FAME_CONTEXT.cycles_counter += cycles_to_add;
1325  
1326  #ifdef FAME_DEBUG
1327      printf("<-PC=0x%08X (%p-%p)\n",UNBASED_PC,PC,BasePC);
1328  #endif
1329  }
1330  
1331  #ifndef FAME_GOTOS
1332  
1333  #define OPCODE(N_OP) static void OP_##N_OP(void)
1334  #define CAST_OP(N_OP) (opcode_func)&OP_##N_OP
1335  #include "famec_opcodes.h"
1336  #else
1337  #define OPCODE(N_OP) OP_##N_OP:
1338  #define CAST_OP(N_OP) (opcode_func)&&OP_##N_OP
1339  #endif
1340  
1341  //static opcode_func JumpTable[0x10000];
1342  #include "jumptable.h"
1343  
1344  /***********************/
1345  /* core main functions */
1346  /***********************/
1347  
1348  /***************************************************************************/
1349  /* m68k_init()                                                             */
1350  /* Debe ser llamado para inicializar la tabla de saltos de instruccion     */
1351  /* No recibe parametros y no devuelve nada                                 */
1352  /***************************************************************************/
1353  void FAME_API(init)(void)
1354  {
1355  #ifdef FAME_DEBUG
1356      puts("Initializing FAME...");
1357  #endif
1358  
1359  #ifndef FAME_GOTOS
1360      //BUILD_OPCODE_TABLE
1361      initialised = 1;
1362  #endif
1363  
1364  #ifdef FAME_DEBUG
1365      puts("FAME initialized.");
1366  #endif
1367  }
1368  
1369  /******************************************************************************/
1370  /* m68k_reset()																  */
1371  /* Parametros: Ninguno														  */
1372  /* Retorno: Exito de la operacion                                             */
1373  /*     M68K_OK (0):  La funcion se ha ejecutado satisfactoriamente            */
1374  /*     M68K_RUNNING (1): No se puede resetear porque la CPU esta en ejecucion */
1375  /*     M68K_NO_SUP_ADDR_SPACE (2):  No se puede resetear porque no hay mapa   */
1376  /*             de memoria supervisor de extraccion de opcodes                 */
1377  /******************************************************************************/
1378  u32 FAME_API(reset)(void)
1379  {
1380  #ifndef FAME_GOTOS
1381      assert(initialised);
1382  #endif
1383  
1384      /* Si la CPU esta en ejecucion, salir con M68K_RUNNING */
1385      if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1386          return M68K_RUNNING;
1387  
1388      /* Si no hay mapa de memoria supervisor, salir con M68K_NO_SUP_ADDR_SPACE */
1389      if (!FAME_CONTEXT.sv_fetch)
1390          return M68K_NO_SUP_ADDR_SPACE;
1391  
1392      FAME_CONTEXT.fetch = FAME_CONTEXT.sv_fetch;
1393      FAME_CONTEXT.read_byte = FAME_CONTEXT.sv_read_byte;
1394      FAME_CONTEXT.read_word = FAME_CONTEXT.sv_read_word;
1395      FAME_CONTEXT.write_byte = FAME_CONTEXT.sv_write_byte;
1396      FAME_CONTEXT.write_word = FAME_CONTEXT.sv_write_word;
1397  
1398      /* Resetear registros */
1399      memset(&FAME_CONTEXT.dreg[0], 0, 16*4);
1400  
1401      /* Resetear interrupts, execinfo y ASP */
1402      memset(&FAME_CONTEXT.interrupts[0], 0, 8);
1403      FAME_CONTEXT.execinfo = 0;
1404      ASP = 0;
1405  
1406      /* Fijar registro de estado */
1407      FAME_CONTEXT.sr = 0x2700;
1408  
1409      /* Obtener puntero de pila inicial y PC */
1410  	READ_LONG_F(0, AREG(7));
1411  	READ_LONG_F(4, FAME_CONTEXT.pc);
1412  
1413  #ifdef FAME_DEBUG
1414      puts("Reset 68k done!\n");
1415      printf("PC = 0x%08X\n",FAME_CONTEXT.pc);
1416  #endif
1417  
1418      return M68K_OK;
1419  }
1420  
1421  
1422  /******************************************************************************/
1423  /* m68k_raise_irq(level,vector)			                                      */
1424  /* Parametros: level = nivel de interrupcion                                  */
1425  /*             vector = puntero a la direccion de la rutina de atencion       */
1426  /*                      -1 auto, -2 interrupcion espuria                      */
1427  /* Retorno: Exito de la operacion                                             */
1428  /*         0  La interrupcion se ha habilitado satisfactoriamente             */
1429  /*        -1  No se ha podido habilitar porque ya existe otra interrupcion    */
1430  /*            en ese nivel.                                                   */
1431  /*        -2  No se ha podido habilitar porque el vector no es valido o       */
1432  /*	                 el nivel es igual a 0.                                   */
1433  /******************************************************************************/
1434  s32 FAME_API(raise_irq)(s32 level, s32 vector)
1435  {
1436      /* Enmascarar nivel de interrupcion */
1437      level &=7;
1438  
1439      /* Nivel de interrupcion = 0 no es valido */
1440      if (!level) return M68K_IRQ_INV_PARAMS;
1441  
1442      /* Comprobar si existe una interrupcion activada en ese nivel */
1443      if (FAME_CONTEXT.interrupts[0] & (1 << level))
1444          return M68K_IRQ_LEVEL_ERROR;
1445  
1446      /* El vector de interrupcion no puede ser > 255 ni menor que -2 */
1447      if ((vector > 255) || (vector < M68K_SPURIOUS_IRQ))
1448      {
1449          return M68K_IRQ_INV_PARAMS;
1450      }
1451  
1452      /* Dar de alta la interrupcion en interrupts */
1453      FAME_CONTEXT.interrupts[0] |= (1 << level);
1454  
1455      switch (vector)
1456      {
1457      case M68K_SPURIOUS_IRQ:
1458          FAME_CONTEXT.interrupts[level] = 0x18;
1459          break;
1460      case M68K_AUTOVECTORED_IRQ:
1461          FAME_CONTEXT.interrupts[level] = level + 0x18;
1462          break;
1463      default:
1464          FAME_CONTEXT.interrupts[level] = vector;
1465          break;
1466      }
1467  #ifdef FAME_DEBUG
1468      printf("RAISE interrupts[%i]=0x%X\n",level,FAME_CONTEXT.interrupts[level]);
1469  #endif
1470  
1471      /* Testear si la CPU esta detenida (mediante STOP) */
1472      if (FAME_CONTEXT.execinfo & M68K_HALTED)
1473      {
1474          /* Si la IRQ es NMI o si supera la mascara de interrupcion, */
1475          /* salir de estado parado                                   */
1476          if ((level == 7) || (level > ((FAME_CONTEXT.sr >> 8) & 0x7)))
1477          {
1478              FAME_CONTEXT.execinfo &= ~M68K_HALTED;
1479          }
1480      }
1481  
1482      return M68K_OK;
1483  }
1484  
1485  
1486  /******************************************************************************/
1487  /* m68k_lower_irq(level)                                                      */
1488  /* Parametros: Nivel de la interrupcion a retirar                             */
1489  /* Retorno: Exito de la operacion                                             */
1490  /*         0  La interrupcion se ha retirado satisfactoriamente               */
1491  /*        -1  No se ha podido retirar porque esa interrupcion                 */
1492  /*			  no esta habilitada.                                             */
1493  /*        -2  No se ha podido retirar porque el nivel es 0 o mayor            */
1494  /*				o igual que 7 (no se puede retirar la NMI)                    */
1495  /******************************************************************************/
1496  s32 FAME_API(lower_irq)(s32 level)
1497  {
1498      /* Enmascarar nivel de interrupcion */
1499      level &=7;
1500  
1501      /* Nivel de interrupcion = 0 no es valido */
1502      if (!level) return M68K_IRQ_INV_PARAMS;
1503  
1504      /* La interrupcion de nivel 7 (NMI) no se puede bajar */
1505      if (level > 6)
1506      {
1507          return M68K_IRQ_INV_PARAMS;
1508      }
1509  
1510      /* Comprobar que la interrupcion este activada */
1511      if (FAME_CONTEXT.interrupts[0] & (1 << level))
1512      {
1513          /* Dar de baja la interrupcion */
1514          FAME_CONTEXT.interrupts[0] &= ~(1 << level);
1515      }
1516      else
1517      {
1518          return M68K_IRQ_LEVEL_ERROR;
1519      }
1520  
1521      return M68K_OK;
1522  }
1523  
1524  /******************************************************************************/
1525  /* m68k_get_context_size                                                      */
1526  /* No recibe parametros                                                       */
1527  /* Retorno: Tamano del contexto en bytes                                      */
1528  /******************************************************************************/
1529  s32 FAME_API(get_context_size)(void)
1530  {
1531      return sizeof(M68K_CONTEXT);
1532  }
1533  
1534  /***************************************************************************/
1535  /* m68k_get_context(address)                                               */
1536  /* Parametro: Direccion del contexto                                       */
1537  /* No retorna ningun valor                                                 */
1538  /***************************************************************************/
1539  void FAME_API(get_context)(void *context)
1540  {
1541      memcpy(context,&FAME_CONTEXT,sizeof(M68K_CONTEXT));
1542  }
1543  
1544  /***************************************************************************/
1545  /* m68k_set_context(address)                                               */
1546  /* Parametro: Direccion del contexto                                       */
1547  /* No retorna ningun valor                                                 */
1548  /***************************************************************************/
1549  void FAME_API(set_context)(void *context)
1550  {
1551      memcpy(&FAME_CONTEXT,context,sizeof(M68K_CONTEXT));
1552      famec_SetBanks();
1553  }
1554  
1555  /****************************************************************************/
1556  /* m68k_get_pc()                                                            */
1557  /* No recibe parametros                                                     */
1558  /* Retorna 68k PC                                                           */
1559  /****************************************************************************/
1560  u32 FAME_API(get_pc)(void)
1561  {
1562      return (FAME_CONTEXT.execinfo & M68K_RUNNING) ? UNBASED_PC : FAME_CONTEXT.pc;
1563  }
1564  
1565  /***************************************************************************/
1566  /*  m68k_get_register(register)                                            */
1567  /*  Parametro: Registro a obtener valor (indice)                           */
1568  /*  Retorno: Valor del registro requerido                                  */
1569  /*  Observacion: En caso de que el indice no sea correcto                  */
1570  /*               la funcion devolvera -1                                   */
1571  /***************************************************************************/
1572  s32 FAME_API(get_register)(m68k_register reg)
1573  {
1574      switch (reg)
1575      {
1576      case M68K_REG_D0:
1577      case M68K_REG_D1:
1578      case M68K_REG_D2:
1579      case M68K_REG_D3:
1580      case M68K_REG_D4:
1581      case M68K_REG_D5:
1582      case M68K_REG_D6:
1583      case M68K_REG_D7:
1584          return DREG(reg - M68K_REG_D0);
1585  
1586      case M68K_REG_A0:
1587      case M68K_REG_A1:
1588      case M68K_REG_A2:
1589      case M68K_REG_A3:
1590      case M68K_REG_A4:
1591      case M68K_REG_A5:
1592      case M68K_REG_A6:
1593      case M68K_REG_A7:
1594          return AREG(reg - M68K_REG_A0);
1595  
1596      case M68K_REG_ASP:
1597          return ASP;
1598  
1599      case M68K_REG_PC:
1600          return FAME_API(get_pc)();
1601  
1602      case M68K_REG_SR:
1603  		return (FAME_CONTEXT.execinfo & M68K_RUNNING) ? GET_SR : FAME_CONTEXT.sr;
1604  
1605      default:
1606          return M68K_INV_REG;
1607      }
1608  }
1609  
1610  /***********************************************************************/
1611  /*  m68k_set_register(register,value)                                  */
1612  /*  Parametros: Registro (indice) y valor a asignar                    */
1613  /*  Retorno: Exito de la operacion                                     */
1614  /*           0  La operacion se ha realizado satisfactoriamente        */
1615  /*           1  El indice del registro no es valido (fuera de limites) */
1616  /***********************************************************************/
1617  s32 FAME_API(set_register)(m68k_register reg, u32 value)
1618  {
1619      switch (reg)
1620      {
1621      case M68K_REG_D0:
1622      case M68K_REG_D1:
1623      case M68K_REG_D2:
1624      case M68K_REG_D3:
1625      case M68K_REG_D4:
1626      case M68K_REG_D5:
1627      case M68K_REG_D6:
1628      case M68K_REG_D7:
1629          DREG(reg - M68K_REG_D0) = value;
1630          break;
1631  
1632      case M68K_REG_A0:
1633      case M68K_REG_A1:
1634      case M68K_REG_A2:
1635      case M68K_REG_A3:
1636      case M68K_REG_A4:
1637      case M68K_REG_A5:
1638      case M68K_REG_A6:
1639      case M68K_REG_A7:
1640          AREG(reg - M68K_REG_A0) = value;
1641          break;
1642  
1643      case M68K_REG_ASP:
1644          ASP = value;
1645          break;
1646  
1647      case M68K_REG_PC:
1648          if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1649          {
1650              SET_PC(value);
1651          }
1652          else
1653          {
1654              FAME_CONTEXT.pc = value;
1655          }
1656          break;
1657  
1658      case M68K_REG_SR:
1659          if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1660          {
1661  			SET_SR(value);
1662  		}
1663  		else
1664  		{
1665  	        FAME_CONTEXT.sr = value & 0xFFFF;
1666  		}
1667          break;
1668  
1669      default:
1670          return M68K_INV_REG;
1671      }
1672  
1673      return M68K_OK;
1674  }
1675  
1676  /*********************************************************/
1677  /*  m68k_fetch(address,access_type)                      */
1678  /*  Lee una palabra del espacio de memoria del 68k       */
1679  /*  Parametro: Direccion de la palabra y tipo de acceso  */
1680  /*  Retorno: La palabra o -1 en caso de dir. no valida   */
1681  /*********************************************************/
1682  s32 FAME_API(fetch)(u32 addr, u32 memory_space)
1683  {
1684      u32 i=0;
1685      s32 val;
1686      M68K_DATA *ds = NULL;
1687      M68K_PROGRAM *ps = NULL;
1688  
1689      switch (memory_space & 2)
1690      {
1691      case M68K_SUP_ADDR_SPACE:
1692          if ((memory_space & 1) == M68K_PROG_ADDR_SPACE)
1693              ps = FAME_CONTEXT.sv_fetch;
1694          else
1695              ds = FAME_CONTEXT.sv_read_word;
1696          break;
1697  
1698      case M68K_USER_ADDR_SPACE:
1699          if ((memory_space & 1) == M68K_PROG_ADDR_SPACE)
1700              ps = FAME_CONTEXT.user_fetch;
1701          else
1702              ds = FAME_CONTEXT.user_read_word;
1703          break;
1704      }
1705  
1706      if (ps == NULL)
1707      {
1708          while ( ((ds[i].low_addr > addr) || (ds[i].high_addr < addr)) && (ds[i].low_addr != BANKEND_TAG) )
1709          {
1710  #ifdef FAME_DEBUG
1711              printf("RW not found in %d region... 0x%08X - 0x%08X --> 0x%08X\n",i,ds[i].low_addr,ds[i].high_addr,addr);
1712  #endif
1713  
1714              i++;
1715          }
1716  
1717          if (ds[i].low_addr == BANKEND_TAG)
1718          {
1719              /* Error de BUS */
1720  #ifdef FAME_DEBUG
1721              printf("ERROR de BUS en region %d...\n",i);
1722  #endif
1723              return -1;
1724          }
1725          else
1726          {
1727              if (ds[i].mem_handler != NULL)
1728              {
1729  #ifdef FAME_DEBUG
1730                  puts("Handled...\n");
1731  #endif
1732                  val= (*((mem16_handler_func *)&ds[i].mem_handler))(addr);
1733              }
1734              else
1735              {
1736  #ifdef FAME_DEBUG
1737                  printf("Ptr en region %d... addr: %p\n",i,ds[i].data);
1738  #endif
1739                  val = *((u16 *)(((u32)ds[i].data) + addr));
1740  #ifdef FAME_DEBUG
1741                  puts("read");
1742  #endif
1743              }
1744          }
1745  
1746  #ifdef FAME_DEBUG
1747          printf("Reading 0x%08X = 0x%04X...\n",addr,val);
1748  #endif
1749      }
1750      else
1751      {
1752          u32 tmp=Fetch[((addr) >> M68K_FETCHSFT) & M68K_FETCHMASK];
1753          u16 *p= (u16*)(((addr) & M68K_ADDR_MASK) + (tmp));
1754          val = *p;
1755  #ifdef FAME_DEBUG
1756          printf("@%08X *%p=%04X\n",addr,p,val);
1757  #endif
1758      }
1759  
1760      return val;
1761  }
1762  
1763  /******************************************************/
1764  /*  m68k_get_cycles_counter()                         */
1765  /*  Retorna el cycles_counter                         */
1766  /*  Parametro: Ninguno                                */
1767  /*  Retorno: cycles_counter                           */
1768  /******************************************************/
1769  u32 FAME_API(get_cycles_counter)(void)
1770  {
1771      if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1772  		return (cycles_to_do - io_cycle_counter) + FAME_CONTEXT.cycles_counter;
1773  	else
1774  		return FAME_CONTEXT.cycles_counter;
1775  }
1776  
1777  /******************************************************/
1778  /*  m68k_trip_cycles_counter()                        */
1779  /*  Retorna el cycles_counter y lo reinicializa       */
1780  /*  Parametro: Ninguno                                */
1781  /*  Retorno: cycles_counter                           */
1782  /******************************************************/
1783  u32 FAME_API(trip_cycles_counter)(void)
1784  {
1785      s32 ret=FAME_CONTEXT.cycles_counter;
1786  
1787      if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1788      {
1789          cycles_to_do-=io_cycle_counter;
1790          io_cycle_counter=0;
1791      }
1792      io_cycle_counter=FAME_CONTEXT.cycles_counter=0;
1793      return ret;
1794  }
1795  
1796  /**********************************************************/
1797  /*  m68k_control_cycles_counter(n)                        */
1798  /*  Retorna el cycles_counter y lo reinicializa si        */
1799  /*  cycles_counter = n                                    */
1800  /*  Parametro: ciclos = n                                 */
1801  /*  Retorno: cycles_counter                               */
1802  /**********************************************************/
1803  u32 FAME_API(control_cycles_counter)(s32 cycles)
1804  {
1805      return (cycles)?FAME_API(trip_cycles_counter)():FAME_API(get_cycles_counter)();
1806  }
1807  
1808  /******************************************************/
1809  /*  m68k_release_timeslice()                          */
1810  /*  Finaliza la ejecucion del micro                   */
1811  /*   los ciclos sin ejecutar quedan en cycles_counter */
1812  /*  Parametro: Ninguno                                */
1813  /*  Retorno: Ninguno                                  */
1814  /******************************************************/
1815  void FAME_API(release_timeslice)(void)
1816  {
1817      if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1818      {
1819          io_cycle_counter = 0;
1820      }
1821  }
1822  
1823  /******************************************************/
1824  /*  m68k_stop_emulating()                             */
1825  /*  Finaliza la ejecucion del micro si esta en        */
1826  /*  ejecucion. los ciclos ejecutados seran menos      */
1827  /*  de lo normal reflejando asi la salida             */
1828  /*  Parametro: Ninguno                                */
1829  /*  Retorno: Ninguno                                  */
1830  /******************************************************/
1831  void FAME_API(stop_emulating)(void)
1832  {
1833      if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1834      {
1835  		/*
1836  		   es necesario quitar los ciclos de cycles_counter
1837  		   para que no sean vistos como ejecutados al final
1838  		   de emulate, ya que stop_emulating incrementa
1839  		   el contador con los ejecutados realmente, no los
1840  		   ciclos requeridos por la llamada a emulate
1841  		*/
1842  		FAME_CONTEXT.cycles_counter -= io_cycle_counter;
1843          io_cycle_counter = 0;
1844      }
1845  }
1846  
1847  /******************************************************/
1848  /*  m68k_add_cycles()                                 */
1849  /*  Incrementa los ciclos de reloj a ejecutar por la  */
1850  /*  CPU en las llamadas a emulate                     */
1851  /*  Parametro: Ninguno                                */
1852  /*  Retorno: Ninguno                                  */
1853  /******************************************************/
1854  void FAME_API(add_cycles)(s32 cycles)
1855  {
1856      if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1857      {
1858      	/*
1859  		  when the CPU is running, io_cycle_counter stores the remaining cycles to be run
1860  		  therefore, we have to substract in order to "increment" the clock counter
1861      	*/
1862          io_cycle_counter -= cycles;
1863      }
1864      else
1865      {
1866          FAME_CONTEXT.cycles_counter += cycles;
1867      }
1868  }
1869  
1870  
1871  /******************************************************/
1872  /*  m68k_release_cycles()                             */
1873  /*  Decrementa los ciclos de reloj a ejecutar por la  */
1874  /*  CPU en las llamadas a emulate                     */
1875  /*  Parametro: Ninguno                                */
1876  /*  Retorno: Ninguno                                  */
1877  /******************************************************/
1878  void FAME_API(release_cycles)(s32 cycles)
1879  {
1880      if (FAME_CONTEXT.execinfo & M68K_RUNNING)
1881      {
1882      	/*
1883      	  when the CPU is running, io_cycle_counter stores the remaining cycles to be run
1884      	  therefore, we have to add in order to "decrement" the clock counter
1885      	*/
1886          io_cycle_counter += cycles;
1887      }
1888      else
1889      {
1890          FAME_CONTEXT.cycles_counter -= cycles;
1891      }
1892  }
1893  
1894  /*****************************************************************************/
1895  /* m68k_get_cpu_state()                                                      */
1896  /* No recibe parametros                                                      */
1897  /* Retorna el estado de la CPU                                               */
1898  /*****************************************************************************/
1899  u32 FAME_API(get_cpu_state)(void)
1900  {
1901      return FAME_CONTEXT.execinfo;
1902  }
1903  
1904  
1905  /*
1906   main exec function
1907  */
1908  
1909  /*
1910   m68k_emulate()
1911   Parametros: Numero de ciclos a ejecutar
1912   Retorno: Exito de la operacion
1913            0  La operacion se ha realizado satisfactoriamente
1914            -1 La CPU esta detenida debido a un ERROR DE BUS DOBLE (linea)
1915               El PC ha salido de los limites (bucle no en linea)
1916  */
1917  u32 FAME_API(emulate)(s32 cycles)
1918  {
1919  #ifdef FAME_GOTOS
1920      if (!initialised)
1921      {
1922          //BUILD_OPCODE_TABLE
1923          initialised = 1;
1924      }
1925  #else
1926      assert(initialised);
1927  #endif
1928  
1929  #ifdef FAME_DEBUG
1930      printf("m68k_emulate(%d)\n",cycles);
1931  #endif
1932  
1933  #if 0
1934      /* El bit M68K_FAULTED no esta actualmente en uso */
1935      /* Comprobar si la CPU esta detenida debido a un doble error de bus */
1936      if (FAME_CONTEXT.execinfo & M68K_FAULTED) return (u32)-1;
1937  #endif
1938  
1939      /* Poner la CPU en estado de ejecucion */
1940      FAME_CONTEXT.execinfo |= M68K_RUNNING;
1941  
1942      /* Cache SR */
1943      SET_SR(FAME_CONTEXT.sr)
1944  
1945      /* Cache PPL */
1946      flag_I = M68K_PPL;
1947  
1948      /* Fijar PC */
1949      SET_PC(FAME_CONTEXT.pc)
1950  
1951  #ifdef FAME_DEBUG
1952      printf("->PC=0x%08X (%p-%p)\n",UNBASED_PC,PC,BasePC);
1953  #endif
1954  
1955      /* guardar ciclos de ejecucion solicitados */
1956      io_cycle_counter = cycles_to_do = cycles;
1957      cycles_needed = 0;
1958  
1959  #ifdef FAME_EMULATE_TRACE
1960      if (!(FAME_CONTEXT.execinfo & M68K_EMULATE_TRACE))
1961  #endif
1962      {
1963          s32 line = interrupt_chk();
1964         if (line > 0)
1965          {
1966          	interrupt_attend(line);
1967  
1968  #ifdef FAME_IRQ_CLOCKING
1969  			if(io_cycle_counter <= 0)
1970  			{
1971  				finish_emulate(cycles_to_do - io_cycle_counter);
1972  				return M68K_OK;
1973  			}
1974  #endif
1975          }
1976  #ifdef FAME_EMULATE_TRACE
1977          else if (flag_T)
1978          {
1979              /* al atender la excepcion de traza, la CPU sale del estado parado */
1980              FAME_CONTEXT.execinfo &= ~M68K_HALTED;
1981  
1982              FAME_CONTEXT.execinfo |= M68K_EMULATE_TRACE;
1983              cycles_needed= io_cycle_counter;
1984              io_cycle_counter=0;
1985          }
1986  #endif
1987      }
1988  
1989      /* Comprobar si la CPU esta parada */
1990      if (FAME_CONTEXT.execinfo & M68K_HALTED)
1991      {
1992          /* La CPU esta detenida mediante la instruccion STOP */
1993          /* Agregar ciclos de reloj requeridos */
1994          finish_emulate(cycles_to_do);
1995          return M68K_OK;
1996      }
1997  
1998  #ifdef FAME_GOTOS
1999  famec_Exec:
2000  #endif
2001  
2002  #ifdef FAME_DEBUG
2003      printf("Antes de NEXT... PC = 0x%08X\n",UNBASED_PC);
2004  #endif
2005  
2006      NEXT
2007  
2008  #ifdef FAME_GOTOS
2009  #include "famec_opcodes.h"
2010  
2011  famec_Exec_End:
2012  #endif
2013  
2014  #ifdef FAME_EMULATE_TRACE
2015      if (FAME_CONTEXT.execinfo & M68K_EMULATE_TRACE)
2016      {
2017          io_cycle_counter= cycles_needed;
2018          cycles_needed=0;
2019          FAME_CONTEXT.execinfo &= ~M68K_EMULATE_TRACE;
2020          FAME_CONTEXT.execinfo |= M68K_DO_TRACE;
2021          execute_exception(M68K_TRACE_EX);
2022          flag_T=0;
2023          if (io_cycle_counter > 0)
2024          {
2025              NEXT
2026          }
2027      }
2028      else
2029  #endif
2030          if (cycles_needed>0)
2031  			{
2032  				s32 line=interrupt_chk();
2033  				io_cycle_counter= cycles_needed;
2034  				cycles_needed=0;
2035  				if (line>0)
2036  				{
2037  					interrupt_attend(line);
2038  				}
2039  #ifdef FAME_EMULATE_TRACE
2040  				else
2041  					if (!(flag_T))
2042  #endif
2043  						if (io_cycle_counter > 0)
2044  						{
2045  							NEXT
2046  						}
2047          }
2048  
2049  	finish_emulate(cycles_to_do - io_cycle_counter);
2050      return M68K_OK;
2051  }