BizHawk/BizHawk.Emulation.Cores/CPUs/MC6809/Indexed_Modes.cs

455 lines
12 KiB
C#

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;
}
}
}