forked from koniifer/ableos
Maybe fixed relative addressing bugs
This commit is contained in:
parent
b4923cfb95
commit
83563fff84
|
@ -5,8 +5,8 @@ use core::convert::TryFrom;
|
||||||
type OpR = u8;
|
type OpR = u8;
|
||||||
|
|
||||||
type OpA = u64;
|
type OpA = u64;
|
||||||
type OpO = u32;
|
type OpO = i32;
|
||||||
type OpP = u16;
|
type OpP = i16;
|
||||||
|
|
||||||
type OpB = u8;
|
type OpB = u8;
|
||||||
type OpH = u16;
|
type OpH = u16;
|
||||||
|
|
|
@ -112,11 +112,20 @@ pub trait AddressOp {
|
||||||
fn cast_u64(self) -> u64;
|
fn cast_u64(self) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_address_ops(($($ty:ty),* $(,)?) => {
|
macro_rules! impl_address_ops_u(($($ty:ty),* $(,)?) => {
|
||||||
$(impl AddressOp for $ty {
|
$(impl AddressOp for $ty {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn cast_u64(self) -> u64 { self as _ }
|
fn cast_u64(self) -> u64 { self as _ }
|
||||||
})*
|
})*
|
||||||
});
|
});
|
||||||
|
|
||||||
impl_address_ops!(u8, u16, u32, u64, usize);
|
macro_rules! impl_address_ops_i(($($ty:ty),* $(,)?) => {
|
||||||
|
$(impl AddressOp for $ty {
|
||||||
|
#[inline(always)]
|
||||||
|
fn cast_u64(self) -> u64 { self as i64 as u64 }
|
||||||
|
})*
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
impl_address_ops_u!(u8, u16, u32, u64, usize);
|
||||||
|
impl_address_ops_i!(i8, i16, i32, i64, isize);
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
use hbbytecode::RoundingMode;
|
use hbbytecode::RoundingMode;
|
||||||
|
|
||||||
|
use crate::mem::addr::AddressOp;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
super::{
|
super::{
|
||||||
bmc::BlockCopier,
|
bmc::BlockCopier,
|
||||||
|
@ -201,10 +203,12 @@ where
|
||||||
LI16 => handler!(self, |OpsRH(tg, imm)| self.write_reg(tg, imm)),
|
LI16 => handler!(self, |OpsRH(tg, imm)| self.write_reg(tg, imm)),
|
||||||
LI32 => handler!(self, |OpsRW(tg, imm)| self.write_reg(tg, imm)),
|
LI32 => handler!(self, |OpsRW(tg, imm)| self.write_reg(tg, imm)),
|
||||||
LI64 => handler!(self, |OpsRD(tg, imm)| self.write_reg(tg, imm)),
|
LI64 => handler!(self, |OpsRD(tg, imm)| self.write_reg(tg, imm)),
|
||||||
LRA => handler!(self, |OpsRRO(tg, reg, imm)| {
|
LRA => handler!(self, |OpsRRO(tg, reg, off)| {
|
||||||
self.write_reg(
|
self.write_reg(
|
||||||
tg,
|
tg,
|
||||||
(self.pc + self.read_reg(reg).cast::<u64>() + imm + 3_u16).get(),
|
self.pcrel(off, 3)
|
||||||
|
.wrapping_add(self.read_reg(reg).cast::<i64>())
|
||||||
|
.get(),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
LD => handler!(self, |OpsRRAH(dst, base, off, count)| {
|
LD => handler!(self, |OpsRRAH(dst, base, off, count)| {
|
||||||
|
@ -216,20 +220,10 @@ where
|
||||||
self.store(dst, base, off, count)?;
|
self.store(dst, base, off, count)?;
|
||||||
}),
|
}),
|
||||||
LDR => handler!(self, |OpsRROH(dst, base, off, count)| {
|
LDR => handler!(self, |OpsRROH(dst, base, off, count)| {
|
||||||
self.load(
|
self.load(dst, base, self.pcrel(off, 3).get(), count)?;
|
||||||
dst,
|
|
||||||
base,
|
|
||||||
u64::from(off).wrapping_add((self.pc + 3_u64).get()),
|
|
||||||
count,
|
|
||||||
)?;
|
|
||||||
}),
|
}),
|
||||||
STR => handler!(self, |OpsRROH(dst, base, off, count)| {
|
STR => handler!(self, |OpsRROH(dst, base, off, count)| {
|
||||||
self.store(
|
self.store(dst, base, self.pcrel(off, 3).get(), count)?;
|
||||||
dst,
|
|
||||||
base,
|
|
||||||
u64::from(off).wrapping_add((self.pc + 3_u64).get()),
|
|
||||||
count,
|
|
||||||
)?;
|
|
||||||
}),
|
}),
|
||||||
BMC => {
|
BMC => {
|
||||||
// Block memory copy
|
// Block memory copy
|
||||||
|
@ -278,14 +272,13 @@ where
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
JMP => handler!(self, |OpsO(off)| self.pc = self.pc.wrapping_add(off)),
|
JMP => handler!(self, |OpsO(off)| self.pc = self.pc.wrapping_add(off)),
|
||||||
JAL => handler!(self, |OpsRRW(save, reg, offset)| {
|
JAL => handler!(self, |OpsRRO(save, reg, offset)| {
|
||||||
// Jump and link. Save PC after this instruction to
|
// Jump and link. Save PC after this instruction to
|
||||||
// specified register and jump to reg + relative offset.
|
// specified register and jump to reg + relative offset.
|
||||||
self.write_reg(save, self.pc.get());
|
self.write_reg(save, self.pc.get());
|
||||||
self.pc = self
|
self.pc = self
|
||||||
.pc
|
.pcrel(offset, 3)
|
||||||
.wrapping_add(self.read_reg(reg).cast::<u64>())
|
.wrapping_add(self.read_reg(reg).cast::<i64>());
|
||||||
.wrapping_add(offset);
|
|
||||||
}),
|
}),
|
||||||
JALA => handler!(self, |OpsRRW(save, reg, offset)| {
|
JALA => handler!(self, |OpsRRW(save, reg, offset)| {
|
||||||
// Jump and link. Save PC after this instruction to
|
// Jump and link. Save PC after this instruction to
|
||||||
|
@ -387,12 +380,12 @@ where
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
LDR16 => handler!(self, |OpsRRPH(dst, base, off, count)| {
|
LDR16 => handler!(self, |OpsRRPH(dst, base, off, count)| {
|
||||||
self.load(dst, base, u64::from(off).wrapping_add(self.pc.get()), count)?;
|
self.load(dst, base, self.pcrel(off, 3).get(), count)?;
|
||||||
}),
|
}),
|
||||||
STR16 => handler!(self, |OpsRRPH(dst, base, off, count)| {
|
STR16 => handler!(self, |OpsRRPH(dst, base, off, count)| {
|
||||||
self.store(dst, base, u64::from(off).wrapping_add(self.pc.get()), count)?;
|
self.store(dst, base, self.pcrel(off, 3).get(), count)?;
|
||||||
}),
|
}),
|
||||||
JMP16 => handler!(self, |OpsP(off)| self.pc = self.pc.wrapping_add(off)),
|
JMP16 => handler!(self, |OpsP(off)| self.pc = self.pcrel(off, 1)),
|
||||||
op => return Err(VmRunError::InvalidOpcode(op)),
|
op => return Err(VmRunError::InvalidOpcode(op)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,6 +530,12 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate pc-relative address
|
||||||
|
#[inline(always)]
|
||||||
|
fn pcrel(&self, offset: impl AddressOp, pos: u8) -> Address {
|
||||||
|
self.pc.wrapping_add(pos).wrapping_add(offset)
|
||||||
|
}
|
||||||
|
|
||||||
/// Jump at `PC + #3` if ordering on `#0 <=> #1` is equal to expected
|
/// Jump at `PC + #3` if ordering on `#0 <=> #1` is equal to expected
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn cond_jmp<T: ValueVariant + Ord>(&mut self, expected: Ordering) {
|
unsafe fn cond_jmp<T: ValueVariant + Ord>(&mut self, expected: Ordering) {
|
||||||
|
@ -547,7 +546,7 @@ where
|
||||||
.cmp(&self.read_reg(a1).cast::<T>())
|
.cmp(&self.read_reg(a1).cast::<T>())
|
||||||
== expected
|
== expected
|
||||||
{
|
{
|
||||||
self.pc = Address::new(((self.pc.get() as i64).wrapping_add(ja as i64)) as u64);
|
self.pc = self.pcrel(ja, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.bump_pc::<OpsRRP, true>();
|
self.bump_pc::<OpsRRP, true>();
|
||||||
|
|
Loading…
Reference in a new issue