MSXHawk: Z80 with prebuilt instruction tables

This commit is contained in:
alyosha-tas 2020-01-19 22:41:41 -05:00
parent ebfccf51de
commit 6b99a792b9
1 changed files with 284 additions and 131 deletions

View File

@ -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++;