summaryrefslogtreecommitdiff
path: root/test/test.rs
blob: 856db45da2ff1361525fc10c517bfab74f75ef1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use std::fmt::Write;

extern crate yaxpeax_arch;
extern crate yaxpeax_sm83;

use yaxpeax_arch::{AddressBase, Decoder, LengthedInstruction};
use yaxpeax_sm83::InstDecoder;

fn test_invalid(data: &[u8]) {
    test_invalid_under(&InstDecoder::default(), data);
}

fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) {
    if let Ok(inst) = decoder.decode(data.into_iter().cloned()) {
        panic!("decoded {:?} from {:02x?}", inst.opcode(), data);
    } else {
        // this is fine
    }
}

fn test_display(data: &[u8], expected: &'static str) {
    test_display_under(&InstDecoder::default(), data, expected);
}

fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str) {
    let mut hex = String::new();
    for b in data {
        write!(hex, "{:02x}", b).unwrap();
    }
    match decoder.decode(data.into_iter().map(|x| *x)) {
        Ok(instr) => {
            let text = format!("{}", instr);
            assert!(
                text == expected,
                "display error for {}:\n  decoded: {:?}\n displayed: {}\n expected: {}\n",
                hex,
                instr,
                text,
                expected
            );
            // while we're at it, test that the instruction is as long, and no longer, than its
            // input
            assert_eq!((0u16.wrapping_offset(instr.len()).to_linear()) as usize, data.len(), "instruction length is incorrect, wanted instruction {}", expected);
        },
        Err(e) => {
            assert!(false, "decode error ({}) for {}:\n  expected: {}\n", e, hex, expected);
        }
    }
}

#[test]
fn test_invalid_ops() {
    test_invalid(&[0xd3]);
    test_invalid(&[0xdb]);
    test_invalid(&[0xdd]);
    test_invalid(&[0xe3]);
    test_invalid(&[0xe4]);
    test_invalid(&[0xeb]);
    test_invalid(&[0xec]);
    test_invalid(&[0xed]);
    test_invalid(&[0xf4]);
    test_invalid(&[0xfc]);
    test_invalid(&[0xfd]);
}

#[test]
fn test_ld_decode() {
    test_display(&[0x6f], "ld l, a");
    test_display(&[0x6e], "ld l, [hl]");
    test_display(&[0x32], "ld [hl-], a");
    test_display(&[0x3a], "ld a, [hl-]");
    test_display(&[0x73], "ld [hl], e");
    test_display(&[0x74], "ld [hl], h");
    test_display(&[0x67], "ld h, a");
    test_display(&[0x79], "ld a, c");
    test_display(&[0x52], "ld d, d");
    test_display(&[0x64], "ld h, h");
    test_display(&[0x0e, 0x75], "ld c, $75");
    test_display(&[0x3e, 0x75], "ld a, $75");
    test_display(&[0x01, 0x99, 0x88], "ld bc, $8899");
    test_display(&[0x11, 0x99, 0x88], "ld de, $8899");
    test_display(&[0x21, 0x99, 0x88], "ld hl, $8899");
    test_display(&[0x31, 0x99, 0x88], "ld sp, $8899");
    test_display(&[0xea, 0x34, 0x12], "ld [$1234], a");
}

#[test]
fn test_push_pop() {
    test_display(&[0xf1], "pop af");
    test_display(&[0xe1], "pop hl");
    test_display(&[0xe5], "push hl");
}

#[test]
fn test_control_flow() {
    test_display(&[0xc3, 0x10, 0x20], "jp $2010");       // should this be relative?
    test_display(&[0xda, 0x10, 0x20], "jp C, $2010");    // should this be relative?
    test_display(&[0x20, 0x33], "jr nZ, $+$33");
    test_display(&[0xd9], "reti");
    test_display(&[0xc9], "ret");
    test_display(&[0x00], "nop");
    test_display(&[0xcd, 0x44, 0x66], "call $6644");       // not relative, right
    test_display(&[0xfe, 0x10], "cp $10");
    test_display(&[0xb8], "cp b");
}

#[test]
fn test_arithmetic() {
    test_display(&[0xce, 0x40], "adc $40");
    test_display(&[0x19], "add hl, de");
    test_display(&[0x81], "add c");
    test_display(&[0x83], "add e");
    test_display(&[0x88], "adc b");
    test_display(&[0x89], "adc c");
    test_display(&[0x99], "sbc c");
    test_display(&[0x9d], "sbc l");
    test_display(&[0x91], "sub c");
    test_display(&[0x0c], "inc c");
    test_display(&[0x0d], "dec c");
    test_display(&[0x2d], "dec l");
}

#[test]
fn test_bitwise() {
    test_display(&[0xb5], "or l");
    test_display(&[0xf6, 0x10], "or $10");
    test_display(&[0xcb, 0x71], "bit 6, c");
    test_display(&[0xaf], "xor a");
    test_display(&[0x2b], "dec hl");
    test_display(&[0x34], "inc [hl]");
}

#[test]
fn test_misc() {
    test_display(&[0x37], "scf");
    test_display(&[0x10], "stop");
}