mirror of
https://git.sr.ht/~asya/copycat
synced 2024-11-21 23:18:42 -06:00
Start CrabBIOS, implement firmware loading and push/pop/ret
Signed-off-by: AsyaTheAbove <asya@waifu.club>
This commit is contained in:
parent
911d6e844b
commit
e3906f2dc3
160
Cargo.lock
generated
160
Cargo.lock
generated
|
@ -19,6 +19,54 @@ version = "0.2.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.0"
|
||||
|
@ -31,11 +79,45 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "copycat"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
|
@ -55,8 +137,86 @@ version = "1.18.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
|
|
@ -7,4 +7,5 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
bitflags = "2.4.0"
|
||||
clap = { version = "4.4.6", features = ["cargo"] }
|
||||
hashbrown = "0.14.0"
|
||||
|
|
13
build.rs
Normal file
13
build.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
// Tell Cargo that if the given file changes, to rerun this build script.
|
||||
println!("cargo:rerun-if-changed=crabbios/crabbios.asm");
|
||||
Command::new("nasm")
|
||||
.arg("crabbios/crabbios.asm")
|
||||
.args(["-f", "bin"])
|
||||
.args(["-o", "roms/crabbios.bin"])
|
||||
.args(["-I", "crabbios"])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
3
crabbios/README.md
Normal file
3
crabbios/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# CrabBIOS
|
||||
|
||||
BIOS implementation in x86 real mode assembly
|
27
crabbios/crabbios.asm
Normal file
27
crabbios/crabbios.asm
Normal file
|
@ -0,0 +1,27 @@
|
|||
bits 16 ; we're in 16 bit real mode
|
||||
org 0xfe000 ; that's where we're loaded
|
||||
|
||||
start: ; we jump here after the entry point
|
||||
mov ax, 0xFF
|
||||
push ax
|
||||
pop bx
|
||||
hlt
|
||||
|
||||
; fill until the reset vector
|
||||
times 4080 - ($ - start) db 0
|
||||
|
||||
; entry point
|
||||
; we shouldn't assume any initial state here
|
||||
cli
|
||||
|
||||
; set up stack at 0:0x7c00
|
||||
; that's just below where we'll load the boot sector
|
||||
mov ax, 0
|
||||
mov ss, ax
|
||||
mov sp, 0x7c00
|
||||
|
||||
; jump over to start
|
||||
jmp start
|
||||
|
||||
; fill the last bytes
|
||||
times 4096 - ($ - start) db 0
|
30
src/main.rs
30
src/main.rs
|
@ -4,16 +4,40 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
use std::fs;
|
||||
|
||||
use clap::{command, arg};
|
||||
use copycat::memory::{Memory, KiB};
|
||||
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; 4 * KiB as usize] = include_bytes!("../roms/crabbios.bin");
|
||||
|
||||
fn main() {
|
||||
let matches = command!()
|
||||
.arg(arg!(-b --bios <BIOS> "Firmware image to load"))
|
||||
.get_matches();
|
||||
|
||||
let maybe_bios;
|
||||
let bios: &[u8] = match matches.get_one::<String>("bios") {
|
||||
Some(bios) => {
|
||||
maybe_bios = fs::read(bios).unwrap();
|
||||
&maybe_bios
|
||||
},
|
||||
None => BIOS_ROM,
|
||||
};
|
||||
if bios.len() == 0 {
|
||||
panic!("firmware image empty");
|
||||
}
|
||||
if bios.len() % 4 * KiB as usize != 0 {
|
||||
panic!("firmware image length not a multiple of a page");
|
||||
}
|
||||
let bios_len = bios.len() / (4 * KiB) as usize;
|
||||
|
||||
let mut mem = Memory::new(64 * KiB);
|
||||
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());
|
||||
for i in 0xff - bios_len + 1..=0xff {
|
||||
mem.add_tlb_entry(i as u64, unsafe { bios.as_ptr().add((i - (0xff - bios_len + 1)) * 4 * KiB as usize) }.cast_mut().cast());
|
||||
}
|
||||
// mem.write(0xffff0, [0x90, 0x04, 0x69, 0xF4]);
|
||||
let mut io = IoBus::default();
|
||||
let mut cpu = Processor::default();
|
||||
|
|
|
@ -98,6 +98,22 @@ impl Instruction {
|
|||
0x4D => (Dec, BP, NoOperand),
|
||||
0x4E => (Dec, SI, NoOperand),
|
||||
0x4F => (Dec, DI, NoOperand),
|
||||
0x50 => (Push, AX, NoOperand),
|
||||
0x51 => (Push, CX, NoOperand),
|
||||
0x52 => (Push, DX, NoOperand),
|
||||
0x53 => (Push, BX, NoOperand),
|
||||
0x54 => (Push, SP, NoOperand),
|
||||
0x55 => (Push, BP, NoOperand),
|
||||
0x56 => (Push, SI, NoOperand),
|
||||
0x57 => (Push, DI, NoOperand),
|
||||
0x58 => (Pop, AX, NoOperand),
|
||||
0x59 => (Pop, CX, NoOperand),
|
||||
0x5A => (Pop, DX, NoOperand),
|
||||
0x5B => (Pop, BX, NoOperand),
|
||||
0x5C => (Pop, SP, NoOperand),
|
||||
0x5D => (Pop, BP, NoOperand),
|
||||
0x5E => (Pop, SI, NoOperand),
|
||||
0x5F => (Pop, DI, NoOperand),
|
||||
0x70 => (Jo, Imm8, NoOperand),
|
||||
0x71 => (Jno, Imm8, NoOperand),
|
||||
0x72 => (Jc, Imm8, NoOperand),
|
||||
|
@ -139,6 +155,10 @@ impl Instruction {
|
|||
0xBD => (Mov, BP, Imm16),
|
||||
0xBE => (Mov, SI, Imm16),
|
||||
0xBF => (Mov, DI, Imm16),
|
||||
0xC2 => (Retn, Imm16, NoOperand),
|
||||
0xC3 => (Retn, NoOperand, NoOperand),
|
||||
0xCA => (Retf, Imm16, NoOperand),
|
||||
0xCB => (Retf, NoOperand, NoOperand),
|
||||
0xD0 => {
|
||||
modrm = ModRM::from_bits(memory.read_u8(address + size as u64));
|
||||
size += 1;
|
||||
|
@ -448,6 +468,10 @@ pub enum Mnemonic {
|
|||
Nop,
|
||||
Or,
|
||||
Out,
|
||||
Pop,
|
||||
Push,
|
||||
Retf,
|
||||
Retn,
|
||||
Sahf,
|
||||
Sbb,
|
||||
Shl,
|
||||
|
|
|
@ -195,6 +195,14 @@ impl Processor {
|
|||
|
||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||
},
|
||||
(Push, Operand(op1, Word), _) => {
|
||||
let value = self.operand16(memory, op1, instruction.segment_override);
|
||||
self.push16(value, memory);
|
||||
},
|
||||
(Pop, Operand(op1, Word), _) => {
|
||||
let value = self.pop16(memory);
|
||||
self.set_operand16(value, memory, op1, instruction.segment_override);
|
||||
},
|
||||
(Jo, Operand(Imm8(op1), Byte), _) =>
|
||||
if self.registers.of() { self.registers.add_ip(op1 as i8 as i16) },
|
||||
(Jno, Operand(Imm8(op1), Byte), _) =>
|
||||
|
@ -238,6 +246,28 @@ impl Processor {
|
|||
self.set_operand8(self.operand8(memory, op2, instruction.segment_override), memory, op1, instruction.segment_override),
|
||||
(Mov, Operand(op1, Word), Operand(op2, Word)) =>
|
||||
self.set_operand16(self.operand16(memory, op2, instruction.segment_override), memory, op1, instruction.segment_override),
|
||||
(Retn, Operand(Imm16(parameters), _), _) => {
|
||||
let ip = self.pop16(memory);
|
||||
self.registers.set_ip(ip);
|
||||
self.registers.set_sp(self.registers.sp() + parameters);
|
||||
},
|
||||
(Retn, _, _) => {
|
||||
let ip = self.pop16(memory);
|
||||
self.registers.set_ip(ip);
|
||||
},
|
||||
(Retf, Operand(Imm16(parameters), _), _) => {
|
||||
let ip = self.pop16(memory);
|
||||
let cs = self.pop16(memory);
|
||||
self.registers.set_ip(ip);
|
||||
self.registers.set_cs(cs);
|
||||
self.registers.set_sp(self.registers.sp() + parameters);
|
||||
},
|
||||
(Retf, _, _) => {
|
||||
let ip = self.pop16(memory);
|
||||
let cs = self.pop16(memory);
|
||||
self.registers.set_ip(ip);
|
||||
self.registers.set_cs(cs);
|
||||
},
|
||||
(Shl, Operand(op1, Byte), Operand(op2, Byte)) => 'shl: {
|
||||
let dst = self.operand8(memory, op1, instruction.segment_override);
|
||||
let shift = self.operand8(memory, op2, instruction.segment_override);
|
||||
|
@ -500,4 +530,16 @@ impl Processor {
|
|||
SegmentOverride::DS | SegmentOverride::None => self.registers.ds(),
|
||||
} as u64) << 4) + offset as u64
|
||||
}
|
||||
|
||||
fn push16(&mut self, value: u16, memory: &mut Memory) {
|
||||
self.registers.set_sp(self.registers.sp() - 2);
|
||||
let address = ((self.registers.ss() as u64) << 4) + self.registers.sp() as u64;
|
||||
memory.write_u16(address, value);
|
||||
}
|
||||
|
||||
fn pop16(&mut self, memory: &Memory) -> u16 {
|
||||
let address = ((self.registers.ss() as u64) << 4) + self.registers.sp() as u64;
|
||||
self.registers.set_sp(self.registers.sp() + 2);
|
||||
memory.read_u16(address)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue