1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-02 19:54:35 +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:
Thomas Harte 2020-10-08 16:48:46 -04:00
parent b578240993
commit 907c3374c3
3 changed files with 37 additions and 35 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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,