ttvm 0.4.1

tt64 emulator API for Rust
Documentation
use super::*;

pub const EFLAGS: u8 = 1 << 32 / 32;
pub const RFLAGS: u8 = 1 << 64 / 32;

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct CPU {
    pub(crate) mem_bus: Bus<Mem>,
    pub(crate) pc: u128,
    pub(crate) sp: u128,
    pub(crate) eax: u32,
    pub(crate) ebx: u32,
    pub(crate) ecx: u32,
    pub(crate) edx: u32,
    pub(crate) ebp: u32,
    pub(crate) esi: u32,
    pub(crate) edi: u32,
    pub(crate) esp: u32,
    pub(crate) ymm0: u256,
    pub(crate) ymm1: u256,
    pub(crate) ymm2: u256,
    pub(crate) ymm3: u256,
    pub(crate) ymm4: u256,
    pub(crate) ymm5: u256,
    pub(crate) ymm6: u256,
    pub(crate) ymm7: u256,
    pub(crate) ymm8: u256,
    pub(crate) ymm9: u256,
    pub(crate) ymm10: u256,
    pub(crate) ymm11: u256,
    pub(crate) ymm12: u256,
    pub(crate) ymm13: u256,
    pub(crate) ymm14: u256,
    pub(crate) ymm15: u256,
    pub(crate) xmm0: u128,
    pub(crate) xmm1: u128,
    pub(crate) xmm2: u128,
    pub(crate) xmm3: u128,
    pub(crate) xmm4: u128,
    pub(crate) xmm5: u128,
    pub(crate) xmm6: u128,
    pub(crate) xmm7: u128,
    pub(crate) xmm8: u128,
    pub(crate) xmm9: u128,
    pub(crate) xmm10: u128,
    pub(crate) xmm11: u128,
    pub(crate) xmm12: u128,
    pub(crate) xmm13: u128,
    pub(crate) xmm14: u128,
    pub(crate) xmm15: u128,
    pub(crate) mmx0: u64,
    pub(crate) mmx1: u64,
    pub(crate) mmx2: u64,
    pub(crate) mmx3: u64,
    pub(crate) mmx4: u64,
    pub(crate) mmx5: u64,
    pub(crate) mmx6: u64,
    pub(crate) mmx7: u64,
    pub(crate) fpr0: u80,
    pub(crate) fpr1: u80,
    pub(crate) fpr2: u80,
    pub(crate) fp3: u80,
    pub(crate) fp4: u80,
    pub(crate) fp5: u80,
    pub(crate) fp6: u80,
    pub(crate) fp7: u80,
    pub(crate) eip: u32,
    pub(crate) eflags: u32,
    pub(crate) rax: u64,
    pub(crate) rbx: u64,
    pub(crate) rcx: u64,
    pub(crate) rdx: u64,
    pub(crate) rbp: u64,
    pub(crate) rsi: u64,
    pub(crate) rdi: u64,
    pub(crate) rsp: u64,
    pub(crate) r8: u64,
    pub(crate) r9: u64,
    pub(crate) r10: u64,
    pub(crate) r11: u64,
    pub(crate) r12: u64,
    pub(crate) r13: u64,
    pub(crate) r14: u64,
    pub(crate) r15: u64,
    pub(crate) rip: u64,
    pub(crate) rflags: u64,
    pub(crate) disks: Box<[Option<Bus<Disk>>]>,
    pub(crate) power: bool,
}

impl CPU {
    pub fn new(mem: &mut Mem) -> Self {
        CPU {
            mem_bus: Bus::new(mem),
            pc: 0,
            sp: 0,
            eax: 0,
            ebx: 0,
            ecx: 0,
            edx: 0,
            ebp: 0,
            esi: 0,
            edi: 0,
            esp: 0,
            ymm0: u256::new(0),
            ymm1: u256::new(0),
            ymm2: u256::new(0),
            ymm3: u256::new(0),
            ymm4: u256::new(0),
            ymm5: u256::new(0),
            ymm6: u256::new(0),
            ymm7: u256::new(0),
            ymm8: u256::new(0),
            ymm9: u256::new(0),
            ymm10: u256::new(0),
            ymm11: u256::new(0),
            ymm12: u256::new(0),
            ymm13: u256::new(0),
            ymm14: u256::new(0),
            ymm15: u256::new(0),
            xmm0: 0,
            xmm1: 0,
            xmm2: 0,
            xmm3: 0,
            xmm4: 0,
            xmm5: 0,
            xmm6: 0,
            xmm7: 0,
            xmm8: 0,
            xmm9: 0,
            xmm10: 0,
            xmm11: 0,
            xmm12: 0,
            xmm13: 0,
            xmm14: 0,
            xmm15: 0,
            mmx0: 0,
            mmx1: 0,
            mmx2: 0,
            mmx3: 0,
            mmx4: 0,
            mmx5: 0,
            mmx6: 0,
            mmx7: 0,
            fpr0: u80::new(0),
            fpr1: u80::new(0),
            fpr2: u80::new(0),
            fp3: u80::new(0),
            fp4: u80::new(0),
            fp5: u80::new(0),
            fp6: u80::new(0),
            fp7: u80::new(0),
            eip: 0,
            eflags: 0,
            rax: 0,
            rbx: 0,
            rcx: 0,
            rdx: 0,
            rbp: 0,
            rsi: 0,
            rdi: 0,
            rsp: 0,
            r8: 0,
            r9: 0,
            r10: 0,
            r11: 0,
            r12: 0,
            r13: 0,
            r14: 0,
            r15: 0,
            rip: 0,
            rflags: 0,
            disks: vec![None; 4].into_boxed_slice(),
            power: false,
        }
    }

