1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Implements BBS and BBR.

This commit is contained in:
Thomas Harte 2018-08-07 21:52:17 -04:00
parent 32338bea4d
commit e46bde35f5
3 changed files with 70 additions and 22 deletions

View File

@ -13,7 +13,7 @@
*/
template <typename T, bool uses_ready_line> void Processor<T, uses_ready_line>::run_for(const Cycles cycles) {
static const MicroOp doBranch[] = {
static const MicroOp do_branch[] = {
CycleReadFromPC,
CycleAddSignedOperandToPC,
OperationMoveToNextProgram
@ -460,7 +460,7 @@ if(number_of_cycles <= Cycles(0)) break;
// MARK: - Branching
#define BRA(condition) pc_.full++; if(condition) scheduled_program_counter_ = doBranch
#define BRA(condition) pc_.full++; if(condition) scheduled_program_counter_ = do_branch
case OperationBPL: BRA(!(negative_result_&0x80)); continue;
case OperationBMI: BRA(negative_result_&0x80); continue;
@ -483,6 +483,39 @@ if(number_of_cycles <= Cycles(0)) break;
}
continue;
case CycleFetchFromHalfUpdatedPC: {
uint16_t halfUpdatedPc = static_cast<uint16_t>(((pc_.bytes.low + (int8_t)operand_) & 0xff) | (pc_.bytes.high << 8));
throwaway_read(halfUpdatedPc);
} break;
case OperationAddSignedOperandToPC16:
pc_.full = static_cast<uint16_t>(pc_.full + (int8_t)operand_);
continue;
case OperationBBRBBS: {
// To reach here, the 6502 has (i) read the operation; (ii) read the first operand;
// and (iii) read from the corresponding zero page.
const uint8_t mask = static_cast<uint8_t>(1 << ((operation_ >> 4)&7));
if((operand_ & mask) == ((operation_ & 0x80) ? mask : 0)) {
static const MicroOp do_branch[] = {
CycleFetchOperand, // Fetch offset.
OperationIncrementPC,
CycleFetchFromHalfUpdatedPC,
OperationAddSignedOperandToPC16,
OperationMoveToNextProgram
};
scheduled_program_counter_ = do_branch;
} else {
static const MicroOp do_not_branch[] = {
CycleFetchOperand,
OperationIncrementPC,
CycleFetchFromHalfUpdatedPC,
OperationMoveToNextProgram
};
scheduled_program_counter_ = do_not_branch;
}
} break;
#undef BRA
// MARK: - Transfers

View File

@ -76,8 +76,6 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
decimal_flag_ &= Flag::Decimal;
overflow_flag_ &= Flag::Overflow;
using InstructionList = ProcessorStorage::MicroOp[10];
const InstructionList operations_6502[256] = {
/* 0x00 BRK */ Program(CycleIncPCPushPCH, CyclePushPCL, OperationBRKPickVector, OperationSetOperandFromFlagsWithBRKSet, CyclePushOperand, OperationSetI, CycleReadVectorLow, CycleReadVectorHigh),
/* 0x01 ORA x, ind */ IndexedIndirectRead(OperationORA),
@ -220,22 +218,30 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
memcpy(operations_, operations_6502, sizeof(operations_));
// Patch the table according to the chip's personality.
#define Install(location, code) memcpy(&operations_[location], code, sizeof(InstructionList))
#define Install(location, instructions) {\
const InstructionList code = instructions; \
memcpy(&operations_[location], code, sizeof(InstructionList)); \
}
if(personality != P6502) {
// Add P[L/H][X/Y].
const InstructionList phx = Program(CyclePushX);
const InstructionList phy = Program(CyclePushY);
const InstructionList plx = Program(CycleReadFromS, CyclePullX, OperationSetFlagsFromX);
const InstructionList ply = Program(CycleReadFromS, CyclePullY, OperationSetFlagsFromY);
Install(0x5a, Program(CyclePushY));
Install(0xda, Program(CyclePushX));
Install(0x7a, Program(CycleReadFromS, CyclePullY, OperationSetFlagsFromY));
Install(0xfa, Program(CycleReadFromS, CyclePullX, OperationSetFlagsFromX));
Install(0x5a, phy);
Install(0xda, phx);
Install(0x7a, ply);
Install(0xfa, plx);
// Add BRA.
Install(0x80, Program(OperationBRA));
// Add BRA and the various BBS and BBRs.
const InstructionList bra = Program(OperationBRA);
Install(0x80, bra);
// Add BBS and BBR. These take five cycles. My guessed breakdown is:
// 1. read opcode
// 2. read operand
// 3. read zero page
// 4. read second operand
// 5. read from PC without top byte fixed yet
// ... with the caveat that (3) and (4) could be the other way around.
for(int location = 0x0f; location <= 0xff; location += 0x10) {
Install(location, Program(OperationLoadAddressZeroPage, CycleFetchOperandFromAddress, OperationBBRBBS));
}
}
#undef Install
}

View File

@ -52,19 +52,28 @@ class ProcessorStorage {
OperationCLC, OperationCLI, OperationCLV, OperationCLD,
OperationSEC, OperationSEI, OperationSED, OperationINC,
OperationDEC, OperationINX, OperationDEX, OperationINY,
OperationDEY, OperationBPL, OperationBMI, OperationBVC,
OperationBVS, OperationBCC, OperationBCS, OperationBNE,
OperationBEQ, OperationBRA, OperationTXA, OperationTYA,
OperationTXS, OperationTAY, OperationTAX, OperationTSX,
OperationDEY,
OperationBPL, OperationBMI, OperationBVC, OperationBVS,
OperationBCC, OperationBCS, OperationBNE, OperationBEQ,
OperationBRA, OperationBBRBBS,
OperationTXA, OperationTYA, OperationTXS, OperationTAY,
OperationTAX, OperationTSX,
OperationARR, OperationSBX, OperationLXA, OperationANE,
OperationANC, OperationLAS,
CycleAddSignedOperandToPC, OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet,
CycleFetchFromHalfUpdatedPC, CycleAddSignedOperandToPC, OperationAddSignedOperandToPC16,
OperationSetFlagsFromOperand, OperationSetOperandFromFlagsWithBRKSet,
OperationSetOperandFromFlags,
OperationSetFlagsFromA, OperationSetFlagsFromX, OperationSetFlagsFromY,
CycleScheduleJam
};
MicroOp operations_[256][10];
using InstructionList = MicroOp[10];
InstructionList operations_[256];
const MicroOp *scheduled_program_counter_ = nullptr;