mirror of
https://git.sr.ht/~asya/copycat
synced 2024-11-16 08:18:43 -06:00
Implement a basic IO bus
Implemented in this patch is also more jumps, loop instructions, and the `out` instruction. With this patch, the 5150 BIOS can now checksum itself. Signed-off-by: AsyaTheAbove <asya@waifu.club>
This commit is contained in:
parent
54c6892527
commit
911d6e844b
73
src/io.rs
Normal file
73
src/io.rs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct IoBus {
|
||||||
|
handlers: HashMap<u16, *mut dyn IoHandler>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IoBus {
|
||||||
|
pub fn read<const N: usize>(&mut self, address: u16) -> [u8; N] {
|
||||||
|
let mut buffer = [0; N];
|
||||||
|
for i in 0..N {
|
||||||
|
buffer[i] = unsafe { (*self.handler(address + i as u16)).read(address + i as u16) };
|
||||||
|
}
|
||||||
|
buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write<const N: usize>(&mut self, address: u16, value: [u8; N]) {
|
||||||
|
for i in 0..N {
|
||||||
|
unsafe {
|
||||||
|
(*self.handler(address + i as u16)).write(address + i as u16, value[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u8(&mut self, address: u16) -> u8 {
|
||||||
|
self.read::<1>(address)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u8(&mut self, address: u16, value: u8) {
|
||||||
|
self.write::<1>(address, [value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u16(&mut self, address: u16) -> u16 {
|
||||||
|
u16::from_le_bytes(self.read::<2>(address))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u16(&mut self, address: u16, value: u16) {
|
||||||
|
self.write::<2>(address, value.to_le_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handler(&self, address: u16) -> *mut dyn IoHandler {
|
||||||
|
static mut DEFAULT_IO_HANDLER: DefaultIoHandler = DefaultIoHandler;
|
||||||
|
self.handlers.get(&address)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(unsafe { &mut DEFAULT_IO_HANDLER })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_handler(&mut self, address: u16, size: u16, handler: *mut dyn IoHandler) {
|
||||||
|
for i in address..address + size {
|
||||||
|
self.handlers.insert(address + i, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DefaultIoHandler;
|
||||||
|
impl IoHandler for DefaultIoHandler {}
|
||||||
|
|
||||||
|
pub trait IoHandler {
|
||||||
|
fn read(&mut self, address: u16) -> u8 {
|
||||||
|
u8::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn write(&mut self, address: u16, value: u8) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#![feature(bigint_helper_methods)]
|
#![feature(bigint_helper_methods)]
|
||||||
|
|
||||||
|
pub mod io;
|
||||||
pub mod machine;
|
pub mod machine;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub mod processor;
|
pub mod processor;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use copycat::memory::{Memory, KiB};
|
use copycat::memory::{Memory, KiB};
|
||||||
use copycat::processor::{Instruction, Processor};
|
use copycat::processor::{Instruction, Processor};
|
||||||
|
use copycat::io::IoBus;
|
||||||
|
|
||||||
static BIOS_ROM: &[u8; 8 * KiB as usize] = include_bytes!("../roms/BIOS_IBM5150_24APR81_5700051_U33.BIN");
|
static BIOS_ROM: &[u8; 8 * KiB as usize] = include_bytes!("../roms/BIOS_IBM5150_24APR81_5700051_U33.BIN");
|
||||||
|
|
||||||
|
@ -14,13 +15,14 @@ fn main() {
|
||||||
mem.add_tlb_entry(0xfe, BIOS_ROM.as_ptr().cast_mut().cast());
|
mem.add_tlb_entry(0xfe, BIOS_ROM.as_ptr().cast_mut().cast());
|
||||||
mem.add_tlb_entry(0xff, unsafe { BIOS_ROM.as_ptr().add(4 * KiB as usize) }.cast_mut().cast());
|
mem.add_tlb_entry(0xff, unsafe { BIOS_ROM.as_ptr().add(4 * KiB as usize) }.cast_mut().cast());
|
||||||
// mem.write(0xffff0, [0x90, 0x04, 0x69, 0xF4]);
|
// mem.write(0xffff0, [0x90, 0x04, 0x69, 0xF4]);
|
||||||
|
let mut io = IoBus::default();
|
||||||
let mut cpu = Processor::default();
|
let mut cpu = Processor::default();
|
||||||
cpu.registers.dump();
|
cpu.registers.dump();
|
||||||
|
|
||||||
while !cpu.halted {
|
while !cpu.halted {
|
||||||
let instr = Instruction::decode(&mem, &mut cpu.registers);
|
let instr = Instruction::decode(&mem, &mut cpu.registers);
|
||||||
println!("{instr:?}");
|
println!("{instr:?}");
|
||||||
cpu.exec(&mut mem, &instr);
|
cpu.exec(&mut mem, &mut io, &instr);
|
||||||
cpu.registers.dump();
|
cpu.registers.dump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ pub struct Instruction {
|
||||||
|
|
||||||
impl Instruction {
|
impl Instruction {
|
||||||
pub fn decode(memory: &Memory, registers: &mut Registers) -> Instruction {
|
pub fn decode(memory: &Memory, registers: &mut Registers) -> Instruction {
|
||||||
|
use Mnemonic::*;
|
||||||
|
use OperandFormat::*;
|
||||||
|
|
||||||
let address = ((registers.cs() as u64) << 4) + registers.ip() as u64;
|
let address = ((registers.cs() as u64) << 4) + registers.ip() as u64;
|
||||||
let mut opcode = memory.read_u8(address);
|
let mut opcode = memory.read_u8(address);
|
||||||
let mut size: u8 = 1;
|
let mut size: u8 = 1;
|
||||||
|
@ -43,126 +46,153 @@ impl Instruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mnemonic, op1ty, op2ty) = match opcode {
|
let (mnemonic, op1ty, op2ty) = match opcode {
|
||||||
0x00 => (Mnemonic::Add, OperandFormat::RM8, OperandFormat::Reg8),
|
0x00 => (Add, RM8, Reg8),
|
||||||
0x01 => (Mnemonic::Add, OperandFormat::RM16, OperandFormat::Reg16),
|
0x01 => (Add, RM16, Reg16),
|
||||||
0x02 => (Mnemonic::Add, OperandFormat::Reg8, OperandFormat::RM8),
|
0x02 => (Add, Reg8, RM8),
|
||||||
0x03 => (Mnemonic::Add, OperandFormat::Reg16, OperandFormat::RM16),
|
0x03 => (Add, Reg16, RM16),
|
||||||
0x04 => (Mnemonic::Add, OperandFormat::AL, OperandFormat::Imm8),
|
0x04 => (Add, AL, Imm8),
|
||||||
0x05 => (Mnemonic::Add, OperandFormat::AX, OperandFormat::Imm16),
|
0x05 => (Add, AX, Imm16),
|
||||||
0x08 => (Mnemonic::Or, OperandFormat::RM8, OperandFormat::Reg8),
|
0x08 => (Or, RM8, Reg8),
|
||||||
0x09 => (Mnemonic::Or, OperandFormat::RM16, OperandFormat::Reg16),
|
0x09 => (Or, RM16, Reg16),
|
||||||
0x0A => (Mnemonic::Or, OperandFormat::Reg8, OperandFormat::RM8),
|
0x0A => (Or, Reg8, RM8),
|
||||||
0x0B => (Mnemonic::Or, OperandFormat::Reg16, OperandFormat::RM16),
|
0x0B => (Or, Reg16, RM16),
|
||||||
0x0C => (Mnemonic::Or, OperandFormat::AL, OperandFormat::Imm8),
|
0x0C => (Or, AL, Imm8),
|
||||||
0x0D => (Mnemonic::Or, OperandFormat::AX, OperandFormat::Imm16),
|
0x0D => (Or, AX, Imm16),
|
||||||
0x10 => (Mnemonic::Adc, OperandFormat::RM8, OperandFormat::Reg8),
|
0x10 => (Adc, RM8, Reg8),
|
||||||
0x11 => (Mnemonic::Adc, OperandFormat::RM16, OperandFormat::Reg16),
|
0x11 => (Adc, RM16, Reg16),
|
||||||
0x12 => (Mnemonic::Adc, OperandFormat::Reg8, OperandFormat::RM8),
|
0x12 => (Adc, Reg8, RM8),
|
||||||
0x13 => (Mnemonic::Adc, OperandFormat::Reg16, OperandFormat::RM16),
|
0x13 => (Adc, Reg16, RM16),
|
||||||
0x14 => (Mnemonic::Adc, OperandFormat::AL, OperandFormat::Imm8),
|
0x14 => (Adc, AL, Imm8),
|
||||||
0x15 => (Mnemonic::Adc, OperandFormat::AX, OperandFormat::Imm16),
|
0x15 => (Adc, AX, Imm16),
|
||||||
0x18 => (Mnemonic::Sbb, OperandFormat::RM8, OperandFormat::Reg8),
|
0x18 => (Sbb, RM8, Reg8),
|
||||||
0x19 => (Mnemonic::Sbb, OperandFormat::RM16, OperandFormat::Reg16),
|
0x19 => (Sbb, RM16, Reg16),
|
||||||
0x1A => (Mnemonic::Sbb, OperandFormat::Reg8, OperandFormat::RM8),
|
0x1A => (Sbb, Reg8, RM8),
|
||||||
0x1B => (Mnemonic::Sbb, OperandFormat::Reg16, OperandFormat::RM16),
|
0x1B => (Sbb, Reg16, RM16),
|
||||||
0x1C => (Mnemonic::Sbb, OperandFormat::AL, OperandFormat::Imm8),
|
0x1C => (Sbb, AL, Imm8),
|
||||||
0x1D => (Mnemonic::Sbb, OperandFormat::AX, OperandFormat::Imm16),
|
0x1D => (Sbb, AX, Imm16),
|
||||||
0x28 => (Mnemonic::Sub, OperandFormat::RM8, OperandFormat::Reg8),
|
0x28 => (Sub, RM8, Reg8),
|
||||||
0x29 => (Mnemonic::Sub, OperandFormat::RM16, OperandFormat::Reg16),
|
0x29 => (Sub, RM16, Reg16),
|
||||||
0x2A => (Mnemonic::Sub, OperandFormat::Reg8, OperandFormat::RM8),
|
0x2A => (Sub, Reg8, RM8),
|
||||||
0x2B => (Mnemonic::Sub, OperandFormat::Reg16, OperandFormat::RM16),
|
0x2B => (Sub, Reg16, RM16),
|
||||||
0x2C => (Mnemonic::Sub, OperandFormat::AL, OperandFormat::Imm8),
|
0x2C => (Sub, AL, Imm8),
|
||||||
0x2D => (Mnemonic::Sub, OperandFormat::AX, OperandFormat::Imm16),
|
0x2D => (Sub, AX, Imm16),
|
||||||
0x30 => (Mnemonic::Xor, OperandFormat::RM8, OperandFormat::Reg8),
|
0x30 => (Xor, RM8, Reg8),
|
||||||
0x31 => (Mnemonic::Xor, OperandFormat::RM16, OperandFormat::Reg16),
|
0x31 => (Xor, RM16, Reg16),
|
||||||
0x32 => (Mnemonic::Xor, OperandFormat::Reg8, OperandFormat::RM8),
|
0x32 => (Xor, Reg8, RM8),
|
||||||
0x33 => (Mnemonic::Xor, OperandFormat::Reg16, OperandFormat::RM16),
|
0x33 => (Xor, Reg16, RM16),
|
||||||
0x34 => (Mnemonic::Xor, OperandFormat::AL, OperandFormat::Imm8),
|
0x34 => (Xor, AL, Imm8),
|
||||||
0x35 => (Mnemonic::Xor, OperandFormat::AX, OperandFormat::Imm16),
|
0x35 => (Xor, AX, Imm16),
|
||||||
0x40 => (Mnemonic::Inc, OperandFormat::AX, OperandFormat::NoOperand),
|
0x40 => (Inc, AX, NoOperand),
|
||||||
0x41 => (Mnemonic::Inc, OperandFormat::CX, OperandFormat::NoOperand),
|
0x41 => (Inc, CX, NoOperand),
|
||||||
0x42 => (Mnemonic::Inc, OperandFormat::DX, OperandFormat::NoOperand),
|
0x42 => (Inc, DX, NoOperand),
|
||||||
0x43 => (Mnemonic::Inc, OperandFormat::BX, OperandFormat::NoOperand),
|
0x43 => (Inc, BX, NoOperand),
|
||||||
0x44 => (Mnemonic::Inc, OperandFormat::SP, OperandFormat::NoOperand),
|
0x44 => (Inc, SP, NoOperand),
|
||||||
0x45 => (Mnemonic::Inc, OperandFormat::BP, OperandFormat::NoOperand),
|
0x45 => (Inc, BP, NoOperand),
|
||||||
0x46 => (Mnemonic::Inc, OperandFormat::SI, OperandFormat::NoOperand),
|
0x46 => (Inc, SI, NoOperand),
|
||||||
0x47 => (Mnemonic::Inc, OperandFormat::DI, OperandFormat::NoOperand),
|
0x47 => (Inc, DI, NoOperand),
|
||||||
0x48 => (Mnemonic::Dec, OperandFormat::AX, OperandFormat::NoOperand),
|
0x48 => (Dec, AX, NoOperand),
|
||||||
0x49 => (Mnemonic::Dec, OperandFormat::CX, OperandFormat::NoOperand),
|
0x49 => (Dec, CX, NoOperand),
|
||||||
0x4A => (Mnemonic::Dec, OperandFormat::DX, OperandFormat::NoOperand),
|
0x4A => (Dec, DX, NoOperand),
|
||||||
0x4B => (Mnemonic::Dec, OperandFormat::BX, OperandFormat::NoOperand),
|
0x4B => (Dec, BX, NoOperand),
|
||||||
0x4C => (Mnemonic::Dec, OperandFormat::SP, OperandFormat::NoOperand),
|
0x4C => (Dec, SP, NoOperand),
|
||||||
0x4D => (Mnemonic::Dec, OperandFormat::BP, OperandFormat::NoOperand),
|
0x4D => (Dec, BP, NoOperand),
|
||||||
0x4E => (Mnemonic::Dec, OperandFormat::SI, OperandFormat::NoOperand),
|
0x4E => (Dec, SI, NoOperand),
|
||||||
0x4F => (Mnemonic::Dec, OperandFormat::DI, OperandFormat::NoOperand),
|
0x4F => (Dec, DI, NoOperand),
|
||||||
0x70 => (Mnemonic::Jo, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x70 => (Jo, Imm8, NoOperand),
|
||||||
0x71 => (Mnemonic::Jno, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x71 => (Jno, Imm8, NoOperand),
|
||||||
0x72 => (Mnemonic::Jc, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x72 => (Jc, Imm8, NoOperand),
|
||||||
0x73 => (Mnemonic::Jnc, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x73 => (Jnc, Imm8, NoOperand),
|
||||||
0x74 => (Mnemonic::Jz, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x74 => (Jz, Imm8, NoOperand),
|
||||||
0x75 => (Mnemonic::Jnz, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x75 => (Jnz, Imm8, NoOperand),
|
||||||
0x76 => (Mnemonic::Jna, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x76 => (Jna, Imm8, NoOperand),
|
||||||
0x77 => (Mnemonic::Ja, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x77 => (Ja, Imm8, NoOperand),
|
||||||
0x78 => (Mnemonic::Js, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x78 => (Js, Imm8, NoOperand),
|
||||||
0x79 => (Mnemonic::Jns, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x79 => (Jns, Imm8, NoOperand),
|
||||||
0x7A => (Mnemonic::Jp, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x7A => (Jp, Imm8, NoOperand),
|
||||||
0x7B => (Mnemonic::Jnp, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x7B => (Jnp, Imm8, NoOperand),
|
||||||
0x7C => (Mnemonic::Jl, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x7C => (Jl, Imm8, NoOperand),
|
||||||
0x7D => (Mnemonic::Jnl, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x7D => (Jnl, Imm8, NoOperand),
|
||||||
0x7E => (Mnemonic::Jng, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x7E => (Jng, Imm8, NoOperand),
|
||||||
0x7F => (Mnemonic::Jg, OperandFormat::Imm8, OperandFormat::NoOperand),
|
0x7F => (Jg, Imm8, NoOperand),
|
||||||
0x88 => (Mnemonic::Mov, OperandFormat::RM8, OperandFormat::Reg8),
|
0x88 => (Mov, RM8, Reg8),
|
||||||
0x89 => (Mnemonic::Mov, OperandFormat::RM16, OperandFormat::Reg16),
|
0x89 => (Mov, RM16, Reg16),
|
||||||
0x8A => (Mnemonic::Mov, OperandFormat::Reg8, OperandFormat::RM8),
|
0x8A => (Mov, Reg8, RM8),
|
||||||
0x8B => (Mnemonic::Mov, OperandFormat::Reg16, OperandFormat::RM16),
|
0x8B => (Mov, Reg16, RM16),
|
||||||
0x8C => (Mnemonic::Mov, OperandFormat::RM16, OperandFormat::Sreg),
|
0x8C => (Mov, RM16, Sreg),
|
||||||
0x8E => (Mnemonic::Mov, OperandFormat::Sreg, OperandFormat::RM16),
|
0x8E => (Mov, Sreg, RM16),
|
||||||
0x90 => (Mnemonic::Nop, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0x90 => (Nop, NoOperand, NoOperand),
|
||||||
0x9E => (Mnemonic::Sahf, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0x9E => (Sahf, NoOperand, NoOperand),
|
||||||
0x9F => (Mnemonic::Lahf, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0x9F => (Lahf, NoOperand, NoOperand),
|
||||||
0xB0 => (Mnemonic::Mov, OperandFormat::AL, OperandFormat::Imm8),
|
0xB0 => (Mov, AL, Imm8),
|
||||||
0xB1 => (Mnemonic::Mov, OperandFormat::CL, OperandFormat::Imm8),
|
0xB1 => (Mov, CL, Imm8),
|
||||||
0xB2 => (Mnemonic::Mov, OperandFormat::DL, OperandFormat::Imm8),
|
0xB2 => (Mov, DL, Imm8),
|
||||||
0xB3 => (Mnemonic::Mov, OperandFormat::BL, OperandFormat::Imm8),
|
0xB3 => (Mov, BL, Imm8),
|
||||||
0xB4 => (Mnemonic::Mov, OperandFormat::AH, OperandFormat::Imm8),
|
0xB4 => (Mov, AH, Imm8),
|
||||||
0xB5 => (Mnemonic::Mov, OperandFormat::CH, OperandFormat::Imm8),
|
0xB5 => (Mov, CH, Imm8),
|
||||||
0xB6 => (Mnemonic::Mov, OperandFormat::DH, OperandFormat::Imm8),
|
0xB6 => (Mov, DH, Imm8),
|
||||||
0xB7 => (Mnemonic::Mov, OperandFormat::BH, OperandFormat::Imm8),
|
0xB7 => (Mov, BH, Imm8),
|
||||||
0xB8 => (Mnemonic::Mov, OperandFormat::AX, OperandFormat::Imm16),
|
0xB8 => (Mov, AX, Imm16),
|
||||||
0xB9 => (Mnemonic::Mov, OperandFormat::CX, OperandFormat::Imm16),
|
0xB9 => (Mov, CX, Imm16),
|
||||||
0xBA => (Mnemonic::Mov, OperandFormat::DX, OperandFormat::Imm16),
|
0xBA => (Mov, DX, Imm16),
|
||||||
0xBB => (Mnemonic::Mov, OperandFormat::BX, OperandFormat::Imm16),
|
0xBB => (Mov, BX, Imm16),
|
||||||
0xBC => (Mnemonic::Mov, OperandFormat::SP, OperandFormat::Imm16),
|
0xBC => (Mov, SP, Imm16),
|
||||||
0xBD => (Mnemonic::Mov, OperandFormat::BP, OperandFormat::Imm16),
|
0xBD => (Mov, BP, Imm16),
|
||||||
0xBE => (Mnemonic::Mov, OperandFormat::SI, OperandFormat::Imm16),
|
0xBE => (Mov, SI, Imm16),
|
||||||
0xBF => (Mnemonic::Mov, OperandFormat::DI, OperandFormat::Imm16),
|
0xBF => (Mov, DI, Imm16),
|
||||||
0xD0 => {
|
0xD0 => {
|
||||||
modrm = ModRM::from_bits(memory.read_u8(address + size as u64));
|
modrm = ModRM::from_bits(memory.read_u8(address + size as u64));
|
||||||
size += 1;
|
size += 1;
|
||||||
match modrm.unwrap() & ModRM::REG_MASK {
|
match modrm.unwrap() & ModRM::REG_MASK {
|
||||||
ModRM::REG_4 => (Mnemonic::Shl, OperandFormat::RM8, OperandFormat::One),
|
ModRM::REG_4 => (Shl, RM8, One),
|
||||||
ModRM::REG_5 => (Mnemonic::Shr, OperandFormat::RM8, OperandFormat::One),
|
ModRM::REG_5 => (Shr, RM8, One),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
0xD2 => {
|
0xD2 => {
|
||||||
modrm = ModRM::from_bits(memory.read_u8(address + size as u64));
|
modrm = ModRM::from_bits(memory.read_u8(address + size as u64));
|
||||||
size += 1;
|
size += 1;
|
||||||
match modrm.unwrap() & ModRM::REG_MASK {
|
match modrm.unwrap() & ModRM::REG_MASK {
|
||||||
ModRM::REG_4 => (Mnemonic::Shl, OperandFormat::RM8, OperandFormat::CL),
|
ModRM::REG_4 => (Shl, RM8, CL),
|
||||||
ModRM::REG_5 => (Mnemonic::Shr, OperandFormat::RM8, OperandFormat::CL),
|
ModRM::REG_5 => (Shr, RM8, CL),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0xEA => (Mnemonic::Jmp, OperandFormat::Ptr16_16, OperandFormat::NoOperand),
|
0xE0 => (Loopne, Imm8, NoOperand),
|
||||||
0xF4 => (Mnemonic::Hlt, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xE1 => (Loope, Imm8, NoOperand),
|
||||||
0xF8 => (Mnemonic::Clc, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xE2 => (Loop, Imm8, NoOperand),
|
||||||
0xF9 => (Mnemonic::Stc, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xE6 => (Out, Imm8, AL),
|
||||||
0xFA => (Mnemonic::Cli, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xE7 => (Out, Imm8, AX),
|
||||||
0xFB => (Mnemonic::Sti, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xE9 => (Jmp, Imm16, NoOperand),
|
||||||
0xFC => (Mnemonic::Cld, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xEA => (Jmp, Ptr16_16, NoOperand),
|
||||||
0xFD => (Mnemonic::Std, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xEB => (Jmp, Imm8, NoOperand),
|
||||||
_ => (Mnemonic::Invalid, OperandFormat::NoOperand, OperandFormat::NoOperand),
|
0xEE => (Out, DX, AL),
|
||||||
|
0xEF => (Out, DX, AX),
|
||||||
|
0xF4 => (Hlt, NoOperand, NoOperand),
|
||||||
|
0xF8 => (Clc, NoOperand, NoOperand),
|
||||||
|
0xF9 => (Stc, NoOperand, NoOperand),
|
||||||
|
0xFA => (Cli, NoOperand, NoOperand),
|
||||||
|
0xFB => (Sti, NoOperand, NoOperand),
|
||||||
|
0xFC => (Cld, NoOperand, NoOperand),
|
||||||
|
0xFD => (Std, NoOperand, NoOperand),
|
||||||
|
0xFE => {
|
||||||
|
modrm = ModRM::from_bits(memory.read_u8(address + size as u64));
|
||||||
|
size += 1;
|
||||||
|
match modrm.unwrap() & ModRM::REG_MASK {
|
||||||
|
ModRM::REG_0 => (Inc, RM8, NoOperand),
|
||||||
|
ModRM::REG_1 => (Dec, RM8, NoOperand),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0xFF => {
|
||||||
|
modrm = ModRM::from_bits(memory.read_u8(address + size as u64));
|
||||||
|
size += 1;
|
||||||
|
match modrm.unwrap() & ModRM::REG_MASK {
|
||||||
|
ModRM::REG_0 => (Inc, RM16, NoOperand),
|
||||||
|
ModRM::REG_1 => (Dec, RM16, NoOperand),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (Invalid, NoOperand, NoOperand),
|
||||||
};
|
};
|
||||||
|
|
||||||
if modrm.is_none() &&
|
if modrm.is_none() &&
|
||||||
|
@ -411,9 +441,13 @@ pub enum Mnemonic {
|
||||||
Js,
|
Js,
|
||||||
Jz,
|
Jz,
|
||||||
Lahf,
|
Lahf,
|
||||||
|
Loop,
|
||||||
|
Loope,
|
||||||
|
Loopne,
|
||||||
Mov,
|
Mov,
|
||||||
Nop,
|
Nop,
|
||||||
Or,
|
Or,
|
||||||
|
Out,
|
||||||
Sahf,
|
Sahf,
|
||||||
Sbb,
|
Sbb,
|
||||||
Shl,
|
Shl,
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub use instruction::*;
|
||||||
pub use register::Registers;
|
pub use register::Registers;
|
||||||
|
|
||||||
use crate::memory::Memory;
|
use crate::memory::Memory;
|
||||||
|
use crate::io::IoBus;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Processor {
|
pub struct Processor {
|
||||||
|
@ -19,10 +20,12 @@ pub struct Processor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Processor {
|
impl Processor {
|
||||||
pub fn exec(&mut self, memory: &mut Memory, instruction: &Instruction) {
|
pub fn exec(&mut self, memory: &mut Memory, io: &mut IoBus, instruction: &Instruction) {
|
||||||
use Mnemonic::*;
|
use Mnemonic::*;
|
||||||
|
use OperandType::*;
|
||||||
|
use OperandSize::*;
|
||||||
match (instruction.mnemonic, instruction.op1, instruction.op2) {
|
match (instruction.mnemonic, instruction.op1, instruction.op2) {
|
||||||
(Add, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => {
|
(Add, Operand(op1, Byte), Operand(op2, Byte)) => {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand8(memory, op2, instruction.segment_override);
|
let src = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let (value, carry) = dst.overflowing_add(src);
|
let (value, carry) = dst.overflowing_add(src);
|
||||||
|
@ -34,7 +37,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand8(value, memory, op1, instruction.segment_override);
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Add, Operand(op1, OperandSize::Word), Operand(op2, OperandSize::Word)) => {
|
(Add, Operand(op1, Word), Operand(op2, Word)) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand16(memory, op2, instruction.segment_override);
|
let src = self.operand16(memory, op2, instruction.segment_override);
|
||||||
let (value, carry) = dst.overflowing_add(src);
|
let (value, carry) = dst.overflowing_add(src);
|
||||||
|
@ -46,7 +49,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Or, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => {
|
(Or, Operand(op1, Byte), Operand(op2, Byte)) => {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand8(memory, op2, instruction.segment_override);
|
let src = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let value = dst | src;
|
let value = dst | src;
|
||||||
|
@ -59,7 +62,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand8(value, memory, op1, instruction.segment_override);
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Or, Operand(op1, OperandSize::Word), Operand(op2, OperandSize::Word)) => {
|
(Or, Operand(op1, Word), Operand(op2, Word)) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand16(memory, op2, instruction.segment_override);
|
let src = self.operand16(memory, op2, instruction.segment_override);
|
||||||
let value = dst | src;
|
let value = dst | src;
|
||||||
|
@ -72,7 +75,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Adc, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => {
|
(Adc, Operand(op1, Byte), Operand(op2, Byte)) => {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand8(memory, op2, instruction.segment_override);
|
let src = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let (value, carry) = dst.carrying_add(src, self.registers.cf());
|
let (value, carry) = dst.carrying_add(src, self.registers.cf());
|
||||||
|
@ -84,7 +87,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand8(value, memory, op1, instruction.segment_override);
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Adc, Operand(op1, OperandSize::Word), Operand(op2, OperandSize::Word)) => {
|
(Adc, Operand(op1, Word), Operand(op2, Word)) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand16(memory, op2, instruction.segment_override);
|
let src = self.operand16(memory, op2, instruction.segment_override);
|
||||||
let (value, carry) = dst.carrying_add(src, self.registers.cf());
|
let (value, carry) = dst.carrying_add(src, self.registers.cf());
|
||||||
|
@ -96,7 +99,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Sbb, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => {
|
(Sbb, Operand(op1, Byte), Operand(op2, Byte)) => {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand8(memory, op2, instruction.segment_override);
|
let src = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let (value, borrow) = dst.borrowing_sub(src, self.registers.cf());
|
let (value, borrow) = dst.borrowing_sub(src, self.registers.cf());
|
||||||
|
@ -108,7 +111,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand8(value, memory, op1, instruction.segment_override);
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Sbb, Operand(op1, OperandSize::Word), Operand(op2, OperandSize::Word)) => {
|
(Sbb, Operand(op1, Word), Operand(op2, Word)) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand16(memory, op2, instruction.segment_override);
|
let src = self.operand16(memory, op2, instruction.segment_override);
|
||||||
let (value, borrow) = dst.borrowing_sub(src, self.registers.cf());
|
let (value, borrow) = dst.borrowing_sub(src, self.registers.cf());
|
||||||
|
@ -120,7 +123,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Sub, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => {
|
(Sub, Operand(op1, Byte), Operand(op2, Byte)) => {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand8(memory, op2, instruction.segment_override);
|
let src = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let (value, borrow) = dst.overflowing_sub(src);
|
let (value, borrow) = dst.overflowing_sub(src);
|
||||||
|
@ -132,7 +135,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand8(value, memory, op1, instruction.segment_override);
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Sub, Operand(op1, OperandSize::Word), Operand(op2, OperandSize::Word)) => {
|
(Sub, Operand(op1, Word), Operand(op2, Word)) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand16(memory, op2, instruction.segment_override);
|
let src = self.operand16(memory, op2, instruction.segment_override);
|
||||||
let (value, borrow) = dst.overflowing_sub(src);
|
let (value, borrow) = dst.overflowing_sub(src);
|
||||||
|
@ -144,7 +147,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Xor, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => {
|
(Xor, Operand(op1, Byte), Operand(op2, Byte)) => {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand8(memory, op2, instruction.segment_override);
|
let src = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let value = dst ^ src;
|
let value = dst ^ src;
|
||||||
|
@ -157,7 +160,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand8(value, memory, op1, instruction.segment_override);
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Xor, Operand(op1, OperandSize::Word), Operand(op2, OperandSize::Word)) => {
|
(Xor, Operand(op1, Word), Operand(op2, Word)) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let src = self.operand16(memory, op2, instruction.segment_override);
|
let src = self.operand16(memory, op2, instruction.segment_override);
|
||||||
let value = dst ^ src;
|
let value = dst ^ src;
|
||||||
|
@ -170,7 +173,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Inc, Operand(op1, OperandSize::Word), _) => {
|
(Inc, Operand(op1, Word), _) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let value = dst.wrapping_add(1);
|
let value = dst.wrapping_add(1);
|
||||||
|
|
||||||
|
@ -181,7 +184,7 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Dec, Operand(op1, OperandSize::Word), _) => {
|
(Dec, Operand(op1, Word), _) => {
|
||||||
let dst = self.operand16(memory, op1, instruction.segment_override);
|
let dst = self.operand16(memory, op1, instruction.segment_override);
|
||||||
let value = dst.wrapping_sub(1);
|
let value = dst.wrapping_sub(1);
|
||||||
|
|
||||||
|
@ -192,50 +195,50 @@ impl Processor {
|
||||||
|
|
||||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||||
},
|
},
|
||||||
(Jo, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jo, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jno, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jno, Operand(Imm8(op1), Byte), _) =>
|
||||||
if !self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
if !self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jc, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jc, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.cf() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.cf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jnc, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jnc, Operand(Imm8(op1), Byte), _) =>
|
||||||
if !self.registers.cf() { self.registers.add_ip(op1 as i8 as i16) },
|
if !self.registers.cf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jz, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jz, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.zf() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.zf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jnz, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jnz, Operand(Imm8(op1), Byte), _) =>
|
||||||
if !self.registers.zf() { self.registers.add_ip(op1 as i8 as i16) },
|
if !self.registers.zf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jna, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jna, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.cf() || self.registers.zf() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.cf() || self.registers.zf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Ja, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Ja, Operand(Imm8(op1), Byte), _) =>
|
||||||
if !(self.registers.cf() || self.registers.zf()) { self.registers.add_ip(op1 as i8 as i16) },
|
if !(self.registers.cf() || self.registers.zf()) { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Js, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Js, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.sf() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.sf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jns, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jns, Operand(Imm8(op1), Byte), _) =>
|
||||||
if !self.registers.sf() { self.registers.add_ip(op1 as i8 as i16) },
|
if !self.registers.sf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jp, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jp, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.pf() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.pf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jnp, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jnp, Operand(Imm8(op1), Byte), _) =>
|
||||||
if !self.registers.pf() { self.registers.add_ip(op1 as i8 as i16) },
|
if !self.registers.pf() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jl, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jl, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.sf() != self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.sf() != self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jnl, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jnl, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.sf() == self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
if self.registers.sf() == self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
||||||
(Jng, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jng, Operand(Imm8(op1), Byte), _) =>
|
||||||
if self.registers.zf() || (self.registers.sf() != self.registers.of()) {
|
if self.registers.zf() || (self.registers.sf() != self.registers.of()) {
|
||||||
self.registers.add_ip(op1 as i8 as i16)
|
self.registers.add_ip(op1 as i8 as i16)
|
||||||
},
|
},
|
||||||
(Jg, Operand(OperandType::Imm8(op1), OperandSize::Byte), _) =>
|
(Jg, Operand(Imm8(op1), Byte), _) =>
|
||||||
if !self.registers.zf() && (self.registers.sf() == self.registers.of()) {
|
if !self.registers.zf() && (self.registers.sf() == self.registers.of()) {
|
||||||
self.registers.add_ip(op1 as i8 as i16)
|
self.registers.add_ip(op1 as i8 as i16)
|
||||||
},
|
},
|
||||||
(Nop, _, _) => {},
|
(Nop, _, _) => {},
|
||||||
(Sahf, _, _) => self.registers.set_flags(self.registers.ah().into()),
|
(Sahf, _, _) => self.registers.set_flags(self.registers.ah().into()),
|
||||||
(Lahf, _, _) => self.registers.set_ah(self.registers.flags() as u8),
|
(Lahf, _, _) => self.registers.set_ah(self.registers.flags() as u8),
|
||||||
(Mov, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) =>
|
(Mov, Operand(op1, Byte), Operand(op2, Byte)) =>
|
||||||
self.set_operand8(self.operand8(memory, op2, instruction.segment_override), memory, op1, instruction.segment_override),
|
self.set_operand8(self.operand8(memory, op2, instruction.segment_override), memory, op1, instruction.segment_override),
|
||||||
(Mov, Operand(op1, OperandSize::Word), Operand(op2, OperandSize::Word)) =>
|
(Mov, Operand(op1, Word), Operand(op2, Word)) =>
|
||||||
self.set_operand16(self.operand16(memory, op2, instruction.segment_override), memory, op1, instruction.segment_override),
|
self.set_operand16(self.operand16(memory, op2, instruction.segment_override), memory, op1, instruction.segment_override),
|
||||||
(Shl, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => 'shl: {
|
(Shl, Operand(op1, Byte), Operand(op2, Byte)) => 'shl: {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let shift = self.operand8(memory, op2, instruction.segment_override);
|
let shift = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let shift = shift & 0b11111;
|
let shift = shift & 0b11111;
|
||||||
|
@ -264,7 +267,7 @@ impl Processor {
|
||||||
self.registers.set_sf(result >> 7 != 0);
|
self.registers.set_sf(result >> 7 != 0);
|
||||||
self.registers.set_zf(result == 0);
|
self.registers.set_zf(result == 0);
|
||||||
},
|
},
|
||||||
(Shr, Operand(op1, OperandSize::Byte), Operand(op2, OperandSize::Byte)) => 'shr: {
|
(Shr, Operand(op1, Byte), Operand(op2, Byte)) => 'shr: {
|
||||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
let shift = self.operand8(memory, op2, instruction.segment_override);
|
let shift = self.operand8(memory, op2, instruction.segment_override);
|
||||||
let shift = shift & 0b11111;
|
let shift = shift & 0b11111;
|
||||||
|
@ -289,10 +292,58 @@ impl Processor {
|
||||||
self.registers.set_sf(result >> 7 != 0);
|
self.registers.set_sf(result >> 7 != 0);
|
||||||
self.registers.set_zf(result == 0);
|
self.registers.set_zf(result == 0);
|
||||||
},
|
},
|
||||||
(Jmp, Operand(OperandType::Ptr16_16(base, offset), _), _) => {
|
(Loopne, Operand(Imm8(offset), _), _) => {
|
||||||
|
self.registers.set_cx(self.registers.cx().wrapping_sub(1));
|
||||||
|
if !self.registers.zf() && self.registers.cx() != 0 {
|
||||||
|
self.registers.add_ip(offset as i8 as i16);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(Loope, Operand(Imm8(offset), _), _) => {
|
||||||
|
self.registers.set_cx(self.registers.cx().wrapping_sub(1));
|
||||||
|
if self.registers.zf() && self.registers.cx() != 0 {
|
||||||
|
self.registers.add_ip(offset as i8 as i16);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(Loop, Operand(Imm8(offset), _), _) => {
|
||||||
|
self.registers.set_cx(self.registers.cx().wrapping_sub(1));
|
||||||
|
if self.registers.cx() != 0 {
|
||||||
|
self.registers.add_ip(offset as i8 as i16);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(Out, Operand(op1, Byte), Operand(op2, Byte)) => {
|
||||||
|
io.write_u8(
|
||||||
|
self.operand8(memory, op1, instruction.segment_override) as u16,
|
||||||
|
self.operand8(memory, op2, instruction.segment_override),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(Out, Operand(op1, Byte), Operand(op2, Word)) => {
|
||||||
|
io.write_u16(
|
||||||
|
self.operand8(memory, op1, instruction.segment_override) as u16,
|
||||||
|
self.operand16(memory, op2, instruction.segment_override),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(Out, Operand(op1, Word), Operand(op2, Byte)) => {
|
||||||
|
io.write_u8(
|
||||||
|
self.operand16(memory, op1, instruction.segment_override),
|
||||||
|
self.operand8(memory, op2, instruction.segment_override),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(Out, Operand(op1, Word), Operand(op2, Word)) => {
|
||||||
|
io.write_u16(
|
||||||
|
self.operand16(memory, op1, instruction.segment_override),
|
||||||
|
self.operand16(memory, op2, instruction.segment_override),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(Jmp, Operand(Imm16(offset), _), _) => {
|
||||||
|
self.registers.add_ip(offset as i16);
|
||||||
|
},
|
||||||
|
(Jmp, Operand(Ptr16_16(base, offset), _), _) => {
|
||||||
self.registers.set_cs(base);
|
self.registers.set_cs(base);
|
||||||
self.registers.set_ip(offset);
|
self.registers.set_ip(offset);
|
||||||
},
|
},
|
||||||
|
(Jmp, Operand(Imm8(offset), _), _) => {
|
||||||
|
self.registers.add_ip(offset as i8 as i16);
|
||||||
|
},
|
||||||
(Hlt, _, _) => self.halted = true,
|
(Hlt, _, _) => self.halted = true,
|
||||||
(Clc, _, _) => self.registers.set_cf(false),
|
(Clc, _, _) => self.registers.set_cf(false),
|
||||||
(Stc, _, _) => self.registers.set_cf(true),
|
(Stc, _, _) => self.registers.set_cf(true),
|
||||||
|
@ -301,6 +352,29 @@ impl Processor {
|
||||||
(Sti, _, _) => self.registers.set_if(true),
|
(Sti, _, _) => self.registers.set_if(true),
|
||||||
(Cld, _, _) => self.registers.set_df(false),
|
(Cld, _, _) => self.registers.set_df(false),
|
||||||
(Std, _, _) => self.registers.set_df(true),
|
(Std, _, _) => self.registers.set_df(true),
|
||||||
|
(Inc, Operand(op1, Byte), _) => {
|
||||||
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
|
let value = dst.wrapping_add(1);
|
||||||
|
|
||||||
|
// FIXME: AF, PF, OF
|
||||||
|
// preserves CF
|
||||||
|
self.registers.set_sf(value >> 7 != 0);
|
||||||
|
self.registers.set_zf(value == 0);
|
||||||
|
|
||||||
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
|
},
|
||||||
|
(Dec, Operand(op1, Byte), _) => {
|
||||||
|
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||||
|
let value = dst.wrapping_sub(1);
|
||||||
|
|
||||||
|
// FIXME: AF, PF, OF
|
||||||
|
// preserves CF
|
||||||
|
self.registers.set_sf(value >> 7 != 0);
|
||||||
|
self.registers.set_zf(value == 0);
|
||||||
|
|
||||||
|
self.set_operand8(value, memory, op1, instruction.segment_override);
|
||||||
|
},
|
||||||
|
|
||||||
_ => unimplemented!("instruction {instruction:?} not implemented"),
|
_ => unimplemented!("instruction {instruction:?} not implemented"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue