mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-11 15:49:38 +00:00
Merge branch 'master' into SeparateFetchClock
This commit is contained in:
commit
e7299c16f6
@ -224,7 +224,7 @@ enum class Operation: uint8_t {
|
||||
/// current EFLAGS DF flag.
|
||||
INS,
|
||||
/// Outputs a byte, word or double word from ES:[e]DI to the port specified by DX,
|
||||
/// incrementing or decrementing [e]DI as per the current EFLAGS DF flag.]
|
||||
/// incrementing or decrementing [e]DI as per the current EFLAGS DF flag.
|
||||
OUTS,
|
||||
|
||||
/// Pushes all general purpose registers to the stack, in the order:
|
||||
|
@ -155,14 +155,14 @@ void print_ram(FILE *file, const std::unordered_map<uint32_t, uint8_t> &data) {
|
||||
- (void)generate {
|
||||
BusHandler handler;
|
||||
|
||||
// Make tests repeatable, at least for any given instance of
|
||||
// the runtime.
|
||||
srand(65816);
|
||||
|
||||
NSString *const tempDir = NSTemporaryDirectory();
|
||||
NSLog(@"Outputting to %@", tempDir);
|
||||
|
||||
for(int operation = 0; operation < 512; operation++) {
|
||||
// Make tests repeatable, at least for any given instance of
|
||||
// the runtime.
|
||||
srand(65816 + operation);
|
||||
|
||||
const bool is_emulated = operation & 256;
|
||||
const uint8_t opcode = operation & 255;
|
||||
|
||||
|
@ -14,10 +14,7 @@ uint16_t ProcessorBase::value_of(Register r) const {
|
||||
switch (r) {
|
||||
case Register::ProgramCounter: return registers_.pc;
|
||||
case Register::LastOperationAddress: return last_operation_pc_;
|
||||
case Register::StackPointer:
|
||||
return
|
||||
(registers_.s.full & (registers_.emulation_flag ? 0xff : 0xffff)) |
|
||||
(registers_.emulation_flag ? 0x100 : 0x000);
|
||||
case Register::StackPointer: return registers_.s.full;
|
||||
case Register::Flags: return get_flags();
|
||||
case Register::A: return registers_.a.full;
|
||||
case Register::X: return registers_.x.full;
|
||||
|
@ -191,6 +191,13 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
--registers_.s.full;
|
||||
break;
|
||||
|
||||
case CyclePushNotEmulation:
|
||||
bus_address_ = registers_.s.full;
|
||||
bus_value_ = data_buffer_.next_output_descending();
|
||||
bus_operation_ = MOS6502Esque::Write;
|
||||
--registers_.s.full;
|
||||
break;
|
||||
|
||||
case CyclePullIfNotEmulation:
|
||||
if(registers_.emulation_flag) {
|
||||
continue;
|
||||
@ -202,6 +209,13 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
stack_access(data_buffer_.next_input(), MOS6502Esque::Read);
|
||||
break;
|
||||
|
||||
case CyclePullNotEmulation:
|
||||
++registers_.s.full;
|
||||
bus_address_ = registers_.s.full;
|
||||
bus_value_ = data_buffer_.next_input();
|
||||
bus_operation_ = MOS6502Esque::Read;
|
||||
break;
|
||||
|
||||
case CycleAccessStack:
|
||||
stack_access(&bus_throwaway_, MOS6502Esque::InternalOperationRead);
|
||||
break;
|
||||
@ -359,15 +373,20 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
continue;
|
||||
|
||||
case OperationConstructDirectIndexedIndirect:
|
||||
data_address_ = (
|
||||
((registers_.direct + registers_.x.full + instruction_buffer_.value) & registers_.e_masks[1]) +
|
||||
(registers_.direct & registers_.e_masks[0])
|
||||
) & 0xffff;
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
|
||||
// Emulation mode plus DL = 0 is required for 6502-style functionality where
|
||||
// only the low byte is the result of the indirect calculation.
|
||||
if(!(registers_.direct&0xff)) {
|
||||
data_address_ = (
|
||||
((registers_.direct + registers_.x.full + instruction_buffer_.value) & registers_.e_masks[1]) +
|
||||
(registers_.direct & registers_.e_masks[0])
|
||||
) & 0xffff;
|
||||
++next_op_;
|
||||
} else {
|
||||
data_address_ = (
|
||||
registers_.direct + registers_.x.full + instruction_buffer_.value
|
||||
) & 0xffff;
|
||||
}
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
continue;
|
||||
|
||||
case OperationConstructDirectIndirectIndexedLong:
|
||||
@ -441,7 +460,9 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
if(registers_.emulation_flag) {
|
||||
if(exception_is_interrupt_) data_buffer_.value &= ~uint32_t(Flag::Break);
|
||||
data_buffer_.size = 3;
|
||||
registers_.data_bank = 0;
|
||||
if(pending_exceptions_ & (Reset | PowerOn)) {
|
||||
registers_.data_bank = 0;
|
||||
}
|
||||
++next_op_;
|
||||
} else {
|
||||
data_buffer_.value |= registers_.program_bank << 8; // The PBR is always held such that
|
||||
|
@ -319,7 +319,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(CycleFetchIncrementPC); // New PCH.
|
||||
|
||||
target(OperationCopyPBRToData); // Copy PBR to the data register.
|
||||
target(CyclePush); // PBR.
|
||||
target(CyclePushNotEmulation); // PBR.
|
||||
target(CycleFetchPreviousThrowaway); // IO.
|
||||
|
||||
target(CycleFetchPC); // New PBR.
|
||||
@ -327,8 +327,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(OperationConstructAbsolute); // Calculate data address.
|
||||
target(OperationPerform); // [JSL]
|
||||
|
||||
target(CyclePush); // PCH.
|
||||
target(CyclePush); // PCL.
|
||||
target(CyclePushNotEmulation); // PCH.
|
||||
target(CyclePushNotEmulation); // PCL.
|
||||
}
|
||||
|
||||
// 5. Absolute long, X; al, x.
|
||||
@ -656,7 +656,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
stack_exception_impl(type, is8bit, target, CycleAccessStack);
|
||||
}
|
||||
|
||||
// 22b. Stack; s, PLx.
|
||||
// 22b(i). Stack; s, PLx, respecting emulation mode. E.g. PLP.
|
||||
static void stack_pull(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
@ -667,7 +667,18 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(OperationPerform);
|
||||
}
|
||||
|
||||
// 22c. Stack; s, PHx.
|
||||
// 22b(ii). Stack; s, PLx, ignoring emulation mode. I.e. PLD.
|
||||
static void stack_pld(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
|
||||
target(CyclePullNotEmulation); // REG low.
|
||||
target(CyclePullNotEmulation); // REG [high].
|
||||
|
||||
target(OperationPerform);
|
||||
}
|
||||
|
||||
// 22c(i). Stack; s, PHx, respecting emulation mode. E.g. PHP.
|
||||
static void stack_push(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
|
||||
@ -677,6 +688,16 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(CyclePush); // REG [low].
|
||||
}
|
||||
|
||||
// 22c(i). Stack; s, PHx, ignoring emulation mode. I.e. PHD.
|
||||
static void stack_phd(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
|
||||
target(OperationPerform);
|
||||
|
||||
target(CyclePushNotEmulation); // REG high.
|
||||
target(CyclePushNotEmulation); // REG [low].
|
||||
}
|
||||
|
||||
// 22d. Stack; s, PEA.
|
||||
static void stack_pea(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||
target(CycleFetchIncrementPC); // AAL.
|
||||
@ -684,8 +705,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
|
||||
target(OperationCopyInstructionToData);
|
||||
|
||||
target(CyclePush); // AAH.
|
||||
target(CyclePush); // AAL.
|
||||
target(CyclePushNotEmulation); // AAH.
|
||||
target(CyclePushNotEmulation); // AAL.
|
||||
}
|
||||
|
||||
// 22e. Stack; s, PEI.
|
||||
@ -697,8 +718,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
|
||||
target(CycleFetchIncrementData); // AAL.
|
||||
target(CycleFetchData); // AAH.
|
||||
target(CyclePush); // AAH.
|
||||
target(CyclePush); // AAL.
|
||||
target(CyclePushNotEmulation); // AAH.
|
||||
target(CyclePushNotEmulation); // AAL.
|
||||
}
|
||||
|
||||
// 22f. Stack; s, PER.
|
||||
@ -709,8 +730,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
|
||||
target(OperationConstructPER);
|
||||
|
||||
target(CyclePush); // AAH.
|
||||
target(CyclePush); // AAL.
|
||||
target(CyclePushNotEmulation); // AAH.
|
||||
target(CyclePushNotEmulation); // AAL.
|
||||
}
|
||||
|
||||
// 22g. Stack; s, RTI.
|
||||
@ -743,9 +764,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
target(CycleFetchPCThrowaway); // IO.
|
||||
|
||||
target(CyclePull); // New PCL.
|
||||
target(CyclePull); // New PCH.
|
||||
target(CyclePull); // New PBR.
|
||||
target(CyclePullNotEmulation); // New PCL.
|
||||
target(CyclePullNotEmulation); // New PCH.
|
||||
target(CyclePullNotEmulation); // New PBR.
|
||||
|
||||
target(OperationPerform); // [RTL]
|
||||
}
|
||||
@ -818,7 +839,7 @@ ProcessorStorage::ProcessorStorage() {
|
||||
/* 0x08 PHP s */ op(stack_push, PHP, AccessMode::Always8Bit);
|
||||
/* 0x09 ORA # */ op(immediate, ORA);
|
||||
/* 0x0a ASL A */ op(accumulator, ASL);
|
||||
/* 0x0b PHD s */ op(stack_push, PHD, AccessMode::Always16Bit);
|
||||
/* 0x0b PHD s */ op(stack_phd, PHD);
|
||||
/* 0x0c TSB a */ op(absolute_rmw, TSB);
|
||||
/* 0x0d ORA a */ op(absolute, ORA);
|
||||
/* 0x0e ASL a */ op(absolute_rmw, ASL);
|
||||
@ -852,7 +873,7 @@ ProcessorStorage::ProcessorStorage() {
|
||||
/* 0x28 PLP s */ op(stack_pull, PLP, AccessMode::Always8Bit);
|
||||
/* 0x29 AND # */ op(immediate, AND);
|
||||
/* 0x2a ROL A */ op(accumulator, ROL);
|
||||
/* 0x2b PLD s */ op(stack_pull, PLD, AccessMode::Always16Bit);
|
||||
/* 0x2b PLD s */ op(stack_pld, PLD);
|
||||
/* 0x2c BIT a */ op(absolute, BIT);
|
||||
/* 0x2d AND a */ op(absolute, AND);
|
||||
/* 0x2e ROL a */ op(absolute_rmw, ROL);
|
||||
|
@ -58,6 +58,11 @@ enum MicroOp: uint8_t {
|
||||
/// Performs as CyclePull if the 65816 is not in emulation mode; otherwise skips itself.
|
||||
CyclePullIfNotEmulation,
|
||||
|
||||
/// Pushes a single byte from the data buffer to the stack, always using its full 16-bit address.
|
||||
CyclePushNotEmulation,
|
||||
/// Pulls a single byte to the data buffer from the stack, always using its full 16-bit address.
|
||||
CyclePullNotEmulation,
|
||||
|
||||
/// Issues a BusOperation::None and regresses the micro-op counter until an established
|
||||
/// STP or WAI condition is satisfied.
|
||||
CycleRepeatingNone,
|
||||
|
Loading…
Reference in New Issue
Block a user