/********************************************************************* * * * M65816: Portable 65816 CPU Emulator * * * * Written and Copyright (C)1996 by Joshua M. Thompson * * * * You are free to distribute this code for non-commercial purposes * * I ask only that you notify me of any changes you make to the code * * Commercial use is prohibited without my written permission * * * *********************************************************************/ #include "m65816.h" #include "macros.h" dualw A; /* Accumulator */ dualw D; /* Direct Page Register */ byte P; /* Processor Status Register */ int E; /* Emulation Mode Flag */ dualw S; /* Stack Pointer */ dualw X; /* X Index Register */ dualw Y; /* Y Index Register */ byte DB; /* Data Bank Register */ byte PB; /* Program Bank Register */ dualw PC; /* Program Counter */ int RESET,ABORT,NMI,IRQ; /* Signals from the hardware */ int STOP,WAIT; /* Set by STP and WAI opcodes */ int TRACE = 0; /* Set this to nonzero to enable tracing */ int uperiod = 10000; int ucnt = 0; #ifdef DEBUG #include "debugger.h" #endif void M65816_uperiod(int period) { uperiod = period; } void M65816_trace(int mode) { TRACE = mode; } void M65816_reset(void) { RESET = 1; } void M65816_abort(void) { ABORT = 1; } void M65816_nmi(void) { NMI = 1; } void M65816_irq(void) { IRQ = 1; } void M65816_run(void) { byte opcode; duala atmp,opaddr; dualw wtmp,otmp,operand; while (1) { if (ucnt == uperiod) { ucnt = 0; E_UPDATE(); } if (RESET) { RESET = 0; ABORT = 0; NMI = 0; IRQ = 0; STOP = 0; WAIT = 0; P = 0x34; E = 1; D.W = 0; DB = 0; PB = 0; S.W = 0x1FF; A.W = 0; X.W = 0; Y.W = 0; PC.B.L = M_READ(0xFFFC); PC.B.H = M_READ(0xFFFD); } if (STOP) continue; /* Only reset can abort STP */ if (ABORT) { WAIT = 0; if (F_getE) { S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P & ~0x10); F_setD(0); F_setI(1); PB = 0; PC.B.L = M_READ(0xFFF8); PC.B.H = M_READ(0xFFF9); } else { S_PUSH(PB); S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P); F_setD(0); F_setI(1); PB = 0; PC.B.L = M_READ(0xFFE8); PC.B.H = M_READ(0xFFE9); } } if (NMI) { WAIT = 0; if (F_getE) { S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P & ~0x10); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFFA); PC.B.H = M_READ(0xFFFB); } else { S_PUSH(PB); S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFEA); PC.B.H = M_READ(0xFFEB); } } if (IRQ && F_getI) { WAIT = 0; if (F_getE) { PC.W--; S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P & ~0x10); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFFE); PC.B.H = M_READ(0xFFFF); } else { PC.W--; S_PUSH(PB); S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFEE); PC.B.H = M_READ(0xFFEF); } } if (WAIT) continue; /* reset, abort, or interrupts can abort WAI */ #ifdef DEBUG M65816_Debug(); #endif atmp.A = PC.W++; atmp.B.B = PB; opcode = M_READ(atmp.A); switch(opcode) { case 0x00 : if (F_getE) { /* BRK s */ PC.W--; S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P | 0x10); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFFE); PC.B.H = M_READ(0xFFFF); } else { PC.W--; S_PUSH(PB); S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFE6); PC.B.H = M_READ(0xFFE7); } break; case 0x01 : O_dxi(opaddr); /* ORA (d,x) */ C_ORA(opaddr); break; case 0x02 : if (F_getE) { /* COP s */ PC.W--; S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P | ~0x10); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFF4); PC.B.H = M_READ(0xFFF5); } else { PC.W--; S_PUSH(PB); S_PUSH(PC.B.H); S_PUSH(PC.B.L); S_PUSH(P); F_setD(0); F_setI(1); PB = 0x00; PC.B.L = M_READ(0xFFE4); PC.B.H = M_READ(0xFFE5); } break; case 0x03 : O_sr(opaddr); /* ORA d,s */ C_ORA(opaddr); break; case 0x04 : O_d(opaddr); /* TSB d */ C_TSB(opaddr); break; case 0x05 : O_d(opaddr); /* ORA d */ C_ORA(opaddr); break; case 0x06 : O_d(opaddr); /* ASL d */ C_ASL(opaddr); break; case 0x07 : O_dil(opaddr); /* ORA [d] */ C_ORA(opaddr); break; case 0x08 : S_PUSH(P); /* PHP s */ break; case 0x09 : if (F_getM) { /* ORA # */ O_i8(operand); C_ORA8(operand.B.L); } else { O_i16(operand); C_ORA16(operand.W); } break; case 0x0A : if (F_getM) { /* ASL A */ C_ASL8(A.B.L); } else { C_ASL16(A.W); } break; case 0x0B : S_PUSH(D.B.H); /* PHD s */ S_PUSH(D.B.L); break; case 0x0C : O_a(opaddr); /* TSB a */ C_TSB(opaddr); break; case 0x0D : O_a(opaddr); /* ORA a */ C_ORA(opaddr); break; case 0x0E : O_a(opaddr); /* ASL a */ C_ASL(opaddr); break; case 0x0F : O_al(opaddr); /* ORA al */ C_ORA(opaddr); break; case 0x10 : O_pcr(opaddr); /* BPL r */ if (!F_getN) PC.W = opaddr.A; break; case 0x11 : O_dix(opaddr); /* ORA (d),y */ C_ORA(opaddr); break; case 0x12 : O_di(opaddr); /* ORA (d) */ C_ORA(opaddr); break; case 0x13 : O_srix(opaddr); /* ORA (d,s),y */ C_ORA(opaddr); break; case 0x14 : O_d(opaddr); /* TRB d */ C_TRB(opaddr); break; case 0x15 : O_dxx(opaddr); /* ORA d,x */ C_ORA(opaddr); break; case 0x16 : O_dxx(opaddr); /* ASL d,x */ C_ASL(opaddr); break; case 0x17 : O_dixl(opaddr); /* ORA [d],y */ C_ORA(opaddr); break; case 0x18 : F_setC(0); /* CLC i */ break; case 0x19 : O_axy(opaddr); /* ORA a,y */ C_ORA(opaddr); break; case 0x1A : if (F_getM) { /* INC A */ C_INC8(A.B.L); } else { C_INC16(A.W); } break; case 0x1B : if (F_getE) { /* TCS i */ S.B.L = A.B.L; } else { S.W = A.W; } break; case 0x1C : O_a(opaddr); /* TRB a */ C_TRB(opaddr); break; case 0x1D : O_axx(opaddr); /* ORA a,x */ C_ORA(opaddr); break; case 0x1E : O_axx(opaddr); /* ASL a,x */ C_ASL(opaddr); break; case 0x1F : O_alxx(opaddr); /* ORA al,x */ C_ORA(opaddr); break; case 0x20 : O_a(opaddr); /* JSR a */ PC.W--; S_PUSH(PC.B.H); S_PUSH(PC.B.L); PC.W = opaddr.A; break; case 0x21 : O_dxi(opaddr); /* AND (d,x) */ C_AND(opaddr); break; case 0x22 : O_al(opaddr); /* JSL al */ S_PUSH(PB); PC.W--; S_PUSH(PC.B.H); S_PUSH(PC.B.L); PC.W = opaddr.A; PB = opaddr.B.B; break; case 0x23 : O_sr(opaddr); /* AND d,s */ C_AND(opaddr); break; case 0x24 : O_d(opaddr); /* BIT d */ C_BIT(opaddr); break; case 0x25 : O_d(opaddr); /* AND d */ C_AND(opaddr); break; case 0x26 : O_d(opaddr); /* ROL d */ C_ROL(opaddr); break; case 0x27 : O_dil(opaddr); /* AND [d] */ C_AND(opaddr); break; case 0x28 : S_PULL(P); /* PLP s */ if (F_getE) P |= 0x30; break; case 0x29 : if (F_getM) { /* AND # */ O_i8(operand); C_AND8(operand.B.L); } else { O_i16(operand); C_AND16(operand.W); } break; case 0x2A : if (F_getM) { /* ROL A */ C_ROL8(A.B.L); } else { C_ROL16(A.W); } break; case 0x2B : S_PULL(D.B.L); /* PLD s */ S_PULL(D.B.H); break; case 0x2C : O_a(opaddr); /* BIT a */ C_BIT(opaddr); break; case 0x2D : O_a(opaddr); /* AND a */ C_AND(opaddr); break; case 0x2E : O_a(opaddr); /* ROL a */ C_ROL(opaddr); break; case 0x2F : O_al(opaddr); /* AND al */ C_AND(opaddr); break; case 0x30 : O_pcr(opaddr); /* BMI r */ if (F_getN) PC.W = opaddr.A; break; case 0x31 : O_dix(opaddr); /* AND (d),y */ C_AND(opaddr); break; case 0x32 : O_di(opaddr); /* AND (d) */ C_AND(opaddr); break; case 0x33 : O_srix(opaddr); /* AND (d,s),y */ C_AND(opaddr); break; case 0x34 : O_dxx(opaddr); /* BIT d,x */ C_BIT(opaddr); break; case 0x35 : O_dxx(opaddr); /* AND d,x */ C_AND(opaddr); break; case 0x36 : O_dxx(opaddr); /* ROL d,x */ C_ROL(opaddr); break; case 0x37 : O_dixl(opaddr); /* AND [d],y */ C_AND(opaddr); break; case 0x38 : F_setC(1); /* SEC i */ break; case 0x39 : O_axy(opaddr); /* AND a,y */ C_AND(opaddr); break; case 0x3A : if (F_getM) { /* DEC A */ C_DEC8(A.B.L); } else { C_DEC16(A.W); } break; case 0x3B : C_LDA16(S.W); /* TSC i */ break; case 0x3C : O_axx(opaddr); /* BIT a,x */ C_BIT(opaddr); break; case 0x3D : O_axx(opaddr); /* AND a,x */ C_AND(opaddr); break; case 0x3E : O_axx(opaddr); /* ROL a,x */ C_ROL(opaddr); break; case 0x3F : O_alxx(opaddr); /* AND al,x */ C_AND(opaddr); break; case 0x40 : S_PULL(P); /* RTI */ S_PULL(PC.B.L); S_PULL(PC.B.H); if (F_getE) S_PULL(PB); PC.W++; break; case 0x41 : O_dxi(opaddr); /* EOR (d,x) */ C_EOR(opaddr); break; case 0x42 : break; /* ??? */ case 0x43 : O_sr(opaddr); /* EOR d,s */ C_EOR(opaddr); break; case 0x44 : DB = M_READ(PC.W++); /* MVP xyc */ operand.W = M_READ(PC.W++); M_WRITE((DB << 16) | X.W,M_READ((operand.W << 16) | Y.W)); if (F_getX) { X.B.L++; Y.B.L++; } else { X.W++; Y.W++; } if (F_getM) { if (A.B.L) { A.B.L--; PC.W -= 3; } } else { if (A.W) { A.W--; PC.W -= 3; } } break; case 0x45 : O_d(opaddr); /* EOR d */ C_EOR(opaddr); break; case 0x46 : O_d(opaddr); /* LSR d */ C_LSR(opaddr); break; case 0x47 : O_dil(opaddr); /* EOR [d] */ C_EOR(opaddr); break; case 0x48 : if (!F_getM) S_PUSH(A.B.H); /* PHA */ S_PUSH(A.B.L); break; case 0x49 : if (F_getM) { /* EOR # */ O_i8(operand); C_EOR8(operand.B.L); } else { O_i16(operand); C_EOR16(operand.W); } break; case 0x4A : if (F_getM) { /* LSR A */ C_LSR8(A.B.L); } else { C_LSR16(A.W); } break; case 0x4B : S_PUSH(PB); /* PHK */ break; case 0x4C : O_a(opaddr); /* JMP a */ PC.W = opaddr.A; break; case 0x4D : O_a(opaddr); /* EOR a */ C_EOR(opaddr); break; case 0x4E : O_a(opaddr); /* LSR a */ C_LSR(opaddr); break; case 0x4F : O_al(opaddr); /* EOR al */ C_EOR(opaddr); break; case 0x50 : O_pcr(opaddr); /* BVC r */ if (!F_getV) PC.W = opaddr.A; break; case 0x51 : O_dix(opaddr); /* EOR (d),y */ C_EOR(opaddr); break; case 0x52 : O_di(opaddr); /* EOR (d) */ C_EOR(opaddr); break; case 0x53 : O_srix(opaddr); /* EOR (d,s),y */ C_EOR(opaddr); break; case 0x54 : DB = M_READ(PC.W++); /* MVN xyc */ operand.W = M_READ(PC.W++); M_WRITE((DB << 16) | X.W,M_READ((operand.W << 16) | Y.W)); if (F_getX) { X.B.L--; Y.B.L--; } else { X.W--; Y.W--; } if (F_getM) { if (A.B.L) { A.B.L--; PC.W -= 3; } } else { if (A.W) { A.W--; PC.W -= 3; } } break; case 0x55 : O_dxx(opaddr); /* EOR d,x */ C_EOR(opaddr); break; case 0x56 : O_dxx(opaddr); /* LSR d,x */ C_LSR(opaddr); break; case 0x57 : O_dixl(opaddr); /* EOR [d],y */ C_EOR(opaddr); break; case 0x58 : F_setI(0); /* CLI i */ break; case 0x59 : O_axy(opaddr); /* EOR a,y */ C_EOR(opaddr); break; case 0x5A : if (!F_getX) S_PUSH(Y.B.H); /* PHY s */ S_PUSH(Y.B.L); break; case 0x5B : D.W = A.W; /* TCD i */ break; case 0x5C : O_al(opaddr); /* JMP al */ PC.W = opaddr.A; PB = opaddr.B.B; break; case 0x5D : O_axx(opaddr); /* EOR a,x */ C_EOR(opaddr); break; case 0x5E : O_axx(opaddr); /* LSR a,x */ C_LSR(opaddr); break; case 0x5F : O_alxx(opaddr); /* EOR al,x */ C_EOR(opaddr); break; case 0x60 : S_PULL(PC.B.L); /* RTS s */ S_PULL(PC.B.H); PC.W++; break; case 0x61 : O_dxi(opaddr); /* ADC (d,x) */ C_ADC(opaddr); break; case 0x62 : O_pcrl(opaddr); /* PER s */ S_PUSH(opaddr.B.H); S_PUSH(opaddr.B.L); break; case 0x63 : O_sr(opaddr); /* ADC d,s */ C_ADC(opaddr); break; case 0x64 : O_d(opaddr); /* STZ d */ C_STZ(opaddr); break; case 0x65 : O_d(opaddr); /* ADC d */ C_ADC(opaddr); break; case 0x66 : O_d(opaddr); /* ROR d */ C_ROR(opaddr); break; case 0x67 : O_dil(opaddr); /* ADC [d] */ C_ADC(opaddr); break; case 0x68 : S_PULL(A.B.L); /* PLA s */ if (F_getM) { C_SETF8(A.B.L); } else { S_PULL(A.B.H); C_SETF16(A.W); } break; case 0x69 : if (F_getM) { /* ADC # */ O_i8(operand); C_ADC8(operand.B.L); } else { O_i16(operand); C_ADC16(operand.W); } break; case 0x6A : if (F_getM) { /* ROR A */ C_ROR8(A.B.L); } else { C_ROR16(A.W); } break; case 0x6B : S_PULL(PC.B.L); /* RTL s */ S_PULL(PC.B.H); S_PULL(PB); PC.W++; break; case 0x6C : O_ai(opaddr); /* JMP (a) */ PC.W = opaddr.A; break; case 0x6D : O_a(opaddr); /* ADC a */ C_ADC(opaddr); break; case 0x6E : O_a(opaddr); /* ROR a */ C_ROR(opaddr); break; case 0x6F : O_al(opaddr); /* ADC al */ C_ADC(opaddr); break; case 0x70 : O_pcr(opaddr); /* BVS r */ if (F_getV) PC.W = opaddr.A; break; case 0x71 : O_dix(opaddr); /* ADC (d),y */ C_ADC(opaddr); break; case 0x72 : O_di(opaddr); /* ADC (d) */ C_ADC(opaddr); break; case 0x73 : O_srix(opaddr); /* ADC (d,s),y */ C_ADC(opaddr); break; case 0x74 : O_dxx(opaddr); /* STZ d,x */ C_STZ(opaddr); break; case 0x75 : O_dxx(opaddr); /* ADC d,x */ C_ADC(opaddr); break; case 0x76 : O_dxx(opaddr); /* ROR d,x */ C_ROR(opaddr); break; case 0x77 : O_dixl(opaddr); /* ADC [d],y */ C_ADC(opaddr); break; case 0x78 : F_setI(1); /* SEI i */ break; case 0x79 : O_axy(opaddr); /* ADC a,y */ C_ADC(opaddr); break; case 0x7A : S_PULL(Y.B.L); /* PLY */ if (F_getX) { C_SETF8(Y.B.L); } else { S_PULL(Y.B.H); C_SETF16(Y.W); } break; case 0x7B : C_LDA16(D.W); /* TDC i */ break; case 0x7C : O_axi(opaddr); /* JMP (a,x) */ PC.W = opaddr.A; break; case 0x7D : O_axx(opaddr); /* ADC a,x */ C_ADC(opaddr); break; case 0x7E : O_axx(opaddr); /* ROR a,x */ C_ROR(opaddr); break; case 0x7F : O_alxx(opaddr); /* ADC al,x */ C_ADC(opaddr); break; case 0x80 : O_pcr(opaddr); /* BRA r */ PC.W = opaddr.A; break; case 0x81 : O_dxi(opaddr); /* STA (d,x) */ C_STA(opaddr); break; case 0x82 : O_pcrl(opaddr); /* BRL rl */ PC.W = opaddr.A; break; case 0x83 : O_sr(opaddr); /* STA d,s */ C_STA(opaddr); break; case 0x84 : O_d(opaddr); /* STY d */ C_STY(opaddr); break; case 0x85 : O_d(opaddr); /* STA d */ C_STA(opaddr); break; case 0x86 : O_d(opaddr); /* STX d */ C_STX(opaddr); break; case 0x87 : O_dil(opaddr); /* STA [d] */ C_STA(opaddr); break; case 0x88 : if (F_getX) { /* DEY i */ C_DEC8(Y.B.L); } else { C_DEC16(Y.W); } break; case 0x89 : if (F_getM) { /* BIT # */ O_i8(operand); F_setZ(!(A.B.L & operand.B.L)); } else { O_i16(operand); F_setZ(!(A.W & operand.W)); } break; case 0x8A : if (F_getM) { /* TXA i */ C_LDA8(X.B.L); } else { C_LDA16(X.W); } break; case 0x8B : S_PUSH(DB); /* PHB */ break; case 0x8C : O_a(opaddr); /* STY a */ C_STY(opaddr); break; case 0x8D : O_a(opaddr); /* STA a */ C_STA(opaddr); break; case 0x8E : O_a(opaddr); /* STX a */ C_STX(opaddr); break; case 0x8F : O_al(opaddr); /* STA al */ C_STA(opaddr); break; case 0x90 : O_pcr(opaddr); /* BCC r */ if (!F_getC) PC.W = opaddr.A; break; case 0x91 : O_dix(opaddr); /* STA (d),y */ C_STA(opaddr); break; case 0x92 : O_di(opaddr); /* STA (d) */ C_STA(opaddr); break; case 0x93 : O_srix(opaddr); /* STA (d,s),y */ C_STA(opaddr); break; case 0x94 : O_dxx(opaddr); /* STY d,x */ C_STY(opaddr); break; case 0x95 : O_dxx(opaddr); /* STA d,x */ C_STA(opaddr); break; case 0x96 : O_dxx(opaddr); /* STX d,x */ C_STX(opaddr); break; case 0x97 : O_dixl(opaddr); /* STA [d],y */ C_STA(opaddr); break; case 0x98 : if (F_getM) { /* TYA i */ C_LDA8(Y.B.L); } else { C_LDA16(Y.W); } break; case 0x99 : O_axy(opaddr); /* STA a,y */ C_STA(opaddr); break; case 0x9A : if (F_getE) { /* TXS i */ S.B.L = X.B.L; } else { S.W = X.W; } break; case 0x9B : if (F_getX) { /* TXY i */ C_LDY8(X.B.L); } else { C_LDY16(X.W); } break; case 0x9C : O_a(opaddr); /* STZ a */ C_STZ(opaddr); break; case 0x9D : O_axx(opaddr); /* STA a,x */ C_STA(opaddr); break; case 0x9E : O_axx(opaddr); /* STZ a,x */ C_STZ(opaddr); break; case 0x9F : O_alxx(opaddr); /* STA al,x */ C_STA(opaddr); break; case 0xA0 : if (F_getX) { /* LDY # */ O_i8(operand); C_LDY8(operand.B.L); } else { O_i16(operand); C_LDY16(operand.W); } break; case 0xA1 : O_dxi(opaddr); /* LDA (d,x) */ C_LDA(opaddr); break; case 0xA2 : if (F_getX) { /* LDX # */ O_i8(operand); C_LDX8(operand.B.L); } else { O_i16(operand); C_LDX16(operand.W); } break; case 0xA3 : O_dxi(opaddr); /* LDA d,s */ C_LDA(opaddr); break; case 0xA4 : O_d(opaddr); /* LDY d */ C_LDY(opaddr); break; case 0xA5 : O_d(opaddr); /* LDA d */ C_LDA(opaddr); break; case 0xA6 : O_d(opaddr); /* LDX d */ C_LDX(opaddr); break; case 0xA7 : O_dil(opaddr); /* LDA [d] */ C_LDA(opaddr); break; case 0xA8 : if (F_getX) { /* TAY i */ C_LDY8(A.B.L); } else { C_LDY16(A.W); } break; case 0xA9 : if (F_getM) { /* LDA # */ O_i8(operand); C_LDA8(operand.B.L); } else { O_i16(operand); C_LDA16(operand.W); } break; case 0xAA : if (F_getX) { /* TAX i */ C_LDX8(A.B.L); } else { C_LDX16(A.W); } break; case 0xAB : S_PULL(DB); /* PLB s */ break; case 0xAC : O_a(opaddr); /* LDY a */ C_LDY(opaddr); break; case 0xAD : O_a(opaddr); /* LDA a */ C_LDA(opaddr); break; case 0xAE : O_a(opaddr); /* LDX a */ C_LDX(opaddr); break; case 0xAF : O_al(opaddr); /* LDA al */ C_LDA(opaddr); break; case 0xB0 : O_pcr(opaddr); /* BCS r */ if (F_getC) PC.W = opaddr.A; break; case 0xB1 : O_dix(opaddr); /* LDA (d),y */ C_LDA(opaddr); break; case 0xB2 : O_di(opaddr); /* LDA (d) */ C_LDA(opaddr); break; case 0xB3 : O_srix(opaddr); /* LDA (d,s),y */ C_LDA(opaddr); break; case 0xB4 : O_dxx(opaddr); /* LDY d,x */ C_LDY(opaddr); break; case 0xB5 : O_dxx(opaddr); /* LDA d,x */ C_LDA(opaddr); break; case 0xB6 : O_dxy(opaddr); /* LDX d,y */ C_LDX(opaddr); break; case 0xB7 : O_dixl(opaddr); /* LDA [d],y */ C_LDA(opaddr); break; case 0xB8 : F_setV(0); /* CLV i */ break; case 0xB9 : O_axy(opaddr); /* LDA a,y */ C_LDA(opaddr); break; case 0xBA : if (F_getX) { /* TSX i */ C_LDX8(S.B.L); } else { C_LDX16(S.W); } break; case 0xBB : if (F_getX) { /* TYX i */ C_LDX8(Y.B.L); } else { C_LDX16(Y.W); } break; case 0xBC : O_axx(opaddr); /* LDY a,x */ C_LDY(opaddr); break; case 0xBD : O_axx(opaddr); /* LDA a,x */ C_LDA(opaddr); break; case 0xBE : O_axy(opaddr); /* LDX a,y */ C_LDX(opaddr); break; case 0xBF : O_alxx(opaddr); /* LDA al,x */ C_LDA(opaddr); break; case 0xC0 : if (F_getX) { /* CPY # */ O_i8(operand); C_CPY8(operand.B.L); } else { O_i16(operand); C_CPY16(operand.W); } break; case 0xC1 : O_dxi(opaddr); /* CMP (d,x) */ C_CMP(opaddr); break; case 0xC2 : O_i8(operand); /* REP # */ if (F_getE) operand.B.L &= ~0x30; P &= ~operand.B.L; break; case 0xC3 : O_sr(opaddr); /* CMP d,s */ C_CMP(opaddr); break; case 0xC4 : O_d(opaddr); /* CPY d */ C_CPY(opaddr); break; case 0xC5 : O_d(opaddr); /* CMP d */ C_CMP(opaddr); break; case 0xC6 : O_d(opaddr); /* DEC d */ C_DEC(opaddr); break; case 0xC7 : O_dil(opaddr); /* CMP [d] */ C_CMP(opaddr); break; case 0xC8 : if (F_getX) { /* INY */ C_INC8(Y.B.L); } else { C_INC16(Y.W); } break; case 0xC9 : if (F_getM) { /* CMP # */ O_i8(operand); C_CMP8(operand.B.L); } else { O_i16(operand); C_CMP16(operand.W); } break; case 0xCA : if (F_getX) { /* DEX i */ C_DEC8(X.B.L); } else { C_DEC16(X.W); } break; case 0xCB : WAIT = 1; /* WAI */ break; case 0xCC : O_a(opaddr); /* CPY a */ C_CPY(opaddr); break; case 0xCD : O_a(opaddr); /* CMP a */ C_CMP(opaddr); break; case 0xCE : O_a(opaddr); /* DEC a */ C_DEC(opaddr); break; case 0xCF : O_al(opaddr); /* CMP al */ C_CMP(opaddr); break; case 0xD0 : O_pcr(opaddr); /* BNE r */ if (!F_getZ) PC.W = opaddr.A; break; case 0xD1 : O_dix(opaddr); /* CMP (d),y */ C_CMP(opaddr); break; case 0xD2 : O_di(opaddr); /* CMP (d) */ C_CMP(opaddr); break; case 0xD3 : O_srix(opaddr); /* CMP (d,s),y */ C_CMP(opaddr); break; case 0xD4 : O_i16(operand); /* PEI s */ opaddr.A = operand.W; opaddr.B.B = DB; operand.B.L = M_READ(opaddr.A+1); S_PUSH(operand.B.L); operand.B.L = M_READ(opaddr.A); S_PUSH(operand.B.L); break; case 0xD5 : O_dxx(opaddr); /* CMP d,x */ C_CMP(opaddr); break; case 0xD6 : O_dxx(opaddr); /* DEC d,x */ C_DEC(opaddr); break; case 0xD7 : O_dixl(opaddr); /* CMP [d],y */ C_CMP(opaddr); break; case 0xD8 : F_setD(0); /* CLD i */ break; case 0xD9 : O_axy(opaddr); /* CMP a,y */ C_CMP(opaddr); break; case 0xDA : if (!F_getX) S_PUSH(X.B.H); /* PHX */ S_PUSH(X.B.L); break; case 0xDB : STOP = 1; /* STP */ break; case 0xDC : O_ail(opaddr); /* JML (a) */ PC.W = opaddr.A; PB = opaddr.B.B; break; case 0xDD : O_axx(opaddr); /* CMP a,x */ C_CMP(opaddr); break; case 0xDE : O_axx(opaddr); /* DEC a,x */ C_DEC(opaddr); break; case 0xDF : O_alxx(opaddr); /* CMP al,x */ C_CMP(opaddr); break; case 0xE0 : if (F_getX) { /* CPX # */ O_i8(operand); C_CPX8(operand.B.L); } else { O_i16(operand); C_CPX16(operand.W); } break; case 0xE1 : O_dxi(opaddr); /* SBC (d,x) */ C_SBC(opaddr); break; case 0xE2 : O_i8(operand); /* SEP # */ P |= operand.B.L; break; case 0xE3 : O_sr(opaddr); /* SBC d,s */ C_SBC(opaddr); break; case 0xE4 : O_d(opaddr); /* CPX d */ C_CPX(opaddr); break; case 0xE5 : O_d(opaddr); /* SBC d */ C_SBC(opaddr); break; case 0xE6 : O_d(opaddr); /* INC d */ C_INC(opaddr); break; case 0xE7 : O_di(opaddr); /* SBC [d] */ C_SBC(opaddr); break; case 0xE8 : if (F_getX) { /* INX */ C_INC8(X.B.L); } else { C_INC16(X.W); } break; case 0xE9 : if (F_getM) { /* SBC # */ O_i8(operand); C_SBC8(operand.B.L); } else { O_i16(operand); C_SBC16(operand.W); } break; case 0xEA : break; /* NOP */ case 0xEB : operand.B.L = A.B.H; /* XBA i */ A.B.H = A.B.L; A.B.L = operand.B.L; break; case 0xEC : O_a(opaddr); /* CPX a */ C_CPX(opaddr); break; case 0xED : O_a(opaddr); /* SBC a */ C_SBC(opaddr); break; case 0xEE : O_a(opaddr); /* INC a */ C_INC(opaddr); break; case 0xEF : O_al(opaddr); /* SBC al */ C_SBC(opaddr); break; case 0xF0 : O_pcr(opaddr); /* BEQ r */ if (F_getZ) PC.W = opaddr.A; break; case 0xF1 : O_dix(opaddr); /* SBC (d),y */ C_SBC(opaddr); break; case 0xF2 : O_di(opaddr); /* SBC (d) */ C_SBC(opaddr); break; case 0xF3 : O_srix(opaddr); /* SBC (d,s),y */ C_SBC(opaddr); break; case 0xF4 : O_i16(operand); /* PEA s */ S_PUSH(operand.B.H); S_PUSH(operand.B.L); break; case 0xF5 : O_dxx(opaddr); /* SBC d,x */ C_SBC(opaddr); break; case 0xF6 : O_dxx(opaddr); /* INC d,x */ C_INC(opaddr); break; case 0xF7 : O_dixl(opaddr); /* SBC [d],y */ C_SBC(opaddr); break; case 0xF8 : F_setD(1); /* SED i */ break; case 0xF9 : O_axy(opaddr); /* SBC a,y */ C_SBC(opaddr); break; case 0xFA : S_PULL(X.B.L); /* PLX s */ if (F_getX) { C_SETF8(X.B.L); } else { S_PULL(X.B.H); C_SETF16(X.W); } break; case 0xFB : if (F_getE) { /* XCE i */ E = F_getC; F_setC(1); } else { E = F_getC; F_setC(0); } if (F_getE) { F_setM(1); F_setX(1); X.B.H = 0; Y.B.H = 0; S.B.H = 1; } break; case 0xFC : O_axi(opaddr); /* JSR (a,x) */ PC.W--; S_PUSH(PC.B.H); S_PUSH(PC.B.L); PC.W = opaddr.A; break; case 0xFD : O_axx(opaddr); /* SBC a,x */ C_SBC(opaddr); break; case 0xFE : O_axx(opaddr); /* INC a,x */ C_INC(opaddr); break; case 0xFF : O_alxx(opaddr); /* SBC al,x */ C_SBC(opaddr); break; } ucnt++; } }