<commit_before>//
//  Z80Storage.cpp
//  Clock Signal
//
//  Created by <NAME> on 04/09/2017.
//  Copyright 2017 <NAME>. All rights reserved.
//

#include "../Z80.hpp"
#include <cstring>

using namespace CPU::Z80;

ProcessorStorage::ProcessorStorage() {
	set_flags(0xff);
}

// Elemental bus operations
#define ReadOpcodeStart()			PartialMachineCycle(PartialMachineCycle::ReadOpcodeStart, HalfCycles(3), &pc_.full, &operation_, false)
#define ReadOpcodeWait(f)			PartialMachineCycle(PartialMachineCycle::ReadOpcodeWait, HalfCycles(2), &pc_.full, &operation_, f)
#define ReadOpcodeEnd()				PartialMachineCycle(PartialMachineCycle::ReadOpcode, HalfCycles(1), &pc_.full, &operation_, false)

#define Refresh(len)				PartialMachineCycle(PartialMachineCycle::Refresh, HalfCycles(len), &refresh_addr_.full, nullptr, false)

#define ReadStart(addr, val)		PartialMachineCycle(PartialMachineCycle::ReadStart, HalfCycles(3), &addr.full, &val, false)
#define ReadWait(l, addr, val, f)	PartialMachineCycle(PartialMachineCycle::ReadWait, HalfCycles(l), &addr.full, &val, f)
#define ReadEnd(addr, val)			PartialMachineCycle(PartialMachineCycle::Read, HalfCycles(3), &addr.full, &val, false)

#define WriteStart(addr, val)		PartialMachineCycle(PartialMachineCycle::WriteStart,HalfCycles(3), &addr.full, &val, false)
#define WriteWait(l, addr, val, f)	PartialMachineCycle(PartialMachineCycle::WriteWait, HalfCycles(l), &addr.full, &val, f)
#define WriteEnd(addr, val)			PartialMachineCycle(PartialMachineCycle::Write, HalfCycles(3), &addr.full, &val, false)

#define InputStart(addr, val)		PartialMachineCycle(PartialMachineCycle::InputStart, HalfCycles(3), &addr.full, &val, false)
#define InputWait(addr, val, f)		PartialMachineCycle(PartialMachineCycle::InputWait, HalfCycles(2), &addr.full, &val, f)
#define InputEnd(addr, val)			PartialMachineCycle(PartialMachineCycle::Input, HalfCycles(3), &addr.full, &val, false)

#define OutputStart(addr, val)		PartialMachineCycle(PartialMachineCycle::OutputStart, HalfCycles(3), &addr.full, &val, false)
#define OutputWait(addr, val, f)	PartialMachineCycle(PartialMachineCycle::OutputWait, HalfCycles(2), &addr.full, &val, f)
#define OutputEnd(addr, val)		PartialMachineCycle(PartialMachineCycle::Output, HalfCycles(3), &addr.full, &val, false)

#define IntAckStart(length, val)	PartialMachineCycle(PartialMachineCycle::InterruptStart, HalfCycles(length), nullptr, &val, false)
#define IntWait(val)				PartialMachineCycle(PartialMachineCycle::InterruptWait, HalfCycles(2), nullptr, &val, true)
#define IntAckEnd(val)				PartialMachineCycle(PartialMachineCycle::Interrupt, HalfCycles(3), nullptr, &val, false)


// A wrapper to express a bus operation as a micro-op
#define BusOp(op)					{MicroOp::BusOperation, nullptr, nullptr, op}

// Compound bus operations, as micro-ops

// Read3 is a standard read cycle: 1.5 cycles, then check the wait line, then 1.5 cycles;
// Read4 is a four-cycle read that has to do something to calculate the address: 1.5 cycles, then an extra wait cycle, then check the wait line, then 1.5 cycles;
// Read4Pre is a four-cycle read that has to do something after reading: 1.5 cycles, then check the wait line, then an extra wait cycle, then 1.5 cycles;
// Read5 is a five-cycle read: 1.5 cycles, two wait cycles, check the wait line, 1.5 cycles.
#define Read3(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val))
#define Read4(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, false)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val))
#define Read4Pre(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadWait(2, addr, val, false)), BusOp(ReadEnd(addr, val))
#define Read5(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(4, addr, val, false)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val))

