MSXHawk: Z80 with prebuilt instruction tables
This commit is contained in:
parent
ebfccf51de
commit
6b99a792b9
|
@ -51,6 +51,7 @@ namespace MSXHawk
|
||||||
bool nonMaskableInterrupt;
|
bool nonMaskableInterrupt;
|
||||||
bool nonMaskableInterruptPending;
|
bool nonMaskableInterruptPending;
|
||||||
bool jp_cond_chk;
|
bool jp_cond_chk;
|
||||||
|
bool cond_chk_fail;
|
||||||
|
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
uint8_t temp_R;
|
uint8_t temp_R;
|
||||||
|
@ -58,6 +59,9 @@ namespace MSXHawk
|
||||||
uint8_t interruptMode;
|
uint8_t interruptMode;
|
||||||
// when connected devices do not output a value on the BUS, they are responsible for determining open bus behaviour and returning it
|
// when connected devices do not output a value on the BUS, they are responsible for determining open bus behaviour and returning it
|
||||||
uint8_t ExternalDB;
|
uint8_t ExternalDB;
|
||||||
|
// since absolute pointer locations are not saved, we need to know where current pointer is looking in order to load it
|
||||||
|
// this combined with opcode and instr_pntr gives the current cpu execution location
|
||||||
|
uint8_t instr_bank;
|
||||||
uint8_t Regs[36] = {};
|
uint8_t Regs[36] = {};
|
||||||
|
|
||||||
uint32_t PRE_SRC;
|
uint32_t PRE_SRC;
|
||||||
|
@ -67,20 +71,17 @@ namespace MSXHawk
|
||||||
uint32_t mem_pntr = 0;
|
uint32_t mem_pntr = 0;
|
||||||
uint32_t irq_pntr = 0;
|
uint32_t irq_pntr = 0;
|
||||||
uint32_t IRQS;
|
uint32_t IRQS;
|
||||||
|
uint32_t Ztemp2_saver = 0;
|
||||||
|
uint32_t IRQS_cond_offset;
|
||||||
|
|
||||||
// since absolute pointer locations are not saved, we need to know where current pointer is looking in order to load it
|
uint64_t TotalExecutedCycles;
|
||||||
// this combined with opcode and instr_pntr gives the current cpu execution location
|
|
||||||
uint8_t instr_bank;
|
|
||||||
|
|
||||||
uint32_t* cur_instr_ofst = nullptr;
|
uint32_t* cur_instr_ofst = nullptr;
|
||||||
uint32_t* cur_bus_ofst = nullptr;
|
uint32_t* cur_bus_ofst = nullptr;
|
||||||
uint32_t* cur_mem_ofst = nullptr;
|
uint32_t* cur_mem_ofst = nullptr;
|
||||||
uint32_t* cur_irqs_ofst = nullptr;
|
uint32_t* cur_irqs_ofst = nullptr;
|
||||||
|
|
||||||
uint64_t TotalExecutedCycles;
|
|
||||||
|
|
||||||
// non-state variables
|
// non-state variables
|
||||||
// EXCEPTION!: Ztemp2 must be stated to restore the instruction vector
|
|
||||||
bool checker;
|
bool checker;
|
||||||
uint32_t Ztemp1, Ztemp2, Ztemp3, Ztemp4;
|
uint32_t Ztemp1, Ztemp2, Ztemp3, Ztemp4;
|
||||||
uint32_t Reg16_d, Reg16_s, ans, temp, carry, dest_t, src_t;
|
uint32_t Reg16_d, Reg16_s, ans, temp, carry, dest_t, src_t;
|
||||||
|
@ -341,6 +342,90 @@ namespace MSXHawk
|
||||||
uint32_t REP_OP_O_MEMRQ[5] = { 0, 0, 0, 0, 0 };
|
uint32_t REP_OP_O_MEMRQ[5] = { 0, 0, 0, 0, 0 };
|
||||||
uint32_t REP_OP_O_IRQS = 5;
|
uint32_t REP_OP_O_IRQS = 5;
|
||||||
|
|
||||||
|
// halt
|
||||||
|
uint32_t HALT_INST[4] = { IDLE,
|
||||||
|
WAIT,
|
||||||
|
OP_F,
|
||||||
|
OP };
|
||||||
|
|
||||||
|
uint32_t HALT_BUSRQ[4] = { PCh, 0, 0, 0 };
|
||||||
|
uint32_t HALT_MEMRQ[4] = { PCh, 0, 0, 0 };
|
||||||
|
uint32_t HALT_IRQS = 4;
|
||||||
|
|
||||||
|
// NMI
|
||||||
|
uint32_t NMI_INST[25] = { IDLE,
|
||||||
|
IDLE,
|
||||||
|
IDLE,
|
||||||
|
IDLE,
|
||||||
|
DEC16, SPl, SPh,
|
||||||
|
TR, ALU, PCl,
|
||||||
|
WAIT,
|
||||||
|
WR_DEC, SPl, SPh, PCh,
|
||||||
|
TR16, PCl, PCh, NMI_V, ZERO,
|
||||||
|
WAIT,
|
||||||
|
WR, SPl, SPh, ALU };
|
||||||
|
|
||||||
|
uint32_t NMI_BUSRQ[11] = { 0, 0, 0, 0, 0, SPh, 0, 0, SPh, 0, 0 };
|
||||||
|
uint32_t NMI_MEMRQ[11] = { 0, 0, 0, 0, 0, SPh, 0, 0, SPh, 0, 0 };
|
||||||
|
uint32_t NMI_IRQS = 11;
|
||||||
|
|
||||||
|
// IRQ0
|
||||||
|
uint32_t IRQ0_INST[10] = { IDLE,
|
||||||
|
IDLE,
|
||||||
|
IORQ,
|
||||||
|
WAIT,
|
||||||
|
IDLE,
|
||||||
|
WAIT,
|
||||||
|
RD_INC, ALU, PCl, PCh };
|
||||||
|
|
||||||
|
uint32_t IRQ0_BUSRQ[7] = { 0, 0, 0, 0, PCh, 0, 0 };
|
||||||
|
uint32_t IRQ0_MEMRQ[7] = { 0, 0, 0, 0, PCh, 0, 0 };
|
||||||
|
uint32_t IRQ0_IRQS = 7;
|
||||||
|
|
||||||
|
// IRQ1
|
||||||
|
uint32_t IRQ1_INST[27] = { IDLE,
|
||||||
|
IDLE,
|
||||||
|
IORQ,
|
||||||
|
WAIT,
|
||||||
|
IDLE,
|
||||||
|
TR, ALU, PCl,
|
||||||
|
DEC16, SPl, SPh,
|
||||||
|
IDLE,
|
||||||
|
WAIT,
|
||||||
|
WR_DEC, SPl, SPh, PCh,
|
||||||
|
TR16, PCl, PCh, IRQ_V, ZERO,
|
||||||
|
WAIT,
|
||||||
|
WR, SPl, SPh, ALU };
|
||||||
|
|
||||||
|
uint32_t IRQ1_BUSRQ[13] = { 0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0 };
|
||||||
|
uint32_t IRQ1_MEMRQ[13] = { 0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0 };
|
||||||
|
uint32_t IRQ1_IRQS = 13;
|
||||||
|
|
||||||
|
// IRQ2
|
||||||
|
uint32_t IRQ2_INST[37] = { IDLE,
|
||||||
|
IDLE,
|
||||||
|
IORQ,
|
||||||
|
WAIT,
|
||||||
|
FTCH_DB,
|
||||||
|
IDLE,
|
||||||
|
DEC16, SPl, SPh,
|
||||||
|
TR16, Z, W, DB, I,
|
||||||
|
WAIT,
|
||||||
|
WR_DEC, SPl, SPh, PCh,
|
||||||
|
IDLE,
|
||||||
|
WAIT,
|
||||||
|
WR, SPl, SPh, PCl,
|
||||||
|
IDLE,
|
||||||
|
WAIT,
|
||||||
|
RD_INC, PCl, Z, W,
|
||||||
|
IDLE,
|
||||||
|
WAIT,
|
||||||
|
RD, PCh, Z, W };
|
||||||
|
|
||||||
|
uint32_t IRQ2_BUSRQ[19] = { 0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0, 0 };
|
||||||
|
uint32_t IRQ2_MEMRQ[19] = { 0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0, 0 };
|
||||||
|
uint32_t IRQ2_IRQS = 19;
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Z80 functions
|
#pragma region Z80 functions
|
||||||
|
@ -413,7 +498,7 @@ namespace MSXHawk
|
||||||
NO_prefix = true;
|
NO_prefix = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FetchInstruction()
|
inline void FetchInstruction()
|
||||||
{
|
{
|
||||||
if (NO_prefix)
|
if (NO_prefix)
|
||||||
{
|
{
|
||||||
|
@ -494,6 +579,7 @@ namespace MSXHawk
|
||||||
void ExecuteOne()
|
void ExecuteOne()
|
||||||
{
|
{
|
||||||
bus_pntr++; mem_pntr++;
|
bus_pntr++; mem_pntr++;
|
||||||
|
|
||||||
switch (cur_instr_ofst[instr_pntr++])
|
switch (cur_instr_ofst[instr_pntr++])
|
||||||
{
|
{
|
||||||
case IDLE:
|
case IDLE:
|
||||||
|
@ -845,7 +931,7 @@ namespace MSXHawk
|
||||||
if (((Regs[C] | (Regs[B] << 8)) != 0) && (Ztemp3 > 0))
|
if (((Regs[C] | (Regs[B] << 8)) != 0) && (Ztemp3 > 0))
|
||||||
{
|
{
|
||||||
cur_instr_ofst = &LD_OP_R_INST[0];
|
cur_instr_ofst = &LD_OP_R_INST[0];
|
||||||
cur_instr_ofst[14] = Ztemp2;
|
cur_instr_ofst[14] = Ztemp2; Ztemp2_saver = Ztemp2;
|
||||||
cur_bus_ofst = &LD_OP_R_BUSRQ[0];
|
cur_bus_ofst = &LD_OP_R_BUSRQ[0];
|
||||||
cur_mem_ofst = &LD_OP_R_MEMRQ[0];
|
cur_mem_ofst = &LD_OP_R_MEMRQ[0];
|
||||||
cur_irqs_ofst = &LD_OP_R_IRQS;
|
cur_irqs_ofst = &LD_OP_R_IRQS;
|
||||||
|
@ -871,7 +957,7 @@ namespace MSXHawk
|
||||||
if (((Regs[C] | (Regs[B] << 8)) != 0) && (Ztemp3 > 0) && !FlagZget())
|
if (((Regs[C] | (Regs[B] << 8)) != 0) && (Ztemp3 > 0) && !FlagZget())
|
||||||
{
|
{
|
||||||
cur_instr_ofst = &LD_CP_R_INST[0];
|
cur_instr_ofst = &LD_CP_R_INST[0];
|
||||||
cur_instr_ofst[14] = Ztemp2;
|
cur_instr_ofst[14] = Ztemp2; Ztemp2_saver = Ztemp2;
|
||||||
cur_bus_ofst = &LD_CP_R_BUSRQ[0];
|
cur_bus_ofst = &LD_CP_R_BUSRQ[0];
|
||||||
cur_mem_ofst = &LD_CP_R_MEMRQ[0];
|
cur_mem_ofst = &LD_CP_R_MEMRQ[0];
|
||||||
cur_irqs_ofst = &LD_CP_R_IRQS;
|
cur_irqs_ofst = &LD_CP_R_IRQS;
|
||||||
|
@ -945,7 +1031,7 @@ namespace MSXHawk
|
||||||
if ((Regs[B] != 0) && (Ztemp3 > 0))
|
if ((Regs[B] != 0) && (Ztemp3 > 0))
|
||||||
{
|
{
|
||||||
cur_instr_ofst = &REP_OP_I_INST[0];
|
cur_instr_ofst = &REP_OP_I_INST[0];
|
||||||
cur_instr_ofst[8] = Ztemp2;
|
cur_instr_ofst[8] = Ztemp2; Ztemp2_saver = Ztemp2;
|
||||||
cur_bus_ofst = &REP_OP_I_BUSRQ[0];
|
cur_bus_ofst = &REP_OP_I_BUSRQ[0];
|
||||||
cur_mem_ofst = &REP_OP_I_MEMRQ[0];
|
cur_mem_ofst = &REP_OP_I_MEMRQ[0];
|
||||||
cur_irqs_ofst = &REP_OP_I_IRQS;
|
cur_irqs_ofst = &REP_OP_I_IRQS;
|
||||||
|
@ -1086,22 +1172,28 @@ namespace MSXHawk
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
cond_chk_fail = true;
|
||||||
switch (cur_instr_ofst[instr_pntr++])
|
switch (cur_instr_ofst[instr_pntr++])
|
||||||
{
|
{
|
||||||
case 0: // DJNZ
|
case 0: // DJNZ
|
||||||
cur_irqs_ofst = &False_IRQS[0];
|
cur_irqs_ofst = &False_IRQS[0];
|
||||||
|
IRQS_cond_offset = 0;
|
||||||
break;
|
break;
|
||||||
case 1: // JR COND
|
case 1: // JR COND
|
||||||
cur_irqs_ofst = &False_IRQS[1];
|
cur_irqs_ofst = &False_IRQS[1];
|
||||||
|
IRQS_cond_offset = 1;
|
||||||
break;
|
break;
|
||||||
case 2: // JP COND
|
case 2: // JP COND
|
||||||
cur_irqs_ofst = &False_IRQS[2];
|
cur_irqs_ofst = &False_IRQS[2];
|
||||||
|
IRQS_cond_offset = 2;
|
||||||
break;
|
break;
|
||||||
case 3: // RET COND
|
case 3: // RET COND
|
||||||
cur_irqs_ofst = &False_IRQS[3];
|
cur_irqs_ofst = &False_IRQS[3];
|
||||||
|
IRQS_cond_offset = 3;
|
||||||
break;
|
break;
|
||||||
case 4: // CALL
|
case 4: // CALL
|
||||||
cur_irqs_ofst = &False_IRQS[4];
|
cur_irqs_ofst = &False_IRQS[4];
|
||||||
|
IRQS_cond_offset = 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1116,6 +1208,8 @@ namespace MSXHawk
|
||||||
}
|
}
|
||||||
else if (++irq_pntr == cur_irqs_ofst[0])
|
else if (++irq_pntr == cur_irqs_ofst[0])
|
||||||
{
|
{
|
||||||
|
cond_chk_fail = false;
|
||||||
|
|
||||||
if (EI_pending > 0)
|
if (EI_pending > 0)
|
||||||
{
|
{
|
||||||
EI_pending--;
|
EI_pending--;
|
||||||
|
@ -1177,15 +1271,12 @@ namespace MSXHawk
|
||||||
// otherwise start a new normal access
|
// otherwise start a new normal access
|
||||||
else if (!halted)
|
else if (!halted)
|
||||||
{
|
{
|
||||||
PopulateCURINSTR
|
cur_instr_ofst = &HALT_INST[0];
|
||||||
(IDLE,
|
cur_bus_ofst = &HALT_BUSRQ[0];
|
||||||
WAIT,
|
cur_mem_ofst = &HALT_MEMRQ[0];
|
||||||
OP_F,
|
cur_irqs_ofst = &HALT_IRQS;
|
||||||
OP);
|
|
||||||
|
|
||||||
PopulateBUSRQ(PCh, 0, 0, 0);
|
instr_bank = 11;
|
||||||
PopulateMEMRQ(PCh, 0, 0, 0);
|
|
||||||
IRQS = 4;
|
|
||||||
|
|
||||||
instr_pntr = mem_pntr = bus_pntr = irq_pntr = 0;
|
instr_pntr = mem_pntr = bus_pntr = irq_pntr = 0;
|
||||||
}
|
}
|
||||||
|
@ -1285,21 +1376,12 @@ namespace MSXHawk
|
||||||
#pragma region Interrupts
|
#pragma region Interrupts
|
||||||
void NMI_()
|
void NMI_()
|
||||||
{
|
{
|
||||||
PopulateCURINSTR(IDLE,
|
cur_instr_ofst = &NMI_INST[0];
|
||||||
IDLE,
|
cur_bus_ofst = &NMI_BUSRQ[0];
|
||||||
IDLE,
|
cur_mem_ofst = &NMI_MEMRQ[0];
|
||||||
IDLE,
|
cur_irqs_ofst = &NMI_IRQS;
|
||||||
DEC16, SPl, SPh,
|
|
||||||
TR, ALU, PCl,
|
|
||||||
WAIT,
|
|
||||||
WR_DEC, SPl, SPh, PCh,
|
|
||||||
TR16, PCl, PCh, NMI_V, ZERO,
|
|
||||||
WAIT,
|
|
||||||
WR, SPl, SPh, ALU);
|
|
||||||
|
|
||||||
PopulateBUSRQ(0, 0, 0, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
instr_bank = 12;
|
||||||
PopulateMEMRQ(0, 0, 0, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
|
||||||
IRQS = 11;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode 0 interrupts only take effect if a CALL or RST is on the data bus
|
// Mode 0 interrupts only take effect if a CALL or RST is on the data bus
|
||||||
|
@ -1309,67 +1391,34 @@ namespace MSXHawk
|
||||||
//NOTE: TODO: When a CALL is present on the data bus, adjust WZ accordingly
|
//NOTE: TODO: When a CALL is present on the data bus, adjust WZ accordingly
|
||||||
void INTERRUPT_0(uint32_t src)
|
void INTERRUPT_0(uint32_t src)
|
||||||
{
|
{
|
||||||
PopulateCURINSTR(IDLE,
|
cur_instr_ofst = &IRQ0_INST[0];
|
||||||
IDLE,
|
cur_bus_ofst = &IRQ0_BUSRQ[0];
|
||||||
IORQ,
|
cur_mem_ofst = &IRQ0_MEMRQ[0];
|
||||||
WAIT,
|
cur_irqs_ofst = &IRQ0_IRQS;
|
||||||
IDLE,
|
|
||||||
WAIT,
|
|
||||||
RD_INC, ALU, PCl, PCh);
|
|
||||||
|
|
||||||
PopulateBUSRQ(0, 0, 0, 0, PCh, 0, 0);
|
instr_bank = 13;
|
||||||
PopulateMEMRQ(0, 0, 0, 0, PCh, 0, 0);
|
|
||||||
IRQS = 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just jump to $0038
|
// Just jump to $0038
|
||||||
void INTERRUPT_1()
|
void INTERRUPT_1()
|
||||||
{
|
{
|
||||||
PopulateCURINSTR(IDLE,
|
cur_instr_ofst = &IRQ1_INST[0];
|
||||||
IDLE,
|
cur_bus_ofst = &IRQ1_BUSRQ[0];
|
||||||
IORQ,
|
cur_mem_ofst = &IRQ1_MEMRQ[0];
|
||||||
WAIT,
|
cur_irqs_ofst = &IRQ1_IRQS;
|
||||||
IDLE,
|
|
||||||
TR, ALU, PCl,
|
|
||||||
DEC16, SPl, SPh,
|
|
||||||
IDLE,
|
|
||||||
WAIT,
|
|
||||||
WR_DEC, SPl, SPh, PCh,
|
|
||||||
TR16, PCl, PCh, IRQ_V, ZERO,
|
|
||||||
WAIT,
|
|
||||||
WR, SPl, SPh, ALU);
|
|
||||||
|
|
||||||
PopulateBUSRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
instr_bank = 14;
|
||||||
PopulateMEMRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0);
|
|
||||||
IRQS = 13;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interrupt mode 2 uses the I vector combined with a byte on the data bus
|
// Interrupt mode 2 uses the I vector combined with a byte on the data bus
|
||||||
void INTERRUPT_2()
|
void INTERRUPT_2()
|
||||||
{
|
{
|
||||||
PopulateCURINSTR(IDLE,
|
cur_instr_ofst = &IRQ2_INST[0];
|
||||||
IDLE,
|
cur_bus_ofst = &IRQ2_BUSRQ[0];
|
||||||
IORQ,
|
cur_mem_ofst = &IRQ2_MEMRQ[0];
|
||||||
WAIT,
|
cur_irqs_ofst = &IRQ2_IRQS;
|
||||||
FTCH_DB,
|
|
||||||
IDLE,
|
|
||||||
DEC16, SPl, SPh,
|
|
||||||
TR16, Z, W, DB, I,
|
|
||||||
WAIT,
|
|
||||||
WR_DEC, SPl, SPh, PCh,
|
|
||||||
IDLE,
|
|
||||||
WAIT,
|
|
||||||
WR, SPl, SPh, PCl,
|
|
||||||
IDLE,
|
|
||||||
WAIT,
|
|
||||||
RD_INC, PCl, Z, W,
|
|
||||||
IDLE,
|
|
||||||
WAIT,
|
|
||||||
RD, PCh, Z, W);
|
|
||||||
|
|
||||||
PopulateBUSRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0, 0);
|
instr_bank = 15;
|
||||||
PopulateMEMRQ(0, 0, 0, 0, I, 0, 0, SPh, 0, 0, SPh, 0, 0, W, 0, 0, W, 0, 0);
|
|
||||||
IRQS = 19;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetInterrupts()
|
void ResetInterrupts()
|
||||||
|
@ -2641,12 +2690,12 @@ namespace MSXHawk
|
||||||
case 0xFF: RST_(0x38); break; // RST 0x38
|
case 0xFF: RST_(0x38); break; // RST 0x38
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(&NoIndex[i * 38], &cur_instr, 38);
|
std::memcpy(&NoIndex[i * 38], &cur_instr, sizeof(uint32_t) * 38);
|
||||||
std::memcpy(&NoIndexBUSRQ[i * 19], &BUSRQ, 19);
|
std::memcpy(&NoIndexBUSRQ[i * 19], &BUSRQ, sizeof(uint32_t) * 19);
|
||||||
std::memcpy(&NoIndexMEMRQ[i * 19], &MEMRQ, 19);
|
std::memcpy(&NoIndexMEMRQ[i * 19], &MEMRQ, sizeof(uint32_t) * 19);
|
||||||
NoIndexIRQS[i] = IRQS;
|
NoIndexIRQS[i] = IRQS;
|
||||||
|
|
||||||
switch (opcode)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0x00: INT_OP(RLC, B); break; // RLC B
|
case 0x00: INT_OP(RLC, B); break; // RLC B
|
||||||
case 0x01: INT_OP(RLC, C); break; // RLC C
|
case 0x01: INT_OP(RLC, C); break; // RLC C
|
||||||
|
@ -2906,12 +2955,12 @@ namespace MSXHawk
|
||||||
case 0xFF: BIT_OP(SET, 7, A); break; // SET 7, A
|
case 0xFF: BIT_OP(SET, 7, A); break; // SET 7, A
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(&CBIndex[i * 38], &cur_instr, 38);
|
std::memcpy(&CBIndex[i * 38], &cur_instr, sizeof(uint32_t) * 38);
|
||||||
std::memcpy(&CBIndexBUSRQ[i * 19], &BUSRQ, 19);
|
std::memcpy(&CBIndexBUSRQ[i * 19], &BUSRQ, sizeof(uint32_t) * 19);
|
||||||
std::memcpy(&CBIndexMEMRQ[i * 19], &MEMRQ, 19);
|
std::memcpy(&CBIndexMEMRQ[i * 19], &MEMRQ, sizeof(uint32_t) * 19);
|
||||||
CBIndexIRQS[i] = IRQS;
|
CBIndexIRQS[i] = IRQS;
|
||||||
|
|
||||||
switch (opcode)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0x40: IN_REG_(B, C); break; // IN B, (C)
|
case 0x40: IN_REG_(B, C); break; // IN B, (C)
|
||||||
case 0x41: OUT_REG_(C, B); break; // OUT (C), B
|
case 0x41: OUT_REG_(C, B); break; // OUT (C), B
|
||||||
|
@ -2997,12 +3046,12 @@ namespace MSXHawk
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(&EXTIndex[i * 38], &cur_instr, 38);
|
std::memcpy(&EXTIndex[i * 38], &cur_instr, sizeof(uint32_t) * 38);
|
||||||
std::memcpy(&EXTIndexBUSRQ[i * 19], &BUSRQ, 19);
|
std::memcpy(&EXTIndexBUSRQ[i * 19], &BUSRQ, sizeof(uint32_t) * 19);
|
||||||
std::memcpy(&EXTIndexMEMRQ[i * 19], &MEMRQ, 19);
|
std::memcpy(&EXTIndexMEMRQ[i * 19], &MEMRQ, sizeof(uint32_t) * 19);
|
||||||
EXTIndexIRQS[i] = IRQS;
|
EXTIndexIRQS[i] = IRQS;
|
||||||
|
|
||||||
switch (opcode)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0x00: NOP_(); break; // NOP
|
case 0x00: NOP_(); break; // NOP
|
||||||
case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn
|
case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn
|
||||||
|
@ -3262,12 +3311,12 @@ namespace MSXHawk
|
||||||
case 0xFF: RST_(0x38); break; // RST $38
|
case 0xFF: RST_(0x38); break; // RST $38
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(&IXIndex[i * 38], &cur_instr, 38);
|
std::memcpy(&IXIndex[i * 38], &cur_instr, sizeof(uint32_t) * 38);
|
||||||
std::memcpy(&IXIndexBUSRQ[i * 19], &BUSRQ, 19);
|
std::memcpy(&IXIndexBUSRQ[i * 19], &BUSRQ, sizeof(uint32_t) * 19);
|
||||||
std::memcpy(&IXIndexMEMRQ[i * 19], &MEMRQ, 19);
|
std::memcpy(&IXIndexMEMRQ[i * 19], &MEMRQ, sizeof(uint32_t) * 19);
|
||||||
IXIndexIRQS[i] = IRQS;
|
IXIndexIRQS[i] = IRQS;
|
||||||
|
|
||||||
switch (opcode)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0x00: NOP_(); break; // NOP
|
case 0x00: NOP_(); break; // NOP
|
||||||
case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn
|
case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn
|
||||||
|
@ -3527,12 +3576,12 @@ namespace MSXHawk
|
||||||
case 0xFF: RST_(0x38); break; // RST $38
|
case 0xFF: RST_(0x38); break; // RST $38
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(&IYIndex[i * 38], &cur_instr, 38);
|
std::memcpy(&IYIndex[i * 38], &cur_instr, sizeof(uint32_t) * 38);
|
||||||
std::memcpy(&IYIndexBUSRQ[i * 19], &BUSRQ, 19);
|
std::memcpy(&IYIndexBUSRQ[i * 19], &BUSRQ, sizeof(uint32_t) * 19);
|
||||||
std::memcpy(&IYIndexMEMRQ[i * 19], &MEMRQ, 19);
|
std::memcpy(&IYIndexMEMRQ[i * 19], &MEMRQ, sizeof(uint32_t) * 19);
|
||||||
IYIndexIRQS[i] = IRQS;
|
IYIndexIRQS[i] = IRQS;
|
||||||
|
|
||||||
switch (opcode)
|
switch (i)
|
||||||
{
|
{
|
||||||
case 0x00: I_INT_OP(RLC, B); break; // RLC (I* + n) -> B
|
case 0x00: I_INT_OP(RLC, B); break; // RLC (I* + n) -> B
|
||||||
case 0x01: I_INT_OP(RLC, C); break; // RLC (I* + n) -> C
|
case 0x01: I_INT_OP(RLC, C); break; // RLC (I* + n) -> C
|
||||||
|
@ -3792,9 +3841,9 @@ namespace MSXHawk
|
||||||
case 0xFF: I_BIT_OP(SET, 7, A); break; // SET 7, (I* + n) -> A
|
case 0xFF: I_BIT_OP(SET, 7, A); break; // SET 7, (I* + n) -> A
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(&IXYCBIndex[i * 38], &cur_instr, 38);
|
std::memcpy(&IXYCBIndex[i * 38], &cur_instr, sizeof(uint32_t) * 38);
|
||||||
std::memcpy(&IXYCBIndexBUSRQ[i * 19], &BUSRQ, 19);
|
std::memcpy(&IXYCBIndexBUSRQ[i * 19], &BUSRQ, sizeof(uint32_t) * 19);
|
||||||
std::memcpy(&IXYCBIndexMEMRQ[i * 19], &MEMRQ, 19);
|
std::memcpy(&IXYCBIndexMEMRQ[i * 19], &MEMRQ, sizeof(uint32_t) * 19);
|
||||||
IXYCBIndexIRQS[i] = IRQS;
|
IXYCBIndexIRQS[i] = IRQS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5340,12 +5389,15 @@ namespace MSXHawk
|
||||||
*saver = (uint8_t)(IFF2 ? 1 : 0); saver++;
|
*saver = (uint8_t)(IFF2 ? 1 : 0); saver++;
|
||||||
*saver = (uint8_t)(nonMaskableInterrupt ? 1 : 0); saver++;
|
*saver = (uint8_t)(nonMaskableInterrupt ? 1 : 0); saver++;
|
||||||
*saver = (uint8_t)(nonMaskableInterruptPending ? 1 : 0); saver++;
|
*saver = (uint8_t)(nonMaskableInterruptPending ? 1 : 0); saver++;
|
||||||
|
*saver = (uint8_t)(jp_cond_chk ? 1 : 0); saver++;
|
||||||
|
*saver = (uint8_t)(cond_chk_fail ? 1 : 0); saver++;
|
||||||
|
|
||||||
*saver = opcode; saver++;
|
*saver = opcode; saver++;
|
||||||
*saver = temp_R; saver++;
|
*saver = temp_R; saver++;
|
||||||
*saver = EI_pending; saver++;
|
*saver = EI_pending; saver++;
|
||||||
*saver = interruptMode; saver++;
|
*saver = interruptMode; saver++;
|
||||||
*saver = ExternalDB; saver++;
|
*saver = ExternalDB; saver++;
|
||||||
|
*saver = instr_bank; saver++;
|
||||||
|
|
||||||
for (int i = 0; i < 36; i++) { *saver = Regs[i]; saver++; }
|
for (int i = 0; i < 36; i++) { *saver = Regs[i]; saver++; }
|
||||||
|
|
||||||
|
@ -5367,23 +5419,11 @@ namespace MSXHawk
|
||||||
*saver = (uint8_t)(IRQS & 0xFF); saver++; *saver = (uint8_t)((IRQS >> 8) & 0xFF); saver++;
|
*saver = (uint8_t)(IRQS & 0xFF); saver++; *saver = (uint8_t)((IRQS >> 8) & 0xFF); saver++;
|
||||||
*saver = (uint8_t)((IRQS >> 16) & 0xFF); saver++; *saver = (uint8_t)((IRQS >> 24) & 0xFF); saver++;
|
*saver = (uint8_t)((IRQS >> 16) & 0xFF); saver++; *saver = (uint8_t)((IRQS >> 24) & 0xFF); saver++;
|
||||||
|
|
||||||
for (int i = 0; i < 38; i++)
|
*saver = (uint8_t)(Ztemp2_saver & 0xFF); saver++; *saver = (uint8_t)((Ztemp2_saver >> 8) & 0xFF); saver++;
|
||||||
{
|
*saver = (uint8_t)((Ztemp2_saver >> 16) & 0xFF); saver++; *saver = (uint8_t)((Ztemp2_saver >> 24) & 0xFF); saver++;
|
||||||
*saver = (uint8_t)(cur_instr[i] & 0xFF); saver++; *saver = (uint8_t)((cur_instr[i] >> 8) & 0xFF); saver++;
|
|
||||||
*saver = (uint8_t)((cur_instr[i] >> 16) & 0xFF); saver++; *saver = (uint8_t)((cur_instr[i] >> 24) & 0xFF); saver++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 19; i++)
|
*saver = (uint8_t)(IRQS_cond_offset & 0xFF); saver++; *saver = (uint8_t)((IRQS_cond_offset >> 8) & 0xFF); saver++;
|
||||||
{
|
*saver = (uint8_t)((IRQS_cond_offset >> 16) & 0xFF); saver++; *saver = (uint8_t)((IRQS_cond_offset >> 24) & 0xFF); saver++;
|
||||||
*saver = (uint8_t)(BUSRQ[i] & 0xFF); saver++; *saver = (uint8_t)((BUSRQ[i] >> 8) & 0xFF); saver++;
|
|
||||||
*saver = (uint8_t)((BUSRQ[i] >> 16) & 0xFF); saver++; *saver = (uint8_t)((BUSRQ[i] >> 24) & 0xFF); saver++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 19; i++)
|
|
||||||
{
|
|
||||||
*saver = (uint8_t)(MEMRQ[i] & 0xFF); saver++; *saver = (uint8_t)((MEMRQ[i] >> 8) & 0xFF); saver++;
|
|
||||||
*saver = (uint8_t)((MEMRQ[i] >> 16) & 0xFF); saver++; *saver = (uint8_t)((MEMRQ[i] >> 24) & 0xFF); saver++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*saver = (uint8_t)(TotalExecutedCycles & 0xFF); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 8) & 0xFF); saver++;
|
*saver = (uint8_t)(TotalExecutedCycles & 0xFF); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 8) & 0xFF); saver++;
|
||||||
*saver = (uint8_t)((TotalExecutedCycles >> 16) & 0xFF); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 24) & 0xFF); saver++;
|
*saver = (uint8_t)((TotalExecutedCycles >> 16) & 0xFF); saver++; *saver = (uint8_t)((TotalExecutedCycles >> 24) & 0xFF); saver++;
|
||||||
|
@ -5410,12 +5450,15 @@ namespace MSXHawk
|
||||||
IFF2 = *loader == 1; loader++;
|
IFF2 = *loader == 1; loader++;
|
||||||
nonMaskableInterrupt = *loader == 1; loader++;
|
nonMaskableInterrupt = *loader == 1; loader++;
|
||||||
nonMaskableInterruptPending = *loader == 1; loader++;
|
nonMaskableInterruptPending = *loader == 1; loader++;
|
||||||
|
jp_cond_chk = *loader == 1; loader++;
|
||||||
|
cond_chk_fail = *loader == 1; loader++;
|
||||||
|
|
||||||
opcode = *loader; loader++;
|
opcode = *loader; loader++;
|
||||||
temp_R = *loader; loader++;
|
temp_R = *loader; loader++;
|
||||||
EI_pending = *loader; loader++;
|
EI_pending = *loader; loader++;
|
||||||
interruptMode = *loader; loader++;
|
interruptMode = *loader; loader++;
|
||||||
ExternalDB = *loader; loader++;
|
ExternalDB = *loader; loader++;
|
||||||
|
instr_bank = *loader; loader++;
|
||||||
|
|
||||||
for (int i = 0; i < 36; i++) { Regs[i] = *loader; loader++; }
|
for (int i = 0; i < 36; i++) { Regs[i] = *loader; loader++; }
|
||||||
|
|
||||||
|
@ -5437,22 +5480,132 @@ namespace MSXHawk
|
||||||
IRQS = *loader; loader++; IRQS |= (*loader << 8); loader++;
|
IRQS = *loader; loader++; IRQS |= (*loader << 8); loader++;
|
||||||
IRQS |= (*loader << 16); loader++; IRQS |= (*loader << 24); loader++;
|
IRQS |= (*loader << 16); loader++; IRQS |= (*loader << 24); loader++;
|
||||||
|
|
||||||
for (int i = 0; i < 38; i++)
|
Ztemp2_saver = *loader; loader++; Ztemp2_saver |= (*loader << 8); loader++;
|
||||||
|
Ztemp2_saver |= (*loader << 16); loader++; Ztemp2_saver |= (*loader << 24); loader++;
|
||||||
|
|
||||||
|
IRQS_cond_offset = *loader; loader++; IRQS_cond_offset |= (*loader << 8); loader++;
|
||||||
|
IRQS_cond_offset |= (*loader << 16); loader++; IRQS_cond_offset |= (*loader << 24); loader++;
|
||||||
|
|
||||||
|
// load instruction pointers based on state
|
||||||
|
if (instr_bank == 0)
|
||||||
{
|
{
|
||||||
cur_instr[i] = *loader; loader++; cur_instr[i] |= (*loader << 8); loader++;
|
cur_instr_ofst = &NoIndex[opcode * 38];
|
||||||
cur_instr[i] |= (*loader << 16); loader++; cur_instr[i] |= (*loader << 24); loader++;
|
cur_bus_ofst = &NoIndexBUSRQ[opcode * 19];
|
||||||
|
cur_mem_ofst = &NoIndexMEMRQ[opcode * 19];
|
||||||
|
cur_irqs_ofst = &NoIndexIRQS[opcode];
|
||||||
|
}
|
||||||
|
else if (instr_bank == 1)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &CBIndex[opcode * 38];
|
||||||
|
cur_bus_ofst = &CBIndexBUSRQ[opcode * 19];
|
||||||
|
cur_mem_ofst = &CBIndexMEMRQ[opcode * 19];
|
||||||
|
cur_irqs_ofst = &CBIndexIRQS[opcode];
|
||||||
|
}
|
||||||
|
else if (instr_bank == 2)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &EXTIndex[opcode * 38];
|
||||||
|
cur_bus_ofst = &EXTIndexBUSRQ[opcode * 19];
|
||||||
|
cur_mem_ofst = &EXTIndexMEMRQ[opcode * 19];
|
||||||
|
cur_irqs_ofst = &EXTIndexIRQS[opcode];
|
||||||
|
}
|
||||||
|
else if (instr_bank == 3)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &IXIndex[opcode * 38];
|
||||||
|
cur_bus_ofst = &IXIndexBUSRQ[opcode * 19];
|
||||||
|
cur_mem_ofst = &IXIndexMEMRQ[opcode * 19];
|
||||||
|
cur_irqs_ofst = &IXIndexIRQS[opcode];
|
||||||
|
}
|
||||||
|
else if (instr_bank == 4)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &IYIndex[opcode * 38];
|
||||||
|
cur_bus_ofst = &IYIndexBUSRQ[opcode * 19];
|
||||||
|
cur_mem_ofst = &IYIndexMEMRQ[opcode * 19];
|
||||||
|
cur_irqs_ofst = &IYIndexIRQS[opcode];
|
||||||
|
}
|
||||||
|
else if (instr_bank == 5)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &IXYCBIndex[opcode * 38];
|
||||||
|
cur_bus_ofst = &IXYCBIndexBUSRQ[opcode * 19];
|
||||||
|
cur_mem_ofst = &IXYCBIndexMEMRQ[opcode * 19];
|
||||||
|
cur_irqs_ofst = &IXYCBIndexIRQS[opcode];
|
||||||
|
}
|
||||||
|
else if (instr_bank == 6)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &Reset_CPU[0];
|
||||||
|
cur_bus_ofst = &Reset_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &Reset_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &Reset_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 7)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &LD_OP_R_INST[0];
|
||||||
|
cur_instr_ofst[14] = Ztemp2_saver;
|
||||||
|
cur_bus_ofst = &LD_OP_R_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &LD_OP_R_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &LD_OP_R_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 8)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &LD_CP_R_INST[0];
|
||||||
|
cur_instr_ofst[14] = Ztemp2_saver;
|
||||||
|
cur_bus_ofst = &LD_CP_R_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &LD_CP_R_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &LD_CP_R_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 9)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &REP_OP_I_INST[0];
|
||||||
|
cur_instr_ofst[8] = Ztemp2_saver;
|
||||||
|
cur_bus_ofst = &REP_OP_I_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &REP_OP_I_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &REP_OP_I_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 10)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &REP_OP_O_INST[0];
|
||||||
|
cur_bus_ofst = &REP_OP_O_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &REP_OP_O_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &REP_OP_O_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 11)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &HALT_INST[0];
|
||||||
|
cur_bus_ofst = &HALT_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &HALT_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &HALT_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 12)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &NMI_INST[0];
|
||||||
|
cur_bus_ofst = &NMI_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &NMI_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &NMI_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 13)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &IRQ0_INST[0];
|
||||||
|
cur_bus_ofst = &IRQ0_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &IRQ0_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &IRQ0_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 14)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &IRQ1_INST[0];
|
||||||
|
cur_bus_ofst = &IRQ1_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &IRQ1_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &IRQ1_IRQS;
|
||||||
|
}
|
||||||
|
else if (instr_bank == 15)
|
||||||
|
{
|
||||||
|
cur_instr_ofst = &IRQ2_INST[0];
|
||||||
|
cur_bus_ofst = &IRQ2_BUSRQ[0];
|
||||||
|
cur_mem_ofst = &IRQ2_MEMRQ[0];
|
||||||
|
cur_irqs_ofst = &IRQ2_IRQS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 19; i++)
|
if (cond_chk_fail)
|
||||||
{
|
{
|
||||||
BUSRQ[i] = *loader; loader++; BUSRQ[i] |= (*loader << 8); loader++;
|
cur_irqs_ofst = &False_IRQS[IRQS_cond_offset];
|
||||||
BUSRQ[i] |= (*loader << 16); loader++; BUSRQ[i] |= (*loader << 24); loader++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 19; i++)
|
|
||||||
{
|
|
||||||
MEMRQ[i] = *loader; loader++; MEMRQ[i] |= (*loader << 8); loader++;
|
|
||||||
MEMRQ[i] |= (*loader << 16); loader++; MEMRQ[i] |= (*loader << 24); loader++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TotalExecutedCycles = *loader; loader++; TotalExecutedCycles |= ((uint64_t)*loader << 8); loader++;
|
TotalExecutedCycles = *loader; loader++; TotalExecutedCycles |= ((uint64_t)*loader << 8); loader++;
|
||||||
|
|
Loading…
Reference in New Issue