    pub fn attach_disk(
        &mut self,
        disk: &mut Disk,
        port: usize,
    ) -> Result<&mut Bus<Disk>, CPUError> {
        if port >= self.disks.len() {
            return Err(CPUError::new(port.to_string()));
        }

        let disk_ref = match self.disks.get_mut(port) {
            Some(some) => some,
            None => return Err(CPUError::new("failed to attach the disk")),
        };

        *disk_ref = Some(Bus::new(disk));

        Ok(match disk_ref {
            Some(some) => some,
            None => return Err(CPUError::new(port.to_string())),
        })
    }

    pub fn detach_disk(&mut self, port: usize) -> Result<usize, CPUError> {
        if port >= self.disks.len() {
            return Err(CPUError::new(port.to_string()));
        }

        let disk_ref = match self.disks.get_mut(port) {
            Some(some) => some,
            None => return Err(CPUError::new("failed to detach the disk")),
        };

        let disk_size = match disk_ref {
            Some(some) => some.size(),
            None => return Err(CPUError::new(port.to_string())),
        };

        *disk_ref = None;

        Ok(disk_size)
    }

    pub fn power(&mut self) {
        if self.power {
            self.power = false;
        } else {
            self.power = true;

            for addr in 0..self.mem_bus.size() {
                match self.mem_bus.write(addr, 0x0) {
                    Ok(_) => (),
                    Err(_) => {
                        self.power = false;

                        dbg!("break");
                        break;
                    }
                };
            }

            if self.power {
                let disk = match self.disks.get(0) {
                    Some(some) => match some {
                        Some(some) => some.clone(),
                        None => {
                            self.power = false;

                            return;
                        }
                    },
                    None => {
                        self.power = false;

                        return;
                    }
                };

                for addr in 0..512 {
                    match self.mem_bus.write(
                        addr + 10,
                        match disk.read(addr) {
                            Ok(ok) => *ok,
                            Err(err) => {
                                dbg!(err);
                                break;
                            }
                        },
                    ) {
                        Ok(_) => (),
                        Err(_) => {
                            self.power = false;

                            dbg!("break");
                            break;
                        }
                    };
                }

                if self.power {
                    loop {
                        if self.mem_bus[self.pc as usize] == FLAG {
                            self.pc += 1;

                            let flag_id = match self.mem_bus.read(self.pc as usize) {
                                Ok(ok) => *ok,
                                Err(_) => {
                                    self.power = false;

                                    dbg!("break");
                                    break;
                                }
                            };

                            match flag_id {
                                EFLAGS => {
                                    let mut eflags: u32 = 0;

                                    for _ in 0..4 {
                                        self.pc += 1;

                                        let flag_value = match self.mem_bus.read(self.pc as usize) {
                                            Ok(ok) => *ok,
                                            Err(_) => {
                                                self.power = false;

                                                dbg!("break");
                                                break;
                                            }
                                        };

                                        eflags = eflags * 256 + flag_value as u32;
                                    }
                                }
                                RFLAGS => {
                                    let mut rflags: u32 = 0;

                                    for _ in 0..8 {
                                        self.pc += 1;

                                        let flag_value = match self.mem_bus.read(self.pc as usize) {
                                            Ok(ok) => *ok,
                                            Err(_) => {
                                                self.power = false;

                                                dbg!("break");
                                                break;
                                            }
                                        };

                                        rflags = rflags * 256 + flag_value as u32;
                                    }
                                }
                                _ => {
                                    self.power = false;

                                    dbg!("break");
                                    break;
                                }
                            }
                        } else if self.mem_bus[self.pc as usize] == PUSH {
                            self.pc += 1;

                            let value = match self.mem_bus.read(self.pc as usize) {
                                Ok(ok) => *ok,
                                Err(_) => {
                                    self.power = false;

                                    dbg!("break");
                                    break;
                                }
                            };

                            self.sp += 1;

                            match self
                                .mem_bus
                                .write(((self.mem_bus.size() / 4) * 3) + self.sp as usize, value)
                            {
                                Ok(_) => (),
                                Err(_) => {
                                    self.power = false;

                                    dbg!("break");
                                    break;
                                }
                            };
                        } else if self.mem_bus[self.pc as usize] == POP {
                            self.pc += 1;

                            self.sp -= 1;
                        }

                        self.pc += 1;

                        if self.pc as usize >= self.mem_bus.size() {
                            self.pc = 0;
                        }
                    }
                }
            }

            self.power = false;
        }
    }
}

pub type CPUError = mtk::Error;