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 }