Lightningbeam/lightningbeam-ui/beamdsp/src/opcodes.rs

224 lines
6.7 KiB
Rust

/// Bytecode opcodes for the BeamDSP VM
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OpCode {
// Stack operations
PushF32 = 0, // next 4 bytes: f32 constant index (u16)
PushI32 = 1, // next 2 bytes: i32 constant index (u16)
PushBool = 2, // next 1 byte: 0 or 1
Pop = 3,
// Variable access (all use u16 index)
LoadLocal = 10,
StoreLocal = 11,
LoadParam = 12,
LoadState = 13,
StoreState = 14,
// Buffer access (u8 port index)
// LoadInput: pops index from stack, pushes input[port][index]
LoadInput = 20,
// StoreOutput: pops value then index, stores output[port][index] = value
StoreOutput = 21,
// State arrays (u16 array id)
LoadStateArray = 22, // pops index, pushes state_array[id][index]
StoreStateArray = 23, // pops value then index, stores state_array[id][index]
// Sample access (u8 slot index)
SampleLen = 25, // pushes frame count
SampleRead = 26, // pops index, pushes sample data
SampleRateOf = 27, // pushes sample rate
// Float arithmetic
AddF = 30,
SubF = 31,
MulF = 32,
DivF = 33,
ModF = 34,
NegF = 35,
// Int arithmetic
AddI = 40,
SubI = 41,
MulI = 42,
DivI = 43,
ModI = 44,
NegI = 45,
// Float comparison (push bool)
EqF = 50,
NeF = 51,
LtF = 52,
GtF = 53,
LeF = 54,
GeF = 55,
// Int comparison (push bool)
EqI = 60,
NeI = 61,
LtI = 62,
GtI = 63,
LeI = 64,
GeI = 65,
// Logical
And = 70,
Or = 71,
Not = 72,
// Type conversion
F32ToI32 = 80,
I32ToF32 = 81,
// Control flow (u32 offset)
Jump = 90,
JumpIfFalse = 91,
// Built-in math functions (operate on stack)
Sin = 100,
Cos = 101,
Tan = 102,
Asin = 103,
Acos = 104,
Atan = 105,
Atan2 = 106,
Exp = 107,
Log = 108,
Log2 = 109,
Pow = 110,
Sqrt = 111,
Floor = 112,
Ceil = 113,
Round = 114,
Trunc = 115,
Fract = 116,
Abs = 117,
Clamp = 118,
Min = 119,
Max = 120,
Sign = 121,
Mix = 122,
Smoothstep = 123,
IsNan = 124,
// Array/buffer info
ArrayLen = 130, // u16 array_id, pushes length as int
// Built-in constants
LoadSampleRate = 140,
LoadBufferSize = 141,
// Draw commands (pop args from stack, push to draw command buffer)
DrawFillCircle = 150, // pops: color(i32), r, cy, cx
DrawStrokeCircle = 151, // pops: width, color(i32), r, cy, cx
DrawStrokeArc = 152, // pops: width, color(i32), end_deg, start_deg, r, cy, cx
DrawLine = 153, // pops: width, color(i32), y2, x2, y1, x1
DrawFillRect = 154, // pops: color(i32), h, w, y, x
DrawStrokeRect = 155, // pops: width, color(i32), h, w, y, x
// Mouse input (push onto stack)
MouseX = 160, // pushes canvas-relative X as f32
MouseY = 161, // pushes canvas-relative Y as f32
MouseDown = 162, // pushes 1.0 if pressed, 0.0 if not
// Param write (draw context only)
StoreParam = 170, // u16 param index, pops value from stack
Halt = 255,
}
impl OpCode {
pub fn from_u8(v: u8) -> Option<OpCode> {
// Safety: we validate the opcode values
match v {
0 => Some(OpCode::PushF32),
1 => Some(OpCode::PushI32),
2 => Some(OpCode::PushBool),
3 => Some(OpCode::Pop),
10 => Some(OpCode::LoadLocal),
11 => Some(OpCode::StoreLocal),
12 => Some(OpCode::LoadParam),
13 => Some(OpCode::LoadState),
14 => Some(OpCode::StoreState),
20 => Some(OpCode::LoadInput),
21 => Some(OpCode::StoreOutput),
22 => Some(OpCode::LoadStateArray),
23 => Some(OpCode::StoreStateArray),
25 => Some(OpCode::SampleLen),
26 => Some(OpCode::SampleRead),
27 => Some(OpCode::SampleRateOf),
30 => Some(OpCode::AddF),
31 => Some(OpCode::SubF),
32 => Some(OpCode::MulF),
33 => Some(OpCode::DivF),
34 => Some(OpCode::ModF),
35 => Some(OpCode::NegF),
40 => Some(OpCode::AddI),
41 => Some(OpCode::SubI),
42 => Some(OpCode::MulI),
43 => Some(OpCode::DivI),
44 => Some(OpCode::ModI),
45 => Some(OpCode::NegI),
50 => Some(OpCode::EqF),
51 => Some(OpCode::NeF),
52 => Some(OpCode::LtF),
53 => Some(OpCode::GtF),
54 => Some(OpCode::LeF),
55 => Some(OpCode::GeF),
60 => Some(OpCode::EqI),
61 => Some(OpCode::NeI),
62 => Some(OpCode::LtI),
63 => Some(OpCode::GtI),
64 => Some(OpCode::LeI),
65 => Some(OpCode::GeI),
70 => Some(OpCode::And),
71 => Some(OpCode::Or),
72 => Some(OpCode::Not),
80 => Some(OpCode::F32ToI32),
81 => Some(OpCode::I32ToF32),
90 => Some(OpCode::Jump),
91 => Some(OpCode::JumpIfFalse),
100 => Some(OpCode::Sin),
101 => Some(OpCode::Cos),
102 => Some(OpCode::Tan),
103 => Some(OpCode::Asin),
104 => Some(OpCode::Acos),
105 => Some(OpCode::Atan),
106 => Some(OpCode::Atan2),
107 => Some(OpCode::Exp),
108 => Some(OpCode::Log),
109 => Some(OpCode::Log2),
110 => Some(OpCode::Pow),
111 => Some(OpCode::Sqrt),
112 => Some(OpCode::Floor),
113 => Some(OpCode::Ceil),
114 => Some(OpCode::Round),
115 => Some(OpCode::Trunc),
116 => Some(OpCode::Fract),
117 => Some(OpCode::Abs),
118 => Some(OpCode::Clamp),
119 => Some(OpCode::Min),
120 => Some(OpCode::Max),
121 => Some(OpCode::Sign),
122 => Some(OpCode::Mix),
123 => Some(OpCode::Smoothstep),
124 => Some(OpCode::IsNan),
130 => Some(OpCode::ArrayLen),
140 => Some(OpCode::LoadSampleRate),
141 => Some(OpCode::LoadBufferSize),
150 => Some(OpCode::DrawFillCircle),
151 => Some(OpCode::DrawStrokeCircle),
152 => Some(OpCode::DrawStrokeArc),
153 => Some(OpCode::DrawLine),
154 => Some(OpCode::DrawFillRect),
155 => Some(OpCode::DrawStrokeRect),
160 => Some(OpCode::MouseX),
161 => Some(OpCode::MouseY),
162 => Some(OpCode::MouseDown),
170 => Some(OpCode::StoreParam),
255 => Some(OpCode::Halt),
_ => None,
}
}
}