1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-29 00:29:34 +00:00

Filled in most of the loads.

This commit is contained in:
Thomas Harte 2017-05-19 22:57:43 -04:00
parent bc3b5f3e35
commit 6766845e21
2 changed files with 106 additions and 37 deletions

View File

@ -91,6 +91,19 @@ struct MicroOp {
AssembleAF,
DisassembleAF,
And,
Or,
Xor,
TestNZ,
TestZ,
TestNC,
TestC,
TestPO,
TestPE,
TestP,
TestM,
None
} type;
void *source;
@ -115,7 +128,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
RegisterPair bc_, de_, hl_;
RegisterPair afDash_, bcDash_, deDash_, hlDash_;
RegisterPair ix_, iy_, pc_, sp_;
uint8_t carry_flag_, sign_result_, bit5_result_, half_carry_flag_, bit3_result_, parity_overflow_flag_, subtract_flag_;
uint8_t sign_result_, zero_result_, bit5_result_, half_carry_flag_, bit3_result_, parity_overflow_flag_, subtract_flag_, carry_flag_;
int number_of_cycles_;
const MicroOp **program_table_;
@ -137,6 +150,13 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
#define PUSH(x) {MicroOp::Decrement16, &sp_.full}, STOREL(x.bytes.high, sp_), {MicroOp::Decrement16, &sp_.full}, STOREL(x.bytes.low, sp_)
#define POP(x) FETCHL(x.bytes.low, sp_), {MicroOp::Increment16, &sp_.full}, FETCHL(x.bytes.high, sp_), {MicroOp::Increment16, &sp_.full}
#define JP(cc) Program(FETCH16(temporary_, pc_), {MicroOp::cc}, {MicroOp::Move16, &address_.full, &pc_.full})
#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, hl_.bytes.high), LD(r, hl_.bytes.low), Program(FETCHL(r, hl_)), LD(r, a_)
#define WAIT(n) {MicroOp::BusOperation, nullptr, nullptr, {Internal, n} }
#define Program(...) { __VA_ARGS__, {MicroOp::MoveToNextProgram} }
@ -152,7 +172,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
XX, /* 0x07 RLCA */
XX, /* 0x08 EX AF, AF' */
XX, /* 0x09 ADD HL, BC */
XX, /* 0x0a LD A, (BC) */
Program(FETCHL(a_, bc_)), /* 0x0a LD A, (BC) */
Program(WAIT(2), {MicroOp::Decrement16, &bc_.full}), /* 0x0b DEC BC */
XX, /* 0x0c INC C */
XX, /* 0x0d DEC C */
@ -168,7 +188,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
XX, /* 0x17 RLA */
XX, /* 0x18 JR */
XX, /* 0x19 ADD HL, DE */
XX, /* 0x1a LD A, (DE) */
Program(FETCHL(a_, de_)), /* 0x1a LD A, (DE) */
Program(WAIT(2), {MicroOp::Decrement16, &de_.full}), /* 0x1b DEC DE */
XX, /* 0x1c INC E */
XX, /* 0x1d DEC E */
@ -206,39 +226,32 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
XX, /* 0x3d DEC A */
XX, /* 0x3e LD A, n */
XX, /* 0x3f CCF */
XX, XX, XX, XX, XX, XX, XX, XX, // 0x40
XX, /* 0x48 LD C, B */
XX, /* 0x49 LD C, C */
XX, /* 0x4a LD C, D */
XX, /* 0x4b LD C, E */
XX, /* 0x4c LD C, H */
XX, /* 0x4d LD C, L */
Program(FETCHL(bc_.bytes.low, hl_)), /* 0x4e LD C,(HL) */
XX, /* 0x4f LD C, A */
XX, XX, XX, XX, XX, XX, XX, XX, // 0x50
XX, XX, XX, XX, XX, XX, XX, XX, // 0x58
XX, XX, XX, XX, XX, XX, XX, XX, // 0x60
XX, XX, XX, XX, XX, XX, XX, XX, // 0x68
LD_GROUP(bc_.bytes.high), /* 0x40 LD B, B; 0x41 LD B, C; 0x42 LD B, D; 0x43 LD B, E; 0x44 LD B, H; 0x45 LD B, L; 0x46 LD B, (HL); 0x47 LD B, A */
LD_GROUP(bc_.bytes.low), /* 0x48 LD C, B; 0x49 LD C, C; 0x4a LD C, D; 0x4b LD C, E; 0x4c LD C, H; 0x4d LD C, L; 0x4e LD C, (HL); 0x4f LD C, A */
LD_GROUP(de_.bytes.high), /* 0x50 LD D, B; 0x51 LD D, C; 0x52 LD D, D; 0x53 LD D, E; 0x54 LD D, H; 0x55 LD D, L; 0x56 LD D, (HL); 0x57 LD D, A */
LD_GROUP(de_.bytes.low), /* 0x58 LD E, B; 0x59 LD E, C; 0x5a LD E, D; 0x5b LD E, E; 0x5c LD E, H; 0x5d LD E, L; 0x5e LD E, (HL); 0x5f LD E, A */
LD_GROUP(hl_.bytes.high), /* 0x60 LD H, B; 0x61 LD H, C; 0x62 LD H, D; 0x63 LD H, E; 0x64 LD H, H; 0x65 LD H, L; 0x66 LD H, (HL); 0x67 LD H, A */
LD_GROUP(hl_.bytes.low), /* 0x68 LD L, B; 0x69 LD L, C; 0x6a LD L, D; 0x6b LD L, E; 0x6c LD L, H; 0x6d LD H, L; 0x6e LD L, (HL); 0x6f LD L, A */
XX, XX, XX, XX, XX, XX, XX, XX, // 0x70
XX, /* 0x78 LD A, B */
XX, /* 0x79 LD A, C */
XX, /* 0x7a LD A, D */
XX, /* 0x7b LD A, E */
XX, /* 0x7c LD A, H */
XX, /* 0x7d LD A, L */
Program(FETCHL(a_, hl_)), /* 0x7e LD A, (HL) */
XX, /* 0x7f LD A, A */
LD_GROUP(a_), /* 0x78 LD A, B; 0x79 LD A, C; 0x7a LD A, D; 0x7b LD A, E; 0x7c LD A, H; 0x7d LD A, L; 0x7e LD A, (HL); 0x7f LD A, A */
XX, XX, XX, XX, XX, XX, XX, XX, // 0x80
XX, XX, XX, XX, XX, XX, XX, XX, // 0x88
XX, XX, XX, XX, XX, XX, XX, XX, // 0x90
XX, XX, XX, XX, XX, XX, XX, XX, // 0x98
XX, XX, XX, XX, XX, XX, XX, XX, // 0xa0
XX, XX, XX, XX, XX, XX, XX, XX, // 0xa8
XX, XX, XX, XX, XX, XX, XX, XX, // 0xb0
Program({MicroOp::Or, &hl_.bytes.high}), /* 0xb0 OR B */
Program({MicroOp::Or, &bc_.bytes.low}), /* 0xb1 OR C */
Program({MicroOp::Or, &hl_.bytes.high}), /* 0xb2 OR D */
Program({MicroOp::Or, &de_.bytes.low}), /* 0xb3 OR E */
Program({MicroOp::Or, &hl_.bytes.high}), /* 0xb4 OR H */
Program({MicroOp::Or, &hl_.bytes.low}), /* 0xb5 OR L */
Program(FETCHL(temporary_.bytes.low, hl_), {MicroOp::Or, &temporary_.bytes.low}), /* 0xb6 OR (HL) */
Program({MicroOp::Or, &a_}), /* 0xb7 OR A */
XX, XX, XX, XX, XX, XX, XX, XX, // 0xb8
XX, /* 0xc0 RET NZ */
Program(POP(bc_)), /* 0xc1 POP BC */
XX, /* 0xc2 JP NZ */
JP(TestNZ), /* 0xc2 JP NZ */
Program(FETCH16L(address_, pc_), {MicroOp::Move16, &address_.full, &pc_.full}), /* 0xc3 JP nn */
XX, /* 0xc4 CALL NZ */
Program(WAIT(1), PUSH(bc_)), /* 0xc5 PUSH BC */
@ -246,7 +259,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
XX, /* 0xc7 RST 00h */
XX, /* 0xc8 RET Z */
Program(POP(pc_)), /* 0xc9 RET */
XX, /* 0xca JP Z */
JP(TestZ), /* 0xca JP Z */
XX, /* 0xcb [CB page] */
XX, /* 0xcc CALL Z */
Program(FETCH16(address_, pc_), WAIT(1), PUSH(pc_), {MicroOp::Move16, &address_.full, &pc_.full}), /* 0xcd CALL */
@ -254,25 +267,39 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
XX, /* 0xcf RST 08h */
XX, /* 0xd0 RET NC */
Program(POP(de_)), /* 0xd1 POP DE */
XX, /* 0xd2 JP NC */
JP(TestNC), /* 0xd2 JP NC */
XX, /* 0xd3 OUT (n), A */
XX, /* 0xd4 CALL NC */
Program(WAIT(1), PUSH(de_)), /* 0xd5 PUSH DE */
XX, /* 0xd6 SUB n */
XX, /* 0xd7 RST 10h */
XX, XX, XX, XX, XX, XX, XX, XX, // 0xd8
XX, /* 0xd8 RET C */
XX, /* 0xd9 EXX */
JP(TestC), /* 0xda JP C */
XX, /* 0xdb IN A, (n) */
XX, /* 0xdc CALL C */
XX, /* 0xdd [DD page] */
XX, /* 0xde SBC A, n */
XX, /* 0xdf RST 18h */
XX, /* 0xe0 RET PO */
Program(POP(hl_)), /* 0xe1 POP HL */
XX, /* 0xe2 JP PO */
JP(TestPO), /* 0xe2 JP PO */
XX, /* 0xe3 EX (SP), HL */
XX, /* 0xe4 CALL PO */
Program(WAIT(1), PUSH(hl_)), /* 0xe5 PUSH HL */
XX, /* 0xe6 AND n */
XX, /* 0xe7 RST 20h */
XX, XX, XX, XX, XX, XX, XX, XX, // 0xe8
XX, /* 0xe8 RET PE */
XX, /* 0xe9 JP (HL) */
JP(TestPE), /* 0xea JP PE */
XX, /* 0xeb EX DE, HL */
XX, /* 0xec CALL PE */
XX, /* 0xed [ED page] */
XX, /* 0xee XOR n */
XX, /* 0xef RST 28h */
XX, /* 0xf0 RET p */
Program(POP(temporary_), {MicroOp::DisassembleAF}), /* 0xf1 POP AF */
XX, /* 0xf2 JP P */
JP(TestP), /* 0xf2 JP P */
XX, /* 0xf3 DI */
XX, /* 0xf4 CALL P */
Program(WAIT(1), {MicroOp::AssembleAF}, PUSH(temporary_)), /* 0xf5 PUSH AF */
@ -280,7 +307,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
XX, /* 0xf7 RST 30h */
XX, /* 0xf8 RET M */
Program(WAIT(2), {MicroOp::Move16, &hl_.full, &sp_.full}), /* 0xf9 LD SP, HL */
XX, /* 0xfa JP M */
JP(TestM), /* 0xfa JP M */
XX, /* 0xfb EI */
XX, /* 0xfc CALL M */
XX, /* 0xfd [FD page] */
@ -357,6 +384,45 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
set_flags(temporary_.bytes.low);
break;
#define set_parity(v) \
parity_overflow_flag_ = v^1;\
parity_overflow_flag_ ^= parity_overflow_flag_ >> 4;\
parity_overflow_flag_ ^= parity_overflow_flag_ << 2;\
parity_overflow_flag_ ^= parity_overflow_flag_ >> 1;\
parity_overflow_flag_ &= Flag::Parity;
case MicroOp::And:
a_ &= *(uint8_t *)operation->source;
sign_result_ = zero_result_ = bit5_result_ = bit3_result_ = a_;
parity_overflow_flag_ = 0;
set_parity(a_);
break;
case MicroOp::Or:
a_ |= *(uint8_t *)operation->source;
sign_result_ = zero_result_ = bit5_result_ = bit3_result_ = a_;
parity_overflow_flag_ = 0;
set_parity(a_);
break;
case MicroOp::Xor:
a_ ^= *(uint8_t *)operation->source;
sign_result_ = zero_result_ = bit5_result_ = bit3_result_ = a_;
parity_overflow_flag_ = 0;
set_parity(a_);
break;
#undef set_parity
case MicroOp::TestNZ: if(!zero_result_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestZ: if(zero_result_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestNC: if(carry_flag_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestC: if(!carry_flag_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestPO: if(parity_overflow_flag_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestPE: if(!parity_overflow_flag_) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestP: if(sign_result_ & 0x80) { move_to_next_program(); checkSchedule(); } break;
case MicroOp::TestM: if(!(sign_result_ & 0x80)) { move_to_next_program(); checkSchedule(); } break;
default:
printf("Unhandled Z80 operation %d\n", operation->type);
return;
@ -384,13 +450,14 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
*/
uint8_t get_flags() {
return
carry_flag_ |
(sign_result_ & Flag::Sign) |
(zero_result_ ? 0 : Flag::Zero) |
(bit5_result_ & Flag::Bit5) |
half_carry_flag_ |
(bit3_result_ & Flag::Bit3) |
parity_overflow_flag_ |
subtract_flag_;
subtract_flag_ |
carry_flag_;
}
/*!
@ -401,13 +468,14 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
@param flags The new value of the flags register.
*/
void set_flags(uint8_t flags) {
carry_flag_ = flags & Flag::Carry;
sign_result_ = flags;
zero_result_ = (flags & Flag::Zero) ^ Flag::Zero;
bit5_result_ = flags;
half_carry_flag_ = flags & Flag::HalfCarry;
bit3_result_ = flags;
parity_overflow_flag_ = flags & Flag::Parity;
subtract_flag_ = flags & Flag::Subtract;
carry_flag_ = flags & Flag::Carry;
}
/*!

View File

@ -16,9 +16,10 @@ AllRAMProcessor::AllRAMProcessor() : ::CPU::AllRAMProcessor(65536) {}
int AllRAMProcessor::perform_machine_cycle(const MachineCycle *cycle) {
switch(cycle->operation) {
case BusOperation::ReadOpcode:
printf("! ");
check_address_for_trap(*cycle->address);
case BusOperation::Read:
printf("r %04x\n", *cycle->address);
printf("r %04x [%02x]\n", *cycle->address, memory_[*cycle->address]);
*cycle->value = memory_[*cycle->address];
break;
case BusOperation::Write: