GB/CPU/LR35902 扩展指令集

标准的算术逻辑指令通常将结果写回到寄存器 A. 它们所完成任务可以用如下语言描述: 从寄存器 A 拿出数据, 进行一些算术逻辑运算后再重新放回寄存器 A. 想象一下下面这个需求: 对寄存器 B 内存储的数据右移一位. 如下的操作步骤是一个可行的方案:

  1. 将寄存器 A 的值保存到内存中.
  2. 将寄存器 B 的值保存到寄存器 A.
  3. 将寄存器 A 右移一位.
  4. 将寄存器 A 的值保存到寄存器 B.
  5. 将第一步保存的值写回寄存器 A.

这样操作显得有点麻烦, 如果可以直接对寄存器 B 的数据进行位移运算就好了! 但是 LR35902 是 8 位 CPU, 因此如果使用一个 Byte 来表示一个操作码的话, 其最多只允许表示 2^8 = 256 个指令, 如果读者曾注意上一节中标准指令集的操作码个数的话, 会发现单单标准指令集就已经有接近 256 个了. 现在已经没有足够的空位来为不同的寄存器都实现算术逻辑指令, 那么, 是否可以将指令扩展到两个 Byte?

什么是扩展指令集

扩展指令集是指为 CPU 增加新的指令集, 这些扩展指令可以提高 CPU 处理数学运算的能力. 在现代 CPU 中, 常见的有 MMX, SSE 等扩展指令集. 一个早期的比较著名的扩展指令集出现在上世纪 70 年代的街机游戏太空侵略者(其游戏画面如下图所示), 该街机使用 Intel 8080 CPU, 但 Intel 8080 CPU 的标准指令集不带数字的移位指令, 因此该街机选择通过外接硬件电路, 通过 CPU I/O 串口来实现移位操作.

img

LR35902 的扩展指令大小是两个 Byte, 其中第一个 Byte 固定是 0xcb. 因此在实现过程中, 如果发现取得的指令是 0xcb, 则需要继续取一个 Byte. 代码实现如下:

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                ...
            }
        }
        ...
    }
}

下面给出了扩展指令的摘要以及仿真实现. 如果该指令影响了标志位, 则会在指令描述中指明.

循环和移位操作

RLC r8

1) 描述

目标寄存器按位左移. 最高位移动至溢出标志位.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 原始值的最高位.

3) 指令

InstructionParametersOpcodeCycles
RLCB008
RLCC018
RLCD028
RLCE038
RLCH048
RLCL058
RLC(HL)0616
RLCA078

4) 代码实现

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x00 => self.reg.b = self.alu_rlc(self.reg.b),
                0x01 => self.reg.c = self.alu_rlc(self.reg.c),
                0x02 => self.reg.d = self.alu_rlc(self.reg.d),
                0x03 => self.reg.e = self.alu_rlc(self.reg.e),
                0x04 => self.reg.h = self.alu_rlc(self.reg.h),
                0x05 => self.reg.l = self.alu_rlc(self.reg.l),
                0x06 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_rlc(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x07 => self.reg.a = self.alu_rlc(self.reg.a),
                ...
            }
        }
        ...
    }
}

RRC r8

1) 描述

目标寄存器按位右移. 最低位移动至溢出标志位.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 原始值的最低位

3) 指令

InstructionParametersOpcodeCycles
RRCB088
RRCC098
RRCD0a8
RRCE0b8
RRCH0c8
RRCL0d8
RRC(HL)0e16
RRCA0f8

4) 代码实现

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x08 => self.reg.b = self.alu_rrc(self.reg.b),
                0x09 => self.reg.c = self.alu_rrc(self.reg.c),
                0x0a => self.reg.d = self.alu_rrc(self.reg.d),
                0x0b => self.reg.e = self.alu_rrc(self.reg.e),
                0x0c => self.reg.h = self.alu_rrc(self.reg.h),
                0x0d => self.reg.l = self.alu_rrc(self.reg.l),
                0x0e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_rrc(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x0f => self.reg.a = self.alu_rrc(self.reg.a),
                ...
            }
        }
        ...
    }
}

RL r8

1) 描述

