//--------------------------------------------------------------------------- // NEOPOP : Emulator as in Dreamland // // Copyright (c) 2001-2002 by neopop_uk //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. See also the license.txt file for // additional informations. //--------------------------------------------------------------------------- /* //--------------------------------------------------------------------------- //========================================================================= TLCS900h_interpret_single.c //========================================================================= //--------------------------------------------------------------------------- History of changes: =================== 20 JUL 2002 - neopop_uk ======================================= - Cleaned and tidied up for the source release 22 JUL 2002 - neopop_uk ======================================= - Removed setting the register file pointer to 3 in the SWI instruction This has fixed "Metal Slug 2" and flash saving in many games. 26 JUL 2002 - neopop_uk ======================================= - Prefixed all instruction functions with "sng" to avoid a repeat of the the 'EX' fiasco. 30 JUL 2002 - neopop_uk ======================================= - Um... SWI doesn't cause a problem if IFF is set to 3... why did "Metal Slug 2" start working??? //--------------------------------------------------------------------------- */ #include "../neopop.h" #include "TLCS900h_interpret.h" #include "TLCS900h_registers.h" #include "../mem.h" #include "../interrupt.h" namespace TLCS900H { //========================================================================= //===== NOP void sngNOP() { cycles = 2; } //===== NORMAL void sngNORMAL() { //Not supported cycles = 4; } //===== PUSH SR void sngPUSHSR() { push16(sr); cycles = 4; } //===== POP SR void sngPOPSR() { sr = pop16(); changedSP(); cycles = 6; } //===== MAX void sngMAX() { //Not supported cycles = 4; } //===== HALT void sngHALT() { MDFN_printf("CPU halt requested and ignored.\nPlease send me a saved state."); cycles = 8; } //===== EI #3 void sngEI() { setStatusIFF(FETCH8); int_check_pending(); cycles = 5; } //===== RETI void sngRETI() { uint16 temp = pop16(); pc = pop32(); sr = temp; changedSP(); cycles = 12; } //===== LD (n), n void sngLD8_8() { uint8 dst = FETCH8; uint8 src = FETCH8; storeB(dst, src); cycles = 5; } //===== PUSH n void sngPUSH8() { uint8 data = FETCH8; push8(data); cycles = 4; } //===== LD (n), nn void sngLD8_16() { uint8 dst = FETCH8; uint16 src = fetch16(); storeW(dst, src); cycles = 6; } //===== PUSH nn void sngPUSH16() { push16(fetch16()); cycles = 5; } //===== INCF void sngINCF() { setStatusRFP(((sr & 0x300) >> 8) + 1); cycles = 2; } //===== DECF void sngDECF() { setStatusRFP(((sr & 0x300) >> 8) - 1); cycles = 2; } //===== RET condition void sngRET() { pc = pop32(); cycles = 9; } //===== RETD dd void sngRETD() { int16 d = (int16)fetch16(); pc = pop32(); REGXSP += d; cycles = 9; } //===== RCF void sngRCF() { SETFLAG_N0; SETFLAG_V0; SETFLAG_C0; cycles = 2; } //===== SCF void sngSCF() { SETFLAG_H0; SETFLAG_N0; SETFLAG_C1; cycles = 2; } //===== CCF void sngCCF() { SETFLAG_N0; SETFLAG_C(!FLAG_C); cycles = 2; } //===== ZCF void sngZCF() { SETFLAG_N0; SETFLAG_C(!FLAG_Z); cycles = 2; } //===== PUSH A void sngPUSHA() { push8(REGA); cycles = 3; } //===== POP A void sngPOPA() { REGA = pop8(); cycles = 4; } //===== EX F,F' void sngEX() { uint8 f = sr & 0xFF; sr = (sr & 0xFF00) | f_dash; f_dash = f; cycles = 2; } //===== LDF #3 void sngLDF() { setStatusRFP(FETCH8); cycles = 2; } //===== PUSH F void sngPUSHF() { push8(sr & 0xFF); cycles = 3; } //===== POP F void sngPOPF() { sr = (sr & 0xFF00) | pop8(); cycles = 4; } //===== JP nn void sngJP16() { pc = fetch16(); cycles = 7; } //===== JP nnn void sngJP24() { pc = fetch24(); cycles = 7; } //===== CALL #16 void sngCALL16() { uint32 target = fetch16(); push32(pc); pc = target; cycles = 12; } //===== CALL #24 void sngCALL24() { uint32 target = fetch24(); push32(pc); pc = target; cycles = 12; } //===== CALR $+3+d16 void sngCALR() { int16 displacement = (int16)fetch16(); uint32 target = pc + displacement; push32(pc); pc = target; cycles = 12; } //===== LD R, n void sngLDB() { regB(first & 7) = FETCH8; cycles = 2; } //===== PUSH RR void sngPUSHW() { push16(regW(first & 7)); cycles = 3; } //===== LD RR, nn void sngLDW() { regW(first & 7) = fetch16(); cycles = 3; } //===== PUSH XRR void sngPUSHL() { push32(regL(first & 7)); cycles = 5; } //===== LD XRR, nnnn void sngLDL() { regL(first & 7) = fetch32(); cycles = 5; } //===== POP RR void sngPOPW() { regW(first & 7) = pop16(); cycles = 4; } //===== POP XRR void sngPOPL() { regL(first & 7) = pop32(); cycles = 6; } //===== JR cc,PC + d void sngJR() { if (conditionCode(first & 0xF)) { int8 displacement = (int8)FETCH8; cycles = 8; pc += displacement; } else { cycles = 4; FETCH8; } } //===== JR cc,PC + dd void sngJRL() { if (conditionCode(first & 0xF)) { int16 displacement = (int16)fetch16(); cycles = 8; pc += displacement; } else { cycles = 4; fetch16(); } } //===== LDX dst,src void sngLDX() { uint8 dst, src; FETCH8; //00 dst = FETCH8; //#8 FETCH8; //00 src = FETCH8; //# FETCH8; //00 storeB(dst, src); cycles = 9; } //===== SWI num void sngSWI() { cycles = 16; //printf("SWI: %02x\n", first & 0x7); switch(first & 7) { //System Call case 1: push32(pc); pc = loadL(0xFFFE00 + ((rCodeB(0x31) & 0x1F) << 2)); break; case 3: interrupt(0); //SWI 3 break; case 4: interrupt(1); //SWI 4 break; case 5: interrupt(2); //SWI 5 break; case 6: interrupt(3); //SWI 6 break; default: instruction_error("SWI %d is not valid.", first & 7); break; } } }; //=============================================================================