mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 01:32:55 +00:00
Merge pull request #1388 from TomHarte/6502BBSBBR
Correct 65c02 BBS/BBR bus activity.
This commit is contained in:
commit
94058d498c
@ -708,12 +708,23 @@ void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case CycleFetchFromHalfUpdatedPC: {
|
case CycleFetchFromHalfUpdatedPC: {
|
||||||
uint16_t halfUpdatedPc = uint16_t(((pc_.halves.low + int8_t(operand_)) & 0xff) | (pc_.halves.high << 8));
|
uint16_t half_updated_pc = uint16_t(((pc_.halves.low + int8_t(operand_)) & 0xff) | (pc_.halves.high << 8));
|
||||||
throwaway_read(halfUpdatedPc);
|
throwaway_read(half_updated_pc);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case CycleFetchFromNextAddress:
|
||||||
|
throwaway_read(next_address_.full);
|
||||||
|
break;
|
||||||
|
|
||||||
case OperationAddSignedOperandToPC16:
|
case OperationAddSignedOperandToPC16:
|
||||||
|
next_address_ = pc_.full;
|
||||||
pc_.full = uint16_t(pc_.full + int8_t(operand_));
|
pc_.full = uint16_t(pc_.full + int8_t(operand_));
|
||||||
|
|
||||||
|
// Skip a step if 8-bit arithmetic would have been sufficient;
|
||||||
|
// in practise this operation is used only by BBS/BBR.
|
||||||
|
if(pc_.halves.high == next_address_.halves.high) {
|
||||||
|
++scheduled_program_counter_;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case OperationBBRBBS: {
|
case OperationBBRBBS: {
|
||||||
@ -725,7 +736,7 @@ void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
|
|||||||
} else {
|
} else {
|
||||||
scheduled_program_counter_ = operations_[size_t(OperationsSlot::DoNotBBRBBS)];
|
scheduled_program_counter_ = operations_[size_t(OperationsSlot::DoNotBBRBBS)];
|
||||||
}
|
}
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
// MARK: - Transfers
|
// MARK: - Transfers
|
||||||
|
|
||||||
|
@ -269,18 +269,35 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
|
|||||||
|
|
||||||
/* 0x105: Do BBR or BBS. */
|
/* 0x105: Do BBR or BBS. */
|
||||||
Program(
|
Program(
|
||||||
CycleFetchOperand, // Fetch offset.
|
CycleFetchOperand, // Fetch offset, and increment PC.
|
||||||
OperationIncrementPC,
|
OperationIncrementPC,
|
||||||
CycleFetchFromHalfUpdatedPC,
|
|
||||||
OperationAddSignedOperandToPC16
|
OperationAddSignedOperandToPC16, // Calculate target PC, leaving old PC in next_address_
|
||||||
|
// and possibly skipping the next instruction.
|
||||||
|
|
||||||
|
CycleFetchFromNextAddress,
|
||||||
|
CycleFetchFromNextAddress
|
||||||
),
|
),
|
||||||
|
// Six or seven cycles total are:
|
||||||
|
// (1) operation;
|
||||||
|
// (2) zero page address as operand;
|
||||||
|
// (3) zero page address;
|
||||||
|
// (4) duplicate of (3);
|
||||||
|
// (5) further operand;
|
||||||
|
// (6) read from next PC;
|
||||||
|
// (7) repeat read from next PC if 16-bit arithmetic was required.
|
||||||
|
|
||||||
/* 0x106: Complete BBR or BBS without branching. */
|
/* 0x106: Complete BBR or BBS without branching. */
|
||||||
Program(
|
Program(
|
||||||
CycleFetchOperand,
|
CycleFetchOperand, // Fetch offset.
|
||||||
OperationIncrementPC,
|
OperationIncrementPC
|
||||||
CycleFetchFromHalfUpdatedPC
|
|
||||||
)
|
)
|
||||||
|
// Five cycles total are:
|
||||||
|
// (1) operation;
|
||||||
|
// (2) zero page address as operand;
|
||||||
|
// (3) zero page address;
|
||||||
|
// (4) duplicate of (3);
|
||||||
|
// (5) further operand, which goes unused.
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(operations_6502) == sizeof(operations_));
|
static_assert(sizeof(operations_6502) == sizeof(operations_));
|
||||||
@ -408,15 +425,25 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
|
|||||||
// 0xc7, 0xcb, 0xcf, 0xd7, 0xdb, 0xdf,
|
// 0xc7, 0xcb, 0xcf, 0xd7, 0xdb, 0xdf,
|
||||||
// 0xe7, 0xef, 0xf7, 0xff
|
// 0xe7, 0xef, 0xf7, 0xff
|
||||||
if(has_bbrbbsrmbsmb(personality)) {
|
if(has_bbrbbsrmbsmb(personality)) {
|
||||||
// Add BBS and BBR. These take five cycles. My guessed breakdown is:
|
// Add BBS and BBR. These take five, six or seven cycles. First five:
|
||||||
// 1. read opcode
|
// 1. read opcode
|
||||||
// 2. read operand
|
// 2. read first operand (i.e. zero-page address)
|
||||||
// 3. read zero page
|
// 3. read zero page
|
||||||
// 4. read second operand
|
// 4. reread zero page (presumably as a stall, to make a decision on the above)
|
||||||
// 5. read from PC without top byte fixed yet
|
// 5. read second operand (i.e. branch offset)
|
||||||
// ... with the caveat that (3) and (4) could be the other way around.
|
//
|
||||||
|
// ... and then, if the branch is taken:
|
||||||
|
//
|
||||||
|
// 6. read from where next instruction would have been
|
||||||
|
// 7. reread, if a further stall is necessary to cover up for a 16-bit address change.
|
||||||
for(int location = 0x0f; location <= 0xff; location += 0x10) {
|
for(int location = 0x0f; location <= 0xff; location += 0x10) {
|
||||||
Install(location, Program(OperationLoadAddressZeroPage, CycleFetchOperandFromAddress, OperationBBRBBS));
|
Install(location, Program(
|
||||||
|
OperationLoadAddressZeroPage,
|
||||||
|
CycleFetchOperandFromAddress, // (cycle 3)
|
||||||
|
CycleFetchOperandFromAddress, // (cycle 4)
|
||||||
|
OperationBBRBBS // Branches to either OperationsSlot::DoBBRBBS, or to
|
||||||
|
// OperationSlot::DoNotBBRBBS, depending on data read.
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add RMB and SMB.
|
// Add RMB and SMB.
|
||||||
|
@ -186,7 +186,9 @@ class ProcessorStorage {
|
|||||||
|
|
||||||
CycleFetchFromHalfUpdatedPC, // performs a throwaway read from (PC + (signed)operand).l combined with PC.h
|
CycleFetchFromHalfUpdatedPC, // performs a throwaway read from (PC + (signed)operand).l combined with PC.h
|
||||||
CycleAddSignedOperandToPC, // sets next_address to PC + (signed)operand. If the high byte of next_address differs from the PC, schedules a throwaway read from the half-updated PC. 65C02 specific: if the top two bytes are the same, proceeds directly to fetch-decode-execute, ignoring any pending interrupts.
|
CycleAddSignedOperandToPC, // sets next_address to PC + (signed)operand. If the high byte of next_address differs from the PC, schedules a throwaway read from the half-updated PC. 65C02 specific: if the top two bytes are the same, proceeds directly to fetch-decode-execute, ignoring any pending interrupts.
|
||||||
OperationAddSignedOperandToPC16, // adds (signed)operand into the PC
|
OperationAddSignedOperandToPC16, // adds (signed)operand into the PC, leaving old PC in next_address_ and skipping a program step if there was no carry from low to high byte
|
||||||
|
|
||||||
|
CycleFetchFromNextAddress, // performs a throwaway fetch from next_address_
|
||||||
|
|
||||||
OperationSetFlagsFromOperand, // sets all flags based on operand_
|
OperationSetFlagsFromOperand, // sets all flags based on operand_
|
||||||
OperationSetOperandFromFlagsWithBRKSet, // sets operand_ to the value of all flags, with the break flag set
|
OperationSetOperandFromFlagsWithBRKSet, // sets operand_ to the value of all flags, with the break flag set
|
||||||
|
Loading…
Reference in New Issue
Block a user