目标寄存器按位左移运算. 溢出标志位补充最低位, 同时最高位移动至溢出标志位.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 原始值的最高位.

3) 指令

InstructionParametersOpcodeCycles
RLB108
RLC118
RLD128
RLE138
RLH148
RLL158
RL(HL)1616
RLA178

4) 代码实现

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x10 => self.reg.b = self.alu_rl(self.reg.b),
                0x11 => self.reg.c = self.alu_rl(self.reg.c),
                0x12 => self.reg.d = self.alu_rl(self.reg.d),
                0x13 => self.reg.e = self.alu_rl(self.reg.e),
                0x14 => self.reg.h = self.alu_rl(self.reg.h),
                0x15 => self.reg.l = self.alu_rl(self.reg.l),
                0x16 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_rl(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x17 => self.reg.a = self.alu_rl(self.reg.a),
                ...
            }
        }
        ...
    }
}

RR r8

1) 描述

目标寄存器按位右移运算. 溢出标志位移动至最高位, 同时最低位移动至溢出标志位.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 原始数据最低位

3) 指令

InstructionParametersOpcodeCycles
RRB188
RRC198
RRD1a8
RRE1b8
RRH1c8
RRL1d8
RR(HL)1e16
RRA1f8

4) 代码实现

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x18 => self.reg.b = self.alu_rr(self.reg.b),
                0x19 => self.reg.c = self.alu_rr(self.reg.c),
                0x1a => self.reg.d = self.alu_rr(self.reg.d),
                0x1b => self.reg.e = self.alu_rr(self.reg.e),
                0x1c => self.reg.h = self.alu_rr(self.reg.h),
                0x1d => self.reg.l = self.alu_rr(self.reg.l),
                0x1e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_rr(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x1f => self.reg.a = self.alu_rr(self.reg.a),
                ...
            }
        }
        ...
    }
}

SLA r8

1) 描述

目标寄存器按位左移运算. 最高位移动至溢出标志位, 最低位设置为零.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 原始数据最高位

3) 指令

InstructionParametersOpcodeCycles
SLAB208
SLAC218
SLAD228
SLAE238
SLAH248
SLAL258
SLA(HL)2616
SLAA278

4) 代码实现

impl Cpu {
    // Shift n left into Carry. LSB of n set to 0.
    // n = A,B,C,D,E,H,L,(HL)
    //
    // Flags affected:
    // Z - Set if result is zero.
    // N - Reset.
    // H - Reset.
    // C - Contains old bit 7 data
    fn alu_sla(&mut self, a: u8) -> u8 {
        let c = (a & 0x80) >> 7 == 0x01;
        let r = a << 1;
        self.reg.set_flag(C, c);
        self.reg.set_flag(H, false);
        self.reg.set_flag(N, false);
        self.reg.set_flag(Z, r == 0x00);
        r
    }
}

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x20 => self.reg.b = self.alu_sla(self.reg.b),
                0x21 => self.reg.c = self.alu_sla(self.reg.c),
                0x22 => self.reg.d = self.alu_sla(self.reg.d),
                0x23 => self.reg.e = self.alu_sla(self.reg.e),
                0x24 => self.reg.h = self.alu_sla(self.reg.h),
                0x25 => self.reg.l = self.alu_sla(self.reg.l),
                0x26 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_sla(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x27 => self.reg.a = self.alu_sla(self.reg.a),
                ...
            }
        }
        ...
    }
}

SRA r8

1) 描述

目标寄存器按位右移运算. 最低位保存入溢出标志位, 最高位保持不变.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 原始数据最低位

3) 指令

InstructionParametersOpcodeCycles
SRAB288
SRAC298
SRAD2a8
SRAE2b8
SRAH2c8
SRAL2d8
SRA(HL)2e16
SRAA2f8

4) 代码实现

