1 //
2 //  gravity_opcodes.h
3 //  gravity
4 //
5 //  Created by Marco Bambini on 24/09/14.
6 //  Copyright (c) 2014 CreoLabs. All rights reserved.
7 //
8 
9 #ifndef __GRAVITY_OPCODES__
10 #define __GRAVITY_OPCODES__
11 
12 /*
13         Big-endian vs Little-endian machines
14 
15         ARM architecture runs both little & big endianess, but the android, iOS, and windows phone platforms run little endian.
16         95% of modern desktop computers are little-endian.
17         All x86 desktops (which is nearly all desktops with the demise of the PowerPC-based Macs several years ago) are little-endian.
18         It's probably actually a lot more than 95% nowadays. PowerPC was the only non-x86 architecture that has been popular for desktop
19         computers in the last 20 years and Apple abandoned it in favor of x86.
20         Sparc, Alpha, and Itanium did exist, but they were all very rare in the desktop market.
21  */
22 
23 /*
24         Instructions are 32bit in length
25 
26         // 2 registers and 1 register/constant
27         +------------------------------------+
28         |  OP  |   Ax   |   Bx   |    Cx/K   |
29         +------------------------------------+
30 
31         // instructions with no parameters
32         +------------------------------------+
33         |  OP  |0                            |
34         +------------------------------------+
35 
36         // unconditional JUMP
37         +------------------------------------+
38         |  OP  |             N1              |
39         +------------------------------------+
40 
41         // LOADI and JUMPF
42         +------------------------------------+
43         |  OP  |   Ax   |S|       N2         |
44         +------------------------------------+
45 
46         OP   =>  6 bits
47         Ax   =>  8 bits
48         Bx   =>  8 bits
49         Cx/K =>  8/10 bits
50         S    =>  1 bit
51         N1   =>  26 bits
52         N2   =>  17 bits
53  */
54 
55 typedef enum {
56 
57     //      ***********************************************************************************************************
58     //      56 OPCODE INSTRUCTIONS (for a register based virtual machine)
59     //      opcode is a 6 bit value so at maximum 2^6 = 64 opcodes can be declared
60     //      ************************************************************************************************************
61     //
62     //      MNEMONIC        PARAMETERS          DESCRIPTION                                 OPERATION
63     //      --------        ----------          ------------------------------------        ----------------------------
64     //
65                                                 //  *** GENERAL COMMANDS (5) ***
66             RET0 = 0,       //  NONE            //  return nothing from a function          MUST BE THE FIRST OPCODE (because an implicit 0 is added
67                                                 //                                          as a safeguard at the end of any bytecode
68             HALT,           //  NONE            //  stop VM execution
69             NOP,            //  NONE            //  NOP                                     http://en.wikipedia.org/wiki/NOP
70             RET,            //  A               //  return from a function                  R(-1) = R(A)
71             CALL,           //  A, B, C         //  call a function                         R(A) = B(C0...Cn) B is callable object and C is num args
72 
73                                                 //  *** LOAD/STORE OPERATIONS (11) ***
74             LOAD,           //  A, B, C         //  load C from B and store in A            R(A) = R(B)[C]
75             LOADS,          //  A, B, C         //  load C from B and store in A            R(A) = R(B)[C] (super variant)
76             LOADAT,         //  A, B, C         //  load C from B and store in A            R(A) = R(B)[C]
77             LOADK,          //  A, B            //  load constant into register             R(A) = K(B)
78             LOADG,          //  A, B            //  load global into register               R(A) = G[K(B)]
79             LOADI,          //  A, B            //  load integer into register              R(A) = I
80             LOADU,          //  A, B            //  load upvalue into register              R(A) = U(B)
81             MOVE,           //  A, B            //  move registers                          R(A) = R(B)
82             STORE,          //  A, B, C         //  store A into R(B)[C]                    R(B)[C] = R(A)
83             STOREAT,        //  A, B, C         //  store A into R(B)[C]                    R(B)[C] = R(A)
84             STOREG,         //  A, B            //  store global                            G[K(B)] = R(A)
85             STOREU,         //  A, B            //  store upvalue                           U(B) = R(A)
86 
87                                                 //  *** JUMP OPERATIONS (3) ***
88             JUMP,           //  A               //  unconditional jump                      PC += A
89             JUMPF,          //  A, B            //  jump if R(A) is false                   (R(A) == 0)    ? PC += B : 0
90             SWITCH,         //                  //  switch statement
91 
92                                                 //  *** MATH OPERATIONS (19) ***
93             ADD,            //  A, B, C         //  add operation                           R(A) = R(B) + R(C)
94             SUB,            //  A, B, C         //  sub operation                           R(A) = R(B) - R(C)
95             DIV,            //  A, B, C         //  div operation                           R(A) = R(B) / R(C)
96             MUL,            //  A, B, C         //  mul operation                           R(A) = R(B) * R(C)
97             REM,            //  A, B, C         //  rem operation                           R(A) = R(B) % R(C)
98             AND,            //  A, B, C         //  and operation                           R(A) = R(B) && R(C)
99             OR,             //  A, B, C         //  or operation                            R(A) = R(B) || R(C)
100             LT,             //  A, B, C         //  < comparison                            R(A) = R(B) < R(C)
101             GT,             //  A, B, C         //  > comparison                            R(A) = R(B) > R(C)
102             EQ,             //  A, B, C         //  == comparison                           R(A) = R(B) == R(C)
103             LEQ,            //  A, B, C         //  <= comparison                           R(A) = R(B) <= R(C)
104             GEQ,            //  A, B, C         //  >= comparison                           R(A) = R(B) >= R(C)
105             NEQ,            //  A, B, C         //  != comparison                           R(A) = R(B) != R(C)
106             EQQ,            //  A, B, C         //  === comparison                          R(A) = R(B) === R(C)
107             NEQQ,           //  A, B, C         //  !== comparison                          R(A) = R(B) !== R(C)
108             ISA,            //  A, B, C         //  isa comparison                          R(A) = R(A).class == R(B).class
109             MATCH,          //  A, B, C         //  =~ pattern match                        R(A) = R(B) =~ R(C)
110             NEG,            //  A, B            //  neg operation                           R(A) = -R(B)
111             NOT,            //  A, B            //  not operation                           R(A) = !R(B)
112 
113                                                 //  *** BIT OPERATIONS (6) ***
114             LSHIFT,         //  A, B, C         //  shift left                              R(A) = R(B) << R(C)
115             RSHIFT,         //  A, B, C         //  shift right                             R(A) = R(B) >> R(C)
116             BAND,           //  A, B, C         //  bit and                                 R(A) = R(B) & R(C)
117             BOR,            //  A, B, C         //  bit or                                  R(A) = R(B) | R(C)
118             BXOR,           //  A, B, C         //  bit xor                                 R(A) = R(B) ^ R(C)
119             BNOT,           //  A, B            //  bit not                                 R(A) = ~R(B)
120 
121                                                 //  *** ARRAY/MAP/RANGE OPERATIONS (4) ***
122             MAPNEW,         //  A, B            //  create a new map                        R(A) = Alloc a MAP(B)
123             LISTNEW,        //  A, B            //  create a new array                      R(A) = Alloc a LIST(B)
124             RANGENEW,       //  A, B, C, f      //  create a new range                      R(A) = Alloc a RANGE(B,C) f flag tells if B inclusive or exclusive
125             SETLIST,        //  A, B, C         //  set list/map items
126 
127                                                 //  *** CLOSURES (2) ***
128             CLOSURE,        //  A, B            //  create a new closure                    R(A) = closure(K(B))
129             CLOSE,          //  A               //  close all upvalues from R(A)
130 
131                                                 //  *** UNUSED (6) ***
132             CHECK,          //  A               //  checkpoint for structs                  R(A) = R(A).clone (if A is a struct)
133             RESERVED2,      //                  //  reserved for future use
134             RESERVED3,      //                  //  reserved for future use
135             RESERVED4,      //                  //  reserved for future use
136             RESERVED5,      //                  //  reserved for future use
137             RESERVED6       //                  //  reserved for future use
138 } opcode_t;
139 
140 #define GRAVITY_LATEST_OPCODE           RESERVED6    // used in some debug code so it is very useful to define the latest opcode here
141 
142 typedef enum {
143     GRAVITY_NOTFOUND_INDEX              = 0,
144     GRAVITY_ADD_INDEX,
145     GRAVITY_SUB_INDEX,
146     GRAVITY_DIV_INDEX,
147     GRAVITY_MUL_INDEX,
148     GRAVITY_REM_INDEX,
149     GRAVITY_AND_INDEX,
150     GRAVITY_OR_INDEX,
151     GRAVITY_CMP_INDEX,
152     GRAVITY_EQQ_INDEX,
153     GRAVITY_IS_INDEX,
154     GRAVITY_MATCH_INDEX,
155     GRAVITY_NEG_INDEX,
156     GRAVITY_NOT_INDEX,
157     GRAVITY_LSHIFT_INDEX,
158     GRAVITY_RSHIFT_INDEX,
159     GRAVITY_BAND_INDEX,
160     GRAVITY_BOR_INDEX,
161     GRAVITY_BXOR_INDEX,
162     GRAVITY_BNOT_INDEX,
163     GRAVITY_LOAD_INDEX,
164     GRAVITY_LOADS_INDEX,
165     GRAVITY_LOADAT_INDEX,
166     GRAVITY_STORE_INDEX,
167     GRAVITY_STOREAT_INDEX,
168     GRAVITY_INT_INDEX,
169     GRAVITY_FLOAT_INDEX,
170     GRAVITY_BOOL_INDEX,
171     GRAVITY_STRING_INDEX,
172     GRAVITY_EXEC_INDEX,
173     GRAVITY_VTABLE_SIZE                 // MUST BE LAST ENTRY IN THIS ENUM
174 } GRAVITY_VTABLE_INDEX;
175 
176 #define GRAVITY_OPERATOR_ADD_NAME       "+"
177 #define GRAVITY_OPERATOR_SUB_NAME       "-"
178 #define GRAVITY_OPERATOR_DIV_NAME       "/"
179 #define GRAVITY_OPERATOR_MUL_NAME       "*"
180 #define GRAVITY_OPERATOR_REM_NAME       "%"
181 #define GRAVITY_OPERATOR_AND_NAME       "&&"
182 #define GRAVITY_OPERATOR_OR_NAME        "||"
183 #define GRAVITY_OPERATOR_CMP_NAME       "=="
184 #define GRAVITY_OPERATOR_EQQ_NAME       "==="
185 #define GRAVITY_OPERATOR_NEQQ_NAME      "!=="
186 #define GRAVITY_OPERATOR_IS_NAME        "is"
187 #define GRAVITY_OPERATOR_MATCH_NAME     "=~"
188 #define GRAVITY_OPERATOR_NEG_NAME       "neg"
189 #define GRAVITY_OPERATOR_NOT_NAME        "!"
190 #define GRAVITY_OPERATOR_LSHIFT_NAME    "<<"
191 #define GRAVITY_OPERATOR_RSHIFT_NAME    ">>"
192 #define GRAVITY_OPERATOR_BAND_NAME      "&"
193 #define GRAVITY_OPERATOR_BOR_NAME       "|"
194 #define GRAVITY_OPERATOR_BXOR_NAME      "^"
195 #define GRAVITY_OPERATOR_BNOT_NAME      "~"
196 #define GRAVITY_INTERNAL_LOAD_NAME      "load"
197 #define GRAVITY_INTERNAL_LOADS_NAME     "loads"
198 #define GRAVITY_INTERNAL_STORE_NAME     "store"
199 #define GRAVITY_INTERNAL_LOADAT_NAME    "loadat"
200 #define GRAVITY_INTERNAL_STOREAT_NAME   "storeat"
201 #define GRAVITY_INTERNAL_NOTFOUND_NAME  "notfound"
202 #define GRAVITY_INTERNAL_EXEC_NAME      "exec"
203 #define GRAVITY_INTERNAL_LOOP_NAME      "loop"
204 
205 #define GRAVITY_CLASS_INT_NAME          "Int"
206 #define GRAVITY_CLASS_FLOAT_NAME        "Float"
207 #define GRAVITY_CLASS_BOOL_NAME         "Bool"
208 #define GRAVITY_CLASS_STRING_NAME       "String"
209 #define GRAVITY_CLASS_OBJECT_NAME       "Object"
210 #define GRAVITY_CLASS_CLASS_NAME        "Class"
211 #define GRAVITY_CLASS_NULL_NAME         "Null"
212 #define GRAVITY_CLASS_FUNCTION_NAME     "Func"
213 #define GRAVITY_CLASS_FIBER_NAME        "Fiber"
214 #define GRAVITY_CLASS_INSTANCE_NAME     "Instance"
215 #define GRAVITY_CLASS_CLOSURE_NAME      "Closure"
216 #define GRAVITY_CLASS_LIST_NAME         "List"
217 #define GRAVITY_CLASS_MAP_NAME          "Map"
218 #define GRAVITY_CLASS_RANGE_NAME        "Range"
219 #define GRAVITY_CLASS_UPVALUE_NAME      "Upvalue"
220 
221 #define GRAVITY_CLASS_SYSTEM_NAME       "System"
222 #define GRAVITY_SYSTEM_PRINT_NAME       "print"
223 #define GRAVITY_SYSTEM_PUT_NAME         "put"
224 #define GRAVITY_SYSTEM_INPUT_NAME       "input"
225 #define GRAVITY_SYSTEM_NANOTIME_NAME    "nanotime"
226 
227 #define GRAVITY_TOCLASS_NAME            "toClass"
228 #define GRAVITY_TOSTRING_NAME           "toString"
229 #define GRAVITY_TOINT_NAME              "toInt"
230 #define GRAVITY_TOFLOAT_NAME            "toFloat"
231 #define GRAVITY_TOBOOL_NAME             "toBool"
232 
233 #endif
234