mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-09 15:39:08 +00:00
Filled in most of the loads.
This commit is contained in:
parent
bc3b5f3e35
commit
6766845e21
@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user