impl Cpu {
    // Shift n right into Carry. MSB doesn't change.
    // n = A,B,C,D,E,H,L,(HL)
    //
    // Flags affected:
    // Z - Set if result is zero.
    // N - Reset.
    // H - Reset.
    // C - Contains old bit 0 data.
    fn alu_sra(&mut self, a: u8) -> u8 {
        let c = a & 0x01 == 0x01;
        let r = (a >> 1) | (a & 0x80);
        self.reg.set_flag(C, c);
        self.reg.set_flag(H, false);
        self.reg.set_flag(N, false);
        self.reg.set_flag(Z, r == 0x00);
        r
    }
}

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x28 => self.reg.b = self.alu_sra(self.reg.b),
                0x29 => self.reg.c = self.alu_sra(self.reg.c),
                0x2a => self.reg.d = self.alu_sra(self.reg.d),
                0x2b => self.reg.e = self.alu_sra(self.reg.e),
                0x2c => self.reg.h = self.alu_sra(self.reg.h),
                0x2d => self.reg.l = self.alu_sra(self.reg.l),
                0x2e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_sra(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x2f => self.reg.a = self.alu_sra(self.reg.a),
                ...
            }
        }
        ...
    }
}

SRL r8

1) 描述

目标寄存器按位右移运算. 最低位移动至溢出标志位, 最高位置零.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 原始数据最低位

3) 指令

InstructionParametersOpcodeCycles
SRLB388
SRLC398
SRLD3a8
SRLE3b8
SRLH3c8
SRLL3d8
SRL(HL)3e16
SRLA3f8

4) 代码实现

impl Cpu {
    // Shift n right into Carry. MSB set to 0.
    // n = A,B,C,D,E,H,L,(HL)
    //
    // Flags affected:
    // Z - Set if result is zero.
    // N - Reset.
    // H - Reset.
    // C - Contains old bit 0 data.
    fn alu_srl(&mut self, a: u8) -> u8 {
        let c = a & 0x01 == 0x01;
        let r = a >> 1;
        self.reg.set_flag(C, c);
        self.reg.set_flag(H, false);
        self.reg.set_flag(N, false);
        self.reg.set_flag(Z, r == 0x00);
        r
    }
}

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x38 => self.reg.b = self.alu_srl(self.reg.b),
                0x39 => self.reg.c = self.alu_srl(self.reg.c),
                0x3a => self.reg.d = self.alu_srl(self.reg.d),
                0x3b => self.reg.e = self.alu_srl(self.reg.e),
                0x3c => self.reg.h = self.alu_srl(self.reg.h),
                0x3d => self.reg.l = self.alu_srl(self.reg.l),
                0x3e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_srl(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x3f => self.reg.a = self.alu_srl(self.reg.a),
                ...
            }
        }
        ...
    }
}

交换

SWAP r8

1) 描述

交换目标寄存器高 4 位与低 4 位的比特.

2) 标志位变化

  • Z - 计算结果为零, 则置位
  • N - 置零
  • H - 置零
  • C - 置零

3) 指令

InstructionParametersOpcodeCycles
SWAPB308
SWAPC318
SWAPD328
SWAPE338
SWAPH348
SWAPL358
SWAP(HL)3616
SWAPA378

4) 代码实现

impl Cpu {
    // Swap upper & lower nibles of n.
    // n = A,B,C,D,E,H,L,(HL)
    //
    // Flags affected:
    // Z - Set if result is zero.
    // N - Reset.
    // H - Reset.
    // C - Reset.
    fn alu_swap(&mut self, a: u8) -> u8 {
        self.reg.set_flag(C, false);
        self.reg.set_flag(H, false);
        self.reg.set_flag(N, false);
        self.reg.set_flag(Z, a == 0x00);
        (a >> 4) | (a << 4)
    }
}

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x30 => self.reg.b = self.alu_swap(self.reg.b),
                0x31 => self.reg.c = self.alu_swap(self.reg.c),
                0x32 => self.reg.d = self.alu_swap(self.reg.d),
                0x33 => self.reg.e = self.alu_swap(self.reg.e),
                0x34 => self.reg.h = self.alu_swap(self.reg.h),
                0x35 => self.reg.l = self.alu_swap(self.reg.l),
                0x36 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_swap(v);
                    self.mem.borrow_mut().set(a, h);
                }
                0x37 => self.reg.a = self.alu_swap(self.reg.a),
                ...
            }
        }
        ...
    }
}

位数据获取与设置

BIT

1) 描述

