mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-07 23:25:00 +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:
@@ -448,19 +448,23 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
|
|||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
||||||
case JMP:
|
case JMP:
|
||||||
pc_ = instruction_buffer_.value & 0xffff;
|
pc_ = uint16_t(instruction_buffer_.value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JMPind:
|
||||||
|
pc_ = data_buffer_.value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JSL:
|
case JSL:
|
||||||
program_bank_ = instruction_buffer_.value & 0xff0000;
|
program_bank_ = instruction_buffer_.value & 0xff0000;
|
||||||
instruction_buffer_.size = 2;
|
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
||||||
case JSR: {
|
case JSR:
|
||||||
const uint16_t old_pc = pc_;
|
data_buffer_.value = pc_;
|
||||||
|
data_buffer_.size = 2;
|
||||||
|
|
||||||
pc_ = instruction_buffer_.value;
|
pc_ = instruction_buffer_.value;
|
||||||
instruction_buffer_.value = old_pc;
|
break;
|
||||||
} break;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Block moves.
|
// Block moves.
|
||||||
@@ -639,35 +643,32 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
|
|||||||
#undef cp
|
#undef cp
|
||||||
|
|
||||||
case SBC:
|
case SBC:
|
||||||
if(flags_.decimal) {
|
data_buffer_.value = ~data_buffer_.value & m_masks_[1];
|
||||||
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;
|
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
|
||||||
case ADC: {
|
case ADC: {
|
||||||
int result;
|
int result;
|
||||||
|
const uint16_t a = a_.full & m_masks_[1];
|
||||||
|
|
||||||
if(flags_.decimal) {
|
if(flags_.decimal) {
|
||||||
result = flags_.carry;
|
result = flags_.carry;
|
||||||
|
const int nibble_adjustment = (active_instruction_->operation == SBC) ? 0xa : 0x6;
|
||||||
|
|
||||||
#define nibble(mask, limit, addition, carry) \
|
// TODO: this still isn't quite correct for SBC as the limit test is wrong, I think.
|
||||||
result += (a_.full & mask) + (data_buffer_.value & mask); \
|
|
||||||
if(result >= limit) result = ((result + addition) & (carry - 1)) + carry;
|
|
||||||
|
|
||||||
nibble(0x000f, 0x000a, 0x0006, 0x00010);
|
#define nibble(mask, limit, addition, carry) \
|
||||||
nibble(0x00f0, 0x00a0, 0x0060, 0x00100);
|
result += (a & mask) + (data_buffer_.value & mask); \
|
||||||
nibble(0x0f00, 0x0a00, 0x0600, 0x01000);
|
if(result >= limit) result = ((result + (addition)) & (carry - 1)) + carry;
|
||||||
nibble(0xf000, 0xa000, 0x6000, 0x10000);
|
|
||||||
|
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
|
#undef nibble
|
||||||
|
|
||||||
} else {
|
} 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;
|
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) {
|
static void absolute_jmp(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchIncrementPC); // New PCL.
|
target(CycleFetchIncrementPC); // New PCL.
|
||||||
target(CycleFetchPC); // New PCH.
|
target(CycleFetchPC); // New PCH.
|
||||||
target(OperationConstructAbsolute); // Calculate data address.
|
|
||||||
target(OperationPerform); // [JMP]
|
target(OperationPerform); // [JMP]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +186,6 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // New PCL.
|
target(CycleFetchIncrementPC); // New PCL.
|
||||||
target(CycleFetchPC); // New PCH.
|
target(CycleFetchPC); // New PCH.
|
||||||
target(CycleFetchPCThrowaway); // IO
|
target(CycleFetchPCThrowaway); // IO
|
||||||
target(OperationConstructAbsolute); // Calculate data address.
|
|
||||||
target(OperationPerform); // [JSR]
|
target(OperationPerform); // [JSR]
|
||||||
target(CyclePush); // PCH
|
target(CyclePush); // PCH
|
||||||
target(CyclePush); // PCL
|
target(CyclePush); // PCL
|
||||||
@@ -227,7 +225,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(OperationConstructAbsoluteIndexedIndirect); // Calculate data address.
|
target(OperationConstructAbsoluteIndexedIndirect); // Calculate data address.
|
||||||
target(CycleFetchIncrementData); // New PCL
|
target(CycleFetchIncrementData); // New PCL
|
||||||
target(CycleFetchData); // New PCH.
|
target(CycleFetchData); // New PCH.
|
||||||
target(OperationPerform); // ['JSR' (actually: JMP will do)]
|
target(OperationPerform); // ['JSR' (actually: JMPind will do)]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3a. Absolute Indirect; (a), JML.
|
// 3a. Absolute Indirect; (a), JML.
|
||||||
@@ -814,7 +812,7 @@ ProcessorStorage::ProcessorStorage() {
|
|||||||
/* 0x5e LSR a, x */ op(absolute_x_rmw, LSR);
|
/* 0x5e LSR a, x */ op(absolute_x_rmw, LSR);
|
||||||
/* 0x5f EOR al, x */ op(absolute_long_x, EOR);
|
/* 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);
|
/* 0x61 ADC (d, x) */ op(direct_indexed_indirect, ADC);
|
||||||
/* 0x62 PER s */ op(stack_per, NOP);
|
/* 0x62 PER s */ op(stack_per, NOP);
|
||||||
/* 0x63 ADC d, s */ op(stack_relative, ADC);
|
/* 0x63 ADC d, s */ op(stack_relative, ADC);
|
||||||
@@ -826,7 +824,7 @@ ProcessorStorage::ProcessorStorage() {
|
|||||||
/* 0x69 ADC # */ op(immediate, ADC);
|
/* 0x69 ADC # */ op(immediate, ADC);
|
||||||
/* 0x6a ROR A */ op(accumulator, ROR);
|
/* 0x6a ROR A */ op(accumulator, ROR);
|
||||||
/* 0x6b RTL s */ op(stack_rtl, JML);
|
/* 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);
|
/* 0x6d ADC a */ op(absolute, ADC);
|
||||||
/* 0x6e ROR a */ op(absolute_rmw, ROR);
|
/* 0x6e ROR a */ op(absolute_rmw, ROR);
|
||||||
/* 0x6f ADC al */ op(absolute_long, ADC);
|
/* 0x6f ADC al */ op(absolute_long, ADC);
|
||||||
@@ -843,7 +841,7 @@ ProcessorStorage::ProcessorStorage() {
|
|||||||
/* 0x79 ADC a, y */ op(absolute_y, ADC);
|
/* 0x79 ADC a, y */ op(absolute_y, ADC);
|
||||||
/* 0x7a PLY s */ op(stack_pull, LDY);
|
/* 0x7a PLY s */ op(stack_pull, LDY);
|
||||||
/* 0x7b TDC i */ op(implied, TDC);
|
/* 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);
|
/* 0x7d ADC a, x */ op(absolute_x, ADC);
|
||||||
/* 0x7e ROR a, x */ op(absolute_x_rmw, ROR);
|
/* 0x7e ROR a, x */ op(absolute_x_rmw, ROR);
|
||||||
/* 0x7f ADC al, x */ op(absolute_long_x, ADC);
|
/* 0x7f ADC al, x */ op(absolute_long_x, ADC);
|
||||||
@@ -979,7 +977,7 @@ ProcessorStorage::ProcessorStorage() {
|
|||||||
/* 0xf9 SBC a, y */ op(absolute_y, SBC);
|
/* 0xf9 SBC a, y */ op(absolute_y, SBC);
|
||||||
/* 0xfa PLX s */ op(stack_pull, LDX);
|
/* 0xfa PLX s */ op(stack_pull, LDX);
|
||||||
/* 0xfb XCE i */ op(implied, XCE);
|
/* 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);
|
/* 0xfd SBC a, x */ op(absolute_x, SBC);
|
||||||
/* 0xfe INC a, x */ op(absolute_x_rmw, INC);
|
/* 0xfe INC a, x */ op(absolute_x_rmw, INC);
|
||||||
/* 0xff SBC al, x */ op(absolute_long_x, SBC);
|
/* 0xff SBC al, x */ op(absolute_long_x, SBC);
|
||||||
|
@@ -174,18 +174,21 @@ enum Operation: uint8_t {
|
|||||||
// from the stack.
|
// from the stack.
|
||||||
RTI, RTL,
|
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,
|
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,
|
JML,
|
||||||
|
|
||||||
/// Loads the PC with the operand from the data buffer, replacing
|
/// Loads the PC with the operand from the instruction buffer, placing
|
||||||
/// it with the old PC.
|
/// the current PC into the data buffer.
|
||||||
JSR,
|
JSR,
|
||||||
|
|
||||||
/// Loads the PC and the PBR with the operand from the data buffer,
|
/// Loads the PC and the PBR with the operand from the instruction buffer,
|
||||||
/// replacing it with the old PC (and only the PC; PBR not included).
|
/// placing the old PC into the data buffer (and only the PC; PBR not included).
|
||||||
JSL,
|
JSL,
|
||||||
|
|
||||||
/// i.e. jump to vector. TODO: is this really distinct from JMP? I'm assuming so for now,
|
/// i.e. jump to vector. TODO: is this really distinct from JMP? I'm assuming so for now,
|
||||||
|
Reference in New Issue
Block a user