Compare commits
8 Commits
15e4832623
...
d0f9014f03
Author | SHA1 | Date |
---|---|---|
_ | d0f9014f03 | |
_ | ae858ebe70 | |
_ | 46cf5837bc | |
_ | e59dd85246 | |
_ | 1943f0a40b | |
_ | 81743108c3 | |
_ | 64384e7ca5 | |
_ | 9bfd3c64c3 |
|
@ -1,10 +1,13 @@
|
|||
#[derive (Debug, PartialEq)]
|
||||
pub enum Instruction {
|
||||
Add (u8, u8, u8),
|
||||
AddI (u8, u8, i8),
|
||||
|
||||
Call (u8, u8, u8),
|
||||
Closure (u8, u32),
|
||||
|
||||
Div (u8, u8, u8),
|
||||
|
||||
EqI (u8, i8, bool),
|
||||
|
||||
// Equals Constant?
|
||||
|
@ -51,6 +54,8 @@ pub enum Instruction {
|
|||
// MetaMethod, Binary
|
||||
MmBin (u8, u8, u8),
|
||||
|
||||
MmBinI (u8, i8, u8, bool),
|
||||
|
||||
MmBinK (u8, u8, u8, bool),
|
||||
|
||||
ModK (u8, u8, u8),
|
||||
|
@ -59,6 +64,8 @@ pub enum Instruction {
|
|||
|
||||
Mul (u8, u8, u8),
|
||||
|
||||
MulK (u8, u8, u8),
|
||||
|
||||
NewTable (u8),
|
||||
|
||||
Not (u8, u8),
|
||||
|
@ -79,9 +86,13 @@ pub enum Instruction {
|
|||
|
||||
SetTabUp (u8, u8, u8),
|
||||
|
||||
Sub (u8, u8, u8),
|
||||
|
||||
TailCall (u8, u8, u8, bool),
|
||||
|
||||
Test (u8, bool),
|
||||
|
||||
UnM (u8, u8),
|
||||
|
||||
VarArgPrep (i32),
|
||||
}
|
||||
|
|
|
@ -71,6 +71,11 @@ fn i_sb (buf: [u8; 4]) -> Option <i8> {
|
|||
i8::try_from (i32::try_from (b).ok ()? - 127).ok ()
|
||||
}
|
||||
|
||||
fn i_sc (buf: [u8; 4]) -> Option <i8> {
|
||||
let c = buf [3];
|
||||
i8::try_from (i32::try_from (c).ok ()? - 127).ok ()
|
||||
}
|
||||
|
||||
pub fn parse_inst (buf: [u8; 4]) -> Option <Inst>
|
||||
{
|
||||
let opcode = buf [0] & 0x7f;
|
||||
|
@ -104,11 +109,17 @@ pub fn parse_inst (buf: [u8; 4]) -> Option <Inst>
|
|||
0x11 => Inst::SetI (a, b, c, k),
|
||||
0x12 => Inst::SetField (a, b, c, k),
|
||||
0x13 => Inst::NewTable (a),
|
||||
0x15 => Inst::AddI (a, b, i_sc (buf)?),
|
||||
0x18 => Inst::MulK (a, b, c),
|
||||
0x19 => Inst::ModK (a, b, c),
|
||||
0x22 => Inst::Add (a, b, c),
|
||||
0x23 => Inst::Sub (a, b, c),
|
||||
0x24 => Inst::Mul (a, b, c),
|
||||
0x27 => Inst::Div (a, b, c),
|
||||
0x2e => Inst::MmBin (a, b, c),
|
||||
0x2f => Inst::MmBinI (a, i_sb (buf)?, c, k),
|
||||
0x30 => Inst::MmBinK (a, b, c, k),
|
||||
0x31 => Inst::UnM (a, b),
|
||||
0x33 => Inst::Not (a, b),
|
||||
0x34 => Inst::Len (a, b),
|
||||
0x3c => Inst::EqK (a, b, k),
|
||||
|
@ -219,7 +230,7 @@ pub fn parse_block <R: Read> (rdr: &mut R, blocks: &mut Vec <Block>)
|
|||
parse_byte (rdr).unwrap (); // is_vararg
|
||||
parse_byte (rdr).unwrap (); // maxstacksize, might be same as num slots?
|
||||
|
||||
let inst_count = parse_int (rdr).unwrap ();
|
||||
let inst_count = load_size (rdr);
|
||||
let mut instructions = Vec::with_capacity (inst_count as usize);
|
||||
|
||||
for _ in 0..inst_count {
|
||||
|
@ -285,24 +296,27 @@ pub fn parse_block <R: Read> (rdr: &mut R, blocks: &mut Vec <Block>)
|
|||
// I think this is delta line numbers, e.g. most instructions
|
||||
// have 0, but when you go to a new source line it's 1+.
|
||||
|
||||
let lineinfo_count = parse_int (rdr).unwrap ();
|
||||
let lineinfo_count = load_size (rdr);
|
||||
for _ in 0..lineinfo_count {
|
||||
parse_byte (rdr).unwrap ();
|
||||
}
|
||||
|
||||
// Absolute line info, didn't see that in my test files
|
||||
|
||||
let abslineinfo_count = parse_int (rdr).unwrap ();
|
||||
assert_eq! (abslineinfo_count, 0);
|
||||
|
||||
let local_count = parse_int (rdr).unwrap ();
|
||||
for _ in 0..local_count {
|
||||
parse_string(rdr).unwrap ();
|
||||
parse_int (rdr).unwrap ();
|
||||
parse_int (rdr).unwrap ();
|
||||
let abslineinfo_count = load_size (rdr);
|
||||
for _ in 0..abslineinfo_count {
|
||||
load_unsigned (rdr, usize::MAX);
|
||||
load_unsigned (rdr, usize::MAX);
|
||||
}
|
||||
|
||||
let upvalue_count = parse_int (rdr).unwrap ();
|
||||
let local_count = load_size (rdr);
|
||||
for _ in 0..local_count {
|
||||
parse_string(rdr);
|
||||
load_unsigned (rdr, usize::MAX);
|
||||
load_unsigned (rdr, usize::MAX);
|
||||
}
|
||||
|
||||
let upvalue_count = load_size (rdr);
|
||||
for _ in 0..upvalue_count {
|
||||
parse_string (rdr).unwrap ();
|
||||
}
|
||||
|
|
80
src/state.rs
80
src/state.rs
|
@ -178,6 +178,20 @@ impl <'a> State <'a> {
|
|||
|
||||
*self.reg_mut (*a) = x;
|
||||
},
|
||||
Instruction::AddI (a, b, s_c) => {
|
||||
let v_b = self.reg (*b);
|
||||
|
||||
let x = if let Some (v_b) = v_b.as_int ()
|
||||
{
|
||||
Value::from (v_b + *s_c as i64)
|
||||
}
|
||||
else {
|
||||
let v_b = v_b.as_float ().unwrap_or_else (|| panic! ("{v_b}"));
|
||||
Value::from (v_b + f64::from (*s_c))
|
||||
};
|
||||
|
||||
*self.reg_mut (*a) = x;
|
||||
},
|
||||
Instruction::Call (a, b, _c) => {
|
||||
let b = usize::from (*b);
|
||||
|
||||
|
@ -269,6 +283,22 @@ impl <'a> State <'a> {
|
|||
upvalues: new_upvalues,
|
||||
});
|
||||
},
|
||||
Instruction::Div (a, b, c) => {
|
||||
let v_b = self.reg (*b);
|
||||
let v_c = self.reg (*c);
|
||||
|
||||
let x = if let (Some (v_b), Some (v_c)) = (v_b.as_int (), v_c.as_int ())
|
||||
{
|
||||
Value::from (v_b / v_c)
|
||||
}
|
||||
else {
|
||||
let v_b = v_b.as_float ().unwrap_or_else (|| panic! ("{v_b}"));
|
||||
let v_c = v_c.as_float ().unwrap_or_else (|| panic! ("{v_c}"));
|
||||
Value::from (v_b / v_c)
|
||||
};
|
||||
|
||||
*self.reg_mut (*a) = x;
|
||||
},
|
||||
Instruction::EqI (a, sb, k_flag) => {
|
||||
if (self.reg (*a).as_int ().unwrap () == *sb as i64) != *k_flag
|
||||
{
|
||||
|
@ -311,6 +341,7 @@ impl <'a> State <'a> {
|
|||
},
|
||||
Instruction::GetField (a, b, c) => {
|
||||
let t = match self.reg (*b) {
|
||||
Value::Nil => panic! ("R[B] must not be nil"),
|
||||
Value::Table (t) => t,
|
||||
_ => panic! ("R[B] must be a table"),
|
||||
};
|
||||
|
@ -434,6 +465,9 @@ impl <'a> State <'a> {
|
|||
panic! ("Not sure how to implememtn OP_MMBIN for these 2 values {a:?}, {b:?}");
|
||||
}
|
||||
},
|
||||
Instruction::MmBinI (_a, _s_b, _c, _k) => {
|
||||
// Ignore
|
||||
},
|
||||
Instruction::MmBinK (_a, _b, _c, _k) => {
|
||||
// Ignore
|
||||
},
|
||||
|
@ -465,6 +499,22 @@ impl <'a> State <'a> {
|
|||
|
||||
*self.reg_mut (*a) = x;
|
||||
},
|
||||
Instruction::MulK (a, b, c) => {
|
||||
let v_b = self.reg (*b);
|
||||
let v_c = &k [usize::from (*c)];
|
||||
|
||||
let x = if let (Some (v_b), Some (v_c)) = (v_b.as_int (), v_c.as_int ())
|
||||
{
|
||||
Value::from (v_b * v_c)
|
||||
}
|
||||
else {
|
||||
let v_b = v_b.as_float ().unwrap_or_else (|| panic! ("{v_b}"));
|
||||
let v_c = v_c.as_float ().unwrap_or_else (|| panic! ("{v_c}"));
|
||||
Value::from (v_b * v_c)
|
||||
};
|
||||
|
||||
*self.reg_mut (*a) = x;
|
||||
},
|
||||
Instruction::NewTable (a) => {
|
||||
*self.reg_mut (*a) = Value::Table (Default::default ());
|
||||
},
|
||||
|
@ -603,6 +653,22 @@ impl <'a> State <'a> {
|
|||
}
|
||||
},
|
||||
Instruction::SetTabUp (_a, _b, _c) => unimplemented! (),
|
||||
Instruction::Sub (a, b, c) => {
|
||||
let v_b = self.reg (*b);
|
||||
let v_c = self.reg (*c);
|
||||
|
||||
let x = if let (Some (v_b), Some (v_c)) = (v_b.as_int (), v_c.as_int ())
|
||||
{
|
||||
Value::from (v_b - v_c)
|
||||
}
|
||||
else {
|
||||
let v_b = v_b.as_float ().unwrap_or_else (|| panic! ("{v_b}"));
|
||||
let v_c = v_c.as_float ().unwrap_or_else (|| panic! ("{v_c}"));
|
||||
Value::from (v_b - v_c)
|
||||
};
|
||||
|
||||
*self.reg_mut (*a) = x;
|
||||
},
|
||||
Instruction::TailCall (a, b, _c, k) => {
|
||||
assert! (!k, "closing over values in tail calls not implemented");
|
||||
|
||||
|
@ -638,6 +704,20 @@ impl <'a> State <'a> {
|
|||
next_pc += 1;
|
||||
}
|
||||
},
|
||||
Instruction::UnM (a, b) => {
|
||||
let v_b = self.reg (*b);
|
||||
|
||||
let x = if let Some (v_b) = v_b.as_int ()
|
||||
{
|
||||
Value::from (-v_b)
|
||||
}
|
||||
else {
|
||||
let v_b = v_b.as_float ().unwrap_or_else (|| panic! ("{v_b}"));
|
||||
Value::from (-v_b)
|
||||
};
|
||||
|
||||
*self.reg_mut (*a) = x;
|
||||
},
|
||||
Instruction::VarArgPrep (_) => (),
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
-- The Computer Language Benchmarks Game
|
||||
-- https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
|
||||
-- contributed by Mike Pall
|
||||
-- modified by Geoff Leyland
|
||||
|
||||
local sqrt = math.sqrt
|
||||
|
||||
local PI = 3.141592653589793
|
||||
local SOLAR_MASS = 4 * PI * PI
|
||||
local DAYS_PER_YEAR = 365.24
|
||||
local bodies = {
|
||||
{ -- Sun
|
||||
x = 0,
|
||||
y = 0,
|
||||
z = 0,
|
||||
vx = 0,
|
||||
vy = 0,
|
||||
vz = 0,
|
||||
mass = SOLAR_MASS
|
||||
},
|
||||
{ -- Jupiter
|
||||
x = 4.84143144246472090e+00,
|
||||
y = -1.16032004402742839e+00,
|
||||
z = -1.03622044471123109e-01,
|
||||
vx = 1.66007664274403694e-03 * DAYS_PER_YEAR,
|
||||
vy = 7.69901118419740425e-03 * DAYS_PER_YEAR,
|
||||
vz = -6.90460016972063023e-05 * DAYS_PER_YEAR,
|
||||
mass = 9.54791938424326609e-04 * SOLAR_MASS
|
||||
},
|
||||
{ -- Saturn
|
||||
x = 8.34336671824457987e+00,
|
||||
y = 4.12479856412430479e+00,
|
||||
z = -4.03523417114321381e-01,
|
||||
vx = -2.76742510726862411e-03 * DAYS_PER_YEAR,
|
||||
vy = 4.99852801234917238e-03 * DAYS_PER_YEAR,
|
||||
vz = 2.30417297573763929e-05 * DAYS_PER_YEAR,
|
||||
mass = 2.85885980666130812e-04 * SOLAR_MASS
|
||||
},
|
||||
{ -- Uranus
|
||||
x = 1.28943695621391310e+01,
|
||||
y = -1.51111514016986312e+01,
|
||||
z = -2.23307578892655734e-01,
|
||||
vx = 2.96460137564761618e-03 * DAYS_PER_YEAR,
|
||||
vy = 2.37847173959480950e-03 * DAYS_PER_YEAR,
|
||||
vz = -2.96589568540237556e-05 * DAYS_PER_YEAR,
|
||||
mass = 4.36624404335156298e-05 * SOLAR_MASS
|
||||
},
|
||||
{ -- Neptune
|
||||
x = 1.53796971148509165e+01,
|
||||
y = -2.59193146099879641e+01,
|
||||
z = 1.79258772950371181e-01,
|
||||
vx = 2.68067772490389322e-03 * DAYS_PER_YEAR,
|
||||
vy = 1.62824170038242295e-03 * DAYS_PER_YEAR,
|
||||
vz = -9.51592254519715870e-05 * DAYS_PER_YEAR,
|
||||
mass = 5.15138902046611451e-05 * SOLAR_MASS
|
||||
}
|
||||
}
|
||||
|
||||
local function advance(bodies, nbody, dt)
|
||||
for i=1,nbody do
|
||||
local bi = bodies[i]
|
||||
local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass
|
||||
local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz
|
||||
for j=i+1,nbody do
|
||||
local bj = bodies[j]
|
||||
local dx, dy, dz = bix-bj.x, biy-bj.y, biz-bj.z
|
||||
local mag = sqrt(dx*dx + dy*dy + dz*dz)
|
||||
mag = dt / (mag * mag * mag)
|
||||
local bm = bj.mass*mag
|
||||
bivx = bivx - (dx * bm)
|
||||
bivy = bivy - (dy * bm)
|
||||
bivz = bivz - (dz * bm)
|
||||
bm = bimass*mag
|
||||
bj.vx = bj.vx + (dx * bm)
|
||||
bj.vy = bj.vy + (dy * bm)
|
||||
bj.vz = bj.vz + (dz * bm)
|
||||
end
|
||||
bi.vx = bivx
|
||||
bi.vy = bivy
|
||||
bi.vz = bivz
|
||||
bi.x = bix + dt * bivx
|
||||
bi.y = biy + dt * bivy
|
||||
bi.z = biz + dt * bivz
|
||||
end
|
||||
end
|
||||
|
||||
local function energy(bodies, nbody)
|
||||
local e = 0
|
||||
for i=1,nbody do
|
||||
local bi = bodies[i]
|
||||
local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass
|
||||
e = e + (0.5 * bim * (vx*vx + vy*vy + vz*vz))
|
||||
for j=i+1,nbody do
|
||||
local bj = bodies[j]
|
||||
local dx, dy, dz = bi.x-bj.x, bi.y-bj.y, bi.z-bj.z
|
||||
local distance = sqrt(dx*dx + dy*dy + dz*dz)
|
||||
e = e - ((bim * bj.mass) / distance)
|
||||
end
|
||||
end
|
||||
return e
|
||||
end
|
||||
|
||||
local function offsetMomentum(b, nbody)
|
||||
local px, py, pz = 0, 0, 0
|
||||
for i=1,nbody do
|
||||
local bi = b[i]
|
||||
local bim = bi.mass
|
||||
px = px + (bi.vx * bim)
|
||||
py = py + (bi.vy * bim)
|
||||
pz = pz + (bi.vz * bim)
|
||||
end
|
||||
b[1].vx = -px / SOLAR_MASS
|
||||
b[1].vy = -py / SOLAR_MASS
|
||||
b[1].vz = -pz / SOLAR_MASS
|
||||
end
|
||||
|
||||
local N = tonumber(arg and arg[1]) or 1000
|
||||
local nbody = #bodies
|
||||
|
||||
offsetMomentum(bodies, nbody)
|
||||
io.write( string.format("%0.9f",energy(bodies, nbody)), "\n")
|
||||
for i=1,N do advance(bodies, nbody, 0.01) end
|
||||
io.write( string.format("%0.9f",energy(bodies, nbody)), "\n")
|
Loading…
Reference in New Issue