mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Made minor restructuring changes, slightly to reduce number of conditionals per operation and to drop a big hint to the optimiser.
This commit is contained in:
parent
cb1b81dbef
commit
c253a4258f
@ -626,61 +626,67 @@ template <class T> class Processor {
|
|||||||
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(BusOperation::Ready, busAddress, busValue);
|
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(BusOperation::Ready, busAddress, busValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!_ready_is_active && number_of_cycles > 0) {
|
if(!_ready_is_active)
|
||||||
|
{
|
||||||
|
while(number_of_cycles > 0) {
|
||||||
|
|
||||||
if(nextBusOperation != BusOperation::None) {
|
if(nextBusOperation != BusOperation::None) {
|
||||||
_interrupt_requests = (_interrupt_requests & ~InterruptRequestFlags::IRQ) | (_irq_request_history ? InterruptRequestFlags::IRQ : 0);
|
if(isReadOperation(nextBusOperation) && _ready_line_is_enabled) {
|
||||||
_irq_request_history = _irq_line_is_enabled && !_interruptFlag;
|
_ready_is_active = true;
|
||||||
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(nextBusOperation, busAddress, busValue);
|
break;
|
||||||
nextBusOperation = BusOperation::None;
|
}
|
||||||
}
|
_interrupt_requests = (_interrupt_requests & ~InterruptRequestFlags::IRQ) | (_irq_request_history ? InterruptRequestFlags::IRQ : 0);
|
||||||
|
_irq_request_history = _irq_line_is_enabled && !_interruptFlag;
|
||||||
|
number_of_cycles -= static_cast<T *>(this)->perform_bus_operation(nextBusOperation, busAddress, busValue);
|
||||||
|
nextBusOperation = BusOperation::None;
|
||||||
|
}
|
||||||
|
|
||||||
const MicroOp cycle = program[scheduleProgramProgramCounter];
|
const MicroOp cycle = program[scheduleProgramProgramCounter];
|
||||||
scheduleProgramProgramCounter++;
|
scheduleProgramProgramCounter++;
|
||||||
|
|
||||||
#define read_op(val, addr) nextBusOperation = BusOperation::ReadOpcode; busAddress = addr; busValue = &val
|
#define read_op(val, addr) nextBusOperation = BusOperation::ReadOpcode; busAddress = addr; busValue = &val
|
||||||
#define read_mem(val, addr) nextBusOperation = BusOperation::Read; busAddress = addr; busValue = &val
|
#define read_mem(val, addr) nextBusOperation = BusOperation::Read; busAddress = addr; busValue = &val
|
||||||
#define throwaway_read(addr) nextBusOperation = BusOperation::Read; busAddress = addr; busValue = &throwaway_target
|
#define throwaway_read(addr) nextBusOperation = BusOperation::Read; busAddress = addr; busValue = &throwaway_target
|
||||||
#define write_mem(val, addr) nextBusOperation = BusOperation::Write; busAddress = addr; busValue = &val
|
#define write_mem(val, addr) nextBusOperation = BusOperation::Write; busAddress = addr; busValue = &val
|
||||||
|
|
||||||
switch(cycle) {
|
switch(cycle) {
|
||||||
|
|
||||||
#pragma mark - Fetch/Decode
|
#pragma mark - Fetch/Decode
|
||||||
|
|
||||||
case CycleFetchOperation: {
|
case CycleFetchOperation: {
|
||||||
_lastOperationPC = _pc;
|
_lastOperationPC = _pc;
|
||||||
// printf("%04x x:%02x\n", _pc.full, _x);
|
// printf("%04x x:%02x\n", _pc.full, _x);
|
||||||
_pc.full++;
|
_pc.full++;
|
||||||
read_op(_operation, _lastOperationPC.full);
|
read_op(_operation, _lastOperationPC.full);
|
||||||
|
|
||||||
// static int last_cycles_left_to_run = 0;
|
// static int last_cycles_left_to_run = 0;
|
||||||
// static bool printed_map[256] = {false};
|
// static bool printed_map[256] = {false};
|
||||||
// if(!printed_map[_operation]) {
|
// if(!printed_map[_operation]) {
|
||||||
// printed_map[_operation] = true;
|
// printed_map[_operation] = true;
|
||||||
// if(last_cycles_left_to_run > _cycles_left_to_run)
|
// if(last_cycles_left_to_run > _cycles_left_to_run)
|
||||||
// printf("%02x %d\n", _operation, last_cycles_left_to_run - _cycles_left_to_run);
|
// printf("%02x %d\n", _operation, last_cycles_left_to_run - _cycles_left_to_run);
|
||||||
// else
|
// else
|
||||||
// printf("%02x\n", _operation);
|
// printf("%02x\n", _operation);
|
||||||
// }
|
// }
|
||||||
// last_cycles_left_to_run = _cycles_left_to_run;
|
// last_cycles_left_to_run = _cycles_left_to_run;
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
case CycleFetchOperand:
|
case CycleFetchOperand:
|
||||||
read_mem(_operand, _pc.full);
|
read_mem(_operand, _pc.full);
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationDecodeOperation:
|
case OperationDecodeOperation:
|
||||||
// printf("d %02x\n", _operation);
|
// printf("d %02x\n", _operation);
|
||||||
decode_operation(_operation);
|
decode_operation(_operation);
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationMoveToNextProgram:
|
case OperationMoveToNextProgram:
|
||||||
_scheduledPrograms[scheduleProgramsReadPointer] = NULL;
|
_scheduledPrograms[scheduleProgramsReadPointer] = NULL;
|
||||||
scheduleProgramsReadPointer = (scheduleProgramsReadPointer+1)&3;
|
scheduleProgramsReadPointer = (scheduleProgramsReadPointer+1)&3;
|
||||||
scheduleProgramProgramCounter = 0;
|
scheduleProgramProgramCounter = 0;
|
||||||
checkSchedule();
|
checkSchedule();
|
||||||
program = _scheduledPrograms[scheduleProgramsReadPointer];
|
program = _scheduledPrograms[scheduleProgramsReadPointer];
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
#define push(v) \
|
#define push(v) \
|
||||||
{\
|
{\
|
||||||
@ -688,419 +694,416 @@ template <class T> class Processor {
|
|||||||
write_mem(v, targetAddress);\
|
write_mem(v, targetAddress);\
|
||||||
}
|
}
|
||||||
|
|
||||||
case CycleIncPCPushPCH: _pc.full++; // deliberate fallthrough
|
case CycleIncPCPushPCH: _pc.full++; // deliberate fallthrough
|
||||||
case CyclePushPCH: push(_pc.bytes.high); break;
|
case CyclePushPCH: push(_pc.bytes.high); continue;
|
||||||
case CyclePushPCL: push(_pc.bytes.low); break;
|
case CyclePushPCL: push(_pc.bytes.low); continue;
|
||||||
case CyclePushOperand: push(_operand); break;
|
case CyclePushOperand: push(_operand); continue;
|
||||||
case CyclePushA: push(_a); break;
|
case CyclePushA: push(_a); continue;
|
||||||
case CycleNoWritePush:
|
case CycleNoWritePush:
|
||||||
{
|
{
|
||||||
uint16_t targetAddress = _s | 0x100; _s--;
|
uint16_t targetAddress = _s | 0x100; _s--;
|
||||||
read_mem(_operand, targetAddress);
|
read_mem(_operand, targetAddress);
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
#undef push
|
#undef push
|
||||||
|
|
||||||
case CycleReadFromS: throwaway_read(_s | 0x100); break;
|
case CycleReadFromS: throwaway_read(_s | 0x100); continue;
|
||||||
case CycleReadFromPC: throwaway_read(_pc.full); break;
|
case CycleReadFromPC: throwaway_read(_pc.full); continue;
|
||||||
|
|
||||||
case OperationBRKPickVector:
|
case OperationBRKPickVector:
|
||||||
// NMI can usurp BRK-vector operations
|
// NMI can usurp BRK-vector operations
|
||||||
nextAddress.full = (_interrupt_requests & InterruptRequestFlags::NMI) ? 0xfffa : 0xfffe;
|
nextAddress.full = (_interrupt_requests & InterruptRequestFlags::NMI) ? 0xfffa : 0xfffe;
|
||||||
_interrupt_requests &= ~InterruptRequestFlags::NMI; // TODO: this probably doesn't happen now?
|
_interrupt_requests &= ~InterruptRequestFlags::NMI; // TODO: this probably doesn't happen now?
|
||||||
break;
|
continue;
|
||||||
case OperationNMIPickVector: nextAddress.full = 0xfffa; break;
|
case OperationNMIPickVector: nextAddress.full = 0xfffa; continue;
|
||||||
case OperationRSTPickVector: nextAddress.full = 0xfffc; break;
|
case OperationRSTPickVector: nextAddress.full = 0xfffc; continue;
|
||||||
case CycleReadVectorLow: read_mem(_pc.bytes.low, nextAddress.full); break;
|
case CycleReadVectorLow: read_mem(_pc.bytes.low, nextAddress.full); continue;
|
||||||
case CycleReadVectorHigh: read_mem(_pc.bytes.high, nextAddress.full+1); break;
|
case CycleReadVectorHigh: read_mem(_pc.bytes.high, nextAddress.full+1); continue;
|
||||||
case OperationSetI: _interruptFlag = Flag::Interrupt; break;
|
case OperationSetI: _interruptFlag = Flag::Interrupt; continue;
|
||||||
|
|
||||||
case CyclePullPCL: _s++; read_mem(_pc.bytes.low, _s | 0x100); break;
|
case CyclePullPCL: _s++; read_mem(_pc.bytes.low, _s | 0x100); continue;
|
||||||
case CyclePullPCH: _s++; read_mem(_pc.bytes.high, _s | 0x100); break;
|
case CyclePullPCH: _s++; read_mem(_pc.bytes.high, _s | 0x100); continue;
|
||||||
case CyclePullA: _s++; read_mem(_a, _s | 0x100); break;
|
case CyclePullA: _s++; read_mem(_a, _s | 0x100); continue;
|
||||||
case CyclePullOperand: _s++; read_mem(_operand, _s | 0x100); break;
|
case CyclePullOperand: _s++; read_mem(_operand, _s | 0x100); continue;
|
||||||
case OperationSetFlagsFromOperand: set_flags(_operand); break;
|
case OperationSetFlagsFromOperand: set_flags(_operand); continue;
|
||||||
case OperationSetOperandFromFlagsWithBRKSet: _operand = get_flags() | Flag::Break; break;
|
case OperationSetOperandFromFlagsWithBRKSet: _operand = get_flags() | Flag::Break; continue;
|
||||||
case OperationSetOperandFromFlags: _operand = get_flags(); break;
|
case OperationSetOperandFromFlags: _operand = get_flags(); continue;
|
||||||
case OperationSetFlagsFromA: _zeroResult = _negativeResult = _a; break;
|
case OperationSetFlagsFromA: _zeroResult = _negativeResult = _a; continue;
|
||||||
|
|
||||||
case CycleIncrementPCAndReadStack: _pc.full++; throwaway_read(_s | 0x100); break;
|
case CycleIncrementPCAndReadStack: _pc.full++; throwaway_read(_s | 0x100); continue;
|
||||||
case CycleReadPCLFromAddress: read_mem(_pc.bytes.low, _address.full); break;
|
case CycleReadPCLFromAddress: read_mem(_pc.bytes.low, _address.full); continue;
|
||||||
case CycleReadPCHFromAddress: _address.bytes.low++; read_mem(_pc.bytes.high, _address.full); break;
|
case CycleReadPCHFromAddress: _address.bytes.low++; read_mem(_pc.bytes.high, _address.full); continue;
|
||||||
|
|
||||||
case CycleReadAndIncrementPC: {
|
case CycleReadAndIncrementPC: {
|
||||||
uint16_t oldPC = _pc.full;
|
uint16_t oldPC = _pc.full;
|
||||||
_pc.full++;
|
_pc.full++;
|
||||||
throwaway_read(oldPC);
|
throwaway_read(oldPC);
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
#pragma mark - JAM
|
#pragma mark - JAM
|
||||||
|
|
||||||
case CycleScheduleJam: {
|
case CycleScheduleJam: {
|
||||||
_is_jammed = true;
|
_is_jammed = true;
|
||||||
static const MicroOp jam[] = JAM;
|
static const MicroOp jam[] = JAM;
|
||||||
schedule_program(jam);
|
schedule_program(jam);
|
||||||
|
|
||||||
if(_jam_handler) {
|
if(_jam_handler) {
|
||||||
_jam_handler->processor_did_jam(this, _pc.full - 1);
|
_jam_handler->processor_did_jam(this, _pc.full - 1);
|
||||||
checkSchedule(_is_jammed = false; program = _scheduledPrograms[scheduleProgramsReadPointer]);
|
checkSchedule(_is_jammed = false; program = _scheduledPrograms[scheduleProgramsReadPointer]);
|
||||||
}
|
}
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
#pragma mark - Bitwise
|
#pragma mark - Bitwise
|
||||||
|
|
||||||
case OperationORA: _a |= _operand; _negativeResult = _zeroResult = _a; break;
|
case OperationORA: _a |= _operand; _negativeResult = _zeroResult = _a; continue;
|
||||||
case OperationAND: _a &= _operand; _negativeResult = _zeroResult = _a; break;
|
case OperationAND: _a &= _operand; _negativeResult = _zeroResult = _a; continue;
|
||||||
case OperationEOR: _a ^= _operand; _negativeResult = _zeroResult = _a; break;
|
case OperationEOR: _a ^= _operand; _negativeResult = _zeroResult = _a; continue;
|
||||||
|
|
||||||
#pragma mark - Load and Store
|
#pragma mark - Load and Store
|
||||||
|
|
||||||
case OperationLDA: _a = _negativeResult = _zeroResult = _operand; break;
|
case OperationLDA: _a = _negativeResult = _zeroResult = _operand; continue;
|
||||||
case OperationLDX: _x = _negativeResult = _zeroResult = _operand; break;
|
case OperationLDX: _x = _negativeResult = _zeroResult = _operand; continue;
|
||||||
case OperationLDY: _y = _negativeResult = _zeroResult = _operand; break;
|
case OperationLDY: _y = _negativeResult = _zeroResult = _operand; continue;
|
||||||
case OperationLAX: _a = _x = _negativeResult = _zeroResult = _operand; break;
|
case OperationLAX: _a = _x = _negativeResult = _zeroResult = _operand; continue;
|
||||||
|
|
||||||
case OperationSTA: _operand = _a; break;
|
case OperationSTA: _operand = _a; continue;
|
||||||
case OperationSTX: _operand = _x; break;
|
case OperationSTX: _operand = _x; continue;
|
||||||
case OperationSTY: _operand = _y; break;
|
case OperationSTY: _operand = _y; continue;
|
||||||
case OperationSAX: _operand = _a & _x; break;
|
case OperationSAX: _operand = _a & _x; continue;
|
||||||
case OperationSHA: _operand = _a & _x & (_address.bytes.high+1); break;
|
case OperationSHA: _operand = _a & _x & (_address.bytes.high+1); continue;
|
||||||
case OperationSHX: _operand = _x & (_address.bytes.high+1); break;
|
case OperationSHX: _operand = _x & (_address.bytes.high+1); continue;
|
||||||
case OperationSHY: _operand = _y & (_address.bytes.high+1); break;
|
case OperationSHY: _operand = _y & (_address.bytes.high+1); continue;
|
||||||
case OperationSHS: _s = _a & _x; _operand = _s & (_address.bytes.high+1); break;
|
case OperationSHS: _s = _a & _x; _operand = _s & (_address.bytes.high+1); continue;
|
||||||
|
|
||||||
case OperationLXA:
|
case OperationLXA:
|
||||||
_a = _x = (_a | 0xee) & _operand;
|
_a = _x = (_a | 0xee) & _operand;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
#pragma mark - Compare
|
#pragma mark - Compare
|
||||||
|
|
||||||
case OperationCMP: {
|
case OperationCMP: {
|
||||||
const uint16_t temp16 = _a - _operand;
|
const uint16_t temp16 = _a - _operand;
|
||||||
_negativeResult = _zeroResult = (uint8_t)temp16;
|
_negativeResult = _zeroResult = (uint8_t)temp16;
|
||||||
_carryFlag = ((~temp16) >> 8)&1;
|
_carryFlag = ((~temp16) >> 8)&1;
|
||||||
} break;
|
} continue;
|
||||||
case OperationCPX: {
|
case OperationCPX: {
|
||||||
const uint16_t temp16 = _x - _operand;
|
const uint16_t temp16 = _x - _operand;
|
||||||
_negativeResult = _zeroResult = (uint8_t)temp16;
|
_negativeResult = _zeroResult = (uint8_t)temp16;
|
||||||
_carryFlag = ((~temp16) >> 8)&1;
|
_carryFlag = ((~temp16) >> 8)&1;
|
||||||
} break;
|
} continue;
|
||||||
case OperationCPY: {
|
case OperationCPY: {
|
||||||
const uint16_t temp16 = _y - _operand;
|
const uint16_t temp16 = _y - _operand;
|
||||||
_negativeResult = _zeroResult = (uint8_t)temp16;
|
_negativeResult = _zeroResult = (uint8_t)temp16;
|
||||||
_carryFlag = ((~temp16) >> 8)&1;
|
_carryFlag = ((~temp16) >> 8)&1;
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
#pragma mark - BIT
|
#pragma mark - BIT
|
||||||
|
|
||||||
case OperationBIT:
|
case OperationBIT:
|
||||||
_zeroResult = _operand & _a;
|
_zeroResult = _operand & _a;
|
||||||
_negativeResult = _operand;
|
_negativeResult = _operand;
|
||||||
_overflowFlag = _operand&Flag::Overflow;
|
_overflowFlag = _operand&Flag::Overflow;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
#pragma mark ADC/SBC (and INS)
|
#pragma mark ADC/SBC (and INS)
|
||||||
|
|
||||||
case OperationINS:
|
case OperationINS:
|
||||||
_operand++; // deliberate fallthrough
|
_operand++; // deliberate fallthrough
|
||||||
case OperationSBC:
|
case OperationSBC:
|
||||||
if(_decimalFlag) {
|
if(_decimalFlag) {
|
||||||
const uint16_t notCarry = _carryFlag ^ 0x1;
|
const uint16_t notCarry = _carryFlag ^ 0x1;
|
||||||
const uint16_t decimalResult = (uint16_t)_a - (uint16_t)_operand - notCarry;
|
const uint16_t decimalResult = (uint16_t)_a - (uint16_t)_operand - notCarry;
|
||||||
uint16_t temp16;
|
uint16_t temp16;
|
||||||
|
|
||||||
temp16 = (_a&0xf) - (_operand&0xf) - notCarry;
|
temp16 = (_a&0xf) - (_operand&0xf) - notCarry;
|
||||||
if(temp16 > 0xf) temp16 -= 0x6;
|
if(temp16 > 0xf) temp16 -= 0x6;
|
||||||
temp16 = (temp16&0x0f) | ((temp16 > 0x0f) ? 0xfff0 : 0x00);
|
temp16 = (temp16&0x0f) | ((temp16 > 0x0f) ? 0xfff0 : 0x00);
|
||||||
temp16 += (_a&0xf0) - (_operand&0xf0);
|
temp16 += (_a&0xf0) - (_operand&0xf0);
|
||||||
|
|
||||||
_overflowFlag = ( ( (decimalResult^_a)&(~decimalResult^_operand) )&0x80) >> 1;
|
_overflowFlag = ( ( (decimalResult^_a)&(~decimalResult^_operand) )&0x80) >> 1;
|
||||||
_negativeResult = (uint8_t)temp16;
|
_negativeResult = (uint8_t)temp16;
|
||||||
_zeroResult = (uint8_t)decimalResult;
|
_zeroResult = (uint8_t)decimalResult;
|
||||||
|
|
||||||
if(temp16 > 0xff) temp16 -= 0x60;
|
if(temp16 > 0xff) temp16 -= 0x60;
|
||||||
|
|
||||||
_carryFlag = (temp16 > 0xff) ? 0 : Flag::Carry;
|
_carryFlag = (temp16 > 0xff) ? 0 : Flag::Carry;
|
||||||
_a = (uint8_t)temp16;
|
_a = (uint8_t)temp16;
|
||||||
break;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
_operand = ~_operand;
|
_operand = ~_operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
// deliberate fallthrough
|
// deliberate fallthrough
|
||||||
case OperationADC:
|
case OperationADC:
|
||||||
if(_decimalFlag) {
|
if(_decimalFlag) {
|
||||||
const uint16_t decimalResult = (uint16_t)_a + (uint16_t)_operand + (uint16_t)_carryFlag;
|
const uint16_t decimalResult = (uint16_t)_a + (uint16_t)_operand + (uint16_t)_carryFlag;
|
||||||
|
|
||||||
uint8_t low_nibble = (_a & 0xf) + (_operand & 0xf) + _carryFlag;
|
uint8_t low_nibble = (_a & 0xf) + (_operand & 0xf) + _carryFlag;
|
||||||
if(low_nibble >= 0xa) low_nibble = ((low_nibble + 0x6) & 0xf) + 0x10;
|
if(low_nibble >= 0xa) low_nibble = ((low_nibble + 0x6) & 0xf) + 0x10;
|
||||||
uint16_t result = (uint16_t)(_a & 0xf0) + (uint16_t)(_operand & 0xf0) + (uint16_t)low_nibble;
|
uint16_t result = (uint16_t)(_a & 0xf0) + (uint16_t)(_operand & 0xf0) + (uint16_t)low_nibble;
|
||||||
_negativeResult = (uint8_t)result;
|
_negativeResult = (uint8_t)result;
|
||||||
_overflowFlag = (( (result^_a)&(result^_operand) )&0x80) >> 1;
|
_overflowFlag = (( (result^_a)&(result^_operand) )&0x80) >> 1;
|
||||||
if(result >= 0xa0) result += 0x60;
|
if(result >= 0xa0) result += 0x60;
|
||||||
|
|
||||||
_carryFlag = (result >> 8) ? 1 : 0;
|
_carryFlag = (result >> 8) ? 1 : 0;
|
||||||
_a = (uint8_t)result;
|
_a = (uint8_t)result;
|
||||||
_zeroResult = (uint8_t)decimalResult;
|
_zeroResult = (uint8_t)decimalResult;
|
||||||
} else {
|
} else {
|
||||||
const uint16_t result = (uint16_t)_a + (uint16_t)_operand + (uint16_t)_carryFlag;
|
const uint16_t result = (uint16_t)_a + (uint16_t)_operand + (uint16_t)_carryFlag;
|
||||||
_overflowFlag = (( (result^_a)&(result^_operand) )&0x80) >> 1;
|
_overflowFlag = (( (result^_a)&(result^_operand) )&0x80) >> 1;
|
||||||
_negativeResult = _zeroResult = _a = (uint8_t)result;
|
_negativeResult = _zeroResult = _a = (uint8_t)result;
|
||||||
_carryFlag = (result >> 8)&1;
|
_carryFlag = (result >> 8)&1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix up in case this was INS
|
// fix up in case this was INS
|
||||||
if(cycle == OperationINS) _operand = ~_operand;
|
if(cycle == OperationINS) _operand = ~_operand;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
#pragma mark - Shifts and Rolls
|
#pragma mark - Shifts and Rolls
|
||||||
|
|
||||||
case OperationASL:
|
case OperationASL:
|
||||||
_carryFlag = _operand >> 7;
|
_carryFlag = _operand >> 7;
|
||||||
_operand <<= 1;
|
_operand <<= 1;
|
||||||
_negativeResult = _zeroResult = _operand;
|
_negativeResult = _zeroResult = _operand;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationASO:
|
case OperationASO:
|
||||||
_carryFlag = _operand >> 7;
|
_carryFlag = _operand >> 7;
|
||||||
_operand <<= 1;
|
_operand <<= 1;
|
||||||
_a |= _operand;
|
_a |= _operand;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationROL: {
|
case OperationROL: {
|
||||||
const uint8_t temp8 = (uint8_t)((_operand << 1) | _carryFlag);
|
const uint8_t temp8 = (uint8_t)((_operand << 1) | _carryFlag);
|
||||||
_carryFlag = _operand >> 7;
|
_carryFlag = _operand >> 7;
|
||||||
_operand = _negativeResult = _zeroResult = temp8;
|
_operand = _negativeResult = _zeroResult = temp8;
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
case OperationRLA: {
|
case OperationRLA: {
|
||||||
const uint8_t temp8 = (uint8_t)((_operand << 1) | _carryFlag);
|
const uint8_t temp8 = (uint8_t)((_operand << 1) | _carryFlag);
|
||||||
_carryFlag = _operand >> 7;
|
_carryFlag = _operand >> 7;
|
||||||
_operand = temp8;
|
_operand = temp8;
|
||||||
_a &= _operand;
|
_a &= _operand;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
case OperationLSR:
|
case OperationLSR:
|
||||||
_carryFlag = _operand & 1;
|
_carryFlag = _operand & 1;
|
||||||
_operand >>= 1;
|
_operand >>= 1;
|
||||||
_negativeResult = _zeroResult = _operand;
|
_negativeResult = _zeroResult = _operand;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationLSE:
|
case OperationLSE:
|
||||||
_carryFlag = _operand & 1;
|
_carryFlag = _operand & 1;
|
||||||
_operand >>= 1;
|
_operand >>= 1;
|
||||||
_a ^= _operand;
|
_a ^= _operand;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationASR:
|
case OperationASR:
|
||||||
_a &= _operand;
|
_a &= _operand;
|
||||||
_carryFlag = _a & 1;
|
_carryFlag = _a & 1;
|
||||||
_a >>= 1;
|
_a >>= 1;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationROR: {
|
case OperationROR: {
|
||||||
const uint8_t temp8 = (uint8_t)((_operand >> 1) | (_carryFlag << 7));
|
const uint8_t temp8 = (uint8_t)((_operand >> 1) | (_carryFlag << 7));
|
||||||
_carryFlag = _operand & 1;
|
_carryFlag = _operand & 1;
|
||||||
_operand = _negativeResult = _zeroResult = temp8;
|
_operand = _negativeResult = _zeroResult = temp8;
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
case OperationRRA: {
|
case OperationRRA: {
|
||||||
const uint8_t temp8 = (uint8_t)((_operand >> 1) | (_carryFlag << 7));
|
const uint8_t temp8 = (uint8_t)((_operand >> 1) | (_carryFlag << 7));
|
||||||
_carryFlag = _operand & 1;
|
_carryFlag = _operand & 1;
|
||||||
_operand = temp8;
|
_operand = temp8;
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
case OperationDecrementOperand: _operand--; break;
|
case OperationDecrementOperand: _operand--; continue;
|
||||||
case OperationIncrementOperand: _operand++; break;
|
case OperationIncrementOperand: _operand++; continue;
|
||||||
|
|
||||||
case OperationCLC: _carryFlag = 0; break;
|
case OperationCLC: _carryFlag = 0; continue;
|
||||||
case OperationCLI: _interruptFlag = 0; break;
|
case OperationCLI: _interruptFlag = 0; continue;
|
||||||
case OperationCLV: _overflowFlag = 0; break;
|
case OperationCLV: _overflowFlag = 0; continue;
|
||||||
case OperationCLD: _decimalFlag = 0; break;
|
case OperationCLD: _decimalFlag = 0; continue;
|
||||||
|
|
||||||
case OperationSEC: _carryFlag = Flag::Carry; break;
|
case OperationSEC: _carryFlag = Flag::Carry; continue;
|
||||||
case OperationSEI: _interruptFlag = Flag::Interrupt; break;
|
case OperationSEI: _interruptFlag = Flag::Interrupt; continue;
|
||||||
case OperationSED: _decimalFlag = Flag::Decimal; break;
|
case OperationSED: _decimalFlag = Flag::Decimal; continue;
|
||||||
|
|
||||||
case OperationINC: _operand++; _negativeResult = _zeroResult = _operand; break;
|
case OperationINC: _operand++; _negativeResult = _zeroResult = _operand; continue;
|
||||||
case OperationDEC: _operand--; _negativeResult = _zeroResult = _operand; break;
|
case OperationDEC: _operand--; _negativeResult = _zeroResult = _operand; continue;
|
||||||
case OperationINX: _x++; _negativeResult = _zeroResult = _x; break;
|
case OperationINX: _x++; _negativeResult = _zeroResult = _x; continue;
|
||||||
case OperationDEX: _x--; _negativeResult = _zeroResult = _x; break;
|
case OperationDEX: _x--; _negativeResult = _zeroResult = _x; continue;
|
||||||
case OperationINY: _y++; _negativeResult = _zeroResult = _y; break;
|
case OperationINY: _y++; _negativeResult = _zeroResult = _y; continue;
|
||||||
case OperationDEY: _y--; _negativeResult = _zeroResult = _y; break;
|
case OperationDEY: _y--; _negativeResult = _zeroResult = _y; continue;
|
||||||
|
|
||||||
case OperationANE:
|
case OperationANE:
|
||||||
_a = (_a | 0xee) & _operand & _x;
|
_a = (_a | 0xee) & _operand & _x;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationANC:
|
case OperationANC:
|
||||||
_a &= _operand;
|
_a &= _operand;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
_carryFlag = _a >> 7;
|
_carryFlag = _a >> 7;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationLAS:
|
case OperationLAS:
|
||||||
_a = _x = _s = _s & _operand;
|
_a = _x = _s = _s & _operand;
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
#pragma mark - Addressing Mode Work
|
#pragma mark - Addressing Mode Work
|
||||||
|
|
||||||
case CycleAddXToAddressLow:
|
case CycleAddXToAddressLow:
|
||||||
nextAddress.full = _address.full + _x;
|
nextAddress.full = _address.full + _x;
|
||||||
_address.bytes.low = nextAddress.bytes.low;
|
_address.bytes.low = nextAddress.bytes.low;
|
||||||
if(_address.bytes.high != nextAddress.bytes.high) {
|
if(_address.bytes.high != nextAddress.bytes.high) {
|
||||||
|
throwaway_read(_address.full);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case CycleAddXToAddressLowRead:
|
||||||
|
nextAddress.full = _address.full + _x;
|
||||||
|
_address.bytes.low = nextAddress.bytes.low;
|
||||||
throwaway_read(_address.full);
|
throwaway_read(_address.full);
|
||||||
}
|
continue;
|
||||||
break;
|
case CycleAddYToAddressLow:
|
||||||
case CycleAddXToAddressLowRead:
|
nextAddress.full = _address.full + _y;
|
||||||
nextAddress.full = _address.full + _x;
|
_address.bytes.low = nextAddress.bytes.low;
|
||||||
_address.bytes.low = nextAddress.bytes.low;
|
if(_address.bytes.high != nextAddress.bytes.high) {
|
||||||
throwaway_read(_address.full);
|
throwaway_read(_address.full);
|
||||||
break;
|
}
|
||||||
case CycleAddYToAddressLow:
|
continue;
|
||||||
nextAddress.full = _address.full + _y;
|
case CycleAddYToAddressLowRead:
|
||||||
_address.bytes.low = nextAddress.bytes.low;
|
nextAddress.full = _address.full + _y;
|
||||||
if(_address.bytes.high != nextAddress.bytes.high) {
|
_address.bytes.low = nextAddress.bytes.low;
|
||||||
throwaway_read(_address.full);
|
throwaway_read(_address.full);
|
||||||
}
|
continue;
|
||||||
break;
|
case OperationCorrectAddressHigh:
|
||||||
case CycleAddYToAddressLowRead:
|
_address.full = nextAddress.full;
|
||||||
nextAddress.full = _address.full + _y;
|
continue;
|
||||||
_address.bytes.low = nextAddress.bytes.low;
|
case CycleIncrementPCFetchAddressLowFromOperand:
|
||||||
throwaway_read(_address.full);
|
_pc.full++;
|
||||||
break;
|
read_mem(_address.bytes.low, _operand);
|
||||||
case OperationCorrectAddressHigh:
|
continue;
|
||||||
_address.full = nextAddress.full;
|
case CycleAddXToOperandFetchAddressLow:
|
||||||
break;
|
_operand += _x;
|
||||||
case CycleIncrementPCFetchAddressLowFromOperand:
|
read_mem(_address.bytes.low, _operand);
|
||||||
_pc.full++;
|
continue;
|
||||||
read_mem(_address.bytes.low, _operand);
|
case CycleIncrementOperandFetchAddressHigh:
|
||||||
break;
|
_operand++;
|
||||||
case CycleAddXToOperandFetchAddressLow:
|
read_mem(_address.bytes.high, _operand);
|
||||||
_operand += _x;
|
continue;
|
||||||
read_mem(_address.bytes.low, _operand);
|
case CycleIncrementPCReadPCHLoadPCL: // deliberate fallthrough
|
||||||
break;
|
_pc.full++;
|
||||||
case CycleIncrementOperandFetchAddressHigh:
|
case CycleReadPCHLoadPCL: {
|
||||||
_operand++;
|
uint16_t oldPC = _pc.full;
|
||||||
read_mem(_address.bytes.high, _operand);
|
_pc.bytes.low = _operand;
|
||||||
break;
|
read_mem(_pc.bytes.high, oldPC);
|
||||||
case CycleIncrementPCReadPCHLoadPCL: // deliberate fallthrough
|
} continue;
|
||||||
_pc.full++;
|
|
||||||
case CycleReadPCHLoadPCL: {
|
|
||||||
uint16_t oldPC = _pc.full;
|
|
||||||
_pc.bytes.low = _operand;
|
|
||||||
read_mem(_pc.bytes.high, oldPC);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case CycleReadAddressHLoadAddressL:
|
case CycleReadAddressHLoadAddressL:
|
||||||
_address.bytes.low = _operand; _pc.full++;
|
_address.bytes.low = _operand; _pc.full++;
|
||||||
read_mem(_address.bytes.high, _pc.full);
|
read_mem(_address.bytes.high, _pc.full);
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case CycleLoadAddressAbsolute: {
|
case CycleLoadAddressAbsolute: {
|
||||||
uint16_t nextPC = _pc.full+1;
|
uint16_t nextPC = _pc.full+1;
|
||||||
_pc.full += 2;
|
_pc.full += 2;
|
||||||
_address.bytes.low = _operand;
|
_address.bytes.low = _operand;
|
||||||
read_mem(_address.bytes.high, nextPC);
|
read_mem(_address.bytes.high, nextPC);
|
||||||
} break;
|
} continue;
|
||||||
|
|
||||||
case OperationLoadAddressZeroPage:
|
case OperationLoadAddressZeroPage:
|
||||||
_pc.full++;
|
_pc.full++;
|
||||||
_address.full = _operand;
|
_address.full = _operand;
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case CycleLoadAddessZeroX:
|
case CycleLoadAddessZeroX:
|
||||||
_pc.full++;
|
_pc.full++;
|
||||||
_address.full = (_operand + _x)&0xff;
|
_address.full = (_operand + _x)&0xff;
|
||||||
throwaway_read(_operand);
|
throwaway_read(_operand);
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case CycleLoadAddessZeroY:
|
case CycleLoadAddessZeroY:
|
||||||
_pc.full++;
|
_pc.full++;
|
||||||
_address.full = (_operand + _y)&0xff;
|
_address.full = (_operand + _y)&0xff;
|
||||||
throwaway_read(_operand);
|
throwaway_read(_operand);
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationIncrementPC: _pc.full++; break;
|
case OperationIncrementPC: _pc.full++; continue;
|
||||||
case CycleFetchOperandFromAddress: read_mem(_operand, _address.full); break;
|
case CycleFetchOperandFromAddress: read_mem(_operand, _address.full); continue;
|
||||||
case CycleWriteOperandToAddress: write_mem(_operand, _address.full); break;
|
case CycleWriteOperandToAddress: write_mem(_operand, _address.full); continue;
|
||||||
case OperationCopyOperandFromA: _operand = _a; break;
|
case OperationCopyOperandFromA: _operand = _a; continue;
|
||||||
case OperationCopyOperandToA: _a = _operand; break;
|
case OperationCopyOperandToA: _a = _operand; continue;
|
||||||
|
|
||||||
#pragma mark - Branching
|
#pragma mark - Branching
|
||||||
|
|
||||||
#define BRA(condition) _pc.full++; if(condition) schedule_program(doBranch)
|
#define BRA(condition) _pc.full++; if(condition) schedule_program(doBranch)
|
||||||
|
|
||||||
case OperationBPL: BRA(!(_negativeResult&0x80)); break;
|
case OperationBPL: BRA(!(_negativeResult&0x80)); continue;
|
||||||
case OperationBMI: BRA(_negativeResult&0x80); break;
|
case OperationBMI: BRA(_negativeResult&0x80); continue;
|
||||||
case OperationBVC: BRA(!_overflowFlag); break;
|
case OperationBVC: BRA(!_overflowFlag); continue;
|
||||||
case OperationBVS: BRA(_overflowFlag); break;
|
case OperationBVS: BRA(_overflowFlag); continue;
|
||||||
case OperationBCC: BRA(!_carryFlag); break;
|
case OperationBCC: BRA(!_carryFlag); continue;
|
||||||
case OperationBCS: BRA(_carryFlag); break;
|
case OperationBCS: BRA(_carryFlag); continue;
|
||||||
case OperationBNE: BRA(_zeroResult); break;
|
case OperationBNE: BRA(_zeroResult); continue;
|
||||||
case OperationBEQ: BRA(!_zeroResult); break;
|
case OperationBEQ: BRA(!_zeroResult); continue;
|
||||||
|
|
||||||
case CycleAddSignedOperandToPC:
|
case CycleAddSignedOperandToPC:
|
||||||
nextAddress.full = (uint16_t)(_pc.full + (int8_t)_operand);
|
nextAddress.full = (uint16_t)(_pc.full + (int8_t)_operand);
|
||||||
_pc.bytes.low = nextAddress.bytes.low;
|
_pc.bytes.low = nextAddress.bytes.low;
|
||||||
if(nextAddress.bytes.high != _pc.bytes.high) {
|
if(nextAddress.bytes.high != _pc.bytes.high) {
|
||||||
uint16_t halfUpdatedPc = _pc.full;
|
uint16_t halfUpdatedPc = _pc.full;
|
||||||
_pc.full = nextAddress.full;
|
_pc.full = nextAddress.full;
|
||||||
throwaway_read(halfUpdatedPc);
|
throwaway_read(halfUpdatedPc);
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
#undef BRA
|
#undef BRA
|
||||||
|
|
||||||
#pragma mark - Transfers
|
#pragma mark - Transfers
|
||||||
|
|
||||||
case OperationTXA: _zeroResult = _negativeResult = _a = _x; break;
|
case OperationTXA: _zeroResult = _negativeResult = _a = _x; continue;
|
||||||
case OperationTYA: _zeroResult = _negativeResult = _a = _y; break;
|
case OperationTYA: _zeroResult = _negativeResult = _a = _y; continue;
|
||||||
case OperationTXS: _s = _x; break;
|
case OperationTXS: _s = _x; continue;
|
||||||
case OperationTAY: _zeroResult = _negativeResult = _y = _a; break;
|
case OperationTAY: _zeroResult = _negativeResult = _y = _a; continue;
|
||||||
case OperationTAX: _zeroResult = _negativeResult = _x = _a; break;
|
case OperationTAX: _zeroResult = _negativeResult = _x = _a; continue;
|
||||||
case OperationTSX: _zeroResult = _negativeResult = _x = _s; break;
|
case OperationTSX: _zeroResult = _negativeResult = _x = _s; continue;
|
||||||
|
|
||||||
case OperationARR:
|
case OperationARR:
|
||||||
if(_decimalFlag) {
|
if(_decimalFlag) {
|
||||||
_a &= _operand;
|
_a &= _operand;
|
||||||
uint8_t unshiftedA = _a;
|
uint8_t unshiftedA = _a;
|
||||||
_a = (uint8_t)((_a >> 1) | (_carryFlag << 7));
|
_a = (uint8_t)((_a >> 1) | (_carryFlag << 7));
|
||||||
_zeroResult = _negativeResult = _a;
|
_zeroResult = _negativeResult = _a;
|
||||||
_overflowFlag = (_a^(_a << 1))&Flag::Overflow;
|
_overflowFlag = (_a^(_a << 1))&Flag::Overflow;
|
||||||
|
|
||||||
if((unshiftedA&0xf) + (unshiftedA&0x1) > 5) _a = ((_a + 6)&0xf) | (_a & 0xf0);
|
if((unshiftedA&0xf) + (unshiftedA&0x1) > 5) _a = ((_a + 6)&0xf) | (_a & 0xf0);
|
||||||
|
|
||||||
_carryFlag = ((unshiftedA&0xf0) + (unshiftedA&0x10) > 0x50) ? 1 : 0;
|
_carryFlag = ((unshiftedA&0xf0) + (unshiftedA&0x10) > 0x50) ? 1 : 0;
|
||||||
if(_carryFlag) _a += 0x60;
|
if(_carryFlag) _a += 0x60;
|
||||||
} else {
|
} else {
|
||||||
_a &= _operand;
|
_a &= _operand;
|
||||||
_a = (uint8_t)((_a >> 1) | (_carryFlag << 7));
|
_a = (uint8_t)((_a >> 1) | (_carryFlag << 7));
|
||||||
_negativeResult = _zeroResult = _a;
|
_negativeResult = _zeroResult = _a;
|
||||||
_carryFlag = (_a >> 6)&1;
|
_carryFlag = (_a >> 6)&1;
|
||||||
_overflowFlag = (_a^(_a << 1))&Flag::Overflow;
|
_overflowFlag = (_a^(_a << 1))&Flag::Overflow;
|
||||||
}
|
}
|
||||||
break;
|
continue;
|
||||||
|
|
||||||
case OperationSBX:
|
case OperationSBX:
|
||||||
_x &= _a;
|
_x &= _a;
|
||||||
uint16_t difference = _x - _operand;
|
uint16_t difference = _x - _operand;
|
||||||
_x = (uint8_t)difference;
|
_x = (uint8_t)difference;
|
||||||
_negativeResult = _zeroResult = _x;
|
_negativeResult = _zeroResult = _x;
|
||||||
_carryFlag = ((difference >> 8)&1)^1;
|
_carryFlag = ((difference >> 8)&1)^1;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isReadOperation(nextBusOperation) && _ready_line_is_enabled) {
|
|
||||||
_ready_is_active = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1142,7 +1145,7 @@ template <class T> class Processor {
|
|||||||
case Register::X: return _x;
|
case Register::X: return _x;
|
||||||
case Register::Y: return _y;
|
case Register::Y: return _y;
|
||||||
case Register::S: return _s;
|
case Register::S: return _s;
|
||||||
default: break;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user