取得目标寄存器中指定的 bit 位.

2) 标志位变化

  • Z - 如果指定寄存器的指定 bit 位为零, 则置零.
  • N - 置零
  • H - 置位
  • C - 保持不变

3) 指令

InstructionParametersOpcodeCycles
BITB, 0408
BITC, 0418
BITD, 0428
BITE, 0438
BITH, 0448
BITL, 0458
BIT(HL), 04616
BITA, 0478
BITB, 1488
BITC, 1498
BITD, 14a8
BITE, 14b8
BITH, 14c8
BITL, 14d8
BIT(HL), 14e16
BITA, 14f8
BITB, 2508
BITC, 2518
BITD, 2528
BITE, 2538
BITH, 2548
BITL, 2558
BIT(HL), 25616
BITA, 2578
BITB, 3588
BITC, 3598
BITD, 35a8
BITE, 35b8
BITH, 35c8
BITL, 35d8
BIT(HL), 35e16
BITA, 35f8
BITB, 4608
BITC, 4618
BITD, 4628
BITE, 4638
BITH, 4648
BITL, 4658
BIT(HL), 46616
BITA, 4678
BITB, 5688
BITC, 5698
BITD, 56a8
BITE, 56b8
BITH, 56c8
BITL, 56d8
BIT(HL), 56e16
BITA, 56f8
BITB, 6708
BITC, 6718
BITD, 6728
BITE, 6738
BITH, 6748
BITL, 6758
BIT(HL), 67616
BITA, 6778
BITB, 7788
BITC, 7798
BITD, 77a8
BITE, 77b8
BITH, 77c8
BITL, 77d8
BIT(HL), 77e16
BITA, 77f8

4) 代码实现

impl Cpu {
    // Test bit b in register r.
    // b = 0 - 7, r = A,B,C,D,E,H,L,(HL)
    //
    // Flags affected:
    // Z - Set if bit b of register r is 0.
    // N - Reset.
    // H - Set.
    // C - Not affected
    fn alu_bit(&mut self, a: u8, b: u8) {
        let r = a & (1 << b) == 0x00;
        self.reg.set_flag(H, true);
        self.reg.set_flag(N, false);
        self.reg.set_flag(Z, r);
    }
}

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x40 => self.alu_bit(self.reg.b, 0),
                0x41 => self.alu_bit(self.reg.c, 0),
                0x42 => self.alu_bit(self.reg.d, 0),
                0x43 => self.alu_bit(self.reg.e, 0),
                0x44 => self.alu_bit(self.reg.h, 0),
                0x45 => self.alu_bit(self.reg.l, 0),
                0x46 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 0);
                }
                0x47 => self.alu_bit(self.reg.a, 0),
                0x48 => self.alu_bit(self.reg.b, 1),
                0x49 => self.alu_bit(self.reg.c, 1),
                0x4a => self.alu_bit(self.reg.d, 1),
                0x4b => self.alu_bit(self.reg.e, 1),
                0x4c => self.alu_bit(self.reg.h, 1),
                0x4d => self.alu_bit(self.reg.l, 1),
                0x4e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 1);
                }
                0x4f => self.alu_bit(self.reg.a, 1),
                0x50 => self.alu_bit(self.reg.b, 2),
                0x51 => self.alu_bit(self.reg.c, 2),
                0x52 => self.alu_bit(self.reg.d, 2),
                0x53 => self.alu_bit(self.reg.e, 2),
                0x54 => self.alu_bit(self.reg.h, 2),
                0x55 => self.alu_bit(self.reg.l, 2),
                0x56 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 2);
                }
                0x57 => self.alu_bit(self.reg.a, 2),
                0x58 => self.alu_bit(self.reg.b, 3),
                0x59 => self.alu_bit(self.reg.c, 3),
                0x5a => self.alu_bit(self.reg.d, 3),
                0x5b => self.alu_bit(self.reg.e, 3),
                0x5c => self.alu_bit(self.reg.h, 3),
                0x5d => self.alu_bit(self.reg.l, 3),
                0x5e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 3);
                }
                0x5f => self.alu_bit(self.reg.a, 3),
                0x60 => self.alu_bit(self.reg.b, 4),
                0x61 => self.alu_bit(self.reg.c, 4),
                0x62 => self.alu_bit(self.reg.d, 4),
                0x63 => self.alu_bit(self.reg.e, 4),
                0x64 => self.alu_bit(self.reg.h, 4),
                0x65 => self.alu_bit(self.reg.l, 4),
                0x66 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 4);
                }
                0x67 => self.alu_bit(self.reg.a, 4),
                0x68 => self.alu_bit(self.reg.b, 5),
                0x69 => self.alu_bit(self.reg.c, 5),
                0x6a => self.alu_bit(self.reg.d, 5),
                0x6b => self.alu_bit(self.reg.e, 5),
                0x6c => self.alu_bit(self.reg.h, 5),
                0x6d => self.alu_bit(self.reg.l, 5),
                0x6e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 5);
                }
                0x6f => self.alu_bit(self.reg.a, 5),
                0x70 => self.alu_bit(self.reg.b, 6),
                0x71 => self.alu_bit(self.reg.c, 6),
                0x72 => self.alu_bit(self.reg.d, 6),
                0x73 => self.alu_bit(self.reg.e, 6),
                0x74 => self.alu_bit(self.reg.h, 6),
                0x75 => self.alu_bit(self.reg.l, 6),
                0x76 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 6);
                }
                0x77 => self.alu_bit(self.reg.a, 6),
                0x78 => self.alu_bit(self.reg.b, 7),
                0x79 => self.alu_bit(self.reg.c, 7),
                0x7a => self.alu_bit(self.reg.d, 7),
                0x7b => self.alu_bit(self.reg.e, 7),
                0x7c => self.alu_bit(self.reg.h, 7),
                0x7d => self.alu_bit(self.reg.l, 7),
                0x7e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    self.alu_bit(v, 7);
                }
                0x7f => self.alu_bit(self.reg.a, 7),
                ...
            }
        }
        ...
    }
}

