mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-09 15:39:08 +00:00
Implements BBS and BBR.
This commit is contained in:
parent
32338bea4d
commit
e46bde35f5
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user