rustzx_z80/
codegen.rs

1/// Represents memory where opcodes generated by [`CodeGenerator`] will be placed
2pub trait CodegenMemorySpace {
3    fn write_byte(&mut self, addr: u16, byte: u8);
4
5    fn write_word(&mut self, addr: u16, word: u16) {
6        let [l, h] = word.to_le_bytes();
7        self.write_byte(addr, l);
8        self.write_byte(addr, h);
9    }
10}
11
12/// Provides easy methods to generate some Z80 opcodes. Currently only limited
13/// opcode list is supported
14pub struct CodeGenerator<'a, Mem: CodegenMemorySpace> {
15    mem: &'a mut Mem,
16    current_addr: u16,
17}
18
19impl<'a, Mem: CodegenMemorySpace> CodeGenerator<'a, Mem> {
20    pub fn new(mem: &'a mut Mem) -> Self {
21        Self {
22            mem,
23            current_addr: 0x0000,
24        }
25    }
26
27    /// Sets current base address to write opcodes
28    pub fn codegen_set_addr(&mut self, addr: u16) -> &mut Self {
29        self.current_addr = addr;
30        self
31    }
32
33    /// Generates most optimal jump opcode generation from the current address
34    pub fn jump(&mut self, addr: u16) -> &mut Self {
35        // Currently only direct jump method is implemented
36        self.exact_opcode_jump_direct(addr)
37    }
38
39    /// Generates direct jump opcode (0xC3)
40    pub fn exact_opcode_jump_direct(&mut self, addr: u16) -> &mut Self {
41        self.write_byte(0xC3);
42        self.write_word(addr);
43        self
44    }
45
46    fn write_byte(&mut self, byte: u8) {
47        self.mem.write_byte(self.current_addr, byte);
48        self.current_addr += 1;
49    }
50
51    fn write_word(&mut self, word: u16) {
52        let [l, h] = word.to_le_bytes();
53        self.write_byte(l);
54        self.write_byte(h);
55    }
56}