Disambiguate PostincrementBy1 and Offset8bit.
This commit is contained in:
1 parent
948e49312b
commit
873f10a0d8
3 files changed
+53
-36
No files matched your search
@@ -283,4 +283,18 @@ struct M6809Traits {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testIndexer {
|
||||
using IndexedAddressDecoder = CPU::M6809::IndexedAddressDecoder;
|
||||
IndexedAddressDecoder decoder;
|
||||
|
||||
decoder = IndexedAddressDecoder(0x00);
|
||||
XCTAssertEqual(decoder.required_continuation(), 0);
|
||||
for(int c = 0; c < 65536; c += 13) {
|
||||
CPU::M6809::Registers regs;
|
||||
regs.x = c;
|
||||
XCTAssertEqual(decoder.address(regs), c);
|
||||
XCTAssertEqual(regs.x, c + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -315,7 +315,6 @@ struct Processor {
|
||||
// TODO: test interrupts and more.
|
||||
}
|
||||
|
||||
// printf("--- Fetch\n");
|
||||
read(BusState::Normal, Literal(registers_.pc.full), opcode, ++registers_.pc.full);
|
||||
{
|
||||
operation_ = Reflection::dispatch(op_mapper0, opcode, op_returner);
|
||||
@@ -776,5 +775,4 @@ private:
|
||||
IndexedAddressDecoder indexer_;
|
||||
uint16_t *stack_ = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -203,18 +203,13 @@ struct Registers {
|
||||
default: __builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
/// @returns The value of DP as the high byte of an address.
|
||||
uint16_t dp_high() const {
|
||||
return uint16_t(dp << 8); // TODO: worth precomputing?
|
||||
}
|
||||
};
|
||||
|
||||
struct IndexedAddressDecoder {
|
||||
IndexedAddressDecoder() = default;
|
||||
constexpr IndexedAddressDecoder(const uint8_t format) noexcept : format_(format) {}
|
||||
|
||||
enum FormSuffix: uint8_t {
|
||||
enum class FormSuffix {
|
||||
NoOffset = 0b0100,
|
||||
|
||||
Offset8bit = 0b1000,
|
||||
@@ -226,17 +221,30 @@ struct IndexedAddressDecoder {
|
||||
BRegisterOffset = 0b0101,
|
||||
DRegisterOffset = 0b1011,
|
||||
|
||||
PostincrementBy1 = 0b1000,
|
||||
PostincrementBy1 = 0b0000,
|
||||
PostincrementBy2 = 0b0001,
|
||||
PredecrementBy1 = 0b0010,
|
||||
PredecrementBy2 = 0b0011,
|
||||
};
|
||||
static constexpr uint8_t ExtendedIndirect = 0x9f;
|
||||
|
||||
int required_continuation() const {
|
||||
if(!(format_ & 0x80)) return 0;
|
||||
constexpr FormSuffix suffix() const {
|
||||
return FormSuffix(format_ & 0b1111);
|
||||
}
|
||||
constexpr bool is_5bit() const {
|
||||
return !(format_ & 0xb1000'0000);
|
||||
}
|
||||
constexpr bool indirect() const {
|
||||
return
|
||||
suffix() != FormSuffix::PostincrementBy1 &&
|
||||
suffix() != FormSuffix::PredecrementBy1 &&
|
||||
(format_ & 0b1001'0000) == 0b1001'0000;
|
||||
}
|
||||
|
||||
constexpr int required_continuation() const {
|
||||
if(is_5bit()) return 0;
|
||||
if(format_ == ExtendedIndirect) return 2;
|
||||
switch(format_ & 0b1111) {
|
||||
switch(suffix()) {
|
||||
using enum FormSuffix;
|
||||
case Offset8bit: case Offset8bitFromPC: return 1;
|
||||
case Offset16bit: case Offset16bitFromPC: return 2;
|
||||
@@ -257,32 +265,33 @@ struct IndexedAddressDecoder {
|
||||
return continuation_;
|
||||
}
|
||||
|
||||
const auto reg = [&] () -> uint16_t & {
|
||||
switch((format_ >> 5) & 0b11) {
|
||||
case 0b00: return registers.reg<R16::X>();
|
||||
case 0b01: return registers.reg<R16::Y>();
|
||||
case 0b10: return registers.reg<R16::U>();
|
||||
case 0b11: return registers.reg<R16::S>();
|
||||
default: __builtin_unreachable();
|
||||
}
|
||||
};
|
||||
|
||||
const uint16_t base = [&] {
|
||||
if(is_5bit()) {
|
||||
return reg();
|
||||
}
|
||||
|
||||
if(
|
||||
(format_ & 0x80) &&
|
||||
!is_5bit() &&
|
||||
(
|
||||
((format_ & 0b1111) == FormSuffix::Offset8bitFromPC) ||
|
||||
((format_ & 0b1111) == FormSuffix::Offset16bitFromPC)
|
||||
(suffix() == FormSuffix::Offset8bitFromPC) ||
|
||||
(suffix() == FormSuffix::Offset16bitFromPC)
|
||||
)
|
||||
) {
|
||||
return registers.reg<R16::PC>();
|
||||
}
|
||||
|
||||
auto reg = [&] () -> uint16_t & {
|
||||
switch((format_ >> 5) & 3) {
|
||||
case 0b00: return registers.reg<R16::X>();
|
||||
case 0b01: return registers.reg<R16::Y>();
|
||||
case 0b10: return registers.reg<R16::U>();
|
||||
case 0b11: return registers.reg<R16::S>();
|
||||
default: __builtin_unreachable();
|
||||
}
|
||||
};
|
||||
|
||||
if(!(format_ & 0x80)) {
|
||||
return reg();
|
||||
}
|
||||
|
||||
switch(format_ & 0b1111) {
|
||||
switch(suffix()) {
|
||||
using enum FormSuffix;
|
||||
default: return reg();
|
||||
|
||||
case PredecrementBy2:
|
||||
@@ -308,13 +317,13 @@ struct IndexedAddressDecoder {
|
||||
} ();
|
||||
|
||||
// A high bit of 0 implies the low five bits are the offset.
|
||||
if(!(format_ & 0x80)) {
|
||||
if(is_5bit()) {
|
||||
// Shift sign bit up to bit 7 and convert to int8_t to effect it.
|
||||
// Then shift back down to get the correct value.
|
||||
return uint16_t(base + (int8_t(format_ << 3) >> 3));
|
||||
}
|
||||
|
||||
switch(format_ & 0b1111) {
|
||||
switch(suffix()) {
|
||||
using enum FormSuffix;
|
||||
|
||||
default: return base;
|
||||
@@ -332,10 +341,6 @@ struct IndexedAddressDecoder {
|
||||
return base;
|
||||
}
|
||||
|
||||
bool indirect() const {
|
||||
return (format_ & 0x90) == 0x90;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t format_;
|
||||
uint16_t continuation_ = 0;
|
||||
|
||||
Reference in new issue
Block a user