github.com/coinstack/gopher-lua@v0.0.0-20180626044619-c9c62d4ee45e/opcode.go (about) 1 package lua 2 3 import ( 4 "fmt" 5 ) 6 7 /* 8 gopherlua uses Lua 5.1.4's opcodes. 9 Lua 5.1.4 opcodes layout: 10 11 instruction = 32bit(fixed length) 12 13 +---------------------------------------------+ 14 |0-5(6bits)|6-13(8bit)|14-22(9bit)|23-31(9bit)| 15 |==========+==========+===========+===========| 16 | opcode | A | C | B | 17 |----------+----------+-----------+-----------| 18 | opcode | A | Bx(unsigned) | 19 |----------+----------+-----------+-----------| 20 | opcode | A | sBx(signed) | 21 +---------------------------------------------+ 22 */ 23 24 const opInvalidInstruction = ^uint32(0) 25 26 const opSizeCode = 6 27 const opSizeA = 8 28 const opSizeB = 9 29 const opSizeC = 9 30 const opSizeBx = 18 31 const opSizesBx = 18 32 33 const opMaxArgsA = (1 << opSizeA) - 1 34 const opMaxArgsB = (1 << opSizeB) - 1 35 const opMaxArgsC = (1 << opSizeC) - 1 36 const opMaxArgBx = (1 << opSizeBx) - 1 37 const opMaxArgSbx = opMaxArgBx >> 1 38 39 const ( 40 OP_MOVE int = iota /* A B R(A) := R(B) */ 41 OP_MOVEN /* A B R(A) := R(B); followed by R(C) MOVE ops */ 42 OP_LOADK /* A Bx R(A) := Kst(Bx) */ 43 OP_LOADBOOL /* A B C R(A) := (Bool)B; if (C) pc++ */ 44 OP_LOADNIL /* A B R(A) := ... := R(B) := nil */ 45 OP_GETUPVAL /* A B R(A) := UpValue[B] */ 46 47 OP_GETGLOBAL /* A Bx R(A) := Gbl[Kst(Bx)] */ 48 OP_GETTABLE /* A B C R(A) := R(B)[RK(C)] */ 49 OP_GETTABLEKS /* A B C R(A) := R(B)[RK(C)] ; RK(C) is constant string */ 50 51 OP_SETGLOBAL /* A Bx Gbl[Kst(Bx)] := R(A) */ 52 OP_SETUPVAL /* A B UpValue[B] := R(A) */ 53 OP_SETTABLE /* A B C R(A)[RK(B)] := RK(C) */ 54 OP_SETTABLEKS /* A B C R(A)[RK(B)] := RK(C) ; RK(B) is constant string */ 55 56 OP_NEWTABLE /* A B C R(A) := {} (size = BC) */ 57 58 OP_SELF /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ 59 60 OP_ADD /* A B C R(A) := RK(B) + RK(C) */ 61 OP_SUB /* A B C R(A) := RK(B) - RK(C) */ 62 OP_MUL /* A B C R(A) := RK(B) * RK(C) */ 63 OP_DIV /* A B C R(A) := RK(B) / RK(C) */ 64 OP_MOD /* A B C R(A) := RK(B) % RK(C) */ 65 OP_POW /* A B C R(A) := RK(B) ^ RK(C) */ 66 OP_UNM /* A B R(A) := -R(B) */ 67 OP_NOT /* A B R(A) := not R(B) */ 68 OP_LEN /* A B R(A) := length of R(B) */ 69 70 OP_CONCAT /* A B C R(A) := R(B).. ... ..R(C) */ 71 72 OP_JMP /* sBx pc+=sBx */ 73 74 OP_EQ /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ 75 OP_LT /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ 76 OP_LE /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ 77 78 OP_TEST /* A C if not (R(A) <=> C) then pc++ */ 79 OP_TESTSET /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ 80 81 OP_CALL /* A B C R(A) ... R(A+C-2) := R(A)(R(A+1) ... R(A+B-1)) */ 82 OP_TAILCALL /* A B C return R(A)(R(A+1) ... R(A+B-1)) */ 83 OP_RETURN /* A B return R(A) ... R(A+B-2) (see note) */ 84 85 OP_FORLOOP /* A sBx R(A)+=R(A+2); 86 if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ 87 OP_FORPREP /* A sBx R(A)-=R(A+2); pc+=sBx */ 88 89 OP_TFORLOOP /* A C R(A+3) ... R(A+3+C) := R(A)(R(A+1) R(A+2)); 90 if R(A+3) ~= nil then { pc++; R(A+2)=R(A+3); } */ 91 OP_SETLIST /* A B C R(A)[(C-1)*FPF+i] := R(A+i) 1 <= i <= B */ 92 93 OP_CLOSE /* A close all variables in the stack up to (>=) R(A)*/ 94 OP_CLOSURE /* A Bx R(A) := closure(KPROTO[Bx] R(A) ... R(A+n)) */ 95 96 OP_VARARG /* A B R(A) R(A+1) ... R(A+B-1) = vararg */ 97 98 OP_NOP /* NOP */ 99 ) 100 const opCodeMax = OP_NOP 101 102 type opArgMode int 103 104 const ( 105 opArgModeN opArgMode = iota 106 opArgModeU 107 opArgModeR 108 opArgModeK 109 ) 110 111 type opType int 112 113 const ( 114 opTypeABC = iota 115 opTypeABx 116 opTypeASbx 117 ) 118 119 type opProp struct { 120 Name string 121 IsTest bool 122 SetRegA bool 123 ModeArgB opArgMode 124 ModeArgC opArgMode 125 Type opType 126 InstCount uint64 127 } 128 129 var opProps = []opProp{ 130 opProp{"MOVE", false, true, opArgModeR, opArgModeN, opTypeABC, uint64(1)}, 131 opProp{"MOVEN", false, true, opArgModeR, opArgModeN, opTypeABC, uint64(1)}, 132 opProp{"LOADK", false, true, opArgModeK, opArgModeN, opTypeABx, uint64(1)}, 133 opProp{"LOADBOOL", false, true, opArgModeU, opArgModeU, opTypeABC, uint64(1)}, 134 opProp{"LOADNIL", false, true, opArgModeR, opArgModeN, opTypeABC, uint64(1)}, 135 opProp{"GETUPVAL", false, true, opArgModeU, opArgModeN, opTypeABC, uint64(1)}, 136 opProp{"GETGLOBAL", false, true, opArgModeK, opArgModeN, opTypeABx, uint64(1)}, 137 opProp{"GETTABLE", false, true, opArgModeR, opArgModeK, opTypeABC, uint64(1)}, 138 opProp{"GETTABLEKS", false, true, opArgModeR, opArgModeK, opTypeABC, uint64(1)}, 139 opProp{"SETGLOBAL", false, false, opArgModeK, opArgModeN, opTypeABx, uint64(1)}, 140 opProp{"SETUPVAL", false, false, opArgModeU, opArgModeN, opTypeABC, uint64(1)}, 141 opProp{"SETTABLE", false, false, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 142 opProp{"SETTABLEKS", false, false, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 143 opProp{"NEWTABLE", false, true, opArgModeU, opArgModeU, opTypeABC, uint64(1)}, 144 opProp{"SELF", false, true, opArgModeR, opArgModeK, opTypeABC, uint64(1)}, 145 opProp{"ADD", false, true, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 146 opProp{"SUB", false, true, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 147 opProp{"MUL", false, true, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 148 opProp{"DIV", false, true, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 149 opProp{"MOD", false, true, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 150 opProp{"POW", false, true, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 151 opProp{"UNM", false, true, opArgModeR, opArgModeN, opTypeABC, uint64(1)}, 152 opProp{"NOT", false, true, opArgModeR, opArgModeN, opTypeABC, uint64(1)}, 153 opProp{"LEN", false, true, opArgModeR, opArgModeN, opTypeABC, uint64(1)}, 154 opProp{"CONCAT", false, true, opArgModeR, opArgModeR, opTypeABC, uint64(1)}, 155 opProp{"JMP", false, false, opArgModeR, opArgModeN, opTypeASbx, uint64(1)}, 156 opProp{"EQ", true, false, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 157 opProp{"LT", true, false, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 158 opProp{"LE", true, false, opArgModeK, opArgModeK, opTypeABC, uint64(1)}, 159 opProp{"TEST", true, true, opArgModeR, opArgModeU, opTypeABC, uint64(1)}, 160 opProp{"TESTSET", true, true, opArgModeR, opArgModeU, opTypeABC, uint64(1)}, 161 opProp{"CALL", false, true, opArgModeU, opArgModeU, opTypeABC, uint64(10)}, 162 opProp{"TAILCALL", false, true, opArgModeU, opArgModeU, opTypeABC, uint64(10)}, 163 opProp{"RETURN", false, false, opArgModeU, opArgModeN, opTypeABC, uint64(1)}, 164 opProp{"FORLOOP", false, true, opArgModeR, opArgModeN, opTypeASbx, uint64(1)}, 165 opProp{"FORPREP", false, true, opArgModeR, opArgModeN, opTypeASbx, uint64(1)}, 166 opProp{"TFORLOOP", true, false, opArgModeN, opArgModeU, opTypeABC, uint64(1)}, 167 opProp{"SETLIST", false, false, opArgModeU, opArgModeU, opTypeABC, uint64(1)}, 168 opProp{"CLOSE", false, false, opArgModeN, opArgModeN, opTypeABC, uint64(1)}, 169 opProp{"CLOSURE", false, true, opArgModeU, opArgModeN, opTypeABx, uint64(1)}, 170 opProp{"VARARG", false, true, opArgModeU, opArgModeN, opTypeABC, uint64(1)}, 171 opProp{"NOP", false, false, opArgModeR, opArgModeN, opTypeASbx, uint64(1)}, 172 } 173 174 func opGetOpCode(inst uint32) int { 175 return int(inst >> 26) 176 } 177 178 func opSetOpCode(inst *uint32, opcode int) { 179 *inst = (*inst & 0x3ffffff) | uint32(opcode<<26) 180 } 181 182 func opGetArgA(inst uint32) int { 183 return int(inst>>18) & 0xff 184 } 185 186 func opSetArgA(inst *uint32, arg int) { 187 *inst = (*inst & 0xfc03ffff) | uint32((arg&0xff)<<18) 188 } 189 190 func opGetArgB(inst uint32) int { 191 return int(inst & 0x1ff) 192 } 193 194 func opSetArgB(inst *uint32, arg int) { 195 *inst = (*inst & 0xfffffe00) | uint32(arg&0x1ff) 196 } 197 198 func opGetArgC(inst uint32) int { 199 return int(inst>>9) & 0x1ff 200 } 201 202 func opSetArgC(inst *uint32, arg int) { 203 *inst = (*inst & 0xfffc01ff) | uint32((arg&0x1ff)<<9) 204 } 205 206 func opGetArgBx(inst uint32) int { 207 return int(inst & 0x3ffff) 208 } 209 210 func opSetArgBx(inst *uint32, arg int) { 211 *inst = (*inst & 0xfffc0000) | uint32(arg&0x3ffff) 212 } 213 214 func opGetArgSbx(inst uint32) int { 215 return opGetArgBx(inst) - opMaxArgSbx 216 } 217 218 func opSetArgSbx(inst *uint32, arg int) { 219 opSetArgBx(inst, arg+opMaxArgSbx) 220 } 221 222 func opCreateABC(op int, a int, b int, c int) uint32 { 223 var inst uint32 = 0 224 opSetOpCode(&inst, op) 225 opSetArgA(&inst, a) 226 opSetArgB(&inst, b) 227 opSetArgC(&inst, c) 228 return inst 229 } 230 231 func opCreateABx(op int, a int, bx int) uint32 { 232 var inst uint32 = 0 233 opSetOpCode(&inst, op) 234 opSetArgA(&inst, a) 235 opSetArgBx(&inst, bx) 236 return inst 237 } 238 239 func opCreateASbx(op int, a int, sbx int) uint32 { 240 var inst uint32 = 0 241 opSetOpCode(&inst, op) 242 opSetArgA(&inst, a) 243 opSetArgSbx(&inst, sbx) 244 return inst 245 } 246 247 const opBitRk = 1 << (opSizeB - 1) 248 const opMaxIndexRk = opBitRk - 1 249 250 func opIsK(value int) bool { 251 return bool((value & opBitRk) != 0) 252 } 253 254 func opIndexK(value int) int { 255 return value & ^opBitRk 256 } 257 258 func opRkAsk(value int) int { 259 return value | opBitRk 260 } 261 262 func opToString(inst uint32) string { 263 op := opGetOpCode(inst) 264 if op > opCodeMax { 265 return "" 266 } 267 prop := &(opProps[op]) 268 269 arga := opGetArgA(inst) 270 argb := opGetArgB(inst) 271 argc := opGetArgC(inst) 272 argbx := opGetArgBx(inst) 273 argsbx := opGetArgSbx(inst) 274 275 buf := "" 276 switch prop.Type { 277 case opTypeABC: 278 buf = fmt.Sprintf("%s | %d, %d, %d", prop.Name, arga, argb, argc) 279 case opTypeABx: 280 buf = fmt.Sprintf("%s | %d, %d", prop.Name, arga, argbx) 281 case opTypeASbx: 282 buf = fmt.Sprintf("%s | %d, %d", prop.Name, arga, argsbx) 283 } 284 285 switch op { 286 case OP_MOVE: 287 buf += fmt.Sprintf("; R(%v) := R(%v)", arga, argb) 288 case OP_MOVEN: 289 buf += fmt.Sprintf("; R(%v) := R(%v); followed by %v MOVE ops", arga, argb, argc) 290 case OP_LOADK: 291 buf += fmt.Sprintf("; R(%v) := Kst(%v)", arga, argbx) 292 case OP_LOADBOOL: 293 buf += fmt.Sprintf("; R(%v) := (Bool)%v; if (%v) pc++", arga, argb, argc) 294 case OP_LOADNIL: 295 buf += fmt.Sprintf("; R(%v) := ... := R(%v) := nil", arga, argb) 296 case OP_GETUPVAL: 297 buf += fmt.Sprintf("; R(%v) := UpValue[%v]", arga, argb) 298 case OP_GETGLOBAL: 299 buf += fmt.Sprintf("; R(%v) := Gbl[Kst(%v)]", arga, argbx) 300 case OP_GETTABLE: 301 buf += fmt.Sprintf("; R(%v) := R(%v)[RK(%v)]", arga, argb, argc) 302 case OP_GETTABLEKS: 303 buf += fmt.Sprintf("; R(%v) := R(%v)[RK(%v)] ; RK(%v) is constant string", arga, argb, argc, argc) 304 case OP_SETGLOBAL: 305 buf += fmt.Sprintf("; Gbl[Kst(%v)] := R(%v)", argbx, arga) 306 case OP_SETUPVAL: 307 buf += fmt.Sprintf("; UpValue[%v] := R(%v)", argb, arga) 308 case OP_SETTABLE: 309 buf += fmt.Sprintf("; R(%v)[RK(%v)] := RK(%v)", arga, argb, argc) 310 case OP_SETTABLEKS: 311 buf += fmt.Sprintf("; R(%v)[RK(%v)] := RK(%v) ; RK(%v) is constant string", arga, argb, argc, argb) 312 case OP_NEWTABLE: 313 buf += fmt.Sprintf("; R(%v) := {} (size = BC)", arga) 314 case OP_SELF: 315 buf += fmt.Sprintf("; R(%v+1) := R(%v); R(%v) := R(%v)[RK(%v)]", arga, argb, arga, argb, argc) 316 case OP_ADD: 317 buf += fmt.Sprintf("; R(%v) := RK(%v) + RK(%v)", arga, argb, argc) 318 case OP_SUB: 319 buf += fmt.Sprintf("; R(%v) := RK(%v) - RK(%v)", arga, argb, argc) 320 case OP_MUL: 321 buf += fmt.Sprintf("; R(%v) := RK(%v) * RK(%v)", arga, argb, argc) 322 case OP_DIV: 323 buf += fmt.Sprintf("; R(%v) := RK(%v) / RK(%v)", arga, argb, argc) 324 case OP_MOD: 325 buf += fmt.Sprintf("; R(%v) := RK(%v) %% RK(%v)", arga, argb, argc) 326 case OP_POW: 327 buf += fmt.Sprintf("; R(%v) := RK(%v) ^ RK(%v)", arga, argb, argc) 328 case OP_UNM: 329 buf += fmt.Sprintf("; R(%v) := -R(%v)", arga, argb) 330 case OP_NOT: 331 buf += fmt.Sprintf("; R(%v) := not R(%v)", arga, argb) 332 case OP_LEN: 333 buf += fmt.Sprintf("; R(%v) := length of R(%v)", arga, argb) 334 case OP_CONCAT: 335 buf += fmt.Sprintf("; R(%v) := R(%v).. ... ..R(%v)", arga, argb, argc) 336 case OP_JMP: 337 buf += fmt.Sprintf("; pc+=%v", argsbx) 338 case OP_EQ: 339 buf += fmt.Sprintf("; if ((RK(%v) == RK(%v)) ~= %v) then pc++", argb, argc, arga) 340 case OP_LT: 341 buf += fmt.Sprintf("; if ((RK(%v) < RK(%v)) ~= %v) then pc++", argb, argc, arga) 342 case OP_LE: 343 buf += fmt.Sprintf("; if ((RK(%v) <= RK(%v)) ~= %v) then pc++", argb, argc, arga) 344 case OP_TEST: 345 buf += fmt.Sprintf("; if not (R(%v) <=> %v) then pc++", arga, argc) 346 case OP_TESTSET: 347 buf += fmt.Sprintf("; if (R(%v) <=> %v) then R(%v) := R(%v) else pc++", argb, argc, arga, argb) 348 case OP_CALL: 349 buf += fmt.Sprintf("; R(%v) ... R(%v+%v-2) := R(%v)(R(%v+1) ... R(%v+%v-1))", arga, arga, argc, arga, arga, arga, argb) 350 case OP_TAILCALL: 351 buf += fmt.Sprintf("; return R(%v)(R(%v+1) ... R(%v+%v-1))", arga, arga, arga, argb) 352 case OP_RETURN: 353 buf += fmt.Sprintf("; return R(%v) ... R(%v+%v-2)", arga, arga, argb) 354 case OP_FORLOOP: 355 buf += fmt.Sprintf("; R(%v)+=R(%v+2); if R(%v) <?= R(%v+1) then { pc+=%v; R(%v+3)=R(%v) }", arga, arga, arga, arga, argsbx, arga, arga) 356 case OP_FORPREP: 357 buf += fmt.Sprintf("; R(%v)-=R(%v+2); pc+=%v", arga, arga, argsbx) 358 case OP_TFORLOOP: 359 buf += fmt.Sprintf("; R(%v+3) ... R(%v+3+%v) := R(%v)(R(%v+1) R(%v+2)); if R(%v+3) ~= nil then { pc++; R(%v+2)=R(%v+3); }", arga, arga, argc, arga, arga, arga, arga, arga, arga) 360 case OP_SETLIST: 361 buf += fmt.Sprintf("; R(%v)[(%v-1)*FPF+i] := R(%v+i) 1 <= i <= %v", arga, argc, arga, argb) 362 case OP_CLOSE: 363 buf += fmt.Sprintf("; close all variables in the stack up to (>=) R(%v)", arga) 364 case OP_CLOSURE: 365 buf += fmt.Sprintf("; R(%v) := closure(KPROTO[%v] R(%v) ... R(%v+n))", arga, argbx, arga, arga) 366 case OP_VARARG: 367 buf += fmt.Sprintf("; R(%v) R(%v+1) ... R(%v+%v-1) = vararg", arga, arga, arga, argb) 368 case OP_NOP: 369 /* nothing to do */ 370 } 371 return buf 372 }