mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Attempts to clean up my JMP/JSR mess.
Also takes a step forwards in decimal SBC, but it's not right yet.
This commit is contained in:
parent
b578240993
commit
907c3374c3
@ -448,19 +448,23 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
|
||||
[[fallthrough]];
|
||||
|
||||
case JMP:
|
||||
pc_ = instruction_buffer_.value & 0xffff;
|
||||
pc_ = uint16_t(instruction_buffer_.value);
|
||||
break;
|
||||
|
||||
case JMPind:
|
||||
pc_ = data_buffer_.value;
|
||||
break;
|
||||
|
||||
case JSL:
|
||||
program_bank_ = instruction_buffer_.value & 0xff0000;
|
||||
instruction_buffer_.size = 2;
|
||||
[[fallthrough]];
|
||||
|
||||
case JSR: {
|
||||
const uint16_t old_pc = pc_;
|
||||
case JSR:
|
||||
data_buffer_.value = pc_;
|
||||
data_buffer_.size = 2;
|
||||
|
||||
pc_ = instruction_buffer_.value;
|
||||
instruction_buffer_.value = old_pc;
|
||||
} break;
|
||||
break;
|
||||
|
||||
//
|
||||
// Block moves.
|
||||
@ -639,35 +643,32 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
|
||||
#undef cp
|
||||
|
||||
case SBC:
|
||||
if(flags_.decimal) {
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
// Implement non-decimal SBC by falling through to ADC;
|
||||
// TODO: what do I need to invert to be able to fall through in both cases? And does it matter?
|
||||
data_buffer_.value = ~data_buffer_.value;
|
||||
data_buffer_.value = ~data_buffer_.value & m_masks_[1];
|
||||
[[fallthrough]];
|
||||
|
||||
case ADC: {
|
||||
int result;
|
||||
const uint16_t a = a_.full & m_masks_[1];
|
||||
|
||||
if(flags_.decimal) {
|
||||
result = flags_.carry;
|
||||
const int nibble_adjustment = (active_instruction_->operation == SBC) ? 0xa : 0x6;
|
||||
|
||||
#define nibble(mask, limit, addition, carry) \
|
||||
result += (a_.full & mask) + (data_buffer_.value & mask); \
|
||||
if(result >= limit) result = ((result + addition) & (carry - 1)) + carry;
|
||||
// TODO: this still isn't quite correct for SBC as the limit test is wrong, I think.
|
||||
|
||||
nibble(0x000f, 0x000a, 0x0006, 0x00010);
|
||||
nibble(0x00f0, 0x00a0, 0x0060, 0x00100);
|
||||
nibble(0x0f00, 0x0a00, 0x0600, 0x01000);
|
||||
nibble(0xf000, 0xa000, 0x6000, 0x10000);
|
||||
#define nibble(mask, limit, addition, carry) \
|
||||
result += (a & mask) + (data_buffer_.value & mask); \
|
||||
if(result >= limit) result = ((result + (addition)) & (carry - 1)) + carry;
|
||||
|
||||
nibble(0x000f, 0x000a, nibble_adjustment << 0, 0x00010);
|
||||
nibble(0x00f0, 0x00a0, nibble_adjustment << 8, 0x00100);
|
||||
nibble(0x0f00, 0x0a00, nibble_adjustment << 16, 0x01000);
|
||||
nibble(0xf000, 0xa000, nibble_adjustment << 24, 0x10000);
|
||||
|
||||
#undef nibble
|
||||
|
||||
} else {
|
||||
result = a_.full + data_buffer_.value + flags_.carry;
|
||||
result = a + data_buffer_.value + flags_.carry;
|
||||
}
|
||||
|
||||
flags_.overflow = (( (result ^ a_.full) & (result ^ data_buffer_.value) ) >> (1 + m_shift_))&0x40;
|
||||
|
@ -178,7 +178,6 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
static void absolute_jmp(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||
target(CycleFetchIncrementPC); // New PCL.
|
||||
target(CycleFetchPC); // New PCH.
|
||||
target(OperationConstructAbsolute); // Calculate data address.
|
||||
target(OperationPerform); // [JMP]
|
||||
}
|
||||
|
||||
@ -187,7 +186,6 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(CycleFetchIncrementPC); // New PCL.
|
||||
target(CycleFetchPC); // New PCH.
|
||||
target(CycleFetchPCThrowaway); // IO
|
||||
target(OperationConstructAbsolute); // Calculate data address.
|
||||
target(OperationPerform); // [JSR]
|
||||
target(CyclePush); // PCH
|
||||
target(CyclePush); // PCL
|
||||
@ -227,7 +225,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
||||
target(OperationConstructAbsoluteIndexedIndirect); // Calculate data address.
|
||||
target(CycleFetchIncrementData); // New PCL
|
||||
target(CycleFetchData); // New PCH.
|
||||
target(OperationPerform); // ['JSR' (actually: JMP will do)]
|
||||
target(OperationPerform); // ['JSR' (actually: JMPind will do)]
|
||||
}
|
||||
|
||||
// 3a. Absolute Indirect; (a), JML.
|
||||
@ -814,7 +812,7 @@ ProcessorStorage::ProcessorStorage() {
|
||||
/* 0x5e LSR a, x */ op(absolute_x_rmw, LSR);
|
||||
/* 0x5f EOR al, x */ op(absolute_long_x, EOR);
|
||||
|
||||
/* 0x60 RTS s */ op(stack_rts, JMP); // [sic]; loads the PC from data as per an RTS.
|
||||
/* 0x60 RTS s */ op(stack_rts, JMPind); // [sic]; loads the PC from data as per an RTS.
|
||||
/* 0x61 ADC (d, x) */ op(direct_indexed_indirect, ADC);
|
||||
/* 0x62 PER s */ op(stack_per, NOP);
|
||||
/* 0x63 ADC d, s */ op(stack_relative, ADC);
|
||||
@ -826,7 +824,7 @@ ProcessorStorage::ProcessorStorage() {
|
||||
/* 0x69 ADC # */ op(immediate, ADC);
|
||||
/* 0x6a ROR A */ op(accumulator, ROR);
|
||||
/* 0x6b RTL s */ op(stack_rtl, JML);
|
||||
/* 0x6c JMP (a) */ op(absolute_indirect_jmp, JMP);
|
||||
/* 0x6c JMP (a) */ op(absolute_indirect_jmp, JMPind);
|
||||
/* 0x6d ADC a */ op(absolute, ADC);
|
||||
/* 0x6e ROR a */ op(absolute_rmw, ROR);
|
||||
/* 0x6f ADC al */ op(absolute_long, ADC);
|
||||
@ -843,7 +841,7 @@ ProcessorStorage::ProcessorStorage() {
|
||||
/* 0x79 ADC a, y */ op(absolute_y, ADC);
|
||||
/* 0x7a PLY s */ op(stack_pull, LDY);
|
||||
/* 0x7b TDC i */ op(implied, TDC);
|
||||
/* 0x7c JMP (a, x) */ op(absolute_indexed_indirect_jmp, JMP);
|
||||
/* 0x7c JMP (a, x) */ op(absolute_indexed_indirect_jmp, JMPind);
|
||||
/* 0x7d ADC a, x */ op(absolute_x, ADC);
|
||||
/* 0x7e ROR a, x */ op(absolute_x_rmw, ROR);
|
||||
/* 0x7f ADC al, x */ op(absolute_long_x, ADC);
|
||||
@ -979,7 +977,7 @@ ProcessorStorage::ProcessorStorage() {
|
||||
/* 0xf9 SBC a, y */ op(absolute_y, SBC);
|
||||
/* 0xfa PLX s */ op(stack_pull, LDX);
|
||||
/* 0xfb XCE i */ op(implied, XCE);
|
||||
/* 0xfc JSR (a, x) */ op(absolute_indexed_indirect_jsr, JMP); // [sic]
|
||||
/* 0xfc JSR (a, x) */ op(absolute_indexed_indirect_jsr, JMPind); // [sic]
|
||||
/* 0xfd SBC a, x */ op(absolute_x, SBC);
|
||||
/* 0xfe INC a, x */ op(absolute_x_rmw, INC);
|
||||
/* 0xff SBC al, x */ op(absolute_long_x, SBC);
|
||||
|
@ -174,18 +174,21 @@ enum Operation: uint8_t {
|
||||
// from the stack.
|
||||
RTI, RTL,
|
||||
|
||||
/// Loads the PC with the operand from the data buffer.
|
||||
/// Loads the PC with the contents of the data buffer.
|
||||
JMPind,
|
||||
|
||||
/// Loads the PC with the contents of the instruction bufer.
|
||||
JMP,
|
||||
|
||||
/// Loads the PC and PBR with the operand from the data buffer.
|
||||
/// Loads the PC and PBR with the operand from the instruction buffer.
|
||||
JML,
|
||||
|
||||
/// Loads the PC with the operand from the data buffer, replacing
|
||||
/// it with the old PC.
|
||||
/// Loads the PC with the operand from the instruction buffer, placing
|
||||
/// the current PC into the data buffer.
|
||||
JSR,
|
||||
|
||||
/// Loads the PC and the PBR with the operand from the data buffer,
|
||||
/// replacing it with the old PC (and only the PC; PBR not included).
|
||||
/// Loads the PC and the PBR with the operand from the instruction buffer,
|
||||
/// placing the old PC into the data buffer (and only the PC; PBR not included).
|
||||
JSL,
|
||||
|
||||
/// i.e. jump to vector. TODO: is this really distinct from JMP? I'm assuming so for now,
|
||||
|
Loading…
Reference in New Issue
Block a user