using System; namespace BizHawk.Emulation.Common.Components.MC6809 { public partial class MC6809 { public const ushort LEAX = 0; public const ushort LEAY = 1; public const ushort LEAS = 2; public const ushort LEAU = 3; public const ushort I_NEG = 4; public const ushort I_COM = 5; public const ushort I_LSR = 6; public const ushort I_ROR = 7; public const ushort I_ASR = 8; public const ushort I_ASL = 9; public const ushort I_ROL = 10; public const ushort I_DEC = 11; public const ushort I_INC = 12; public const ushort I_TST = 13; public const ushort I_JMP = 14; public const ushort I_CLR = 15; public const ushort I_SUB = 16; public const ushort I_CMP = 17; public const ushort I_SBC = 18; public const ushort I_AND = 19; public const ushort I_BIT = 20; public const ushort I_LD = 21; public const ushort I_ST = 22; public const ushort I_XOR = 23; public const ushort I_ADC = 24; public const ushort I_OR = 25; public const ushort I_ADD = 26; public const ushort I_SUBD = 27; public const ushort I_ADDD = 28; public const ushort I_CMP16 = 29; public const ushort I_JSR = 30; public const ushort I_LD16 = 31; public const ushort I_ST16 = 32; public const ushort I_LD16D = 33; public const ushort I_ST16D = 34; public const ushort I_CMP16D = 35; public ushort indexed_op; public ushort indexed_reg; public ushort indexed_op_reg; public ushort temp; private void INDEX_OP(ushort oper) { indexed_op = oper; PopulateCURINSTR(RD_INC_OP, ALU, PC, IDX_DCDE); IRQS = -1; } private void INDEX_OP_REG(ushort oper, ushort src) { indexed_op = oper; indexed_op_reg = src; PopulateCURINSTR(RD_INC_OP, ALU, PC, IDX_DCDE); IRQS = -1; } private void INDEX_OP_JMP() { PopulateCURINSTR(TR, PC, IDX_EA); IRQS = 1; } private void INDEX_OP_JSR() { PopulateCURINSTR(TR, ADDR, PC, DEC16, SP, TR, PC, IDX_EA, WR_DEC_LO, SP, ADDR, WR_HI, SP, ADDR); IRQS = 5; } private void INDEX_OP_LEA(ushort dest) { PopulateCURINSTR(LEA, dest, IDX_EA, IDLE); IRQS = 2; } private void INDEX_OP_LD() { PopulateCURINSTR(IDLE, RD_INC, ALU, IDX_EA, RD_INC_OP, ALU2, IDX_EA, LD_16, indexed_op_reg, ALU, ALU2); IRQS = 3; } private void INDEX_OP_ST() { PopulateCURINSTR(ST_16, indexed_op_reg, WR_HI_INC, IDX_EA, indexed_op_reg, WR_DEC_LO, IDX_EA, indexed_op_reg); IRQS = 3; } private void INDEX_OP_LDD() { PopulateCURINSTR(IDLE, RD_INC, A, IDX_EA, RD_INC_OP, B, IDX_EA, LD_16, ADDR, A, B); IRQS = 3; } private void INDEX_OP_STD() { PopulateCURINSTR(ST_16, Dr, WR_LO_INC, IDX_EA, A, WR_DEC_LO, IDX_EA, B); IRQS = 3; } private void INDEX_OP_EX4(ushort oper) { PopulateCURINSTR(IDLE, RD_INC_OP, ALU, IDX_EA, oper, indexed_op_reg, ALU); IRQS = 2; } private void INDEX_OP_EX4_ST() { PopulateCURINSTR(ST_8, indexed_op_reg, WR, IDX_EA, indexed_op_reg); IRQS = 2; } private void INDEX_OP_EX6(ushort oper) { PopulateCURINSTR(IDLE, RD, ALU, IDX_EA, oper, ALU, WR, IDX_EA, ALU); IRQS = 4; } private void INDEX_OP_EX6D(ushort oper) { PopulateCURINSTR(IDLE, RD_INC, ALU, IDX_EA, RD_INC_OP, ALU2, IDX_EA, SET_ADDR, ADDR, ALU, ALU2, oper, ADDR); IRQS = 4; } private void INDEX_CMP_EX6(ushort oper) { PopulateCURINSTR(IDLE, RD_INC, ALU, IDX_EA, RD_INC_OP, ALU2, IDX_EA, SET_ADDR, ADDR, ALU, ALU2, oper, indexed_op_reg, ADDR); IRQS = 4; } // ALU holds the post byte public void Index_decode() { switch ((Regs[ALU] >> 5) & 3) { case 0: indexed_reg = X; break; case 1: indexed_reg = Y; break; case 2: indexed_reg = US; break; case 3: indexed_reg = SP; break; } if ((Regs[ALU] & 0x80) == 0) { temp = (ushort)(Regs[ALU] & 0x1F); if ((Regs[ALU] & 0x10) == 0x10) { temp |= 0xFFE0; } Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + temp); PopulateCURINSTR(IDX_OP_BLD); } else { if ((Regs[ALU] & 0x10) == 0x10) { switch (Regs[ALU] & 0xF) { case 0x0: // Illegal break; case 0x1: Regs[ADDR] = Regs[indexed_reg]; PopulateCURINSTR(INC16, indexed_reg, INC16, indexed_reg, RD_INC, ALU, ADDR, RD_INC, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0x2: // Illegal break; case 0x3: Regs[ADDR] = (ushort)(Regs[indexed_reg] - 2); PopulateCURINSTR(DEC16, indexed_reg, DEC16, indexed_reg, RD_INC, ALU, ADDR, RD_INC, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0x4: Regs[ADDR] = Regs[indexed_reg]; PopulateCURINSTR(RD_INC, ALU, ADDR, RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0x5: Regs[ADDR] = (ushort)(Regs[indexed_reg] + (((Regs[B] & 0x80) == 0x80) ? (Regs[B] | 0xFF00) : Regs[B])); PopulateCURINSTR(RD_INC, ALU, ADDR, RD_INC, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0x6: Regs[ADDR] = (ushort)(Regs[indexed_reg] + (((Regs[A] & 0x80) == 0x80) ? (Regs[A] | 0xFF00) : Regs[A])); PopulateCURINSTR(RD_INC, ALU, ADDR, RD_INC, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0x7: // Illegal break; case 0x8: Regs[ADDR] = Regs[indexed_reg]; PopulateCURINSTR(RD_INC_OP, ALU2, PC, ADD8BR, ADDR, ALU2, RD_INC, ALU, ADDR, RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0x9: Regs[ADDR] = Regs[indexed_reg]; PopulateCURINSTR(RD_INC, ALU, PC, RD_INC, ALU2, PC, SET_ADDR, IDX_EA, ALU, ALU2, ADD16BR, ADDR, IDX_EA, RD_INC, ALU, ADDR, RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0xA: // Illegal break; case 0xB: Regs[ADDR] = Regs[indexed_reg]; PopulateCURINSTR(IDLE, IDLE, SET_ADDR, IDX_EA, A, B, ADD16BR, ADDR, IDX_EA, RD_INC, ALU, ADDR, RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0xC: indexed_reg = PC; Regs[ADDR] = Regs[indexed_reg]; PopulateCURINSTR(RD_INC_OP, ALU2, PC, ADD8BR, ADDR, ALU2, RD_INC, ALU, ADDR, RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0xD: indexed_reg = PC; Regs[ADDR] = Regs[indexed_reg]; PopulateCURINSTR(IDLE, RD_INC, ALU, PC, RD_INC, ALU2, PC, SET_ADDR, IDX_EA, ALU, ALU2, ADD16BR, ADDR, IDX_EA, RD_INC, ALU, ADDR, RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); break; case 0xE: // Illegal break; case 0xF: if (((Regs[ALU] >> 5) & 3) == 0) { PopulateCURINSTR(RD_INC, ALU, PC, RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2, RD_INC, ALU, ADDR, RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2, IDX_OP_BLD); } else { // illegal } break; } } else { switch (Regs[ALU] & 0xF) { case 0x0: Regs[IDX_EA] = Regs[indexed_reg]; PopulateCURINSTR(INC16, indexed_reg, IDX_OP_BLD); break; case 0x1: Regs[IDX_EA] = Regs[indexed_reg]; PopulateCURINSTR(INC16, indexed_reg, INC16, indexed_reg, IDX_OP_BLD); break; case 0x2: Regs[IDX_EA] = (ushort)(Regs[indexed_reg] - 1); PopulateCURINSTR(DEC16, indexed_reg, IDX_OP_BLD); break; case 0x3: Regs[IDX_EA] = (ushort)(Regs[indexed_reg] - 2); PopulateCURINSTR(DEC16, indexed_reg, DEC16, indexed_reg, IDX_OP_BLD); break; case 0x4: Regs[IDX_EA] = Regs[indexed_reg]; Index_Op_Builder(); return; // need to return here or else we run into the code below invalidating irq_pntr break; case 0x5: Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + (((Regs[B] & 0x80) == 0x80) ? (Regs[B] | 0xFF00) : Regs[B])); PopulateCURINSTR(IDX_OP_BLD); break; case 0x6: Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + (((Regs[A] & 0x80) == 0x80) ? (Regs[A] | 0xFF00) : Regs[A])); PopulateCURINSTR(IDX_OP_BLD); break; case 0x7: // Illegal break; case 0x8: PopulateCURINSTR(RD_INC_OP, ALU2, PC, EA_8); break; case 0x9: PopulateCURINSTR(RD_INC, ALU, PC, RD_INC, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2, EA_16); break; case 0xA: // Illegal break; case 0xB: PopulateCURINSTR(IDLE, IDLE, SET_ADDR, ADDR, A, B, EA_16); break; case 0xC: indexed_reg = PC; PopulateCURINSTR(RD_INC_OP, ALU2, PC, EA_8); break; case 0xD: indexed_reg = PC; PopulateCURINSTR(IDLE, RD_INC, ALU, PC, RD_INC, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2, EA_16); break; case 0xE: // Illegal break; case 0xF: // Illegal break; } } } instr_pntr = 0; irq_pntr = 100; } public void Index_Op_Builder() { switch(indexed_op) { case LEAX: INDEX_OP_LEA(X); break; // LEAX case LEAY: INDEX_OP_LEA(Y); break; // LEAY case LEAS: INDEX_OP_LEA(SP); break; // LEAS case LEAU: INDEX_OP_LEA(US); break; // LEAU case I_NEG: INDEX_OP_EX6(NEG); break; // NEG case I_COM: INDEX_OP_EX6(COM); break; // COM case I_LSR: INDEX_OP_EX6(LSR); break; // LSR case I_ROR: INDEX_OP_EX6(ROR); break; // ROR case I_ASR: INDEX_OP_EX6(ASR); break; // ASR case I_ASL: INDEX_OP_EX6(ASL); break; // ASL case I_ROL: INDEX_OP_EX6(ROL); break; // ROL case I_DEC: INDEX_OP_EX6(DEC8); break; // DEC case I_INC: INDEX_OP_EX6(INC8); break; // INC case I_TST: INDEX_OP_EX6(TST); break; // TST case I_JMP: INDEX_OP_JMP(); break; // JMP case I_CLR: INDEX_OP_EX6(CLR); break; // CLR case I_SUB: INDEX_OP_EX4(SUB8); break; // SUB A,B case I_CMP: INDEX_OP_EX4(CMP8); break; // CMP A,B case I_SBC: INDEX_OP_EX4(SBC8); break; // SBC A,B case I_AND: INDEX_OP_EX4(AND8); break; // AND A,B case I_BIT: INDEX_OP_EX4(BIT); break; // BIT A,B case I_LD: INDEX_OP_EX4(LD_8); break; // LD A,B case I_ST: INDEX_OP_EX4_ST(); break; // ST A,B case I_XOR: INDEX_OP_EX4(XOR8); break; // XOR A,B case I_ADC: INDEX_OP_EX4(ADC8); break; // ADC A,B case I_OR: INDEX_OP_EX4(OR8); break; // OR A,B case I_ADD: INDEX_OP_EX4(ADD8); break; // ADD A,B case I_SUBD: INDEX_OP_EX6D(SUB16); break; // SUB D case I_ADDD: INDEX_OP_EX6D(ADD16); break; // ADD D case I_CMP16: INDEX_CMP_EX6(CMP16); break; // CMP X, Y, SP, US case I_JSR: INDEX_OP_JSR(); break; // JSR case I_LD16: INDEX_OP_LD(); break; // LD X, Y, SP, US case I_ST16: INDEX_OP_ST(); break; // ST X, Y, SP, US case I_LD16D: INDEX_OP_LDD(); break; // LD D case I_ST16D: INDEX_OP_STD(); break; // ST D case I_CMP16D: INDEX_OP_EX6D(CMP16D); break; // CMP D } instr_pntr = 0; irq_pntr = -1; } } }