mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-27 16:31:31 +00:00
Found a form I like for indexed addressing, applying it only where obvious for now. Which eliminates more than a couple of hundred of remaining failures.
This commit is contained in:
parent
ab8a98f1df
commit
9bc2b48d9b
@ -57,19 +57,19 @@ fileprivate struct RegisterState {
|
||||
de = UInt16(dictionary["de"] as! NSNumber)
|
||||
hl = UInt16(dictionary["hl"] as! NSNumber)
|
||||
|
||||
afDash = UInt16((dictionary["afDash"] as! NSNumber).int32Value)
|
||||
bcDash = UInt16((dictionary["bcDash"] as! NSNumber).int32Value)
|
||||
deDash = UInt16((dictionary["deDash"] as! NSNumber).int32Value)
|
||||
hlDash = UInt16((dictionary["hlDash"] as! NSNumber).int32Value)
|
||||
afDash = UInt16(dictionary["afDash"] as! NSNumber)
|
||||
bcDash = UInt16(dictionary["bcDash"] as! NSNumber)
|
||||
deDash = UInt16(dictionary["deDash"] as! NSNumber)
|
||||
hlDash = UInt16(dictionary["hlDash"] as! NSNumber)
|
||||
|
||||
ix = UInt16((dictionary["ix"] as! NSNumber).int32Value)
|
||||
iy = UInt16((dictionary["iy"] as! NSNumber).int32Value)
|
||||
ix = UInt16(dictionary["ix"] as! NSNumber)
|
||||
iy = UInt16(dictionary["iy"] as! NSNumber)
|
||||
|
||||
sp = UInt16((dictionary["sp"] as! NSNumber).int32Value)
|
||||
pc = UInt16((dictionary["pc"] as! NSNumber).int32Value)
|
||||
sp = UInt16(dictionary["sp"] as! NSNumber)
|
||||
pc = UInt16(dictionary["pc"] as! NSNumber)
|
||||
|
||||
i = UInt8((dictionary["i"] as! NSNumber).int32Value)
|
||||
r = UInt8((dictionary["r"] as! NSNumber).int32Value)
|
||||
i = UInt8(dictionary["i"] as! NSNumber)
|
||||
r = UInt8(dictionary["r"] as! NSNumber)
|
||||
|
||||
iff1 = (dictionary["iff1"] as! NSNumber).boolValue
|
||||
iff2 = (dictionary["iff2"] as! NSNumber).boolValue
|
||||
@ -151,10 +151,17 @@ class FUSETests: XCTestCase {
|
||||
XCTAssert(inputArray != nil && outputArray != nil)
|
||||
|
||||
var index = 0
|
||||
var failures = 0
|
||||
// var failures = 0
|
||||
for item in inputArray {
|
||||
let itemDictionary = item as! [String: Any]
|
||||
let outputDictionary = outputArray[index] as! [String: Any]
|
||||
index = index + 1
|
||||
|
||||
let name = itemDictionary["name"] as! String
|
||||
|
||||
// if name != "fd86" {
|
||||
// continue
|
||||
// }
|
||||
|
||||
let initialState = RegisterState(dictionary: itemDictionary["state"] as! [String: Any])
|
||||
let targetState = RegisterState(dictionary: outputDictionary["state"] as! [String: Any])
|
||||
@ -175,22 +182,20 @@ class FUSETests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
machine.runForNumber(ofCycles: Int32(initialState.tStates))
|
||||
machine.runToNextInstruction()
|
||||
machine.runForNumber(ofCycles: Int32(targetState.tStates))
|
||||
|
||||
let finalState = RegisterState(machine: machine)
|
||||
|
||||
XCTAssertEqual(finalState, targetState, "Failed \(itemDictionary["name"] as! String)")
|
||||
if finalState != targetState {
|
||||
failures = failures + 1
|
||||
if failures == 5 {
|
||||
return
|
||||
}
|
||||
}
|
||||
XCTAssert(finalState == targetState, "Failed \(name)")
|
||||
// if finalState != targetState {
|
||||
// failures = failures + 1
|
||||
// if failures == 5 {
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO compare bus operations and final memory state
|
||||
|
||||
index = index + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +133,8 @@ struct MicroOp {
|
||||
|
||||
CalculateRSTDestination,
|
||||
|
||||
IndexedPlaceHolder,
|
||||
|
||||
None
|
||||
};
|
||||
Type type;
|
||||
@ -192,6 +194,9 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
|
||||
#define XX {MicroOp::None, 0}
|
||||
|
||||
#define INDEX() {MicroOp::IndexedPlaceHolder}, FETCH(temp8_, pc_), WAIT(5), {MicroOp::CalculateIndexAddress, &index}
|
||||
#define IR_ADDR() (add_offsets ? temp16_ : index)
|
||||
|
||||
/// Fetches into x from address y, and then increments y.
|
||||
#define FETCH(x, y) {MicroOp::BusOperation, nullptr, nullptr, {Read, 3, &y.full, &x}}, {MicroOp::Increment16, &y.full}
|
||||
/// Fetches into x from address y.
|
||||
@ -221,14 +226,14 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
#define LD(a, b) Program({MicroOp::Move8, &b, &a})
|
||||
|
||||
#define LD_GROUP(r) \
|
||||
LD(r, bc_.bytes.high), LD(r, bc_.bytes.low), LD(r, de_.bytes.high), LD(r, de_.bytes.low), \
|
||||
LD(r, bc_.bytes.high), LD(r, bc_.bytes.low), LD(r, de_.bytes.high), LD(r, de_.bytes.low), \
|
||||
LD(r, index.bytes.high), LD(r, index.bytes.low), Program(FETCHL(r, index)), LD(r, a_)
|
||||
|
||||
#define OP_GROUP(op) \
|
||||
Program({MicroOp::op, &bc_.bytes.high}), Program({MicroOp::op, &bc_.bytes.low}), \
|
||||
Program({MicroOp::op, &de_.bytes.high}), Program({MicroOp::op, &de_.bytes.low}), \
|
||||
Program({MicroOp::op, &index.bytes.high}), Program({MicroOp::op, &index.bytes.low}), \
|
||||
Program(FETCHL(temp8_, index), {MicroOp::op, &temp8_}), \
|
||||
Program(INDEX(), FETCHL(temp8_, IR_ADDR()), {MicroOp::op, &temp8_}), \
|
||||
Program({MicroOp::op, &a_})
|
||||
|
||||
#define ADD16(d, s) Program(WAIT(4), WAIT(3), {MicroOp::ADD16, &s.full, &d.full})
|
||||
@ -240,7 +245,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
|
||||
typedef MicroOp InstructionTable[256][20];
|
||||
|
||||
void assemble_page(InstructionPage &target, InstructionTable &table) {
|
||||
void assemble_page(InstructionPage &target, InstructionTable &table, bool add_offsets) {
|
||||
size_t number_of_micro_ops = 0;
|
||||
size_t lengths[256];
|
||||
|
||||
@ -259,9 +264,21 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
// Copy in all programs and set pointers.
|
||||
size_t destination = 0;
|
||||
for(int c = 0; c < 256; c++) {
|
||||
memcpy(&target.all_operations[destination], table[c], lengths[c] * sizeof(MicroOp));
|
||||
target.instructions[c] = &target.all_operations[destination];
|
||||
destination += lengths[c];
|
||||
if(c == 0x86)
|
||||
printf("!");
|
||||
for(int t = 0; t < lengths[c];) {
|
||||
// If an index placeholder is hit then drop it, and if offsets aren't being added,
|
||||
// then also drop the indexing that follows and which is assumed here to be four
|
||||
// micro-ops in length. Coupled to the INDEX() macro.
|
||||
if(table[c][t].type == MicroOp::IndexedPlaceHolder) {
|
||||
t++;
|
||||
if(!add_offsets) t += 4;
|
||||
}
|
||||
target.all_operations[destination] = table[c][t];
|
||||
destination++;
|
||||
t++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +342,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
NOP_ROW(), /* 0xe0 */
|
||||
NOP_ROW(), /* 0xf0 */
|
||||
};
|
||||
assemble_page(target, ed_program_table);
|
||||
assemble_page(target, ed_program_table, false);
|
||||
#undef NOP_ROW
|
||||
}
|
||||
|
||||
@ -389,8 +406,8 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
/* 0x30 JR NC */ JR(TestNC), /* 0x31 LD SP, nn */ Program(FETCH16(sp_, pc_)),
|
||||
/* 0x32 LD (nn), A */ Program(FETCH16(temp16_, pc_), STOREL(a_, temp16_)),
|
||||
/* 0x33 INC SP */ Program(WAIT(2), {MicroOp::Increment16, &sp_.full}),
|
||||
/* 0x34 INC (HL) */ Program(FETCHL(temp8_, hl_), WAIT(1), {MicroOp::Increment8, &temp8_}, STOREL(temp8_, hl_)),
|
||||
/* 0x35 DEC (HL) */ Program(FETCHL(temp8_, hl_), WAIT(1), {MicroOp::Decrement8, &temp8_}, STOREL(temp8_, hl_)),
|
||||
/* 0x34 INC (HL) */ Program( FETCHL(temp8_, index), WAIT(1), {MicroOp::Increment8, &temp8_}, STOREL(temp8_, index)),
|
||||
/* 0x35 DEC (HL) */ Program(FETCHL(temp8_, index), WAIT(1), {MicroOp::Decrement8, &temp8_}, STOREL(temp8_, index)),
|
||||
/* 0x36 LD (HL), n */ Program(FETCH(temp8_, pc_), STOREL(temp8_, index)),
|
||||
/* 0x37 SCF */ Program({MicroOp::SCF}),
|
||||
/* 0x38 JR C */ JR(TestC),
|
||||
@ -494,7 +511,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
/* 0xfe CP n */ Program(FETCH(temp8_, pc_), {MicroOp::CP8, &temp8_}),
|
||||
/* 0xff RST 38h */ RST(),
|
||||
};
|
||||
assemble_page(target, base_program_table);
|
||||
assemble_page(target, base_program_table, add_offsets);
|
||||
}
|
||||
|
||||
void assemble_fetch_decode_execute() {
|
||||
@ -523,8 +540,8 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
public:
|
||||
Processor() : MicroOpScheduler() {
|
||||
assemble_base_page(base_page_, hl_, false);
|
||||
assemble_base_page(dd_page_, ix_, false);
|
||||
assemble_base_page(fd_page_, iy_, false);
|
||||
assemble_base_page(dd_page_, ix_, true);
|
||||
assemble_base_page(fd_page_, iy_, true);
|
||||
assemble_ed_page(ed_page_);
|
||||
assemble_fetch_decode_execute();
|
||||
}
|
||||
@ -568,7 +585,6 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
|
||||
if(number_of_cycles_ < operation->machine_cycle.length) { schedule_program_program_counter_--; return; }
|
||||
number_of_cycles_ -= operation->machine_cycle.length;
|
||||
number_of_cycles_ -= static_cast<T *>(this)->perform_machine_cycle(&operation->machine_cycle);
|
||||
if(number_of_cycles_ <= 0) return;
|
||||
break;
|
||||
case MicroOp::MoveToNextProgram:
|
||||
move_to_next_program();
|
||||
|
Loading…
Reference in New Issue
Block a user