RES

1) 描述

置零目标寄存器中指定的 bit 位.

2) 标志位变化

3) 指令

InstructionParametersOpcodeCycles
RESB, 0808
RESC, 0818
RESD, 0828
RESE, 0838
RESH, 0848
RESL, 0858
RES(HL), 08616
RESA, 0878
RESB, 1888
RESC, 1898
RESD, 18a8
RESE, 18b8
RESH, 18c8
RESL, 18d8
RES(HL), 18e16
RESA, 18f8
RESB, 2908
RESC, 2918
RESD, 2928
RESE, 2938
RESH, 2948
RESL, 2958
RES(HL), 29616
RESA, 2978
RESB, 3988
RESC, 3998
RESD, 39a8
RESE, 39b8
RESH, 39c8
RESL, 39d8
RES(HL), 39e16
RESA, 39f8
RESB, 4a08
RESC, 4a18
RESD, 4a28
RESE, 4a38
RESH, 4a48
RESL, 4a58
RES(HL), 4a616
RESA, 4a78
RESB, 5a88
RESC, 5a98
RESD, 5aa8
RESE, 5ab8
RESH, 5ac8
RESL, 5ad8
RES(HL), 5ae16
RESA, 5af8
RESB, 6b08
RESC, 6b18
RESD, 6b28
RESE, 6b38
RESH, 6b48
RESL, 6b58
RES(HL), 6b616
RESA, 6b78
RESB, 7b88
RESC, 7b98
RESD, 7ba8
RESE, 7bb8
RESH, 7bc8
RESL, 7bd8
RES(HL), 7be16
RESA, 7bf8

4) 代码实现

