mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-23 03:32:32 +00:00
Shifts size-limiting of X and Y to transitions and mutations, away from reads.
Primarily to remove potential bug-causing complexity — this is easier to debug. But let's see.
This commit is contained in:
parent
e3147b6b45
commit
d3c7253981
@ -392,6 +392,9 @@ class ConcreteMachine:
|
||||
}
|
||||
}
|
||||
|
||||
if(operation == CPU::WDC65816::BusOperation::ReadOpcode && address == 0x00fa56) {
|
||||
printf("?");
|
||||
}
|
||||
// log |= (address >= 0xffa6d9) && (address < 0xffa6ec);
|
||||
if(log) {
|
||||
printf("%06x %s %02x", address, isReadOperation(operation) ? "->" : "<-", *value);
|
||||
@ -405,7 +408,8 @@ class ConcreteMachine:
|
||||
m65816_.get_value_of_register(CPU::WDC65816::Register::Flags),
|
||||
m65816_.get_value_of_register(CPU::WDC65816::Register::DataBank),
|
||||
m65816_.get_value_of_register(CPU::WDC65816::Register::ProgramBank),
|
||||
m65816_.get_value_of_register(CPU::WDC65816::Register::Direct)
|
||||
m65816_.get_value_of_register(CPU::WDC65816::Register::Direct
|
||||
)
|
||||
);
|
||||
} else printf("\n");
|
||||
}
|
||||
|
@ -275,6 +275,8 @@ class MemoryMap {
|
||||
e0_region.read = language_state.read ? ram : rom;
|
||||
e0_region.write = language_state.write ? nullptr : ram;
|
||||
|
||||
if(!bank_base) printf("eo region read: %d!\n", language_state.read);
|
||||
|
||||
// Assert assumptions made above re: memory layout.
|
||||
assert(region_map[bank_base | 0xd0] + 1 == region_map[bank_base | 0xe0]);
|
||||
assert(region_map[bank_base | 0xe0] == region_map[bank_base | 0xff]);
|
||||
@ -290,6 +292,7 @@ class MemoryMap {
|
||||
};
|
||||
|
||||
if(inhibit_banks0001) {
|
||||
printf("Language card: disabled!\n");
|
||||
set_no_card(0x0000);
|
||||
set_no_card(0x0100);
|
||||
} else {
|
||||
|
@ -17,8 +17,8 @@ uint16_t ProcessorBase::get_value_of_register(Register r) const {
|
||||
case Register::StackPointer: return registers_.s.full & (registers_.emulation_flag ? 0xff : 0xffff);
|
||||
case Register::Flags: return get_flags();
|
||||
case Register::A: return registers_.a.full;
|
||||
case Register::X: return registers_.x.full & registers_.x_masks[1];
|
||||
case Register::Y: return registers_.y.full & registers_.x_masks[1];
|
||||
case Register::X: return registers_.x.full;
|
||||
case Register::Y: return registers_.y.full;
|
||||
case Register::EmulationFlag: return registers_.emulation_flag;
|
||||
case Register::DataBank: return registers_.data_bank >> 16;
|
||||
case Register::ProgramBank: return registers_.program_bank >> 16;
|
||||
@ -33,8 +33,8 @@ void ProcessorBase::set_value_of_register(Register r, uint16_t value) {
|
||||
case Register::StackPointer: registers_.s.full = value; break;
|
||||
case Register::Flags: set_flags(uint8_t(value)); break;
|
||||
case Register::A: registers_.a.full = value; break;
|
||||
case Register::X: registers_.x.full = value; break;
|
||||
case Register::Y: registers_.y.full = value; break;
|
||||
case Register::X: registers_.x.full = value & registers_.x_mask; break;
|
||||
case Register::Y: registers_.y.full = value & registers_.x_mask; break;
|
||||
case Register::EmulationFlag: set_emulation_mode(value); break;
|
||||
case Register::DataBank: registers_.data_bank = uint32_t(value & 0xff) << 16; break;
|
||||
case Register::ProgramBank: registers_.program_bank = uint32_t(value &0xff) << 16; break;
|
||||
|
@ -19,8 +19,6 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
#define m_flag() registers_.mx_flags[0]
|
||||
#define x_flag() registers_.mx_flags[1]
|
||||
|
||||
#define x() (registers_.x.full & registers_.x_masks[1])
|
||||
#define y() (registers_.y.full & registers_.x_masks[1])
|
||||
#define stack_address() ((registers_.s.full & registers_.e_masks[1]) | (0x0100 & registers_.e_masks[0]))
|
||||
|
||||
Cycles number_of_cycles = cycles + cycles_left_to_run_;
|
||||
@ -143,15 +141,15 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
break;
|
||||
|
||||
case CycleFetchBlockX:
|
||||
read(((instruction_buffer_.value & 0xff00) << 8) | x(), data_buffer_.any_byte());
|
||||
read(((instruction_buffer_.value & 0xff00) << 8) | registers_.x.full, data_buffer_.any_byte());
|
||||
break;
|
||||
|
||||
case CycleFetchBlockY:
|
||||
perform_bus(((instruction_buffer_.value & 0xff00) << 8) | y(), &bus_throwaway_, MOS6502Esque::InternalOperationRead);
|
||||
perform_bus(((instruction_buffer_.value & 0xff00) << 8) | registers_.y.full, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
|
||||
break;
|
||||
|
||||
case CycleStoreBlockY:
|
||||
write(((instruction_buffer_.value & 0xff00) << 8) | y(), data_buffer_.any_byte());
|
||||
write(((instruction_buffer_.value & 0xff00) << 8) | registers_.y.full, data_buffer_.any_byte());
|
||||
break;
|
||||
|
||||
#undef increment_data_address
|
||||
@ -266,18 +264,18 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
|
||||
// Used for JMP and JSR (absolute, x).
|
||||
case OperationConstructAbsoluteIndexedIndirect:
|
||||
data_address_ = registers_.program_bank + ((instruction_buffer_.value + x()) & 0xffff);
|
||||
data_address_ = registers_.program_bank + ((instruction_buffer_.value + registers_.x.full) & 0xffff);
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
continue;
|
||||
|
||||
case OperationConstructAbsoluteLongX:
|
||||
data_address_ = instruction_buffer_.value + x();
|
||||
data_address_ = instruction_buffer_.value + registers_.x.full;
|
||||
data_address_increment_mask_ = 0xff'ff'ff;
|
||||
continue;
|
||||
|
||||
case OperationConstructAbsoluteXRead:
|
||||
case OperationConstructAbsoluteX:
|
||||
data_address_ = instruction_buffer_.value + x() + registers_.data_bank;
|
||||
data_address_ = instruction_buffer_.value + registers_.x.full + registers_.data_bank;
|
||||
incorrect_data_address_ = (data_address_ & 0xff) | (instruction_buffer_.value & 0xff00) + registers_.data_bank;
|
||||
|
||||
// If the incorrect address isn't actually incorrect, skip its usage.
|
||||
@ -289,7 +287,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
|
||||
case OperationConstructAbsoluteYRead:
|
||||
case OperationConstructAbsoluteY:
|
||||
data_address_ = instruction_buffer_.value + y() + registers_.data_bank;
|
||||
data_address_ = instruction_buffer_.value + registers_.y.full + registers_.data_bank;
|
||||
incorrect_data_address_ = (data_address_ & 0xff) + (instruction_buffer_.value & 0xff00) + registers_.data_bank;
|
||||
|
||||
// If the incorrect address isn't actually incorrect, skip its usage.
|
||||
@ -326,7 +324,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
|
||||
case OperationConstructDirectIndexedIndirect:
|
||||
data_address_ = registers_.data_bank + (
|
||||
((registers_.direct + x() + instruction_buffer_.value) & registers_.e_masks[1]) +
|
||||
((registers_.direct + registers_.x.full + instruction_buffer_.value) & registers_.e_masks[1]) +
|
||||
(registers_.direct & registers_.e_masks[0])
|
||||
) & 0xffff;
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
@ -337,7 +335,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
continue;
|
||||
|
||||
case OperationConstructDirectIndirectIndexedLong:
|
||||
data_address_ = y() + data_buffer_.value;
|
||||
data_address_ = registers_.y.full + data_buffer_.value;
|
||||
data_address_increment_mask_ = 0xff'ff'ff;
|
||||
data_buffer_.clear();
|
||||
continue;
|
||||
@ -353,7 +351,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
case OperationConstructDirectX:
|
||||
data_address_ = (
|
||||
(registers_.direct & registers_.e_masks[0]) +
|
||||
((instruction_buffer_.value + registers_.direct + x()) & registers_.e_masks[1])
|
||||
((instruction_buffer_.value + registers_.direct + registers_.x.full) & registers_.e_masks[1])
|
||||
) & 0xffff;
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
|
||||
@ -366,7 +364,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
case OperationConstructDirectY:
|
||||
data_address_ = (
|
||||
(registers_.direct & registers_.e_masks[0]) +
|
||||
((instruction_buffer_.value + registers_.direct + y()) & registers_.e_masks[1])
|
||||
((instruction_buffer_.value + registers_.direct + registers_.y.full) & registers_.e_masks[1])
|
||||
) & 0xffff;
|
||||
data_address_increment_mask_ = 0x00'ff'ff;
|
||||
|
||||
@ -382,7 +380,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
continue;
|
||||
|
||||
case OperationConstructStackRelativeIndexedIndirect:
|
||||
data_address_ = registers_.data_bank + data_buffer_.value + y();
|
||||
data_address_ = registers_.data_bank + data_buffer_.value + registers_.y.full;
|
||||
data_address_increment_mask_ = 0xff'ff'ff;
|
||||
data_buffer_.clear();
|
||||
continue;
|
||||
@ -458,11 +456,8 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
// Performance.
|
||||
//
|
||||
|
||||
#define LD(dest, src, masks) dest.full = (dest.full & masks[0]) | (src & masks[1])
|
||||
#define m_top() (instruction_buffer_.value >> registers_.m_shift) & 0xff
|
||||
#define x_top() (registers_.x.full >> registers_.x_shift) & 0xff
|
||||
#define y_top() (registers_.y.full >> registers_.x_shift) & 0xff
|
||||
#define a_top() (registers_.a.full >> registers_.m_shift) & 0xff
|
||||
#define LDA(src) registers_.a.full = (registers_.a.full & registers_.m_masks[0]) | (src & registers_.m_masks[1])
|
||||
#define LDXY(dest, src) dest = (src) & registers_.x_mask
|
||||
|
||||
case OperationPerform:
|
||||
switch(active_instruction_->operation) {
|
||||
@ -472,17 +467,17 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
//
|
||||
|
||||
case LDA:
|
||||
LD(registers_.a, data_buffer_.value, registers_.m_masks);
|
||||
LDA(data_buffer_.value);
|
||||
registers_.flags.set_nz(registers_.a.full, registers_.m_shift);
|
||||
break;
|
||||
|
||||
case LDX:
|
||||
LD(registers_.x, data_buffer_.value, registers_.x_masks);
|
||||
LDXY(registers_.x, data_buffer_.value);
|
||||
registers_.flags.set_nz(registers_.x.full, registers_.x_shift);
|
||||
break;
|
||||
|
||||
case LDY:
|
||||
LD(registers_.y, data_buffer_.value, registers_.x_masks);
|
||||
LDXY(registers_.y, data_buffer_.value);
|
||||
registers_.flags.set_nz(registers_.y.full, registers_.x_shift);
|
||||
break;
|
||||
|
||||
@ -511,12 +506,12 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
break;
|
||||
|
||||
case STX:
|
||||
data_buffer_.value = registers_.x.full & registers_.x_masks[1];
|
||||
data_buffer_.value = registers_.x.full;
|
||||
data_buffer_.size = 2 - x_flag();
|
||||
break;
|
||||
|
||||
case STY:
|
||||
data_buffer_.value = registers_.y.full & registers_.x_masks[1];
|
||||
data_buffer_.value = registers_.y.full;
|
||||
data_buffer_.size = 2 - x_flag();
|
||||
break;
|
||||
|
||||
@ -554,41 +549,41 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
// (and make reasonable guesses as to the N flag).
|
||||
|
||||
case TXS:
|
||||
registers_.s = registers_.x.full & registers_.x_masks[1];
|
||||
registers_.s = registers_.x.full;
|
||||
break;
|
||||
|
||||
case TSX:
|
||||
LD(registers_.x, registers_.s.full, registers_.x_masks);
|
||||
LDXY(registers_.x, registers_.s.full);
|
||||
registers_.flags.set_nz(registers_.x.full, registers_.x_shift);
|
||||
break;
|
||||
|
||||
case TXY:
|
||||
LD(registers_.y, registers_.x.full, registers_.x_masks);
|
||||
LDXY(registers_.y, registers_.x.full);
|
||||
registers_.flags.set_nz(registers_.y.full, registers_.x_shift);
|
||||
break;
|
||||
|
||||
case TYX:
|
||||
LD(registers_.x, registers_.y.full, registers_.x_masks);
|
||||
LDXY(registers_.x, registers_.y.full);
|
||||
registers_.flags.set_nz(registers_.x.full, registers_.x_shift);
|
||||
break;
|
||||
|
||||
case TAX:
|
||||
LD(registers_.x, registers_.a.full, registers_.x_masks);
|
||||
LDXY(registers_.x, registers_.a.full);
|
||||
registers_.flags.set_nz(registers_.x.full, registers_.x_shift);
|
||||
break;
|
||||
|
||||
case TAY:
|
||||
LD(registers_.y, registers_.a.full, registers_.x_masks);
|
||||
LDXY(registers_.y, registers_.a.full);
|
||||
registers_.flags.set_nz(registers_.y.full, registers_.x_shift);
|
||||
break;
|
||||
|
||||
case TXA:
|
||||
LD(registers_.a, registers_.x.full, registers_.m_masks);
|
||||
LDA(registers_.x.full);
|
||||
registers_.flags.set_nz(registers_.a.full, registers_.m_shift);
|
||||
break;
|
||||
|
||||
case TYA:
|
||||
LD(registers_.a, registers_.y.full, registers_.m_masks);
|
||||
LDA(registers_.y.full);
|
||||
registers_.flags.set_nz(registers_.a.full, registers_.m_shift);
|
||||
break;
|
||||
|
||||
@ -670,16 +665,16 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
|
||||
case MVP:
|
||||
registers_.data_bank = (instruction_buffer_.value & 0xff) << 16;
|
||||
--registers_.x.full;
|
||||
--registers_.y.full;
|
||||
LDXY(registers_.x.full, registers_.x.full - 1);
|
||||
LDXY(registers_.y.full, registers_.y.full - 1);
|
||||
if(registers_.a.full) registers_.pc -= 3;
|
||||
--registers_.a.full;
|
||||
break;
|
||||
|
||||
case MVN:
|
||||
registers_.data_bank = (instruction_buffer_.value & 0xff) << 16;
|
||||
++registers_.x.full;
|
||||
++registers_.y.full;
|
||||
LDXY(registers_.x.full, registers_.x.full + 1);
|
||||
LDXY(registers_.y.full, registers_.y.full + 1);
|
||||
if(registers_.a.full) registers_.pc -= 3;
|
||||
--registers_.a.full;
|
||||
break;
|
||||
@ -725,29 +720,25 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
registers_.flags.set_nz(uint16_t(data_buffer_.value), registers_.m_shift);
|
||||
break;
|
||||
|
||||
case INX: {
|
||||
const uint16_t x_inc = registers_.x.full + 1;
|
||||
LD(registers_.x, x_inc, registers_.x_masks);
|
||||
case INX:
|
||||
LDXY(registers_.x.full, registers_.x.full + 1);
|
||||
registers_.flags.set_nz(registers_.x.full, registers_.x_shift);
|
||||
} break;
|
||||
break;
|
||||
|
||||
case DEX: {
|
||||
const uint16_t x_dec = registers_.x.full - 1;
|
||||
LD(registers_.x, x_dec, registers_.x_masks);
|
||||
case DEX:
|
||||
LDXY(registers_.x.full, registers_.x.full - 1);
|
||||
registers_.flags.set_nz(registers_.x.full, registers_.x_shift);
|
||||
} break;
|
||||
break;
|
||||
|
||||
case INY: {
|
||||
const uint16_t y_inc = registers_.y.full + 1;
|
||||
LD(registers_.y, y_inc, registers_.x_masks);
|
||||
case INY:
|
||||
LDXY(registers_.y.full, registers_.y.full + 1);
|
||||
registers_.flags.set_nz(registers_.y.full, registers_.x_shift);
|
||||
} break;
|
||||
break;
|
||||
|
||||
case DEY: {
|
||||
const uint16_t y_dec = registers_.y.full - 1;
|
||||
LD(registers_.y, y_dec, registers_.x_masks);
|
||||
case DEY:
|
||||
LDXY(registers_.y.full, registers_.y.full - 1);
|
||||
registers_.flags.set_nz(registers_.y.full, registers_.x_shift);
|
||||
} break;
|
||||
break;
|
||||
|
||||
//
|
||||
// Bitwise operations.
|
||||
@ -853,15 +844,15 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
// Arithmetic.
|
||||
//
|
||||
|
||||
#define cp(v, shift, masks) {\
|
||||
const uint32_t temp32 = (v.full & masks[1]) - (data_buffer_.value & masks[1]); \
|
||||
#define cp(v, shift, mask) {\
|
||||
const uint32_t temp32 = (v.full & mask) - (data_buffer_.value & mask); \
|
||||
registers_.flags.set_nz(uint16_t(temp32), shift); \
|
||||
registers_.flags.carry = ((~temp32) >> (8 + shift))&1; \
|
||||
}
|
||||
|
||||
case CMP: cp(registers_.a, registers_.m_shift, registers_.m_masks); break;
|
||||
case CPX: cp(registers_.x, registers_.x_shift, registers_.x_masks); break;
|
||||
case CPY: cp(registers_.y, registers_.x_shift, registers_.x_masks); break;
|
||||
case CMP: cp(registers_.a, registers_.m_shift, registers_.m_masks[1]); break;
|
||||
case CPX: cp(registers_.x, registers_.x_shift, registers_.x_mask); break;
|
||||
case CPY: cp(registers_.y, registers_.x_shift, registers_.x_mask); break;
|
||||
|
||||
#undef cp
|
||||
|
||||
@ -895,7 +886,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
registers_.flags.overflow = (( (decimal_result ^ registers_.a.full) & (~decimal_result ^ data_buffer_.value) ) >> (1 + registers_.m_shift))&0x40;
|
||||
registers_.flags.set_nz(uint16_t(result), registers_.m_shift);
|
||||
registers_.flags.carry = ((borrow >> 16)&1)^1;
|
||||
LD(registers_.a, result, registers_.m_masks);
|
||||
LDA(result);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -932,7 +923,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
|
||||
registers_.flags.set_nz(uint16_t(result), registers_.m_shift);
|
||||
registers_.flags.carry = (result >> (8 + registers_.m_shift))&1;
|
||||
LD(registers_.a, result, registers_.m_masks);
|
||||
LDA(result);
|
||||
} break;
|
||||
|
||||
//
|
||||
@ -950,12 +941,6 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
continue;
|
||||
}
|
||||
|
||||
#undef LD
|
||||
#undef m_top
|
||||
#undef x_top
|
||||
#undef y_top
|
||||
#undef a_top
|
||||
|
||||
// Store a selection as to the exceptions, if any, that would be honoured after this cycle if the
|
||||
// next thing is a MoveToNextProgram.
|
||||
selected_exceptions_ = pending_exceptions_ & (registers_.flags.inverse_interrupt | PowerOn | Reset | NMI);
|
||||
@ -963,6 +948,8 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
||||
}
|
||||
}
|
||||
|
||||
#undef LDA
|
||||
#undef LDXY
|
||||
#undef read
|
||||
#undef write
|
||||
#undef bus_operation
|
||||
|
@ -1109,16 +1109,10 @@ void ProcessorStorage::set_emulation_mode(bool enabled) {
|
||||
}
|
||||
|
||||
void ProcessorStorage::set_m_x_flags(bool m, bool x) {
|
||||
// Reset the top byte of x and y if _exiting_ 8-bit mode.
|
||||
// TODO: rationalise this sort of logic, both here and
|
||||
// with regards to the stack pointer.
|
||||
if(!x && registers_.mx_flags[1]) {
|
||||
registers_.x.halves.high = registers_.y.halves.high = 0;
|
||||
}
|
||||
|
||||
registers_.x_masks[0] = x ? 0xff00 : 0x0000;
|
||||
registers_.x_masks[1] = x ? 0x00ff : 0xffff;
|
||||
registers_.x_mask = x ? 0x00ff : 0xffff;
|
||||
registers_.x_shift = x ? 0 : 8;
|
||||
registers_.x.full &= registers_.x_mask;
|
||||
registers_.y.full &= registers_.x_mask;
|
||||
|
||||
registers_.m_masks[0] = m ? 0xff00 : 0x0000;
|
||||
registers_.m_masks[1] = m ? 0x00ff : 0xffff;
|
||||
|
@ -271,7 +271,7 @@ struct ProcessorStorage {
|
||||
MOS6502Esque::LazyFlags flags;
|
||||
uint8_t mx_flags[2] = {1, 1}; // [0] = m; [1] = x. In both cases either `0` or `1`; `1` => 8-bit.
|
||||
uint16_t m_masks[2] = {0xff00, 0x00ff}; // [0] = src mask; [1] = dst mask.
|
||||
uint16_t x_masks[2] = {0xff00, 0x00ff}; // [0] = src mask; [1] = dst mask.
|
||||
uint16_t x_mask = 0x00ff; // Just a mask representing the current size of the index registers.
|
||||
uint16_t e_masks[2] = {0xff00, 0x00ff};
|
||||
int m_shift = 0;
|
||||
int x_shift = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user