Compare commits
8 Commits
15e4832623
...
d0f9014f03
Author | SHA1 | Date |
---|---|---|
_ | d0f9014f03 | |
_ | ae858ebe70 | |
_ | 46cf5837bc | |
_ | e59dd85246 | |
_ | 1943f0a40b | |
_ | 81743108c3 | |
_ | 64384e7ca5 | |
_ | 9bfd3c64c3 |
|
@ -1,10 +1,13 @@
|
||||||
#[derive (Debug, PartialEq)]
|
#[derive (Debug, PartialEq)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Add (u8, u8, u8),
|
Add (u8, u8, u8),
|
||||||
|
AddI (u8, u8, i8),
|
||||||
|
|
||||||
Call (u8, u8, u8),
|
Call (u8, u8, u8),
|
||||||
Closure (u8, u32),
|
Closure (u8, u32),
|
||||||
|
|
||||||
|
Div (u8, u8, u8),
|
||||||
|
|
||||||
EqI (u8, i8, bool),
|
EqI (u8, i8, bool),
|
||||||
|
|
||||||
// Equals Constant?
|
// Equals Constant?
|
||||||
|
@ -51,6 +54,8 @@ pub enum Instruction {
|
||||||
// MetaMethod, Binary
|
// MetaMethod, Binary
|
||||||
MmBin (u8, u8, u8),
|
MmBin (u8, u8, u8),
|
||||||
|
|
||||||
|
MmBinI (u8, i8, u8, bool),
|
||||||
|
|
||||||
MmBinK (u8, u8, u8, bool),
|
MmBinK (u8, u8, u8, bool),
|
||||||
|
|
||||||
ModK (u8, u8, u8),
|
ModK (u8, u8, u8),
|
||||||
|
@ -59,6 +64,8 @@ pub enum Instruction {
|
||||||
|
|
||||||
Mul (u8, u8, u8),
|
Mul (u8, u8, u8),
|
||||||
|
|
||||||
|
MulK (u8, u8, u8),
|
||||||
|
|
||||||
NewTable (u8),
|
NewTable (u8),
|
||||||
|
|
||||||
Not (u8, u8),
|
Not (u8, u8),
|
||||||
|
@ -79,9 +86,13 @@ pub enum Instruction {
|
||||||
|
|
||||||
SetTabUp (u8, u8, u8),
|
SetTabUp (u8, u8, u8),
|
||||||
|
|
||||||
|
Sub (u8, u8, u8),
|
||||||
|
|
||||||
TailCall (u8, u8, u8, bool),
|
TailCall (u8, u8, u8, bool),
|
||||||
|
|
||||||
Test (u8, bool),
|
Test (u8, bool),
|
||||||
|
|
||||||
|
UnM (u8, u8),
|
||||||
|
|
||||||
VarArgPrep (i32),
|
VarArgPrep (i32),
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,11 @@ fn i_sb (buf: [u8; 4]) -> Option <i8> {
|
||||||
i8::try_from (i32::try_from (b).ok ()? - 127).ok ()
|
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>
|
pub fn parse_inst (buf: [u8; 4]) -> Option <Inst>
|
||||||
{
|
{
|
||||||
let opcode = buf [0] & 0x7f;
|
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),
|
0x11 => Inst::SetI (a, b, c, k),
|
||||||
0x12 => Inst::SetField (a, b, c, k),
|
0x12 => Inst::SetField (a, b, c, k),
|
||||||
0x13 => Inst::NewTable (a),
|
0x13 => Inst::NewTable (a),
|
||||||
|
0x15 => Inst::AddI (a, b, i_sc (buf)?),
|
||||||
|
0x18 => Inst::MulK (a, b, c),
|
||||||
0x19 => Inst::ModK (a, b, c),
|
0x19 => Inst::ModK (a, b, c),
|
||||||
0x22 => Inst::Add (a, b, c),
|
0x22 => Inst::Add (a, b, c),
|
||||||
|
0x23 => Inst::Sub (a, b, c),
|
||||||
0x24 => Inst::Mul (a, b, c),
|
0x24 => Inst::Mul (a, b, c),
|
||||||
|
0x27 => Inst::Div (a, b, c),
|
||||||
0x2e => Inst::MmBin (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),
|
0x30 => Inst::MmBinK (a, b, c, k),
|
||||||
|
0x31 => Inst::UnM (a, b),
|
||||||
0x33 => Inst::Not (a, b),
|
0x33 => Inst::Not (a, b),
|
||||||
0x34 => Inst::Len (a, b),
|
0x34 => Inst::Len (a, b),
|
||||||
0x3c => Inst::EqK (a, b, k),
|
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 (); // is_vararg
|
||||||
parse_byte (rdr).unwrap (); // maxstacksize, might be same as num slots?
|
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);
|
let mut instructions = Vec::with_capacity (inst_count as usize);
|
||||||
|
|
||||||
for _ in 0..inst_count {
|
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
|
// 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+.
|
// 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 {
|
for _ in 0..lineinfo_count {
|
||||||
parse_byte (rdr).unwrap ();
|
parse_byte (rdr).unwrap ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Absolute line info, didn't see that in my test files
|
// Absolute line info, didn't see that in my test files
|
||||||
|
|
||||||
let abslineinfo_count = parse_int (rdr).unwrap ();
|
let abslineinfo_count = load_size (rdr);
|
||||||
assert_eq! (abslineinfo_count, 0);
|
for _ in 0..abslineinfo_count {
|
||||||
|
load_unsigned (rdr, usize::MAX);
|
||||||
let local_count = parse_int (rdr).unwrap ();
|
load_unsigned (rdr, usize::MAX);
|
||||||
for _ in 0..local_count {
|
|
||||||
parse_string(rdr).unwrap ();
|
|
||||||
parse_int (rdr).unwrap ();
|
|
||||||
parse_int (rdr).unwrap ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
for _ in 0..upvalue_count {
|
||||||
parse_string (rdr).unwrap ();
|
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;
|
*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) => {
|
Instruction::Call (a, b, _c) => {
|
||||||
let b = usize::from (*b);
|
let b = usize::from (*b);
|
||||||
|
|
||||||
|
@ -269,6 +283,22 @@ impl <'a> State <'a> {
|
||||||
upvalues: new_upvalues,
|
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) => {
|
Instruction::EqI (a, sb, k_flag) => {
|
||||||
if (self.reg (*a).as_int ().unwrap () == *sb as i64) != *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) => {
|
Instruction::GetField (a, b, c) => {
|
||||||
let t = match self.reg (*b) {
|
let t = match self.reg (*b) {
|
||||||
|
Value::Nil => panic! ("R[B] must not be nil"),
|
||||||
Value::Table (t) => t,
|
Value::Table (t) => t,
|
||||||
_ => panic! ("R[B] must be a table"),
|
_ => 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:?}");
|
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) => {
|
Instruction::MmBinK (_a, _b, _c, _k) => {
|
||||||
// Ignore
|
// Ignore
|
||||||
},
|
},
|
||||||
|
@ -465,6 +499,22 @@ impl <'a> State <'a> {
|
||||||
|
|
||||||
*self.reg_mut (*a) = x;
|
*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) => {
|
Instruction::NewTable (a) => {
|
||||||
*self.reg_mut (*a) = Value::Table (Default::default ());
|
*self.reg_mut (*a) = Value::Table (Default::default ());
|
||||||
},
|
},
|
||||||
|
@ -603,6 +653,22 @@ impl <'a> State <'a> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Instruction::SetTabUp (_a, _b, _c) => unimplemented! (),
|
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) => {
|
Instruction::TailCall (a, b, _c, k) => {
|
||||||
assert! (!k, "closing over values in tail calls not implemented");
|
assert! (!k, "closing over values in tail calls not implemented");
|
||||||
|
|
||||||
|
@ -638,6 +704,20 @@ impl <'a> State <'a> {
|
||||||
next_pc += 1;
|
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 (_) => (),
|
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