Skip to content

Commit

Permalink
Merge pull request #30 from kosarev/kosarev/issue27_z80_variants
Browse files Browse the repository at this point in the history
[#27] Support CMOS Z80 chips.
  • Loading branch information
kosarev authored Aug 24, 2021
2 parents a1ebf66 + d077bd7 commit 59d415f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 11 deletions.
68 changes: 62 additions & 6 deletions tests/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ using z80::fast_u32;
using z80::least_u8;
using z80::reg;
using z80::unreachable;
using z80::unused;
using z80::z80_variant;

static const std::size_t max_line_size = 1024;

Expand Down Expand Up @@ -160,7 +162,7 @@ class test_context {

void handle_end_of_test_entry() {
if(in_skipping_mode)
error("this line is expected, but not found");
input.error("this line is expected, but not found");

in_skipping_mode = false;
}
Expand Down Expand Up @@ -277,6 +279,11 @@ class i8080_disasm : public disasm_base<z80::i8080_disasm<i8080_disasm>> {
bool depends_on_iregp_kind() const {
return false;
}

[[noreturn]] void set_variant(z80_variant v, const test_input &input) {
unused(v);
input.error("unsupported variant");
}
};

class z80_disasm : public disasm_base<z80::z80_disasm<z80_disasm>> {
Expand Down Expand Up @@ -307,8 +314,18 @@ class z80_disasm : public disasm_base<z80::z80_disasm<z80_disasm>> {
base::on_disassemble();
}

void set_variant(z80_variant v, const test_input &input) {
unused(&input);
variant = v;
}

z80_variant on_get_z80_variant() const {
return variant;
}

private:
bool does_depend_on_iregp_kind = false;
z80_variant variant = z80_variant::common;
};

template<typename B>
Expand Down Expand Up @@ -814,6 +831,11 @@ class i8080_machine : public machine_base<z80::i8080_cpu<i8080_machine>> {
base::on_step();
context.match("done", static_cast<unsigned>(get_ticks()));
}

[[noreturn]] void set_variant(z80_variant v, const test_input &input) {
unused(v);
input.error("unsupported variant");
}
};

class z80_machine : public machine_base<z80::z80_cpu<z80_machine>> {
Expand Down Expand Up @@ -851,6 +873,18 @@ class z80_machine : public machine_base<z80::z80_cpu<z80_machine>> {

context.match("done", static_cast<unsigned>(get_ticks()));
}

void set_variant(z80_variant v, const test_input &input) {
unused(&input);
variant = v;
}

z80_variant on_get_z80_variant() const {
return variant;
}

private:
z80_variant variant = z80_variant::common;
};

int translate_hex_digit(char c) {
Expand Down Expand Up @@ -921,13 +955,34 @@ bool parse_set_r_directive(const char *r, fast_u8 &n,
return true;
}

template<typename M>
void handle_directive(const test_input &input, M &mach) {
bool parse_z80_variant_directive(z80_variant &variant,
const test_input &input) {
const char *p = input.get_line();
if(!parse(p, ".z80_variant="))
return false;

if(std::strcmp(p, "common") == 0)
variant = z80_variant::common;
else if(std::strcmp(p, "cmos") == 0)
variant = z80_variant::cmos;
else
input.error("unknown Z80 variant '%s'", p);
return true;
}

template<typename M, typename D>
void handle_directive(M &mach, D &dis, const test_input &input) {
fast_u8 n;
z80_variant variant;
if(parse_set_r_directive("b", n, input))
return mach.set_b(n);
if(parse_set_r_directive("c", n, input))
return mach.set_c(n);
if(parse_z80_variant_directive(variant, input)) {
mach.set_variant(variant, input);
dis.set_variant(variant, input);
return;
}

input.error("unknown directive");
}
Expand All @@ -945,11 +1000,13 @@ void handle_test_entry(test_context &context) {

test_input &input = context.get_input();

// Handle directives.
machine mach(context);
disasm dis(input);

// Handle directives.
const char *p = input.get_line();
while(*p == '.') {
handle_directive(input, mach);
handle_directive(mach, dis, input);
p = input.read_line();
}

Expand All @@ -966,7 +1023,6 @@ void handle_test_entry(test_context &context) {
skip_whitespace(p);

// Test instruction disassembly.
disasm dis(input);
dis.set_encoding(encoding);
dis.on_disassemble();
const char *instr = dis.get_output();
Expand Down
20 changes: 17 additions & 3 deletions tests/tests_z80
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,20 @@ dded61 (db 0xdd), out (c), h
16 set_index_rp ix -> hl
16 done

# NMOS and CMOS versions of OUT (C), 0
ed71 out (c), 0x00
...
8 output 00 at 0000
...
12 done

.z80_variant=cmos
ed71 out (c), 0xff
...
8 output ff at 0000
...
12 done

# Block input.
edb2 inir
0 m1_fetch
Expand Down Expand Up @@ -3863,7 +3877,7 @@ dded6d (db 0xdd), xretn 0xed6d
dded6e (db 0xdd), xim 0xed6e, 0
dded6f (db 0xdd), rld
dded70 (db 0xdd), in (c)
dded71 (db 0xdd), out (c), 0
dded71 (db 0xdd), out (c), 0x00
dded72 (db 0xdd), sbc hl, sp
dded730000 (db 0xdd), ld (0x0000), sp
dded74 (db 0xdd), xneg 0xed74
Expand Down Expand Up @@ -4157,7 +4171,7 @@ ed6d xretn 0xed6d
ed6e xim 0xed6e, 0
ed6f rld
ed70 in (c)
ed71 out (c), 0
ed71 out (c), 0x00
ed72 sbc hl, sp
ed730000 ld (0x0000), sp
ed74 xneg 0xed74
Expand Down Expand Up @@ -4927,7 +4941,7 @@ fded6d (db 0xfd), xretn 0xed6d
fded6e (db 0xfd), xim 0xed6e, 0
fded6f (db 0xfd), rld
fded70 (db 0xfd), in (c)
fded71 (db 0xfd), out (c), 0
fded71 (db 0xfd), out (c), 0x00
fded72 (db 0xfd), sbc hl, sp
fded730000 (db 0xfd), ld (0x0000), sp
fded74 (db 0xfd), xneg 0xed74
Expand Down
20 changes: 18 additions & 2 deletions z80.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ enum class block_out { outi, outd, otir, otdr };

enum class condition { nz, z, nc, c, po, pe, p, m };

enum class z80_variant {
common,
cmos, // Newer chips.
};

// Entities for internal needs of the library.
class internals {
private:
Expand Down Expand Up @@ -507,6 +512,16 @@ class root {
unused(op);
self().on_retn(); }

z80_variant on_get_z80_variant() {
return z80_variant::common; }

fast_u8 on_get_out_c_r_op() {
switch(self().on_get_z80_variant()) {
case z80_variant::common: return 0;
case z80_variant::cmos: return 0xff;
}
unreachable("Unknown Z80 variant."); }

protected:
const derived &self() const{ return static_cast<const derived&>(*this); }
derived &self() { return static_cast<derived&>(*this); }
Expand Down Expand Up @@ -1738,7 +1753,7 @@ class z80_disasm
self().on_format("neg"); }
void on_out_c_r(reg r) {
if(r == reg::at_hl)
self().on_format("out (c), 0");
self().on_format("out (c), N", self().on_get_out_c_r_op());
else
self().on_format("out (c), R", r, iregp::hl, 0); }
void on_out_n_a(fast_u8 n) {
Expand Down Expand Up @@ -3601,7 +3616,8 @@ class z80_executor : public internals::executor_base<B> {
fast_u16 bc = self().on_get_bc();
self().on_set_wz(inc16(bc));
fast_u8 n = (r == reg::at_hl) ?
0 : self().on_get_reg(r, iregp::hl, /* d= */ 0);
self().on_get_out_c_r_op() :
self().on_get_reg(r, iregp::hl, /* d= */ 0);
self().on_output_cycle(bc, n); }
void on_out_n_a(fast_u8 n) {
fast_u8 a = self().on_get_a();
Expand Down

0 comments on commit 59d415f

Please sign in to comment.