diff --git a/hbasm/src/lib.rs b/hbasm/src/lib.rs index 75a5731a..391b2514 100644 --- a/hbasm/src/lib.rs +++ b/hbasm/src/lib.rs @@ -21,11 +21,11 @@ macros::impl_both!( => [LD, ST], bbd(p0: R, p1: R, p2: I) => [ADDI, MULI, ANDI, ORI, XORI, SLI, SRI, SRSI, CMPI, CMPUI, - BMC, JEQ, JNE, JLT, JGT, JLTU, JGTU, ADDFI, MULFI], + BMC, JAL, JEQ, JNE, JLT, JGT, JLTU, JGTU, ADDFI, MULFI], bb(p0: R, p1: R) => [NEG, NOT, CP, SWA, NEGF, ITF, FTI], bd(p0: R, p1: I) - => [LI, JMP], + => [LI], n() => [NOP, ECALL], ); diff --git a/hbbytecode/src/lib.rs b/hbbytecode/src/lib.rs index 19f46487..9b4f60bf 100644 --- a/hbbytecode/src/lib.rs +++ b/hbbytecode/src/lib.rs @@ -54,7 +54,7 @@ constmod!(pub opcode(u8) { BMC = 30, "BBD; [#0] ← [#1], imm #2 bytes"; BRC = 31, "BBB; #0 ← #1, imm #2 registers"; - JMP = 32, "BD; Unconditional jump [#0 + imm #1]"; + JAL = 32, "BD; Copy PC to #0 and unconditional jump [#1 + imm #2]"; JEQ = 33, "BBD; if #0 = #1 → jump imm #2"; JNE = 34, "BBD; if #0 ≠ #1 → jump imm #2"; JLT = 35, "BBD; if #0 < #1 → jump imm #2"; diff --git a/hbvm/src/validate.rs b/hbvm/src/validate.rs index 52f726ff..d75306bf 100644 --- a/hbvm/src/validate.rs +++ b/hbvm/src/validate.rs @@ -50,8 +50,8 @@ pub fn validate(mut program: &[u8]) -> Result<(), Error> { | [DIR | DIRF, _, _, _, _, rest @ ..] | [ADD..=CMPU | BRC | ADDF..=MULF, _, _, _, rest @ ..] | [NEG..=NOT | CP..=SWA | NEGF..=FTI, _, _, rest @ ..] - | [LI | JMP, _, _, _, _, _, _, _, _, _, rest @ ..] - | [ADDI..=CMPUI | BMC | JEQ..=JGTU | ADDFI..=MULFI, _, _, _, _, _, _, _, _, _, _, rest @ ..] + | [LI, _, _, _, _, _, _, _, _, _, rest @ ..] + | [ADDI..=CMPUI | BMC | JAL..=JGTU | ADDFI..=MULFI, _, _, _, _, _, _, _, _, _, _, rest @ ..] | [LD..=ST, _, _, _, _, _, _, _, _, _, _, _, _, rest @ ..] => rest, _ => { return Err(Error { diff --git a/hbvm/src/vm/mem/mod.rs b/hbvm/src/vm/mem/mod.rs index 901c41c3..86095153 100644 --- a/hbvm/src/vm/mem/mod.rs +++ b/hbvm/src/vm/mem/mod.rs @@ -64,6 +64,25 @@ impl Memory { } } + /// Maps host's memory into VM's memory + /// + /// # Safety + /// Who knows. + pub unsafe fn map( + &mut self, + mut host: *mut u8, + target: usize, + pagesize: PageSize, + count: usize, + ) { + todo!() + } + + /// Unmaps pages from VM's memory + pub fn unmap(&mut self, addr: usize, count: usize) { + todo!() + } + /// Load value from an address /// /// # Safety @@ -215,11 +234,11 @@ impl Memory { action: fn(*mut u8, *mut u8, usize), traph: &mut impl HandlePageFault, ) -> Result<(), u64> { - let mut pspl = AddrSplitter::new(src, len, self.root_pt); + let mut pspl = AddrPageLookuper::new(src, len, self.root_pt); loop { match pspl.next() { // Page found - Some(Ok(AddrSplitOk { + Some(Ok(AddrPageLookupOk { vaddr, ptr, size, @@ -233,7 +252,7 @@ impl Memory { action(ptr, dst, size); dst = unsafe { dst.add(size) }; } - Some(Err(AddrSplitError { addr, size })) => { + Some(Err(AddrPageLookupError { addr, size })) => { // Execute page fault handler if traph.page_fault(reason, self, addr, size, dst) { // Shift the splitter address @@ -252,7 +271,7 @@ impl Memory { } /// Result from address split -struct AddrSplitOk { +struct AddrPageLookupOk { /// Virtual address vaddr: u64, @@ -266,7 +285,7 @@ struct AddrSplitOk { perm: Permission, } -struct AddrSplitError { +struct AddrPageLookupError { /// Address of failure addr: u64, @@ -275,7 +294,7 @@ struct AddrSplitError { } /// Address splitter into pages -struct AddrSplitter { +struct AddrPageLookuper { /// Current address addr: u64, @@ -286,7 +305,7 @@ struct AddrSplitter { pagetable: *const PageTable, } -impl AddrSplitter { +impl AddrPageLookuper { /// Create a new page splitter pub const fn new(addr: u64, size: usize, pagetable: *const PageTable) -> Self { Self { @@ -303,8 +322,8 @@ impl AddrSplitter { } } -impl Iterator for AddrSplitter { - type Item = Result; +impl Iterator for AddrPageLookuper { + type Item = Result; fn next(&mut self) -> Option { // The end, everything is fine @@ -328,7 +347,7 @@ impl Iterator for AddrSplitter { match entry.permission() { // No page → page fault Permission::Empty => { - return Some(Err(AddrSplitError { + return Some(Err(AddrPageLookupError { addr: self.addr, size: PageSize::from_lvl(lvl)?, })) @@ -358,7 +377,7 @@ impl Iterator for AddrSplitter { let avail = (size as usize - offset).clamp(0, self.size); self.bump(size); - Some(Ok(AddrSplitOk { + Some(Ok(AddrPageLookupOk { vaddr: self.addr, ptr: unsafe { base.add(offset) }, // Return pointer to the start of region size: avail, diff --git a/hbvm/src/vm/mod.rs b/hbvm/src/vm/mod.rs index d9937a36..1fcee80d 100644 --- a/hbvm/src/vm/mod.rs +++ b/hbvm/src/vm/mod.rs @@ -259,8 +259,9 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize> usize::from(count), ); } - JMP => { - let ParamBD(reg, offset) = param!(self, ParamBD); + JAL => { + let ParamBBD(save, reg, offset) = param!(self, ParamBBD); + self.write_reg(save, self.pc as u64); self.pc = (self.read_reg(reg).as_u64() + offset) as usize; } JEQ => cond_jump!(self, int, Equal), diff --git a/spec.md b/spec.md index b9adf175..55c3aaa4 100644 --- a/spec.md +++ b/spec.md @@ -166,11 +166,11 @@ ## Control flow ### Unconditional jump -- Type BD +- Type BBD -| Opcode | Name | Action | -|:------:|:----:|:---------------------:| -| 32 | JMP | Jump at `#0 + imm #1` | +| Opcode | Name | Action | +|:------:|:----:|:-------------------------------------------------:| +| 32 | JAL | Save current PC to `#0` and jump at `#1 + imm #2` | ### Conditional jumps - Type BBD