Fixed bug + spec update
This commit is contained in:
parent
6fe1fd91bf
commit
1a53c80a62
|
@ -154,6 +154,11 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
SR => binary_op!(self, as_u64, ops::Shr::shr),
|
SR => binary_op!(self, as_u64, ops::Shr::shr),
|
||||||
SRS => binary_op!(self, as_i64, ops::Shr::shr),
|
SRS => binary_op!(self, as_i64, ops::Shr::shr),
|
||||||
CMP => {
|
CMP => {
|
||||||
|
// Compare a0 <=> a1
|
||||||
|
// < → -1
|
||||||
|
// > → 1
|
||||||
|
// = → 0
|
||||||
|
|
||||||
let ParamBBB(tg, a0, a1) = param!(self, ParamBBB);
|
let ParamBBB(tg, a0, a1) = param!(self, ParamBBB);
|
||||||
self.write_reg(
|
self.write_reg(
|
||||||
tg,
|
tg,
|
||||||
|
@ -161,6 +166,7 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
CMPU => {
|
CMPU => {
|
||||||
|
// Unsigned comparsion
|
||||||
let ParamBBB(tg, a0, a1) = param!(self, ParamBBB);
|
let ParamBBB(tg, a0, a1) = param!(self, ParamBBB);
|
||||||
self.write_reg(
|
self.write_reg(
|
||||||
tg,
|
tg,
|
||||||
|
@ -168,10 +174,12 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
NOT => {
|
NOT => {
|
||||||
|
// Logical negation
|
||||||
let param = param!(self, ParamBB);
|
let param = param!(self, ParamBB);
|
||||||
self.write_reg(param.0, !self.read_reg(param.1).as_u64());
|
self.write_reg(param.0, !self.read_reg(param.1).as_u64());
|
||||||
}
|
}
|
||||||
NEG => {
|
NEG => {
|
||||||
|
// Bitwise negation
|
||||||
let param = param!(self, ParamBB);
|
let param = param!(self, ParamBB);
|
||||||
self.write_reg(
|
self.write_reg(
|
||||||
param.0,
|
param.0,
|
||||||
|
@ -182,6 +190,7 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
DIR => {
|
DIR => {
|
||||||
|
// Fused Division-Remainder
|
||||||
let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB);
|
let ParamBBBB(dt, rt, a0, a1) = param!(self, ParamBBBB);
|
||||||
let a0 = self.read_reg(a0).as_u64();
|
let a0 = self.read_reg(a0).as_u64();
|
||||||
let a1 = self.read_reg(a1).as_u64();
|
let a1 = self.read_reg(a1).as_u64();
|
||||||
|
@ -212,19 +221,25 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
self.write_reg(param.0, self.read_reg(param.1));
|
self.write_reg(param.0, self.read_reg(param.1));
|
||||||
}
|
}
|
||||||
SWA => {
|
SWA => {
|
||||||
let ParamBB(src, dst) = param!(self, ParamBB);
|
// Swap registers
|
||||||
if src + dst != 0 {
|
let ParamBB(r0, r1) = param!(self, ParamBB);
|
||||||
|
match (r0, r1) {
|
||||||
|
(0, 0) => (),
|
||||||
|
(dst, 0) | (0, dst) => self.write_reg(dst, 0_u64),
|
||||||
|
(r0, r1) => {
|
||||||
core::ptr::swap(
|
core::ptr::swap(
|
||||||
self.registers.get_unchecked_mut(usize::from(src)),
|
self.registers.get_unchecked_mut(usize::from(r0)),
|
||||||
self.registers.get_unchecked_mut(usize::from(dst)),
|
self.registers.get_unchecked_mut(usize::from(r1)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
LI => {
|
LI => {
|
||||||
let param = param!(self, ParamBD);
|
let param = param!(self, ParamBD);
|
||||||
self.write_reg(param.0, param.1);
|
self.write_reg(param.0, param.1);
|
||||||
}
|
}
|
||||||
LD => {
|
LD => {
|
||||||
|
// Load. If loading more than register size, continue on adjecent registers
|
||||||
let ParamBBDH(dst, base, off, count) = param!(self, ParamBBDH);
|
let ParamBBDH(dst, base, off, count) = param!(self, ParamBBDH);
|
||||||
let n: usize = match dst {
|
let n: usize = match dst {
|
||||||
0 => 1,
|
0 => 1,
|
||||||
|
@ -239,6 +254,7 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
ST => {
|
ST => {
|
||||||
|
// Store. Same rules apply as to LD
|
||||||
let ParamBBDH(dst, base, off, count) = param!(self, ParamBBDH);
|
let ParamBBDH(dst, base, off, count) = param!(self, ParamBBDH);
|
||||||
self.memory.store(
|
self.memory.store(
|
||||||
self.read_reg(base).as_u64() + off,
|
self.read_reg(base).as_u64() + off,
|
||||||
|
@ -248,6 +264,7 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
BMC => {
|
BMC => {
|
||||||
|
// Block memory copy
|
||||||
let ParamBBD(src, dst, count) = param!(self, ParamBBD);
|
let ParamBBD(src, dst, count) = param!(self, ParamBBD);
|
||||||
self.memory.block_copy(
|
self.memory.block_copy(
|
||||||
self.read_reg(src).as_u64(),
|
self.read_reg(src).as_u64(),
|
||||||
|
@ -257,6 +274,7 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
BRC => {
|
BRC => {
|
||||||
|
// Block register copy
|
||||||
let ParamBBB(src, dst, count) = param!(self, ParamBBB);
|
let ParamBBB(src, dst, count) = param!(self, ParamBBB);
|
||||||
core::ptr::copy(
|
core::ptr::copy(
|
||||||
self.registers.get_unchecked(usize::from(src)),
|
self.registers.get_unchecked(usize::from(src)),
|
||||||
|
@ -265,10 +283,13 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
JAL => {
|
JAL => {
|
||||||
|
// Jump and link. Save PC after this instruction to
|
||||||
|
// specified register and jump to reg + offset.
|
||||||
let ParamBBD(save, reg, offset) = param!(self, ParamBBD);
|
let ParamBBD(save, reg, offset) = param!(self, ParamBBD);
|
||||||
self.write_reg(save, self.pc as u64);
|
self.write_reg(save, self.pc as u64);
|
||||||
self.pc = (self.read_reg(reg).as_u64() + offset) as usize;
|
self.pc = (self.read_reg(reg).as_u64() + offset) as usize;
|
||||||
}
|
}
|
||||||
|
// Conditional jumps, jump only to immediates
|
||||||
JEQ => cond_jump!(self, int, Equal),
|
JEQ => cond_jump!(self, int, Equal),
|
||||||
JNE => {
|
JNE => {
|
||||||
let ParamBBD(a0, a1, jt) = param!(self, ParamBBD);
|
let ParamBBD(a0, a1, jt) = param!(self, ParamBBD);
|
||||||
|
@ -282,6 +303,11 @@ impl<'a, PfHandler: HandlePageFault, const TIMER_QUOTIENT: usize>
|
||||||
JGTU => cond_jump!(self, sint, Greater),
|
JGTU => cond_jump!(self, sint, Greater),
|
||||||
ECALL => {
|
ECALL => {
|
||||||
param!(self, ());
|
param!(self, ());
|
||||||
|
|
||||||
|
// So we don't get timer interrupt after ECALL
|
||||||
|
if TIMER_QUOTIENT != 0 {
|
||||||
|
self.timer = self.timer.wrapping_add(1);
|
||||||
|
}
|
||||||
return Ok(VmRunOk::Ecall);
|
return Ok(VmRunOk::Ecall);
|
||||||
}
|
}
|
||||||
ADDF => binary_op!(self, as_f64, ops::Add::add),
|
ADDF => binary_op!(self, as_f64, ops::Add::add),
|
||||||
|
|
7
spec.md
7
spec.md
|
@ -124,6 +124,9 @@
|
||||||
### Swap
|
### Swap
|
||||||
- Type BB
|
- Type BB
|
||||||
- Swap #0 and #1
|
- Swap #0 and #1
|
||||||
|
- Zero register rules:
|
||||||
|
- Both: no-op
|
||||||
|
- One: Copy zero to the non-zero register
|
||||||
|
|
||||||
| Opcode | Name | Action |
|
| Opcode | Name | Action |
|
||||||
|:------:|:----:|:------:|
|
|:------:|:----:|:------:|
|
||||||
|
@ -263,8 +266,8 @@
|
||||||
|
|
||||||
# Program execution
|
# Program execution
|
||||||
- The way of program execution is implementation defined
|
- The way of program execution is implementation defined
|
||||||
- The order of instruction is arbitrary, as long all observable
|
- The execution is arbitrary, as long all effects are obervable
|
||||||
effects are applied in the program's order
|
in the way as program was executed literally, in order.
|
||||||
|
|
||||||
# Program validation
|
# Program validation
|
||||||
- Invalid program should cause runtime error:
|
- Invalid program should cause runtime error:
|
||||||
|
|
Loading…
Reference in a new issue