//--------------------------------------------------------------------------- // 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.c //========================================================================= //--------------------------------------------------------------------------- History of changes: =================== 20 JUL 2002 - neopop_uk ======================================= - Cleaned and tidied up for the source release 26 JUL 2002 - neopop_uk ======================================= - Fixed a nasty bug that only affects [src]"EX (mem), XWA", it was executing "EX F,F'" instead - Very bad! 28 JUL 2002 - neopop_uk ======================================= - Added generic DIV and DIVS functions 30 AUG 2002 - neopop_uk ======================================= - Fixed detection of R32+d16 addressing mode. 02 SEP 2002 - neopop_uk ======================================= - Added the undocumented type 0x13 R32 address mode. 09 SEP 2002 - neopop_uk ======================================= - Extra cycles for addressing modes. //--------------------------------------------------------------------------- */ #include "../neopop.h" #include "TLCS900h_registers.h" #include "../interrupt.h" #include "../mem.h" #include "../bios.h" #include "TLCS900h_interpret.h" #include "TLCS900h_interpret_single.h" #include "TLCS900h_interpret_src.h" #include "TLCS900h_interpret_dst.h" #include "TLCS900h_interpret_reg.h" namespace TLCS900H { static void DUMMY_instruction_error(const char* vaMessage,...) { } void (*instruction_error)(const char* vaMessage,...) = DUMMY_instruction_error; //========================================================================= uint32 mem; //Result of addressing mode int size; //operand size, 0 = Byte, 1 = Word, 2 = Long uint8 first; //The first byte uint8 R; //big R uint8 second; //The second opcode bool brCode; //Register code used? uint8 rCode; //The code int32 cycles; //How many state changes? int32 cycles_extra; //How many extra state changes? //========================================================================= uint16 fetch16(void) { uint16 a = loadW(pc); pc += 2; return a; } uint32 fetch24(void) { uint32 b, a = loadW(pc); pc += 2; b = loadB(pc++); return (b << 16) | a; } uint32 fetch32(void) { uint32 a = loadL(pc); pc += 4; return a; } //============================================================================= void parityB(uint8 value) { uint8 count = 0, i; for (i = 0; i < 8; i++) { if (value & 1) count++; value >>= 1; } // if (count & 1) == FALSE, means even, thus SET SETFLAG_V((count & 1) == 0); } void parityW(uint16 value) { uint8 count = 0, i; for (i = 0; i < 16; i++) { if (value & 1) count++; value >>= 1; } // if (count & 1) == FALSE, means even, thus SET SETFLAG_V((count & 1) == 0); } //========================================================================= void push8(uint8 data) { REGXSP -= 1; storeB(REGXSP, data);} void push16(uint16 data) { REGXSP -= 2; storeW(REGXSP, data);} void push32(uint32 data) { REGXSP -= 4; storeL(REGXSP, data);} uint8 pop8(void) { uint8 temp = loadB(REGXSP); REGXSP += 1; return temp;} uint16 pop16(void) { uint16 temp = loadW(REGXSP); REGXSP += 2; return temp;} uint32 pop32(void) { uint32 temp = loadL(REGXSP); REGXSP += 4; return temp;} //============================================================================= uint16 generic_DIV_B(uint16 val, uint8 div) { if (div == 0) { SETFLAG_V1 return (val << 8) | ((val >> 8) ^ 0xFF); } else { uint16 quo = val / (uint16)div; uint16 rem = val % (uint16)div; if (quo > 0xFF) SETFLAG_V1 else SETFLAG_V0 return (quo & 0xFF) | ((rem & 0xFF) << 8); } } uint32 generic_DIV_W(uint32 val, uint16 div) { if (div == 0) { SETFLAG_V1 return (val << 16) | ((val >> 16) ^ 0xFFFF); } else { uint32 quo = val / (uint32)div; uint32 rem = val % (uint32)div; if (quo > 0xFFFF) SETFLAG_V1 else SETFLAG_V0 return (quo & 0xFFFF) | ((rem & 0xFFFF) << 16); } } //============================================================================= uint16 generic_DIVS_B(int16 val, int8 div) { if (div == 0) { SETFLAG_V1 return (val << 8) | ((val >> 8) ^ 0xFF); } else { int16 quo = val / (int16)div; int16 rem = val % (int16)div; if (quo > 0xFF) SETFLAG_V1 else SETFLAG_V0 return (quo & 0xFF) | ((rem & 0xFF) << 8); } } uint32 generic_DIVS_W(int32 val, int16 div) { if (div == 0) { SETFLAG_V1 return (val << 16) | ((val >> 16) ^ 0xFFFF); } else { int32 quo = val / (int32)div; int32 rem = val % (int32)div; if (quo > 0xFFFF) SETFLAG_V1 else SETFLAG_V0 return (quo & 0xFFFF) | ((rem & 0xFFFF) << 16); } } //============================================================================= uint8 generic_ADD_B(uint8 dst, uint8 src) { uint8 half = (dst & 0xF) + (src & 0xF); uint32 resultC = (uint32)dst + (uint32)src; uint8 result = (uint8)(resultC & 0xFF); SETFLAG_S(result & 0x80); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int8)dst >= 0) && ((int8)src >= 0) && ((int8)result < 0)) || (((int8)dst < 0) && ((int8)src < 0) && ((int8)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N0; SETFLAG_C(resultC > 0xFF); return result; } uint16 generic_ADD_W(uint16 dst, uint16 src) { uint16 half = (dst & 0xF) + (src & 0xF); uint32 resultC = (uint32)dst + (uint32)src; uint16 result = (uint16)(resultC & 0xFFFF); SETFLAG_S(result & 0x8000); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int16)dst >= 0) && ((int16)src >= 0) && ((int16)result < 0)) || (((int16)dst < 0) && ((int16)src < 0) && ((int16)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N0; SETFLAG_C(resultC > 0xFFFF); return result; } uint32 generic_ADD_L(uint32 dst, uint32 src) { uint64 resultC = (uint64)dst + (uint64)src; uint32 result = (uint32)(resultC & 0xFFFFFFFF); SETFLAG_S(result & 0x80000000); SETFLAG_Z(result == 0); if ((((int32)dst >= 0) && ((int32)src >= 0) && ((int32)result < 0)) || (((int32)dst < 0) && ((int32)src < 0) && ((int32)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N0; SETFLAG_C(resultC > 0xFFFFFFFF); return result; } //============================================================================= uint8 generic_ADC_B(uint8 dst, uint8 src) { uint8 half = (dst & 0xF) + (src & 0xF) + FLAG_C; uint32 resultC = (uint32)dst + (uint32)src + (uint32)FLAG_C; uint8 result = (uint8)(resultC & 0xFF); SETFLAG_S(result & 0x80); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int8)dst >= 0) && ((int8)src >= 0) && ((int8)result < 0)) || (((int8)dst < 0) && ((int8)src < 0) && ((int8)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N0; SETFLAG_C(resultC > 0xFF); return result; } uint16 generic_ADC_W(uint16 dst, uint16 src) { uint16 half = (dst & 0xF) + (src & 0xF) + FLAG_C; uint32 resultC = (uint32)dst + (uint32)src + (uint32)FLAG_C; uint16 result = (uint16)(resultC & 0xFFFF); SETFLAG_S(result & 0x8000); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int16)dst >= 0) && ((int16)src >= 0) && ((int16)result < 0)) || (((int16)dst < 0) && ((int16)src < 0) && ((int16)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N0; SETFLAG_C(resultC > 0xFFFF); return result; } uint32 generic_ADC_L(uint32 dst, uint32 src) { uint64 resultC = (uint64)dst + (uint64)src + (uint64)FLAG_C; uint32 result = (uint32)(resultC & 0xFFFFFFFF); SETFLAG_S(result & 0x80000000); SETFLAG_Z(result == 0); if ((((int32)dst >= 0) && ((int32)src >= 0) && ((int32)result < 0)) || (((int32)dst < 0) && ((int32)src < 0) && ((int32)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N0; SETFLAG_C(resultC > 0xFFFFFFFF); return result; } //============================================================================= uint8 generic_SUB_B(uint8 dst, uint8 src) { uint8 half = (dst & 0xF) - (src & 0xF); uint32 resultC = (uint32)dst - (uint32)src; uint8 result = (uint8)(resultC & 0xFF); SETFLAG_S(result & 0x80); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int8)dst >= 0) && ((int8)src < 0) && ((int8)result < 0)) || (((int8)dst < 0) && ((int8)src >= 0) && ((int8)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N1; SETFLAG_C(resultC > 0xFF); return result; } uint16 generic_SUB_W(uint16 dst, uint16 src) { uint16 half = (dst & 0xF) - (src & 0xF); uint32 resultC = (uint32)dst - (uint32)src; uint16 result = (uint16)(resultC & 0xFFFF); SETFLAG_S(result & 0x8000); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int16)dst >= 0) && ((int16)src < 0) && ((int16)result < 0)) || (((int16)dst < 0) && ((int16)src >= 0) && ((int16)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N1; SETFLAG_C(resultC > 0xFFFF); return result; } uint32 generic_SUB_L(uint32 dst, uint32 src) { uint64 resultC = (uint64)dst - (uint64)src; uint32 result = (uint32)(resultC & 0xFFFFFFFF); SETFLAG_S(result & 0x80000000); SETFLAG_Z(result == 0); if ((((int32)dst >= 0) && ((int32)src < 0) && ((int32)result < 0)) || (((int32)dst < 0) && ((int32)src >= 0) && ((int32)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N1; SETFLAG_C(resultC > 0xFFFFFFFF); return result; } //============================================================================= uint8 generic_SBC_B(uint8 dst, uint8 src) { uint8 half = (dst & 0xF) - (src & 0xF) - FLAG_C; uint32 resultC = (uint32)dst - (uint32)src - (uint32)FLAG_C; uint8 result = (uint8)(resultC & 0xFF); SETFLAG_S(result & 0x80); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int8)dst >= 0) && ((int8)src < 0) && ((int8)result < 0)) || (((int8)dst < 0) && ((int8)src >= 0) && ((int8)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N1; SETFLAG_C(resultC > 0xFF); return result; } uint16 generic_SBC_W(uint16 dst, uint16 src) { uint16 half = (dst & 0xF) - (src & 0xF) - FLAG_C; uint32 resultC = (uint32)dst - (uint32)src - (uint32)FLAG_C; uint16 result = (uint16)(resultC & 0xFFFF); SETFLAG_S(result & 0x8000); SETFLAG_Z(result == 0); SETFLAG_H(half > 0xF); if ((((int16)dst >= 0) && ((int16)src < 0) && ((int16)result < 0)) || (((int16)dst < 0) && ((int16)src >= 0) && ((int16)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N1; SETFLAG_C(resultC > 0xFFFF); return result; } uint32 generic_SBC_L(uint32 dst, uint32 src) { uint64 resultC = (uint64)dst - (uint64)src - (uint64)FLAG_C; uint32 result = (uint32)(resultC & 0xFFFFFFFF); SETFLAG_S(result & 0x80000000); SETFLAG_Z(result == 0); if ((((int32)dst >= 0) && ((int32)src < 0) && ((int32)result < 0)) || (((int32)dst < 0) && ((int32)src >= 0) && ((int32)result >= 0))) {SETFLAG_V1} else {SETFLAG_V0} SETFLAG_N1; SETFLAG_C(resultC > 0xFFFFFFFF); return result; } //============================================================================= bool conditionCode(int cc) { switch(cc) { case 0: return 0; //(F) case 1: if (FLAG_S ^ FLAG_V) return 1; else return 0; //(LT) case 2: if (FLAG_Z | (FLAG_S ^ FLAG_V)) return 1; else return 0; //(LE) case 3: if (FLAG_C | FLAG_Z) return 1; else return 0; //(ULE) case 4: if (FLAG_V) return 1; else return 0; //(OV) case 5: if (FLAG_S) return 1; else return 0; //(MI) case 6: if (FLAG_Z) return 1; else return 0; //(Z) case 7: if (FLAG_C) return 1; else return 0; //(C) case 8: return 1; //always True case 9: if (FLAG_S ^ FLAG_V) return 0; else return 1; //(GE) case 10:if (FLAG_Z | (FLAG_S ^ FLAG_V)) return 0; else return 1; //(GT) case 11:if (FLAG_C | FLAG_Z) return 0; else return 1; //(UGT) case 12:if (FLAG_V) return 0; else return 1; //(NOV) case 13:if (FLAG_S) return 0; else return 1; //(PL) case 14:if (FLAG_Z) return 0; else return 1; //(NZ) case 15:if (FLAG_C) return 0; else return 1; //(NC) } #ifdef NEOPOP_DEBUG system_debug_message("Unknown Condition Code %d", cc); #endif return FALSE; } //============================================================================= uint8 get_rr_Target(void) { uint8 target = 0x80; if (size == 0 && first == 0xC7) return rCode; //Create a regCode switch(first & 7) { case 0: if (size == 1) target = 0xE0; break; case 1: if (size == 0) target = 0xE0; if (size == 1) target = 0xE4; break; case 2: if (size == 1) target = 0xE8; break; case 3: if (size == 0) target = 0xE4; if (size == 1) target = 0xEC; break; case 4: if (size == 1) target = 0xF0; break; case 5: if (size == 0) target = 0xE8; if (size == 1) target = 0xF4; break; case 6: if (size == 1) target = 0xF8; break; case 7: if (size == 0) target = 0xEC; if (size == 1) target = 0xFC; break; } return target; } uint8 get_RR_Target(void) { uint8 target = 0x80; //Create a regCode switch(second & 7) { case 0: if (size == 1) target = 0xE0; break; case 1: if (size == 0) target = 0xE0; if (size == 1) target = 0xE4; break; case 2: if (size == 1) target = 0xE8; break; case 3: if (size == 0) target = 0xE4; if (size == 1) target = 0xEC; break; case 4: if (size == 1) target = 0xF0; break; case 5: if (size == 0) target = 0xE8; if (size == 1) target = 0xF4; break; case 6: if (size == 1) target = 0xF8; break; case 7: if (size == 0) target = 0xEC; if (size == 1) target = 0xFC; break; } return target; } //========================================================================= static void ExXWA() {mem = regL(0);} static void ExXBC() {mem = regL(1);} static void ExXDE() {mem = regL(2);} static void ExXHL() {mem = regL(3);} static void ExXIX() {mem = regL(4);} static void ExXIY() {mem = regL(5);} static void ExXIZ() {mem = regL(6);} static void ExXSP() {mem = regL(7);} static void ExXWAd() {mem = regL(0) + (int8)FETCH8; cycles_extra = 2;} static void ExXBCd() {mem = regL(1) + (int8)FETCH8; cycles_extra = 2;} static void ExXDEd() {mem = regL(2) + (int8)FETCH8; cycles_extra = 2;} static void ExXHLd() {mem = regL(3) + (int8)FETCH8; cycles_extra = 2;} static void ExXIXd() {mem = regL(4) + (int8)FETCH8; cycles_extra = 2;} static void ExXIYd() {mem = regL(5) + (int8)FETCH8; cycles_extra = 2;} static void ExXIZd() {mem = regL(6) + (int8)FETCH8; cycles_extra = 2;} static void ExXSPd() {mem = regL(7) + (int8)FETCH8; cycles_extra = 2;} static void Ex8() {mem = FETCH8; cycles_extra = 2;} static void Ex16() {mem = fetch16(); cycles_extra = 2;} static void Ex24() {mem = fetch24(); cycles_extra = 3;} static void ExR32() { uint8 data = FETCH8; if (data == 0x03) { uint8 rIndex, r32; r32 = FETCH8; //r32 rIndex = FETCH8; //r8 mem = rCodeL(r32) + (int8)rCodeB(rIndex); cycles_extra = 8; return; } if (data == 0x07) { uint8 rIndex, r32; r32 = FETCH8; //r32 rIndex = FETCH8; //r16 mem = rCodeL(r32) + (int16)rCodeW(rIndex); cycles_extra = 8; return; } //Undocumented mode! if (data == 0x13) { mem = pc + (int16)fetch16(); cycles_extra = 8; //Unconfirmed... doesn't make much difference return; } cycles_extra = 5; if ((data & 3) == 1) mem = rCodeL(data) + (int16)fetch16(); else mem = rCodeL(data); } static void ExDec() { uint8 data = FETCH8; uint8 r32 = data & 0xFC; cycles_extra = 3; switch(data & 3) { case 0: rCodeL(r32) -= 1; mem = rCodeL(r32); break; case 1: rCodeL(r32) -= 2; mem = rCodeL(r32); break; case 2: rCodeL(r32) -= 4; mem = rCodeL(r32); break; } } static void ExInc() { uint8 data = FETCH8; uint8 r32 = data & 0xFC; cycles_extra = 3; switch(data & 3) { case 0: mem = rCodeL(r32); rCodeL(r32) += 1; break; case 1: mem = rCodeL(r32); rCodeL(r32) += 2; break; case 2: mem = rCodeL(r32); rCodeL(r32) += 4; break; } } static void ExRC() { brCode = TRUE; rCode = FETCH8; cycles_extra = 1; } //========================================================================= //Address Mode & Register Code static void (*decodeExtra[256])() = { /*0*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*1*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*2*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*3*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*4*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*5*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*6*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*7*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /*8*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP, ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd, /*9*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP, ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd, /*A*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP, ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd, /*B*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP, ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd, /*C*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRC, 0, 0, 0, 0, 0, 0, 0, 0, /*D*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRC, 0, 0, 0, 0, 0, 0, 0, 0, /*E*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRC, 0, 0, 0, 0, 0, 0, 0, 0, /*F*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //========================================================================= static void e(void) { instruction_error("Unknown instruction %02X", first); } static void es(void) { //instruction_error("Unknown [src] instruction %02X", second); } static void ed(void) { //instruction_error("Unknown [dst] instruction %02X", second); } static void er(void) { //instruction_error("Unknown [reg] instruction %02X", second); } //========================================================================= //Secondary (SRC) Instruction decode static void (*srcDecode[256])() = { /*0*/ es, es, es, es, srcPUSH, es, srcRLD, srcRRD, es, es, es, es, es, es, es, es, /*1*/ srcLDI, srcLDIR, srcLDD, srcLDDR, srcCPI, srcCPIR, srcCPD, srcCPDR, es, srcLD16m, es, es, es, es, es, es, /*2*/ srcLD, srcLD, srcLD, srcLD, srcLD, srcLD, srcLD, srcLD, es, es, es, es, es, es, es, es, /*3*/ srcEX, srcEX, srcEX, srcEX, srcEX, srcEX, srcEX, srcEX, srcADDi, srcADCi, srcSUBi, srcSBCi, srcANDi, srcXORi, srcORi, srcCPi, /*4*/ srcMUL, srcMUL, srcMUL, srcMUL, srcMUL, srcMUL, srcMUL, srcMUL, srcMULS, srcMULS, srcMULS, srcMULS, srcMULS, srcMULS, srcMULS, srcMULS, /*5*/ srcDIV, srcDIV, srcDIV, srcDIV, srcDIV, srcDIV, srcDIV, srcDIV, srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS, /*6*/ srcINC, srcINC, srcINC, srcINC, srcINC, srcINC, srcINC, srcINC, srcDEC, srcDEC, srcDEC, srcDEC, srcDEC, srcDEC, srcDEC, srcDEC, /*7*/ es, es, es, es, es, es, es, es, srcRLC, srcRRC, srcRL, srcRR, srcSLA, srcSRA, srcSLL, srcSRL, /*8*/ srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR, /*9*/ srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR, /*A*/ srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, /*B*/ srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, /*C*/ srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR, /*D*/ srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR, /*E*/ srcORRm, srcORRm, srcORRm, srcORRm, srcORRm, srcORRm, srcORRm, srcORRm, srcORmR, srcORmR, srcORmR, srcORmR, srcORmR, srcORmR, srcORmR, srcORmR, /*F*/ srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR }; //Secondary (DST) Instruction decode static void (*dstDecode[256])() = { /*0*/ dstLDBi, ed, dstLDWi, ed, dstPOPB, ed, dstPOPW, ed, ed, ed, ed, ed, ed, ed, ed, ed, /*1*/ ed, ed, ed, ed, dstLDBm16, ed, dstLDWm16, ed, ed, ed, ed, ed, ed, ed, ed, ed, /*2*/ dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstANDCFA, dstORCFA, dstXORCFA, dstLDCFA, dstSTCFA, ed, ed, ed, /*3*/ dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL, ed, ed, ed, ed, ed, ed, ed, ed, /*4*/ dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR, ed, ed, ed, ed, ed, ed, ed, ed, /*5*/ dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR, ed, ed, ed, ed, ed, ed, ed, ed, /*6*/ dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR, ed, ed, ed, ed, ed, ed, ed, ed, /*7*/ ed, ed, ed, ed, ed, ed, ed, ed, ed, ed, ed, ed, ed, ed, ed, ed, /*8*/ dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstORCF, dstORCF, dstORCF, dstORCF, dstORCF, dstORCF, dstORCF, dstORCF, /*9*/ dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, /*A*/ dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstTSET, dstTSET, dstTSET, dstTSET, dstTSET, dstTSET, dstTSET, dstTSET, /*B*/ dstRES, dstRES, dstRES, dstRES, dstRES, dstRES, dstRES, dstRES, dstSET, dstSET, dstSET, dstSET, dstSET, dstSET, dstSET, dstSET, /*C*/ dstCHG, dstCHG, dstCHG, dstCHG, dstCHG, dstCHG, dstCHG, dstCHG, dstBIT, dstBIT, dstBIT, dstBIT, dstBIT, dstBIT, dstBIT, dstBIT, /*D*/ dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, /*E*/ dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, /*F*/ dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET }; //Secondary (REG) Instruction decode static void (*regDecode[256])() = { /*0*/ er, er, er, regLDi, regPUSH, regPOP, regCPL, regNEG, regMULi, regMULSi, regDIVi, regDIVSi, regLINK, regUNLK, regBS1F, regBS1B, /*1*/ regDAA, er, regEXTZ, regEXTS, regPAA, er, regMIRR, er, er, regMULA, er, er, regDJNZ, er, er, er, /*2*/ regANDCFi, regORCFi, regXORCFi, regLDCFi, regSTCFi, er, er, er, regANDCFA, regORCFA, regXORCFA, regLDCFA, regSTCFA, er, regLDCcrr, regLDCrcr, /*3*/ regRES, regSET, regCHG, regBIT, regTSET, er, er, er, regMINC1, regMINC2, regMINC4, er, regMDEC1, regMDEC2, regMDEC4, er, /*4*/ regMUL, regMUL, regMUL, regMUL, regMUL, regMUL, regMUL, regMUL, regMULS, regMULS, regMULS, regMULS, regMULS, regMULS, regMULS, regMULS, /*5*/ regDIV, regDIV, regDIV, regDIV, regDIV, regDIV, regDIV, regDIV, regDIVS, regDIVS, regDIVS, regDIVS, regDIVS, regDIVS, regDIVS, regDIVS, /*6*/ regINC, regINC, regINC, regINC, regINC, regINC, regINC, regINC, regDEC, regDEC, regDEC, regDEC, regDEC, regDEC, regDEC, regDEC, /*7*/ regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, /*8*/ regADD, regADD, regADD, regADD, regADD, regADD, regADD, regADD, regLDRr, regLDRr, regLDRr, regLDRr, regLDRr, regLDRr, regLDRr, regLDRr, /*9*/ regADC, regADC, regADC, regADC, regADC, regADC, regADC, regADC, regLDrR, regLDrR, regLDrR, regLDrR, regLDrR, regLDrR, regLDrR, regLDrR, /*A*/ regSUB, regSUB, regSUB, regSUB, regSUB, regSUB, regSUB, regSUB, regLDr3, regLDr3, regLDr3, regLDr3, regLDr3, regLDr3, regLDr3, regLDr3, /*B*/ regSBC, regSBC, regSBC, regSBC, regSBC, regSBC, regSBC, regSBC, regEX, regEX, regEX, regEX, regEX, regEX, regEX, regEX, /*C*/ regAND, regAND, regAND, regAND, regAND, regAND, regAND, regAND, regADDi, regADCi, regSUBi, regSBCi, regANDi, regXORi, regORi, regCPi, /*D*/ regXOR, regXOR, regXOR, regXOR, regXOR, regXOR, regXOR, regXOR, regCPr3, regCPr3, regCPr3, regCPr3, regCPr3, regCPr3, regCPr3, regCPr3, /*E*/ regOR, regOR, regOR, regOR, regOR, regOR, regOR, regOR, regRLCi, regRRCi, regRLi, regRRi, regSLAi, regSRAi, regSLLi, regSRLi, /*F*/ regCP, regCP, regCP, regCP, regCP, regCP, regCP, regCP, regRLCA, regRRCA, regRLA, regRRA, regSLAA, regSRAA, regSLLA, regSRLA }; //========================================================================= static void src_B() { second = FETCH8; //Get the second opcode R = second & 7; size = 0; //Byte Size (*srcDecode[second])(); //Call } static void src_W() { second = FETCH8; //Get the second opcode R = second & 7; size = 1; //Word Size (*srcDecode[second])(); //Call } static void src_L() { second = FETCH8; //Get the second opcode R = second & 7; size = 2; //Long Size (*srcDecode[second])(); //Call } static void dst() { second = FETCH8; //Get the second opcode R = second & 7; (*dstDecode[second])(); //Call } static uint8 rCodeConversionB[8] = { 0xE1, 0xE0, 0xE5, 0xE4, 0xE9, 0xE8, 0xED, 0xEC }; static uint8 rCodeConversionW[8] = { 0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC }; static uint8 rCodeConversionL[8] = { 0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC }; static void reg_B() { second = FETCH8; //Get the second opcode R = second & 7; size = 0; //Byte Size if (brCode == FALSE) { brCode = TRUE; rCode = rCodeConversionB[first & 7]; } (*regDecode[second])(); //Call } static void reg_W() { second = FETCH8; //Get the second opcode R = second & 7; size = 1; //Word Size if (brCode == FALSE) { brCode = TRUE; rCode = rCodeConversionW[first & 7]; } (*regDecode[second])(); //Call } static void reg_L() { second = FETCH8; //Get the second opcode R = second & 7; size = 2; //Long Size if (brCode == FALSE) { brCode = TRUE; rCode = rCodeConversionL[first & 7]; } (*regDecode[second])(); //Call } //============================================================================= //Primary Instruction decode static void (*decode[256])() = { /*0*/ sngNOP, sngNORMAL, sngPUSHSR, sngPOPSR, sngMAX, sngHALT, sngEI, sngRETI, sngLD8_8, sngPUSH8, sngLD8_16, sngPUSH16, sngINCF, sngDECF, sngRET, sngRETD, /*1*/ sngRCF, sngSCF, sngCCF, sngZCF, sngPUSHA, sngPOPA, sngEX, sngLDF, sngPUSHF, sngPOPF, sngJP16, sngJP24, sngCALL16, sngCALL24, sngCALR, iBIOSHLE, /*2*/ sngLDB, sngLDB, sngLDB, sngLDB, sngLDB, sngLDB, sngLDB, sngLDB, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, /*3*/ sngLDW, sngLDW, sngLDW, sngLDW, sngLDW, sngLDW, sngLDW, sngLDW, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, /*4*/ sngLDL, sngLDL, sngLDL, sngLDL, sngLDL, sngLDL, sngLDL, sngLDL, sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW, /*5*/ e, e, e, e, e, e, e, e, sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL, /*6*/ sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, /*7*/ sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, /*8*/ src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B, /*9*/ src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W, /*A*/ src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L, /*B*/ dst, dst, dst, dst, dst, dst, dst, dst, dst, dst, dst, dst, dst, dst, dst, dst, /*C*/ src_B, src_B, src_B, src_B, src_B, src_B, e, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, /*D*/ src_W, src_W, src_W, src_W, src_W, src_W, e, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, /*E*/ src_L, src_L, src_L, src_L, src_L, src_L, e, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, /*F*/ dst, dst, dst, dst, dst, dst, e, sngLDX, sngSWI, sngSWI, sngSWI, sngSWI, sngSWI, sngSWI, sngSWI, sngSWI }; //============================================================================= int32 TLCS900h_interpret(void) { brCode = FALSE; first = FETCH8; //Get the first byte //Is any extra data used by this instruction? cycles_extra = 0; if (decodeExtra[first]) (*decodeExtra[first])(); (*decode[first])(); //Decode return cycles + cycles_extra; } }; //=============================================================================