rslua_march1917/
opcodes.rs

1// Comments from lopcodes.h
2// We assume that instructions are unsigned numbers.
3// All instructions have an opcode in the first 6 bits.
4// Instructions can have the following fields:
5// 	'A' : 8 bits
6// 	'B' : 9 bits
7// 	'C' : 9 bits
8// 	'Ax' : 26 bits ('A', 'B', and 'C' together)
9// 	'Bx' : 18 bits ('B' and 'C' together)
10//  'sBx' : signed Bx
11
12// A signed argument is represented in excess K; that is, the number
13// value is the unsigned value minus K. K is exactly the maximum value
14// for that argument (so that -max is represented by 0, and +max is
15// represented by 2*max), which is half the maximum for the corresponding
16// unsigned argument.
17
18#[derive(Debug, Copy, Clone)]
19pub enum OpMode {
20    IA,
21    IAB,
22    IABC,
23    IABx,
24    IAsBx,
25    IAx,
26    IAC,
27}
28
29pub const SIZE_OP: u32 = 6;
30pub const SIZE_A: u32 = 8;
31pub const SIZE_B: u32 = 9;
32pub const SIZE_C: u32 = 9;
33pub const SIZE_AX: u32 = SIZE_C + SIZE_B + SIZE_A;
34pub const SIZE_BX: u32 = SIZE_C + SIZE_B;
35
36pub const POS_OP: u32 = 0;
37pub const POS_A: u32 = POS_OP + SIZE_OP;
38pub const POS_C: u32 = POS_A + SIZE_A;
39pub const POS_B: u32 = POS_C + SIZE_C;
40pub const POS_BX: u32 = POS_C;
41pub const POS_AX: u32 = POS_A;
42
43pub const MAXARG_A: u32 = (1 << SIZE_A) - 1;
44pub const MAXARG_B: u32 = (1 << SIZE_B) - 1;
45pub const MAXARG_C: u32 = (1 << SIZE_C) - 1;
46pub const MAXARG_AX: u32 = (1 << SIZE_AX) - 1;
47pub const MAXARG_BX: u32 = (1 << SIZE_BX) - 1;
48pub const MAXARG_SBX: i32 = (MAXARG_BX as i32) >> 1;
49
50pub const MASK_K: u32 = 1 << (SIZE_B - 1);
51
52pub const NO_JUMP: i32 = -1;
53pub const NO_REG: u32 = MAXARG_A;
54
55pub fn is_const(index: u32) -> bool {
56    index & MASK_K != 0
57}
58
59pub fn is_var(index: u32) -> bool {
60    !is_const(index)
61}
62
63#[derive(Debug, Clone, Copy, PartialEq)]
64pub enum OpCode {
65    // A B
66    // R(A) := R(B)
67    Move = 0,
68    // A Bx
69    // R(A) := Kst(Bx)
70    LoadK,
71    // A
72    // R(A) := Kst(extra arg)
73    LoadKx,
74    // A B C
75    // R(A) := (bool)B;
76    // if (C) pc++
77    LoadBool,
78    // A B
79    // R(A), R(A + 1), ..., R(A + B) := nil
80    LoadNil,
81    // A B
82    // R(A) := UpValue[B]
83    GetUpVal,
84
85    // A B C
86    // R(A) := UpValue[B][RK(C)]
87    GetTabUp,
88    // A B C
89    // R(A) := R(B)[RK(C)]
90    GetTable,
91
92    // A B C
93    // UpValue[A][RK(B)] := RK(C)
94    SetTabUp,
95    // A B
96    // UpValue[B] := R(A)
97    SetUpVal,
98    // A B C
99    // R(A)[RK(B)] := RK(C)
100    SetTable,
101
102    // A B C
103    // R(A) := {} (size = B, C)
104    NewTable,
105
106    // A B C
107    // R(A + 1) := R(B);
108    // R(A) := R(B)[RK(C)]
109    Self_,
110
111    // A B C
112    // R(A) := RK(B) + RK(C)
113    Add,
114    // A B C
115    // R(A) := RK(B) - RK(C)
116    Sub,
117    // A B C
118    // R(A) := RK(B) * RK(C)
119    Mul,
120    // A B C
121    // R(A) := RK(B) % RK(C)
122    Mod,
123    // A B C
124    // R(A) := RK(B) ^ RK(C)
125    Pow,
126    // A B C
127    // R(A) := RK(B) / RK(C)
128    Div,
129    // A B C
130    // R(A) := RK(B) // RK(C)
131    IDiv,
132    // A B C
133    // R(A) := RK(B) & RK(C)
134    BAdd,
135    // A B C
136    // R(A) := RK(B) | RK(C)
137    BOr,
138    // A B C
139    // R(A) := RK(B) ~ RK(C)
140    BXor,
141    // A B C
142    // R(A) := RK(B) << RK(C)
143    Shl,
144    // A B C
145    // R(A) := RK(B) >> RK(C)
146    Shr,
147
148    // A B
149    // R(A) := -R(B)
150    Unm,
151    // A B
152    // R(A) := ~R(B)
153    BNot,
154    // A B
155    // R(A) := not R(B)
156    Not,
157    // A B
158    // R(A) := # R(B)
159    Len,
160
161    // A B C
162    // R(A) := R(B).. ... ..R(C)
163    Concat,
164
165    // A sBx
166    // pc += sBx;
167    // if (A) close all upvalues >= R(A - 1)
168    Jmp,
169
170    // A B C
171    // if ((RK(B) == RK(C)) ~= A) then pc++
172    Eq,
173    // A B C
174    // if ((RK(B) < RK(C)) ~= A) then pc++
175    Lt,
176    // A B C
177    // if ((RK(B) <= RK(C)) ~= A) then pc++
178    Le,
179
180    // A C
181    // if not (R(A) <=> C) then pc++
182    Test,
183    // A B C
184    // if (R(B) <=> C) then R(A) := R(B) else pc++
185    TestSet,
186
187    // A B C
188    // R(A), ... , R(A + C - 2) := R(A)(R(A + 1), ... , R(A + B - 1))
189    Call,
190
191    // A B C
192    // return R(A)(R(A + 1), ..., R(A + B - 1))
193    TailCall,
194
195    // A B
196    // return R(A), ... , R(A + B - 2)
197    Return,
198
199    // A sBx
200    // R(A) += R(A+2);
201    // if R(A) <= R(A + 1) then { pc += sBx; R(A+3) = R(A) }
202    ForLoop,
203    // A sBx
204    // R(A) -= R(A + 2);
205    // pc += sBx
206    ForPrep,
207
208    // A C
209    // R(A + 3), ... R(A + 2 + C) := R(A)(R(A + 1), R(A + 2))
210    TForCall,
211    // A sBx
212    // if R(A + 1) ~= nil then { R(A) = R(A + 1); pc += sBx }
213    TForLoop,
214
215    // A B C
216    // R(A)[(C-1)*FPF + i] := R(A + i), i <= i <= B
217    SetList,
218
219    // A Bx
220    // R(A) := closure(KPROTO[Bx])
221    Closure,
222
223    // A B
224    // R(A), R(A + 1), ..., R(A + B - 2) = vararg
225    Vararg,
226
227    // Ax
228    // extra (larger) argument for previous opcode
229    ExtraArg,
230}
231
232impl OpCode {
233    pub fn from_u32(u: u32) -> OpCode {
234        match u {
235            _ if OpCode::Move as u32 == u => OpCode::Move,
236            _ if OpCode::LoadK as u32 == u => OpCode::LoadK,
237            _ if OpCode::LoadKx as u32 == u => OpCode::LoadKx,
238            _ if OpCode::LoadBool as u32 == u => OpCode::LoadBool,
239            _ if OpCode::LoadNil as u32 == u => OpCode::LoadNil,
240            _ if OpCode::GetUpVal as u32 == u => OpCode::GetUpVal,
241            _ if OpCode::GetTabUp as u32 == u => OpCode::GetTabUp,
242            _ if OpCode::GetTable as u32 == u => OpCode::GetTable,
243            _ if OpCode::SetTabUp as u32 == u => OpCode::SetTabUp,
244            _ if OpCode::SetUpVal as u32 == u => OpCode::SetUpVal,
245            _ if OpCode::SetTable as u32 == u => OpCode::SetTable,
246            _ if OpCode::NewTable as u32 == u => OpCode::NewTable,
247            _ if OpCode::Self_ as u32 == u => OpCode::Self_,
248            _ if OpCode::Add as u32 == u => OpCode::Add,
249            _ if OpCode::Sub as u32 == u => OpCode::Sub,
250            _ if OpCode::Mul as u32 == u => OpCode::Mul,
251            _ if OpCode::Mod as u32 == u => OpCode::Mod,
252            _ if OpCode::Pow as u32 == u => OpCode::Pow,
253            _ if OpCode::Div as u32 == u => OpCode::Div,
254            _ if OpCode::IDiv as u32 == u => OpCode::IDiv,
255            _ if OpCode::BAdd as u32 == u => OpCode::BAdd,
256            _ if OpCode::BOr as u32 == u => OpCode::BOr,
257            _ if OpCode::BXor as u32 == u => OpCode::BXor,
258            _ if OpCode::Shl as u32 == u => OpCode::Shl,
259            _ if OpCode::Shr as u32 == u => OpCode::Shr,
260            _ if OpCode::Unm as u32 == u => OpCode::Unm,
261            _ if OpCode::BNot as u32 == u => OpCode::BNot,
262            _ if OpCode::Not as u32 == u => OpCode::Not,
263            _ if OpCode::Len as u32 == u => OpCode::Len,
264            _ if OpCode::Concat as u32 == u => OpCode::Concat,
265            _ if OpCode::Jmp as u32 == u => OpCode::Jmp,
266            _ if OpCode::Eq as u32 == u => OpCode::Eq,
267            _ if OpCode::Lt as u32 == u => OpCode::Lt,
268            _ if OpCode::Le as u32 == u => OpCode::Le,
269            _ if OpCode::Test as u32 == u => OpCode::Test,
270            _ if OpCode::TestSet as u32 == u => OpCode::TestSet,
271            _ if OpCode::Call as u32 == u => OpCode::Call,
272            _ if OpCode::TailCall as u32 == u => OpCode::TailCall,
273            _ if OpCode::Return as u32 == u => OpCode::Return,
274            _ if OpCode::ForLoop as u32 == u => OpCode::ForLoop,
275            _ if OpCode::ForPrep as u32 == u => OpCode::ForPrep,
276            _ if OpCode::TForCall as u32 == u => OpCode::TForCall,
277            _ if OpCode::TForLoop as u32 == u => OpCode::TForLoop,
278            _ if OpCode::SetList as u32 == u => OpCode::SetList,
279            _ if OpCode::Closure as u32 == u => OpCode::Closure,
280            _ if OpCode::Vararg as u32 == u => OpCode::Vararg,
281            _ if OpCode::ExtraArg as u32 == u => OpCode::ExtraArg,
282            _ => unreachable!("unknown op code : {}!", u),
283        }
284    }
285}
286
287pub struct Instruction(u32);
288
289#[allow(dead_code)]
290#[allow(non_snake_case)]
291impl Instruction {
292    pub fn new() -> Self {
293        Instruction(0)
294    }
295
296    pub fn get_op(&self) -> OpCode {
297        OpCode::from_u32(((self.0) >> POS_OP) & Instruction::mask1(SIZE_OP, 0))
298    }
299
300    pub fn set_op(&mut self, op: OpCode) {
301        self.set_arg(op as u32, POS_OP, SIZE_OP)
302    }
303
304    pub fn get_arg_A(&self) -> u32 {
305        self.get_arg(POS_A, SIZE_A)
306    }
307
308    pub fn set_arg_A(&mut self, value: u32) {
309        self.set_arg(value, POS_A, SIZE_A);
310    }
311
312    pub fn get_arg_B(&self) -> u32 {
313        self.get_arg(POS_B, SIZE_B)
314    }
315
316    pub fn set_arg_B(&mut self, value: u32) {
317        self.set_arg(value, POS_B, SIZE_B);
318    }
319
320    pub fn get_arg_C(&self) -> u32 {
321        self.get_arg(POS_C, SIZE_C)
322    }
323
324    pub fn set_arg_C(&mut self, value: u32) {
325        self.set_arg(value, POS_C, SIZE_C);
326    }
327
328    pub fn get_arg_Ax(&self) -> u32 {
329        self.get_arg(POS_AX, SIZE_AX)
330    }
331
332    pub fn set_arg_Ax(&mut self, value: u32) {
333        self.set_arg(value, POS_AX, SIZE_AX);
334    }
335
336    pub fn get_arg_Bx(&self) -> u32 {
337        self.get_arg(POS_BX, SIZE_BX)
338    }
339
340    pub fn set_arg_Bx(&mut self, value: u32) {
341        self.set_arg(value, POS_BX, SIZE_BX);
342    }
343
344    pub fn get_arg_sBx(&self) -> i32 {
345        (self.get_arg(POS_BX, SIZE_BX) as i32) - MAXARG_SBX
346    }
347
348    pub fn set_arg_sBx(&mut self, value: i32) {
349        self.set_arg((value + MAXARG_SBX) as u32, POS_BX, SIZE_BX);
350    }
351
352    pub fn create_ABC(op: OpCode, a: u32, b: u32, c: u32) -> Self {
353        Instruction(((op as u32) << POS_OP) | (a << POS_A) | (b << POS_B) | (c << POS_C))
354    }
355
356    pub fn create_ABx(op: OpCode, a: u32, bx: u32) -> Self {
357        Instruction(((op as u32) << POS_OP) | (a << POS_A) | (bx << POS_BX))
358    }
359
360    pub fn create_AsBx(op: OpCode, a: u32, sBx: i32) -> Self {
361        Instruction(
362            ((op as u32) << POS_OP) | (a << POS_A) | (((sBx + MAXARG_SBX) as u32) << POS_BX),
363        )
364    }
365
366    pub fn create_Ax(op: OpCode, a: u32) -> Self {
367        Instruction(((op as u32) << POS_OP) | (a << POS_AX))
368    }
369
370    pub fn save(&mut self, a: u32) {
371        let mask = !(((1 << SIZE_A) - 1) << POS_A);
372        self.0 = (self.0 & mask) | (a << POS_A);
373    }
374
375    fn get_arg(&self, pos: u32, size: u32) -> u32 {
376        (self.0 >> pos) & Instruction::mask1(size, 0)
377    }
378
379    fn set_arg(&mut self, value: u32, pos: u32, size: u32) {
380        self.0 = (Instruction::mask1(size, pos) & (value << pos))
381            | (self.0 & Instruction::mask0(size, pos))
382    }
383
384    fn mask1(n: u32, p: u32) -> u32 {
385        (!((!0u32) << n)) << p
386    }
387
388    fn mask0(n: u32, p: u32) -> u32 {
389        !Instruction::mask1(n, p)
390    }
391
392    pub fn mode(&self) -> OpMode {
393        match self.get_op() {
394            OpCode::Move => OpMode::IAB,
395            OpCode::LoadK => OpMode::IABx,
396            OpCode::LoadKx => OpMode::IA,
397            OpCode::LoadBool => OpMode::IABC,
398            OpCode::LoadNil => OpMode::IAB,
399            OpCode::GetUpVal => OpMode::IAB,
400            OpCode::GetTabUp => OpMode::IABC,
401            OpCode::GetTable => OpMode::IABC,
402            OpCode::SetTabUp => OpMode::IABC,
403            OpCode::SetUpVal => OpMode::IAB,
404            OpCode::SetTable => OpMode::IABC,
405            OpCode::NewTable => OpMode::IABC,
406            OpCode::Self_ => OpMode::IABC,
407            OpCode::Add => OpMode::IABC,
408            OpCode::Sub => OpMode::IABC,
409            OpCode::Mul => OpMode::IABC,
410            OpCode::Mod => OpMode::IABC,
411            OpCode::Pow => OpMode::IABC,
412            OpCode::Div => OpMode::IABC,
413            OpCode::IDiv => OpMode::IABC,
414            OpCode::BAdd => OpMode::IABC,
415            OpCode::BOr => OpMode::IABC,
416            OpCode::BXor => OpMode::IABC,
417            OpCode::Shl => OpMode::IABC,
418            OpCode::Shr => OpMode::IABC,
419            OpCode::Unm => OpMode::IAB,
420            OpCode::BNot => OpMode::IAB,
421            OpCode::Not => OpMode::IAB,
422            OpCode::Len => OpMode::IAB,
423            OpCode::Concat => OpMode::IABC,
424            OpCode::Jmp => OpMode::IAsBx,
425            OpCode::Eq => OpMode::IABC,
426            OpCode::Lt => OpMode::IABC,
427            OpCode::Le => OpMode::IABC,
428            OpCode::Test => OpMode::IAC,
429            OpCode::TestSet => OpMode::IABC,
430            OpCode::Call => OpMode::IABC,
431            OpCode::TailCall => OpMode::IABC,
432            OpCode::Return => OpMode::IAB,
433            OpCode::ForLoop => OpMode::IAsBx,
434            OpCode::ForPrep => OpMode::IAsBx,
435            OpCode::TForCall => OpMode::IAC,
436            OpCode::TForLoop => OpMode::IAsBx,
437            OpCode::SetList => OpMode::IAsBx,
438            OpCode::Closure => OpMode::IABx,
439            OpCode::Vararg => OpMode::IAB,
440            OpCode::ExtraArg => OpMode::IAx,
441        }
442    }
443}
444
445use std::fmt;
446impl fmt::Debug for Instruction {
447    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
448        match self.mode() {
449            OpMode::IA => write!(
450                f,
451                "| {:<10} | {:<5} | {:<5} | {:<5} |",
452                format!("{:?}", self.get_op()),
453                self.get_arg_A(),
454                " ",
455                " "
456            ),
457            OpMode::IAB => write!(
458                f,
459                "| {:<10} | {:<5} | {:<5} | {:<5} |",
460                format!("{:?}", self.get_op()),
461                self.get_arg_A(),
462                self.get_arg_B(),
463                " "
464            ),
465            OpMode::IABC => write!(
466                f,
467                "| {:<10} | {:<5} | {:<5} | {:<5} |",
468                format!("{:?}", self.get_op()),
469                self.get_arg_A(),
470                self.get_arg_B(),
471                self.get_arg_C()
472            ),
473            OpMode::IAC => write!(
474                f,
475                "| {:<10} | {:<5} | {:<5} | {:<5} |",
476                format!("{:?}", self.get_op()),
477                self.get_arg_A(),
478                " ",
479                self.get_arg_C()
480            ),
481            OpMode::IABx => write!(
482                f,
483                "| {:<10} | {:<5} | {:<5} | {:<5} |",
484                format!("{:?}", self.get_op()),
485                self.get_arg_A(),
486                self.get_arg_Bx(),
487                " "
488            ),
489            OpMode::IAsBx => write!(
490                f,
491                "| {:<10} | {:<5} | {:<5} | {:<5} |",
492                format!("{:?}", self.get_op()),
493                self.get_arg_A(),
494                self.get_arg_sBx(),
495                " "
496            ),
497            OpMode::IAx => write!(
498                f,
499                "| {:<10} | {:<5} | {:<5} | {:<5} |",
500                format!("{:?}", self.get_op()),
501                self.get_arg_Ax(),
502                " ",
503                " "
504            ),
505        }
506    }
507}