impl Cpu {
    // Reset bit b in register r.
    // b = 0 - 7, r = A,B,C,D,E,H,L,(HL)
    //
    // Flags affected:  None.
    fn alu_res(&mut self, a: u8, b: u8) -> u8 {
        a & !(1 << b)
    }
}

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0x80 => self.reg.b = self.alu_res(self.reg.b, 0),
                0x81 => self.reg.c = self.alu_res(self.reg.c, 0),
                0x82 => self.reg.d = self.alu_res(self.reg.d, 0),
                0x83 => self.reg.e = self.alu_res(self.reg.e, 0),
                0x84 => self.reg.h = self.alu_res(self.reg.h, 0),
                0x85 => self.reg.l = self.alu_res(self.reg.l, 0),
                0x86 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 0);
                    self.mem.borrow_mut().set(a, h);
                }
                0x87 => self.reg.a = self.alu_res(self.reg.a, 0),
                0x88 => self.reg.b = self.alu_res(self.reg.b, 1),
                0x89 => self.reg.c = self.alu_res(self.reg.c, 1),
                0x8a => self.reg.d = self.alu_res(self.reg.d, 1),
                0x8b => self.reg.e = self.alu_res(self.reg.e, 1),
                0x8c => self.reg.h = self.alu_res(self.reg.h, 1),
                0x8d => self.reg.l = self.alu_res(self.reg.l, 1),
                0x8e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 1);
                    self.mem.borrow_mut().set(a, h);
                }
                0x8f => self.reg.a = self.alu_res(self.reg.a, 1),
                0x90 => self.reg.b = self.alu_res(self.reg.b, 2),
                0x91 => self.reg.c = self.alu_res(self.reg.c, 2),
                0x92 => self.reg.d = self.alu_res(self.reg.d, 2),
                0x93 => self.reg.e = self.alu_res(self.reg.e, 2),
                0x94 => self.reg.h = self.alu_res(self.reg.h, 2),
                0x95 => self.reg.l = self.alu_res(self.reg.l, 2),
                0x96 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 2);
                    self.mem.borrow_mut().set(a, h);
                }
                0x97 => self.reg.a = self.alu_res(self.reg.a, 2),
                0x98 => self.reg.b = self.alu_res(self.reg.b, 3),
                0x99 => self.reg.c = self.alu_res(self.reg.c, 3),
                0x9a => self.reg.d = self.alu_res(self.reg.d, 3),
                0x9b => self.reg.e = self.alu_res(self.reg.e, 3),
                0x9c => self.reg.h = self.alu_res(self.reg.h, 3),
                0x9d => self.reg.l = self.alu_res(self.reg.l, 3),
                0x9e => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 3);
                    self.mem.borrow_mut().set(a, h);
                }
                0x9f => self.reg.a = self.alu_res(self.reg.a, 3),
                0xa0 => self.reg.b = self.alu_res(self.reg.b, 4),
                0xa1 => self.reg.c = self.alu_res(self.reg.c, 4),
                0xa2 => self.reg.d = self.alu_res(self.reg.d, 4),
                0xa3 => self.reg.e = self.alu_res(self.reg.e, 4),
                0xa4 => self.reg.h = self.alu_res(self.reg.h, 4),
                0xa5 => self.reg.l = self.alu_res(self.reg.l, 4),
                0xa6 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 4);
                    self.mem.borrow_mut().set(a, h);
                }
                0xa7 => self.reg.a = self.alu_res(self.reg.a, 4),
                0xa8 => self.reg.b = self.alu_res(self.reg.b, 5),
                0xa9 => self.reg.c = self.alu_res(self.reg.c, 5),
                0xaa => self.reg.d = self.alu_res(self.reg.d, 5),
                0xab => self.reg.e = self.alu_res(self.reg.e, 5),
                0xac => self.reg.h = self.alu_res(self.reg.h, 5),
                0xad => self.reg.l = self.alu_res(self.reg.l, 5),
                0xae => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 5);
                    self.mem.borrow_mut().set(a, h);
                }
                0xaf => self.reg.a = self.alu_res(self.reg.a, 5),
                0xb0 => self.reg.b = self.alu_res(self.reg.b, 6),
                0xb1 => self.reg.c = self.alu_res(self.reg.c, 6),
                0xb2 => self.reg.d = self.alu_res(self.reg.d, 6),
                0xb3 => self.reg.e = self.alu_res(self.reg.e, 6),
                0xb4 => self.reg.h = self.alu_res(self.reg.h, 6),
                0xb5 => self.reg.l = self.alu_res(self.reg.l, 6),
                0xb6 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 6);
                    self.mem.borrow_mut().set(a, h);
                }
                0xb7 => self.reg.a = self.alu_res(self.reg.a, 6),
                0xb8 => self.reg.b = self.alu_res(self.reg.b, 7),
                0xb9 => self.reg.c = self.alu_res(self.reg.c, 7),
                0xba => self.reg.d = self.alu_res(self.reg.d, 7),
                0xbb => self.reg.e = self.alu_res(self.reg.e, 7),
                0xbc => self.reg.h = self.alu_res(self.reg.h, 7),
                0xbd => self.reg.l = self.alu_res(self.reg.l, 7),
                0xbe => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_res(v, 7);
                    self.mem.borrow_mut().set(a, h);
                }
                0xbf => self.reg.a = self.alu_res(self.reg.a, 7),
                ...
            }
        }
        ...
    }
}

SET

1) 描述

置位寄存器中指定的 bit 位.

2) 标志位变化

3) 指令

InstructionParametersOpcodeCycles
SETB, 0c08
SETC, 0c18
SETD, 0c28
SETE, 0c38
SETH, 0c48
SETL, 0c58
SET(HL), 0c616
SETA, 0c78
SETB, 1c88
SETC, 1c98
SETD, 1ca8
SETE, 1cb8
SETH, 1cc8
SETL, 1cd8
SET(HL), 1ce16
SETA, 1cf8
SETB, 2d08
SETC, 2d18
SETD, 2d28
SETE, 2d38
SETH, 2d48
SETL, 2d58
SET(HL), 2d616
SETA, 2d78
SETB, 3d88
SETC, 3d98
SETD, 3da8
SETE, 3db8
SETH, 3dc8
SETL, 3dd8
SET(HL), 3de16
SETA, 3df8
SETB, 4e08
SETC, 4e18
SETD, 4e28
SETE, 4e38
SETH, 4e48
SETL, 4e58
SET(HL), 4e616
SETA, 4e78
SETB, 5e88
SETC, 5e98
SETD, 5ea8
SETE, 5eb8
SETH, 5ec8
SETL, 5ed8
SET(HL), 5ee16
SETA, 5ef8
SETB, 6f08
SETC, 6f18
SETD, 6f28
SETE, 6f38
SETH, 6f48
SETL, 6f58
SET(HL), 6f616
SETA, 6f78
SETB, 7f88
SETC, 7f98
SETD, 7fa8
SETE, 7fb8
SETH, 7fc8
SETL, 7fd8
SET(HL), 7fe16
SETA, 7ff8

4) 代码实现

impl Cpu {
    // Set bit b in register r.
    // b = 0 - 7, r = A,B,C,D,E,H,L,(HL)
    //
    // Flags affected:  None.
    fn alu_set(&mut self, a: u8, b: u8) -> u8 {
        a | (1 << b)
    }
}

