From 9cdc79582468f8c28c1937a0d63d4a3589a7bbf5 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Mon, 10 Mar 2025 21:55:18 +0100 Subject: [PATCH] j immediate decoding fix --- src/emu.rs | 49 ++++++++++++++++++++++++++++++++++++++++++-- src/inst.rs | 11 +++------- tests/check/branch.S | 9 ++++++++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/emu.rs b/src/emu.rs index 8f5dc67..39dcae9 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -172,12 +172,57 @@ fn hash_color(value: u32) -> impl Display { impl Emulator { pub fn start_linux(&mut self) -> Status { - // set top of stack. just some yolo address. with no values there. who needs abi? - self[Reg::SP] = 4096 * 8; + self.setup_linux_stack().unwrap(); self.execute() } + fn setup_linux_stack(&mut self) -> Result<(), Status> { + // set top of stack. just some yolo address. with no values there. who needs abi? + let sp = 4096 * 16; + self[Reg::SP] = sp; + + // The x86-64 psABI has a nice diagram of the stack layout (it's not arch specific). + + // | Purpose | Start Address | Length | + // |----------------------------------|--------- -----|----------------| + // | Information block of strings etc | (high) | varies | + // | Unspecified | | | + // | Null auxiliary vector entry | | word | + // | Auxiliary vector entries | | two words each | + // | 0 | | word | + // | Environment pointers | | word each | + // | 0 | 4+4*argc+sp | word | + // | Argument pointers | 4+sp | argc words | + // | Argument count | sp | word | + // | Undefined | (low) | | + + let xlen = 4; + + let mut offset: u32 = 0; + let mut next_word = || { + let n = offset; + offset += xlen; + sp + n + }; + + // argc + self.mem.store_u32(next_word(), 0)?; + + // null terminated argument pointers... (we have none.) + self.mem.store_u32(next_word(), 0)?; + + // null terminated environment pointers... (we have none.) + self.mem.store_u32(next_word(), 0)?; + + // null terminated auxiliary vector entries + // TODO: add some auxv for the poor process. + self.mem.store_u32(next_word(), 0)?; + + + Ok(()) + } + fn execute(&mut self) -> Status { loop { if let Err(err) = self.step() { diff --git a/src/inst.rs b/src/inst.rs index 0b5054a..f57322b 100644 --- a/src/inst.rs +++ b/src/inst.rs @@ -394,13 +394,8 @@ impl Display for AmoOp { } fn sign_extend(value: u32, size: u32) -> u32 { - assert!(size <= u32::BITS); - let sign = value >> (size - 1); - if sign == 1 { - (u32::MAX << size) | value - } else { - value - } + let right = u32::BITS - size; + (((value << right) as i32) >> right) as u32 } #[derive(Clone, Copy)] @@ -462,7 +457,7 @@ impl InstCode { self.immediate_u(&[(12..=31, 12)]) } fn imm_j(self) -> u32 { - self.immediate_u(&[(31..=31, 20), (21..=30, 1), (20..=20, 11), (12..=19, 12)]) + self.immediate_s(&[(31..=31, 20), (21..=30, 1), (20..=20, 11), (12..=19, 12)]) } } diff --git a/tests/check/branch.S b/tests/check/branch.S index 6e1c299..829d119 100644 --- a/tests/check/branch.S +++ b/tests/check/branch.S @@ -40,6 +40,15 @@ branch6: FAIL branch7: +# Backwards jal + li t0, 0 +backwards: + li t1, 0 + bne t0, t1, end_backwards + li t0, 1 + jal backwards +end_backwards: + # Test link registers being set correctly: auipc t1, 0 jal t0, link2