#define Write3(addr, val)				BusOp(WriteStart(addr, val)), BusOp(WriteWait(2, addr, val, true)), BusOp(WriteEnd(addr, val))
#define Write5(addr, val)				BusOp(WriteStart(addr, val)), BusOp(WriteWait(4, addr, val, false)), BusOp(WriteWait(2, addr, val, true)), BusOp(WriteEnd(addr, val))

#define Input(addr, val)				BusOp(InputStart(addr, val)), BusOp(InputWait(addr, val, false)), BusOp(InputWait(addr, val, true)), BusOp(InputEnd(addr, val))
#define Output(addr, val)				BusOp(OutputStart(addr, val)), BusOp(OutputWait(addr, val, false)), BusOp(OutputWait(addr, val, true)), BusOp(OutputEnd(addr, val))
#define InternalOperation(len)			{MicroOp::BusOperation, nullptr, nullptr, {PartialMachineCycle::Internal, HalfCycles(len), &last_address_bus_, nullptr, false}}

/// A sequence is a series of micro-ops that ends in a move-to-next-program operation.
#define Sequence(...)				{ __VA_ARGS__, {MicroOp::MoveToNextProgram} }

/// An instruction is the part of an instruction that follows instruction fetch; it should include two or more refresh cycles and then the work of the instruction.
#define Instr(r, ...)				Sequence(BusOp(Refresh(r)), __VA_ARGS__)

/// A standard instruction is one with the most normal timing: two cycles of refresh, then the work.
#define StdInstr(...)				Instr(4, __VA_ARGS__)

// Assumption made: those instructions that are rated with an opcode fetch greater than four cycles spend the extra time
// providing a lengthened refresh cycle. I assume this because the CPU doesn't have foresight and presumably spends the
// normal refresh time decoding. So if it gets to cycle four and realises it has two more cycles of work, I have assumed
// it simply maintains the refresh state for an extra two cycles.
<commit_msg>Moves read time in Read4Pre.<commit_after>//
//  Z80Storage.cpp
//  Clock Signal
//
//  Created by <NAME> on 04/09/2017.
//  Copyright 2017 <NAME>. All rights reserved.
//

#include "../Z80.hpp"
#include <cstring>

using namespace CPU::Z80;

ProcessorStorage::ProcessorStorage() {
	set_flags(0xff);
}

// Elemental bus operations
#define ReadOpcodeStart()			PartialMachineCycle(PartialMachineCycle::ReadOpcodeStart, HalfCycles(3), &pc_.full, &operation_, false)
#define ReadOpcodeWait(f)			PartialMachineCycle(PartialMachineCycle::ReadOpcodeWait, HalfCycles(2), &pc_.full, &operation_, f)
#define ReadOpcodeEnd()				PartialMachineCycle(PartialMachineCycle::ReadOpcode, HalfCycles(1), &pc_.full, &operation_, false)

#define Refresh(len)				PartialMachineCycle(PartialMachineCycle::Refresh, HalfCycles(len), &refresh_addr_.full, nullptr, false)

#define ReadStart(addr, val)		PartialMachineCycle(PartialMachineCycle::ReadStart, HalfCycles(3), &addr.full, &val, false)
#define ReadWait(l, addr, val, f)	PartialMachineCycle(PartialMachineCycle::ReadWait, HalfCycles(l), &addr.full, &val, f)
#define ReadEnd(addr, val)			PartialMachineCycle(PartialMachineCycle::Read, HalfCycles(3), &addr.full, &val, false)

#define WriteStart(addr, val)		PartialMachineCycle(PartialMachineCycle::WriteStart,HalfCycles(3), &addr.full, &val, false)
#define WriteWait(l, addr, val, f)	PartialMachineCycle(PartialMachineCycle::WriteWait, HalfCycles(l), &addr.full, &val, f)
#define WriteEnd(addr, val)			PartialMachineCycle(PartialMachineCycle::Write, HalfCycles(3), &addr.full, &val, false)

#define InputStart(addr, val)		PartialMachineCycle(PartialMachineCycle::InputStart, HalfCycles(3), &addr.full, &val, false)
#define InputWait(addr, val, f)		PartialMachineCycle(PartialMachineCycle::InputWait, HalfCycles(2), &addr.full, &val, f)
#define InputEnd(addr, val)			PartialMachineCycle(PartialMachineCycle::Input, HalfCycles(3), &addr.full, &val, false)

#define OutputStart(addr, val)		PartialMachineCycle(PartialMachineCycle::OutputStart, HalfCycles(3), &addr.full, &val, false)
#define OutputWait(addr, val, f)	PartialMachineCycle(PartialMachineCycle::OutputWait, HalfCycles(2), &addr.full, &val, f)
#define OutputEnd(addr, val)		PartialMachineCycle(PartialMachineCycle::Output, HalfCycles(3), &addr.full, &val, false)

#define IntAckStart(length, val)	PartialMachineCycle(PartialMachineCycle::InterruptStart, HalfCycles(length), nullptr, &val, false)
#define IntWait(val)				PartialMachineCycle(PartialMachineCycle::InterruptWait, HalfCycles(2), nullptr, &val, true)
#define IntAckEnd(val)				PartialMachineCycle(PartialMachineCycle::Interrupt, HalfCycles(3), nullptr, &val, false)


// A wrapper to express a bus operation as a micro-op
#define BusOp(op)					{MicroOp::BusOperation, nullptr, nullptr, op}

// Compound bus operations, as micro-ops

#define InternalOperation(len)			{MicroOp::BusOperation, nullptr, nullptr, {PartialMachineCycle::Internal, HalfCycles(len), &last_address_bus_, nullptr, false}}

// Read3 is a standard read cycle: 1.5 cycles, then check the wait line, then 1.5 cycles;
// Read4 is a four-cycle read that has to do something to calculate the address: 1.5 cycles, then an extra wait cycle, then check the wait line, then 1.5 cycles;
// Read4Pre is a four-cycle read that has to do something after reading: 1.5 cycles, then check the wait line, then 1.5 cycles, then a 1-cycle internal operation;
// Read5 is a five-cycle read: 1.5 cycles, two wait cycles, check the wait line, 1.5 cycles.
#define Read3(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val))
#define Read4(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, false)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val))
#define Read4Pre(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val)), InternalOperation(2)
#define Read5(addr, val)				BusOp(ReadStart(addr, val)), BusOp(ReadWait(4, addr, val, false)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val))

#define Write3(addr, val)				BusOp(WriteStart(addr, val)), BusOp(WriteWait(2, addr, val, true)), BusOp(WriteEnd(addr, val))
#define Write5(addr, val)				BusOp(WriteStart(addr, val)), BusOp(WriteWait(4, addr, val, false)), BusOp(WriteWait(2, addr, val, true)), BusOp(WriteEnd(addr, val))

#define Input(addr, val)				BusOp(InputStart(addr, val)), BusOp(InputWait(addr, val, false)), BusOp(InputWait(addr, val, true)), BusOp(InputEnd(addr, val))
#define Output(addr, val)				BusOp(OutputStart(addr, val)), BusOp(OutputWait(addr, val, false)), BusOp(OutputWait(addr, val, true)), BusOp(OutputEnd(addr, val))

/// A sequence is a series of micro-ops that ends in a move-to-next-program operation.
#define Sequence(...)				{ __VA_ARGS__, {MicroOp::MoveToNextProgram} }

/// An instruction is the part of an instruction that follows instruction fetch; it should include two or more refresh cycles and then the work of the instruction.
#define Instr(r, ...)				Sequence(BusOp(Refresh(r)), __VA_ARGS__)

/// A standard instruction is one with the most normal timing: two cycles of refresh, then the work.
#define StdInstr(...)				Instr(4, __VA_ARGS__)

// Assumption made: those instructions that are rated with an opcode fetch greater than four cycles spend the extra time
// providing a lengthened refresh cycle. I assume this because the CPU doesn't have foresight and presumably spends the
// normal refresh time decoding. So if it gets to cycle four and realises it has two more cycles of work, I have assumed
// it simply maintains the refresh state for an extra two cycles.

{'fraction_non_alphanumeric': 0.1306501547987616, 'fraction_numerical': 0.012737726669615215, 'mean_word_length': 6.355888093689004, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '739', 'n_tokens_mistral': 3811, 'n_tokens_neox': 3619, 'n_words': 1091}