Advertisement
Kep13

LuaP

Dec 21st, 2020
24
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.89 KB | None | 0 0
  1. --[[--------------------------------------------------------------------
  2.  
  3. lopcodes.lua
  4. Lua 5 virtual machine opcodes in Lua
  5. This file is part of Yueliang.
  6.  
  7. Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
  8. The COPYRIGHT file describes the conditions
  9. under which this software may be distributed.
  10.  
  11. See the ChangeLog for more information.
  12.  
  13. ----------------------------------------------------------------------]]
  14.  
  15. --[[--------------------------------------------------------------------
  16. -- Notes:
  17. -- * an Instruction is a table with OP, A, B, C, Bx elements; this
  18. -- makes the code easy to follow and should allow instruction handling
  19. -- to work with doubles and ints
  20. -- * WARNING luaP:Instruction outputs instructions encoded in little-
  21. -- endian form and field size and positions are hard-coded
  22. --
  23. -- Not implemented:
  24. -- *
  25. --
  26. -- Added:
  27. -- * luaP:CREATE_Inst(c): create an inst from a number (for OP_SETLIST)
  28. -- * luaP:Instruction(i): convert field elements to a 4-char string
  29. -- * luaP:DecodeInst(x): convert 4-char string into field elements
  30. --
  31. -- Changed in 5.1.x:
  32. -- * POS_OP added, instruction field positions changed
  33. -- * some symbol names may have changed, e.g. LUAI_BITSINT
  34. -- * new operators for RK indices: BITRK, ISK(x), INDEXK(r), RKASK(x)
  35. -- * OP_MOD, OP_LEN is new
  36. -- * OP_TEST is now OP_TESTSET, OP_TEST is new
  37. -- * OP_FORLOOP, OP_TFORLOOP adjusted, OP_FORPREP is new
  38. -- * OP_TFORPREP deleted
  39. -- * OP_SETLIST and OP_SETLISTO merged and extended
  40. -- * OP_VARARG is new
  41. -- * many changes to implementation of OpMode data
  42. ----------------------------------------------------------------------]]
  43.  
  44. local luaP = {}
  45.  
  46. --[[
  47. ===========================================================================
  48. We assume that instructions are unsigned numbers.
  49. All instructions have an opcode in the first 6 bits.
  50. Instructions can have the following fields:
  51. 'A' : 8 bits
  52. 'B' : 9 bits
  53. 'C' : 9 bits
  54. 'Bx' : 18 bits ('B' and 'C' together)
  55. 'sBx' : signed Bx
  56.  
  57. A signed argument is represented in excess K; that is, the number
  58. value is the unsigned value minus K. K is exactly the maximum value
  59. for that argument (so that -max is represented by 0, and +max is
  60. represented by 2*max), which is half the maximum for the corresponding
  61. unsigned argument.
  62. ===========================================================================
  63. --]]
  64.  
  65. luaP.OpMode = { iABC = 0, iABx = 1, iAsBx = 2 } -- basic instruction format
  66.  
  67. ------------------------------------------------------------------------
  68. -- size and position of opcode arguments.
  69. -- * WARNING size and position is hard-coded elsewhere in this script
  70. ------------------------------------------------------------------------
  71. luaP.SIZE_C = 9
  72. luaP.SIZE_B = 9
  73. luaP.SIZE_Bx = luaP.SIZE_C + luaP.SIZE_B
  74. luaP.SIZE_A = 8
  75.  
  76. luaP.SIZE_OP = 6
  77.  
  78. luaP.POS_OP = 0
  79. luaP.POS_A = luaP.POS_OP + luaP.SIZE_OP
  80. luaP.POS_C = luaP.POS_A + luaP.SIZE_A
  81. luaP.POS_B = luaP.POS_C + luaP.SIZE_C
  82. luaP.POS_Bx = luaP.POS_C
  83.  
  84. ------------------------------------------------------------------------
  85. -- limits for opcode arguments.
  86. -- we use (signed) int to manipulate most arguments,
  87. -- so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
  88. ------------------------------------------------------------------------
  89. -- removed "#if SIZE_Bx < BITS_INT-1" test, assume this script is
  90. -- running on a Lua VM with double or int as LUA_NUMBER
  91.  
  92. luaP.MAXARG_Bx = math.ldexp(1, luaP.SIZE_Bx) - 1
  93. luaP.MAXARG_sBx = math.floor(luaP.MAXARG_Bx / 2) -- 'sBx' is signed
  94.  
  95. luaP.MAXARG_A = math.ldexp(1, luaP.SIZE_A) - 1
  96. luaP.MAXARG_B = math.ldexp(1, luaP.SIZE_B) - 1
  97. luaP.MAXARG_C = math.ldexp(1, luaP.SIZE_C) - 1
  98.  
  99. -- creates a mask with 'n' 1 bits at position 'p'
  100. -- MASK1(n,p) deleted, not required
  101. -- creates a mask with 'n' 0 bits at position 'p'
  102. -- MASK0(n,p) deleted, not required
  103.  
  104. --[[--------------------------------------------------------------------
  105. Visual representation for reference:
  106.  
  107. 31 | | | 0 bit position
  108. +-----+-----+-----+----------+
  109. | B | C | A | Opcode | iABC format
  110. +-----+-----+-----+----------+
  111. - 9 - 9 - 8 - 6 - field sizes
  112. +-----+-----+-----+----------+
  113. | [s]Bx | A | Opcode | iABx | iAsBx format
  114. +-----+-----+-----+----------+
  115.  
  116. ----------------------------------------------------------------------]]
  117.  
  118. ------------------------------------------------------------------------
  119. -- the following macros help to manipulate instructions
  120. -- * changed to a table object representation, very clean compared to
  121. -- the [nightmare] alternatives of using a number or a string
  122. -- * Bx is a separate element from B and C, since there is never a need
  123. -- to split Bx in the parser or code generator
  124. ------------------------------------------------------------------------
  125.  
  126. -- these accept or return opcodes in the form of string names
  127. function luaP:GET_OPCODE(i) return self.ROpCode[i.OP] end
  128. function luaP:SET_OPCODE(i, o) i.OP = self.OpCode[o] end
  129.  
  130. function luaP:GETARG_A(i) return i.A end
  131. function luaP:SETARG_A(i, u) i.A = u end
  132.  
  133. function luaP:GETARG_B(i) return i.B end
  134. function luaP:SETARG_B(i, b) i.B = b end
  135.  
  136. function luaP:GETARG_C(i) return i.C end
  137. function luaP:SETARG_C(i, b) i.C = b end
  138.  
  139. function luaP:GETARG_Bx(i) return i.Bx end
  140. function luaP:SETARG_Bx(i, b) i.Bx = b end
  141.  
  142. function luaP:GETARG_sBx(i) return i.Bx - self.MAXARG_sBx end
  143. function luaP:SETARG_sBx(i, b) i.Bx = b + self.MAXARG_sBx end
  144.  
  145. function luaP:CREATE_ABC(o,a,b,c)
  146. return {OP = self.OpCode[o], A = a, B = b, C = c}
  147. end
  148.  
  149. function luaP:CREATE_ABx(o,a,bc)
  150. return {OP = self.OpCode[o], A = a, Bx = bc}
  151. end
  152.  
  153. ------------------------------------------------------------------------
  154. -- create an instruction from a number (for OP_SETLIST)
  155. ------------------------------------------------------------------------
  156. function luaP:CREATE_Inst(c)
  157. local o = c % 64
  158. c = (c - o) / 64
  159. local a = c % 256
  160. c = (c - a) / 256
  161. return self:CREATE_ABx(o, a, c)
  162. end
  163.  
  164. ------------------------------------------------------------------------
  165. -- returns a 4-char string little-endian encoded form of an instruction
  166. ------------------------------------------------------------------------
  167. function luaP:Instruction(i)
  168. if i.Bx then
  169. -- change to OP/A/B/C format
  170. i.C = i.Bx % 512
  171. i.B = (i.Bx - i.C) / 512
  172. end
  173. local I = i.A * 64 + i.OP
  174. local c0 = I % 256
  175. I = i.C * 64 + (I - c0) / 256 -- 6 bits of A left
  176. local c1 = I % 256
  177. I = i.B * 128 + (I - c1) / 256 -- 7 bits of C left
  178. local c2 = I % 256
  179. local c3 = (I - c2) / 256
  180. return string.char(c0, c1, c2, c3)
  181. end
  182.  
  183. ------------------------------------------------------------------------
  184. -- decodes a 4-char little-endian string into an instruction struct
  185. ------------------------------------------------------------------------
  186. function luaP:DecodeInst(x)
  187. local byte = string.byte
  188. local i = {}
  189. local I = byte(x, 1)
  190. local op = I % 64
  191. i.OP = op
  192. I = byte(x, 2) * 4 + (I - op) / 64 -- 2 bits of c0 left
  193. local a = I % 256
  194. i.A = a
  195. I = byte(x, 3) * 4 + (I - a) / 256 -- 2 bits of c1 left
  196. local c = I % 512
  197. i.C = c
  198. i.B = byte(x, 4) * 2 + (I - c) / 512 -- 1 bits of c2 left
  199. local opmode = self.OpMode[tonumber(string.sub(self.opmodes[op + 1], 7, 7))]
  200. if opmode ~= "iABC" then
  201. i.Bx = i.B * 512 + i.C
  202. end
  203. return i
  204. end
  205.  
  206. ------------------------------------------------------------------------
  207. -- Macros to operate RK indices
  208. -- * these use arithmetic instead of bit ops
  209. ------------------------------------------------------------------------
  210.  
  211. -- this bit 1 means constant (0 means register)
  212. luaP.BITRK = math.ldexp(1, luaP.SIZE_B - 1)
  213.  
  214. -- test whether value is a constant
  215. function luaP:ISK(x) return x >= self.BITRK end
  216.  
  217. -- gets the index of the constant
  218. function luaP:INDEXK(x) return x - self.BITRK end
  219.  
  220. luaP.MAXINDEXRK = luaP.BITRK - 1
  221.  
  222. -- code a constant index as a RK value
  223. function luaP:RKASK(x) return x + self.BITRK end
  224.  
  225. ------------------------------------------------------------------------
  226. -- invalid register that fits in 8 bits
  227. ------------------------------------------------------------------------
  228. luaP.NO_REG = luaP.MAXARG_A
  229.  
  230. ------------------------------------------------------------------------
  231. -- R(x) - register
  232. -- Kst(x) - constant (in constant table)
  233. -- RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
  234. ------------------------------------------------------------------------
  235.  
  236. ------------------------------------------------------------------------
  237. -- grep "ORDER OP" if you change these enums
  238. ------------------------------------------------------------------------
  239.  
  240. --[[--------------------------------------------------------------------
  241. Lua virtual machine opcodes (enum OpCode):
  242. ------------------------------------------------------------------------
  243. name args description
  244. ------------------------------------------------------------------------
  245. OP_MOVE A B R(A) := R(B)
  246. OP_LOADK A Bx R(A) := Kst(Bx)
  247. OP_LOADBOOL A B C R(A) := (Bool)B; if (C) pc++
  248. OP_LOADNIL A B R(A) := ... := R(B) := nil
  249. OP_GETUPVAL A B R(A) := UpValue[B]
  250. OP_GETGLOBAL A Bx R(A) := Gbl[Kst(Bx)]
  251. OP_GETTABLE A B C R(A) := R(B)[RK(C)]
  252. OP_SETGLOBAL A Bx Gbl[Kst(Bx)] := R(A)
  253. OP_SETUPVAL A B UpValue[B] := R(A)
  254. OP_SETTABLE A B C R(A)[RK(B)] := RK(C)
  255. OP_NEWTABLE A B C R(A) := {} (size = B,C)
  256. OP_SELF A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]
  257. OP_ADD A B C R(A) := RK(B) + RK(C)
  258. OP_SUB A B C R(A) := RK(B) - RK(C)
  259. OP_MUL A B C R(A) := RK(B) * RK(C)
  260. OP_DIV A B C R(A) := RK(B) / RK(C)
  261. OP_MOD A B C R(A) := RK(B) % RK(C)
  262. OP_POW A B C R(A) := RK(B) ^ RK(C)
  263. OP_UNM A B R(A) := -R(B)
  264. OP_NOT A B R(A) := not R(B)
  265. OP_LEN A B R(A) := length of R(B)
  266. OP_CONCAT A B C R(A) := R(B).. ... ..R(C)
  267. OP_JMP sBx pc+=sBx
  268. OP_EQ A B C if ((RK(B) == RK(C)) ~= A) then pc++
  269. OP_LT A B C if ((RK(B) < RK(C)) ~= A) then pc++
  270. OP_LE A B C if ((RK(B) <= RK(C)) ~= A) then pc++
  271. OP_TEST A C if not (R(A) <=> C) then pc++
  272. OP_TESTSET A B C if (R(B) <=> C) then R(A) := R(B) else pc++
  273. OP_CALL A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
  274. OP_TAILCALL A B C return R(A)(R(A+1), ... ,R(A+B-1))
  275. OP_RETURN A B return R(A), ... ,R(A+B-2) (see note)
  276. OP_FORLOOP A sBx R(A)+=R(A+2);
  277. if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
  278. OP_FORPREP A sBx R(A)-=R(A+2); pc+=sBx
  279. OP_TFORLOOP A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
  280. if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++
  281. OP_SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
  282. OP_CLOSE A close all variables in the stack up to (>=) R(A)
  283. OP_CLOSURE A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))
  284. OP_VARARG A B R(A), R(A+1), ..., R(A+B-1) = vararg
  285. ----------------------------------------------------------------------]]
  286.  
  287. luaP.opnames = {} -- opcode names
  288. luaP.OpCode = {} -- lookup name -> number
  289. luaP.ROpCode = {} -- lookup number -> name
  290.  
  291. ------------------------------------------------------------------------
  292. -- ORDER OP
  293. ------------------------------------------------------------------------
  294. local i = 0
  295. for v in string.gmatch([[
  296. MOVE LOADK LOADBOOL LOADNIL GETUPVAL
  297. GETGLOBAL GETTABLE SETGLOBAL SETUPVAL SETTABLE
  298. NEWTABLE SELF ADD SUB MUL
  299. DIV MOD POW UNM NOT
  300. LEN CONCAT JMP EQ LT
  301. LE TEST TESTSET CALL TAILCALL
  302. RETURN FORLOOP FORPREP TFORLOOP SETLIST
  303. CLOSE CLOSURE VARARG
  304. ]], "%S+") do
  305. local n = "OP_"..v
  306. luaP.opnames[i] = v
  307. luaP.OpCode[n] = i
  308. luaP.ROpCode[i] = n
  309. i = i + 1
  310. end
  311. luaP.NUM_OPCODES = i
  312.  
  313. --[[
  314. ===========================================================================
  315. Notes:
  316. (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
  317. and can be 0: OP_CALL then sets 'top' to last_result+1, so
  318. next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use 'top'.
  319. (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
  320. set top (like in OP_CALL with C == 0).
  321. (*) In OP_RETURN, if (B == 0) then return up to 'top'
  322. (*) In OP_SETLIST, if (B == 0) then B = 'top';
  323. if (C == 0) then next 'instruction' is real C
  324. (*) For comparisons, A specifies what condition the test should accept
  325. (true or false).
  326. (*) All 'skips' (pc++) assume that next instruction is a jump
  327. ===========================================================================
  328. --]]
  329.  
  330. --[[--------------------------------------------------------------------
  331. masks for instruction properties. The format is:
  332. bits 0-1: op mode
  333. bits 2-3: C arg mode
  334. bits 4-5: B arg mode
  335. bit 6: instruction set register A
  336. bit 7: operator is a test
  337.  
  338. for OpArgMask:
  339. OpArgN - argument is not used
  340. OpArgU - argument is used
  341. OpArgR - argument is a register or a jump offset
  342. OpArgK - argument is a constant or register/constant
  343. ----------------------------------------------------------------------]]
  344.  
  345. -- was enum OpArgMask
  346. luaP.OpArgMask = { OpArgN = 0, OpArgU = 1, OpArgR = 2, OpArgK = 3 }
  347.  
  348. ------------------------------------------------------------------------
  349. -- e.g. to compare with symbols, luaP:getOpMode(...) == luaP.OpCode.iABC
  350. -- * accepts opcode parameter as strings, e.g. "OP_MOVE"
  351. ------------------------------------------------------------------------
  352.  
  353. function luaP:getOpMode(m)
  354. return self.opmodes[self.OpCode[m]] % 4
  355. end
  356.  
  357. function luaP:getBMode(m)
  358. return math.floor(self.opmodes[self.OpCode[m]] / 16) % 4
  359. end
  360.  
  361. function luaP:getCMode(m)
  362. return math.floor(self.opmodes[self.OpCode[m]] / 4) % 4
  363. end
  364.  
  365. function luaP:testAMode(m)
  366. return math.floor(self.opmodes[self.OpCode[m]] / 64) % 2
  367. end
  368.  
  369. function luaP:testTMode(m)
  370. return math.floor(self.opmodes[self.OpCode[m]] / 128)
  371. end
  372.  
  373. -- luaP_opnames[] is set above, as the luaP.opnames table
  374.  
  375. -- number of list items to accumulate before a SETLIST instruction
  376. luaP.LFIELDS_PER_FLUSH = 50
  377.  
  378. ------------------------------------------------------------------------
  379. -- build instruction properties array
  380. -- * deliberately coded to look like the C equivalent
  381. ------------------------------------------------------------------------
  382. local function opmode(t, a, b, c, m)
  383. local luaP = luaP
  384. return t * 128 + a * 64 +
  385. luaP.OpArgMask[b] * 16 + luaP.OpArgMask[c] * 4 + luaP.OpMode[m]
  386. end
  387.  
  388. -- ORDER OP
  389. luaP.opmodes = {
  390. -- T A B C mode opcode
  391. opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_LOADK
  392. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_LOADBOOL
  393. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LOADNIL
  394. opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_GETUPVAL
  395. opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_GETGLOBAL
  396. opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_GETTABLE
  397. opmode(0, 0, "OpArgK", "OpArgN", "iABx"), -- OP_SETGLOBAL
  398. opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_SETUPVAL
  399. opmode(0, 0, "OpArgK", "OpArgK", "iABC"), -- OP_SETTABLE
  400. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_NEWTABLE
  401. opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_SELF
  402. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_ADD
  403. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_SUB
  404. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MUL
  405. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_DIV
  406. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MOD
  407. opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_POW
  408. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_UNM
  409. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_NOT
  410. opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LEN
  411. opmode(0, 1, "OpArgR", "OpArgR", "iABC"), -- OP_CONCAT
  412. opmode(0, 0, "OpArgR", "OpArgN", "iAsBx"), -- OP_JMP
  413. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_EQ
  414. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LT
  415. opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LE
  416. opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TEST
  417. opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TESTSET
  418. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_CALL
  419. opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_TAILCALL
  420. opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_RETURN
  421. opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORLOOP
  422. opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORPREP
  423. opmode(1, 0, "OpArgN", "OpArgU", "iABC"), -- OP_TFORLOOP
  424. opmode(0, 0, "OpArgU", "OpArgU", "iABC"), -- OP_SETLIST
  425. opmode(0, 0, "OpArgN", "OpArgN", "iABC"), -- OP_CLOSE
  426. opmode(0, 1, "OpArgU", "OpArgN", "iABx"), -- OP_CLOSURE
  427. opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_VARARG
  428. }
  429. -- an awkward way to set a zero-indexed table...
  430. luaP.opmodes[0] =
  431. opmode(0, 1, "OpArgR", "OpArgN", "iABC") -- OP_MOVE
  432.  
  433. return luaP
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement