From e46bde35f556aa1099f459e0235eff343d9a1ab3 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 7 Aug 2018 21:52:17 -0400 Subject: [PATCH] Implements BBS and BBR. --- .../Implementation/6502Implementation.hpp | 37 ++++++++++++++++++- .../6502/Implementation/6502Storage.cpp | 34 ++++++++++------- .../6502/Implementation/6502Storage.hpp | 21 ++++++++--- 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/Processors/6502/Implementation/6502Implementation.hpp b/Processors/6502/Implementation/6502Implementation.hpp index 043534991..4d3cca800 100644 --- a/Processors/6502/Implementation/6502Implementation.hpp +++ b/Processors/6502/Implementation/6502Implementation.hpp @@ -13,7 +13,7 @@ */ template void Processor::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(((pc_.bytes.low + (int8_t)operand_) & 0xff) | (pc_.bytes.high << 8)); + throwaway_read(halfUpdatedPc); + } break; + + case OperationAddSignedOperandToPC16: + pc_.full = static_cast(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(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 diff --git a/Processors/6502/Implementation/6502Storage.cpp b/Processors/6502/Implementation/6502Storage.cpp index 31efd30e4..264287f4e 100644 --- a/Processors/6502/Implementation/6502Storage.cpp +++ b/Processors/6502/Implementation/6502Storage.cpp @@ -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 } diff --git a/Processors/6502/Implementation/6502Storage.hpp b/Processors/6502/Implementation/6502Storage.hpp index bb9a06d83..bc58eb74a 100644 --- a/Processors/6502/Implementation/6502Storage.hpp +++ b/Processors/6502/Implementation/6502Storage.hpp @@ -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;