fn ex(&mut self) -> u32 {
    let opcode = self.imm();
    match opcode {
        0xcb => {
            cbcode = self.mem.borrow().get(self.reg.pc);
            self.reg.pc += 1;
            match cbcode {
                0xc0 => self.reg.b = self.alu_set(self.reg.b, 0),
                0xc1 => self.reg.c = self.alu_set(self.reg.c, 0),
                0xc2 => self.reg.d = self.alu_set(self.reg.d, 0),
                0xc3 => self.reg.e = self.alu_set(self.reg.e, 0),
                0xc4 => self.reg.h = self.alu_set(self.reg.h, 0),
                0xc5 => self.reg.l = self.alu_set(self.reg.l, 0),
                0xc6 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 0);
                    self.mem.borrow_mut().set(a, h);
                }
                0xc7 => self.reg.a = self.alu_set(self.reg.a, 0),
                0xc8 => self.reg.b = self.alu_set(self.reg.b, 1),
                0xc9 => self.reg.c = self.alu_set(self.reg.c, 1),
                0xca => self.reg.d = self.alu_set(self.reg.d, 1),
                0xcb => self.reg.e = self.alu_set(self.reg.e, 1),
                0xcc => self.reg.h = self.alu_set(self.reg.h, 1),
                0xcd => self.reg.l = self.alu_set(self.reg.l, 1),
                0xce => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 1);
                    self.mem.borrow_mut().set(a, h);
                }
                0xcf => self.reg.a = self.alu_set(self.reg.a, 1),
                0xd0 => self.reg.b = self.alu_set(self.reg.b, 2),
                0xd1 => self.reg.c = self.alu_set(self.reg.c, 2),
                0xd2 => self.reg.d = self.alu_set(self.reg.d, 2),
                0xd3 => self.reg.e = self.alu_set(self.reg.e, 2),
                0xd4 => self.reg.h = self.alu_set(self.reg.h, 2),
                0xd5 => self.reg.l = self.alu_set(self.reg.l, 2),
                0xd6 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 2);
                    self.mem.borrow_mut().set(a, h);
                }
                0xd7 => self.reg.a = self.alu_set(self.reg.a, 2),
                0xd8 => self.reg.b = self.alu_set(self.reg.b, 3),
                0xd9 => self.reg.c = self.alu_set(self.reg.c, 3),
                0xda => self.reg.d = self.alu_set(self.reg.d, 3),
                0xdb => self.reg.e = self.alu_set(self.reg.e, 3),
                0xdc => self.reg.h = self.alu_set(self.reg.h, 3),
                0xdd => self.reg.l = self.alu_set(self.reg.l, 3),
                0xde => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 3);
                    self.mem.borrow_mut().set(a, h);
                }
                0xdf => self.reg.a = self.alu_set(self.reg.a, 3),
                0xe0 => self.reg.b = self.alu_set(self.reg.b, 4),
                0xe1 => self.reg.c = self.alu_set(self.reg.c, 4),
                0xe2 => self.reg.d = self.alu_set(self.reg.d, 4),
                0xe3 => self.reg.e = self.alu_set(self.reg.e, 4),
                0xe4 => self.reg.h = self.alu_set(self.reg.h, 4),
                0xe5 => self.reg.l = self.alu_set(self.reg.l, 4),
                0xe6 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 4);
                    self.mem.borrow_mut().set(a, h);
                }
                0xe7 => self.reg.a = self.alu_set(self.reg.a, 4),
                0xe8 => self.reg.b = self.alu_set(self.reg.b, 5),
                0xe9 => self.reg.c = self.alu_set(self.reg.c, 5),
                0xea => self.reg.d = self.alu_set(self.reg.d, 5),
                0xeb => self.reg.e = self.alu_set(self.reg.e, 5),
                0xec => self.reg.h = self.alu_set(self.reg.h, 5),
                0xed => self.reg.l = self.alu_set(self.reg.l, 5),
                0xee => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 5);
                    self.mem.borrow_mut().set(a, h);
                }
                0xef => self.reg.a = self.alu_set(self.reg.a, 5),
                0xf0 => self.reg.b = self.alu_set(self.reg.b, 6),
                0xf1 => self.reg.c = self.alu_set(self.reg.c, 6),
                0xf2 => self.reg.d = self.alu_set(self.reg.d, 6),
                0xf3 => self.reg.e = self.alu_set(self.reg.e, 6),
                0xf4 => self.reg.h = self.alu_set(self.reg.h, 6),
                0xf5 => self.reg.l = self.alu_set(self.reg.l, 6),
                0xf6 => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 6);
                    self.mem.borrow_mut().set(a, h);
                }
                0xf7 => self.reg.a = self.alu_set(self.reg.a, 6),
                0xf8 => self.reg.b = self.alu_set(self.reg.b, 7),
                0xf9 => self.reg.c = self.alu_set(self.reg.c, 7),
                0xfa => self.reg.d = self.alu_set(self.reg.d, 7),
                0xfb => self.reg.e = self.alu_set(self.reg.e, 7),
                0xfc => self.reg.h = self.alu_set(self.reg.h, 7),
                0xfd => self.reg.l = self.alu_set(self.reg.l, 7),
                0xfe => {
                    let a = self.reg.get_hl();
                    let v = self.mem.borrow().get(a);
                    let h = self.alu_set(v, 7);
                    self.mem.borrow_mut().set(a, h);
                }
                0xff => self.reg.a = self.alu_set(self.reg.a, 7),
                ...
            }
        }
        ...
    }
}