mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-23 03:32:32 +00:00
Merge pull request #1091 from TomHarte/65816DxDy
Fix 65816 direct, [x/y] addressing when E=1, DL != 0.
This commit is contained in:
commit
cb7f1e42ff
@ -334,6 +334,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
|||||||
case OperationConstructDirect:
|
case OperationConstructDirect:
|
||||||
data_address_ = (registers_.direct + instruction_buffer_.value) & 0xffff;
|
data_address_ = (registers_.direct + instruction_buffer_.value) & 0xffff;
|
||||||
data_address_increment_mask_ = 0x00'ff'ff;
|
data_address_increment_mask_ = 0x00'ff'ff;
|
||||||
|
|
||||||
if(!(registers_.direct&0xff)) {
|
if(!(registers_.direct&0xff)) {
|
||||||
// If the low byte is 0 and this is emulation mode, incrementing
|
// If the low byte is 0 and this is emulation mode, incrementing
|
||||||
// is restricted to the low byte.
|
// is restricted to the low byte.
|
||||||
@ -345,6 +346,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
|||||||
case OperationConstructDirectLong:
|
case OperationConstructDirectLong:
|
||||||
data_address_ = (registers_.direct + instruction_buffer_.value) & 0xffff;
|
data_address_ = (registers_.direct + instruction_buffer_.value) & 0xffff;
|
||||||
data_address_increment_mask_ = 0x00'ff'ff;
|
data_address_increment_mask_ = 0x00'ff'ff;
|
||||||
|
|
||||||
if(!(registers_.direct&0xff)) {
|
if(!(registers_.direct&0xff)) {
|
||||||
++next_op_;
|
++next_op_;
|
||||||
}
|
}
|
||||||
@ -380,31 +382,41 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
|||||||
data_buffer_.clear();
|
data_buffer_.clear();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: confirm incorrect_data_address_ below.
|
|
||||||
|
|
||||||
case OperationConstructDirectX:
|
case OperationConstructDirectX:
|
||||||
data_address_ = (
|
// There are no direct, x instructions that access a two-byte value when
|
||||||
(registers_.direct & registers_.e_masks[0]) +
|
// in emulation mode, so this can assume native mode.
|
||||||
((instruction_buffer_.value + registers_.direct + registers_.x.full) & registers_.e_masks[1])
|
|
||||||
) & 0xffff;
|
|
||||||
data_address_increment_mask_ = 0x00'ff'ff;
|
data_address_increment_mask_ = 0x00'ff'ff;
|
||||||
|
|
||||||
incorrect_data_address_ = (registers_.direct & 0xff00) + (data_address_ & 0x00ff);
|
// If the low byte of the direct register is 0, use the current e mask
|
||||||
|
// potentially to keep the high byte of the direct register unmodified.
|
||||||
|
//
|
||||||
|
// Also skip the next program step, which would be a redundant fetch
|
||||||
|
// from the program counter.
|
||||||
|
//
|
||||||
|
// Otherwise: retain a 16-bit address.
|
||||||
|
|
||||||
|
data_address_ = instruction_buffer_.value + registers_.direct + registers_.x.full;
|
||||||
if(!(registers_.direct&0xff)) {
|
if(!(registers_.direct&0xff)) {
|
||||||
|
data_address_ =
|
||||||
|
(registers_.direct & registers_.e_masks[0]) |
|
||||||
|
(data_address_ & registers_.e_masks[1]);
|
||||||
++next_op_;
|
++next_op_;
|
||||||
|
} else {
|
||||||
|
data_address_ &= 0xffff;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case OperationConstructDirectY:
|
case OperationConstructDirectY:
|
||||||
data_address_ = (
|
// Cf. comments above in DirectX.
|
||||||
(registers_.direct & registers_.e_masks[0]) +
|
|
||||||
((instruction_buffer_.value + registers_.direct + registers_.y.full) & registers_.e_masks[1])
|
|
||||||
) & 0xffff;
|
|
||||||
data_address_increment_mask_ = 0x00'ff'ff;
|
data_address_increment_mask_ = 0x00'ff'ff;
|
||||||
|
data_address_ = instruction_buffer_.value + registers_.direct + registers_.y.full;
|
||||||
incorrect_data_address_ = (registers_.direct & 0xff00) + (data_address_ & 0x00ff);
|
|
||||||
if(!(registers_.direct&0xff)) {
|
if(!(registers_.direct&0xff)) {
|
||||||
|
data_address_ =
|
||||||
|
(registers_.direct & registers_.e_masks[0]) |
|
||||||
|
(data_address_ & registers_.e_masks[1]);
|
||||||
++next_op_;
|
++next_op_;
|
||||||
|
} else {
|
||||||
|
data_address_ &= 0xffff;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -281,13 +281,36 @@ struct ProcessorStorage {
|
|||||||
|
|
||||||
// Flags aplenty.
|
// Flags aplenty.
|
||||||
MOS6502Esque::LazyFlags flags;
|
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 (i.e. that which is unaffected by an operation); [1] = dst mask (i.e. 0xffff ^ src mask).
|
// [0] = m; [1] = x. In both cases either `0` or `1`; `1` => 8-bit.
|
||||||
uint16_t x_mask = 0x00ff; // A mask representing the current size of the index registers. Equivalent to m_masks[1].
|
uint8_t mx_flags[2] = {1, 1};
|
||||||
uint16_t e_masks[2] = {0xff00, 0x00ff}; // Akin to m_masks, but set as per emulation mode.
|
|
||||||
int m_shift = 0; // How far to shift memory/A to align its sign bit with that of the flags register. i.e. 8 for 16-bit mode, 0 for 8-bit mode.
|
// Used to determine which parts of a register are currently in use, as a function
|
||||||
int x_shift = 0; // m_shift equivalent for X and Y.
|
// of the M flag.
|
||||||
bool emulation_flag = true; // The emulation flag; true = in emulation mode.
|
//
|
||||||
|
// [0] = src mask (i.e. that which is unaffected by an operation);
|
||||||
|
// [1] = dst mask (i.e. 0xffff ^ src mask).
|
||||||
|
//
|
||||||
|
// e.g. a LDA from the value Q would prima facie leave A as equal to:
|
||||||
|
// (A & m_masks[0]) | (Q & m_masks[1]);
|
||||||
|
uint16_t m_masks[2] = {0xff00, 0x00ff};
|
||||||
|
|
||||||
|
// A mask representing the current size of the index registers.
|
||||||
|
// Equivalent in meaning to m_masks[1] but representative of the X flag.
|
||||||
|
uint16_t x_mask = 0x00ff;
|
||||||
|
|
||||||
|
// Akin to m_masks, but a function of emulation mode; used primarily for address calculation.
|
||||||
|
uint16_t e_masks[2] = {0xff00, 0x00ff};
|
||||||
|
|
||||||
|
// How far to shift memory/A to align its sign bit with that of the flags register.
|
||||||
|
// i.e. 8 for 16-bit mode, 0 for 8-bit mode.
|
||||||
|
int m_shift = 0;
|
||||||
|
|
||||||
|
// m_shift equivalent for X and Y.
|
||||||
|
int x_shift = 0;
|
||||||
|
|
||||||
|
// The emulation flag; true = in emulation mode.
|
||||||
|
bool emulation_flag = true;
|
||||||
|
|
||||||
// The offset for direct addressing (i.e. outside of emulation mode).
|
// The offset for direct addressing (i.e. outside of emulation mode).
|
||||||
uint16_t direct = 0;
|
uint16_t direct = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user