PageRenderTime 54ms CodeModel.GetById 1ms app.highlight 9ms RepoModel.GetById 35ms app.codeStats 0ms

/source/Opcodes.ooc

http://github.com/fperrad/ooc-lua
Unknown | 374 lines | 304 code | 70 blank | 0 comment | 0 complexity | bc1fb972ad7b99df8a1004458af0dd1f MD5 | raw file
  1
  2include stdint
  3
  4
  5/*===========================================================================
  6  We assume that instructions are unsigned numbers.
  7  All instructions have an opcode in the first 6 bits.
  8  Instructions can have the following fields:
  9        `A' : 8 bits
 10        `B' : 9 bits
 11        `C' : 9 bits
 12        'Ax' : 26 bits ('A', 'B', and 'C' together)
 13        `Bx' : 18 bits (`B' and `C' together)
 14        `sBx' : signed Bx
 15
 16  A signed argument is represented in excess K; that is, the number
 17  value is the unsigned value minus K. K is exactly the maximum value
 18  for that argument (so that -max is represented by 0, and +max is
 19  represented by 2*max), which is half the maximum for the corresponding
 20  unsigned argument.
 21===========================================================================*/
 22
 23
 24OpMode: enum {  /* basic instruction format */
 25    iABC,
 26    iABx,
 27    iAsBx,
 28    iAx
 29}
 30
 31
 32/*
 33** size and position of opcode arguments.
 34*/
 35SIZE_C  := const        9
 36SIZE_B  := const        9
 37SIZE_Bx := const        SIZE_C + SIZE_B
 38SIZE_A  := const        8
 39SIZE_Ax := const        SIZE_C + SIZE_B + SIZE_A
 40
 41SIZE_OP := const        6
 42
 43POS_OP  := const        0
 44POS_A   := const        POS_OP + SIZE_OP
 45POS_C   := const        POS_A + SIZE_A
 46POS_B   := const        POS_C + SIZE_C
 47POS_Bx  := const        POS_C
 48POS_Ax  := const        POS_A
 49
 50
 51/*
 52** limits for opcode arguments.
 53** we use (signed) int to manipulate most arguments,
 54** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
 55*/
 56MAXARG_Bx   := const    (1 << SIZE_Bx) - 1
 57MAXARG_sBx  := const    MAXARG_Bx >> 1         /* `sBx' is signed */
 58MAXARG_Ax   := const    (1 << SIZE_Ax) - 1
 59MAXARG_A    := const    (1 << SIZE_A) - 1
 60MAXARG_B    := const    (1 << SIZE_B) - 1
 61MAXARG_C    := const    (1 << SIZE_C) - 1
 62
 63
 64Instruction: cover from uint32_t {
 65    createABC: static inline func(o: OpCode, a, b, c: UInt) -> This {
 66        return (o as UInt << POS_OP | a << POS_A | b << POS_B | c << POS_C) as Instruction
 67    }
 68
 69    createABx: static inline func(o: OpCode, a, bc: UInt) -> This {
 70        return (o as UInt << POS_OP | a << POS_A | bc << POS_Bx) as Instruction
 71    }
 72
 73    createAx: static inline func(o: OpCode, a: UInt) -> This {
 74        return (o as UInt << POS_OP | a << POS_Ax) as Instruction
 75    }
 76
 77    getOpcode: inline func -> OpCode {
 78        return ((this >> POS_OP) & ~(~0 << SIZE_OP)) as OpCode
 79    }
 80
 81    setOpcode: inline func(o: OpCode) -> Instruction {
 82        return (this & ~(~(~0 << SIZE_OP) << POS_OP)) | ((o << POS_OP) & (~(~0 << SIZE_OP)) << POS_OP)
 83    }
 84
 85    getarg_A: inline func -> Int {
 86        return ((this >> POS_A) & ~(~0 << SIZE_A)) as Int
 87    }
 88
 89    setarg_A: inline func(a: UInt) -> Instruction {
 90        return (this & ~(~(~0 << SIZE_A) << POS_A)) | ((a << POS_A) & (~(~0 << SIZE_A)) << POS_A)
 91    }
 92
 93    getarg_B: inline func -> Int {
 94        return ((this >> POS_B) & ~(~0 << SIZE_B)) as Int
 95    }
 96
 97    setarg_B: inline func(b: UInt) -> Instruction {
 98        return (this & ~(~(~0 << SIZE_B) << POS_B)) | ((b << POS_B) & (~(~0 << SIZE_B)) << POS_B)
 99    }
100
101    getarg_C: inline func -> Int {
102        return ((this >> POS_C) & ~(~0 << SIZE_C)) as Int
103    }
104
105    setarg_C: inline func(c: UInt) -> Instruction {
106        return (this & ~(~(~0 << SIZE_C) << POS_C)) | ((c << POS_C) & (~(~0 << SIZE_C)) << POS_C)
107    }
108
109    getarg_Bx: inline func -> Int {
110        return ((this >> POS_Bx) & ~(~0 << SIZE_Bx)) as Int
111    }
112
113    setarg_Bx: inline func(b: UInt) -> Instruction {
114        return (this & ~(~(~0 << SIZE_Bx) << POS_Bx)) | ((b << POS_Bx) & (~(~0 << SIZE_Bx)) << POS_Bx)
115    }
116
117    getarg_Ax: inline func -> Int {
118        return ((this >> POS_Ax) & ~(~0 << SIZE_Ax)) as Int
119    }
120
121    setarg_Ax: inline func(a: UInt) -> Instruction {
122        return (this & ~(~(~0 << SIZE_Ax) << POS_Ax)) | ((a << POS_Ax) & (~(~0 << SIZE_Ax)) << POS_Ax)
123    }
124
125    getarg_sBx: inline func -> Int {
126        return (((this >> POS_Bx) & ~(~0 << SIZE_Bx)) - MAXARG_sBx) as Int
127    }
128
129    setarg_sBx: inline func(b: Int) -> Instruction {
130        return (this & ~(~(~0 << SIZE_Bx) << POS_Bx)) | (((b + MAXARG_sBx) << POS_Bx) & (~(~0 << SIZE_Bx)) << POS_Bx)
131    }
132}
133
134
135/* this bit 1 means constant (0 means register) */
136BITRK   := const        1 << (SIZE_B - 1)
137MAXINDEXRK := const     BITRK - 1
138
139
140/*
141** invalid register that fits in 8 bits
142*/
143NO_REG  := const        MAXARG_A
144
145
146/*
147** R(x) - register
148** Kst(x) - constant (in constant table)
149** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
150*/
151
152/*
153** grep "ORDER OP" if you change these enums
154*/
155
156OpCode: enum {
157    /*----------------------------------------------------------------------
158    name            args    description
159    ------------------------------------------------------------------------*/
160    OP_MOVE,/*      A B     R(A) := R(B)                                    */
161    OP_LOADK,/*     A Bx    R(A) := Kst(Bx - 1)                             */
162    OP_LOADBOOL,/*  A B C   R(A) := (Bool)B; if (C) pc++                    */
163    OP_LOADNIL,/*   A B     R(A) := ... := R(B) := nil                      */
164    OP_GETUPVAL,/*  A B     R(A) := UpValue[B]                              */
165
166    OP_GETTABUP,/*  A B C   R(A) := UpValue[B][RK(C)]                       */
167    OP_GETTABLE,/*  A B C   R(A) := R(B)[RK(C)]                             */
168
169    OP_SETTABUP,/*  A B C   UpValue[A][RK(B)] := RK(C)                      */
170    OP_SETUPVAL,/*  A B     UpValue[B] := R(A)                              */
171    OP_SETTABLE,/*  A B C   R(A)[RK(B)] := RK(C)                            */
172
173    OP_NEWTABLE,/*  A B C   R(A) := {} (size = B,C)                         */
174
175    OP_SELF,/*      A B C   R(A+1) := R(B); R(A) := R(B)[RK(C)]             */
176
177    OP_ADD,/*       A B C   R(A) := RK(B) + RK(C)                           */
178    OP_SUB,/*       A B C   R(A) := RK(B) - RK(C)                           */
179    OP_MUL,/*       A B C   R(A) := RK(B) * RK(C)                           */
180    OP_DIV,/*       A B C   R(A) := RK(B) / RK(C)                           */
181    OP_MOD,/*       A B C   R(A) := RK(B) % RK(C)                           */
182    OP_POW,/*       A B C   R(A) := RK(B) ^ RK(C)                           */
183    OP_UNM,/*       A B     R(A) := -R(B)                                   */
184    OP_NOT,/*       A B     R(A) := not R(B)                                */
185    OP_LEN,/*       A B     R(A) := length of R(B)                          */
186
187    OP_CONCAT,/*    A B C   R(A) := R(B).. ... ..R(C)                       */
188
189    OP_JMP,/*       sBx     pc+=sBx                                         */
190
191    OP_EQ,/*        A B C   if ((RK(B) == RK(C)) ~= A) then pc++            */
192    OP_LT,/*        A B C   if ((RK(B) <  RK(C)) ~= A) then pc++            */
193    OP_LE,/*        A B C   if ((RK(B) <= RK(C)) ~= A) then pc++            */
194
195    OP_TEST,/*      A C     if not (R(A) <=> C) then pc++                   */
196    OP_TESTSET,/*   A B C   if (R(B) <=> C) then R(A) := R(B) else pc++     */
197
198    OP_CALL,/*      A B C   R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
199    OP_TAILCALL,/*  A B C   return R(A)(R(A+1), ... ,R(A+B-1))              */
200    OP_RETURN,/*    A B     return R(A), ... ,R(A+B-2)      (see note)      */
201
202    OP_FORLOOP,/*   A sBx   R(A)+=R(A+2);
203                            if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
204    OP_FORPREP,/*   A sBx   R(A)-=R(A+2); pc+=sBx                           */
205
206    OP_TFORCALL,/*  A C     R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));  */
207    OP_TFORLOOP,/*  A sBx   if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
208
209    OP_SETLIST,/*   A B C   R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B        */
210
211    OP_CLOSE,/*     A       close all variables in the stack up to (>=) R(A)*/
212    OP_CLOSURE,/*   A Bx    R(A) := closure(KPROTO[Bx])                     */
213
214    OP_VARARG,/*    A B     R(A), R(A+1), ..., R(A+B-2) = vararg            */
215
216    OP_EXTRAARG/*   Ax      extra (larger) argument for previous opcode     */
217
218    getOpMode: inline func -> OpMode {
219        return (OP_MODES[this] & 3) as OpMode
220    }
221
222    getBMode: inline func -> OpArgMask {
223        return ((OP_MODES[this] >> 4) & 3) as OpArgMask
224    }
225
226    getCMode: inline func -> OpArgMask {
227        return ((OP_MODES[this] >> 2) & 3) as OpArgMask
228    }
229
230    testAMode: inline func -> Bool {
231        return (OP_MODES[this] & (1 << 6)) != 0
232    }
233
234    testTMode: inline func -> Bool {
235        return (OP_MODES[this] & (1 << 7)) != 0
236    }
237}
238
239
240OP_NAMES := const [
241    "MOVE",
242    "LOADK",
243    "LOADBOOL",
244    "LOADNIL",
245    "GETUPVAL",
246    "GETTABUP",
247    "GETTABLE",
248    "SETTABUP",
249    "SETUPVAL",
250    "SETTABLE",
251    "NEWTABLE",
252    "SELF",
253    "ADD",
254    "SUB",
255    "MUL",
256    "DIV",
257    "MOD",
258    "POW",
259    "UNM",
260    "NOT",
261    "LEN",
262    "CONCAT",
263    "JMP",
264    "EQ",
265    "LT",
266    "LE",
267    "TEST",
268    "TESTSET",
269    "CALL",
270    "TAILCALL",
271    "RETURN",
272    "FORLOOP",
273    "FORPREP",
274    "TFORCALL",
275    "TFORLOOP",
276    "SETLIST",
277    "CLOSE",
278    "CLOSURE",
279    "VARARG",
280    "EXTRAARG"
281]
282
283/*
284** masks for instruction properties. The format is:
285** bits 0-1: op mode
286** bits 2-3: C arg mode
287** bits 4-5: B arg mode
288** bit 6: instruction set register A
289** bit 7: operator is a test (next instruction must be a jump)
290*/
291
292OpArgMask: enum {
293    OpArgN,  /* argument is not used */
294    OpArgU,  /* argument is used */
295    OpArgR,  /* argument is a register or a jump offset */
296    OpArgK   /* argument is a constant or register/constant */
297}
298
299OP_MODES := const [
300/*   T        A                  B                       C                   mode      opcode */
301    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_MOVE */
302    (0<<7) | (1<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgN<<2) | OpMode iABx,  /* OP_LOADK */
303    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_LOADBOOL */
304    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_LOADNIL */
305    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_GETUPVAL */
306    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_GETTABUP */
307    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_GETTABLE */
308    (0<<7) | (0<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_SETTABUP */
309    (0<<7) | (0<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_SETUPVAL */
310    (0<<7) | (0<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_SETTABLE */
311    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_NEWTABLE */
312    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_SELF */
313    (0<<7) | (1<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_ADD */
314    (0<<7) | (1<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_SUB */
315    (0<<7) | (1<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_MUL */
316    (0<<7) | (1<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_DIV */
317    (0<<7) | (1<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_MOD */
318    (0<<7) | (1<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_POW */
319    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_UNM */
320    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_NOT */
321    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_LEN */
322    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgR<<2) | OpMode iABC,  /* OP_CONCAT */
323    (0<<7) | (0<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iAsBx, /* OP_JMP */
324    (1<<7) | (0<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_EQ */
325    (1<<7) | (0<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_LT */
326    (1<<7) | (0<<6) | (OpArgMask OpArgK<<4) | (OpArgMask OpArgK<<2) | OpMode iABC,  /* OP_LE */
327    (1<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_TEST */
328    (1<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_TESTSET */
329    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_CALL */
330    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_TAILCALL */
331    (0<<7) | (0<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_RETURN */
332    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iAsBx, /* OP_FORLOOP */
333    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iAsBx, /* OP_FORPREP */
334    (0<<7) | (0<<6) | (OpArgMask OpArgN<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_TFORCALL */
335    (0<<7) | (1<<6) | (OpArgMask OpArgR<<4) | (OpArgMask OpArgN<<2) | OpMode iAsBx, /* OP_TFORLOOP */
336    (0<<7) | (0<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgU<<2) | OpMode iABC,  /* OP_SETLIST */
337    (0<<7) | (0<<6) | (OpArgMask OpArgN<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_CLOSE */
338    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgN<<2) | OpMode iABx,  /* OP_CLOSURE */
339    (0<<7) | (1<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgN<<2) | OpMode iABC,  /* OP_VARARG */
340    (0<<7) | (0<<6) | (OpArgMask OpArgU<<4) | (OpArgMask OpArgU<<2) | OpMode iAx,   /* OP_EXTRAARG */
341]
342
343/* number of list items to accumulate before a SETLIST instruction */
344LFIELDS_PER_FLUSH := const 50
345
346/* option for multiple returns in 'lua_pcall' and 'lua_call' */
347LUA_MULTRET := const -1
348
349
350/*
351** converts an integer to a "floating point byte", represented as
352** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
353** eeeee != 0 and (xxx) otherwise.
354*/
355int2fb: func(x: UInt32) -> Int {
356    e := 0  /* exponent */
357    if (x < 8)
358        return x
359    while (x >= 0x10) {
360        x = (x+1) >> 1
361        e += 1
362    }
363    return ((e+1) << 3) | (x as Int - 8)
364}
365
366/* converts back */
367fb2int: func(x: Int) -> Int {
368    e := (x >> 3) & 0x1f
369    if (e == 0)
370        return x
371    else
372        return ((x & 7) + 8) << (e - 1)
373}
374