Disable loading bytecode with an extra header (BOM or #!).
[luajit-2.0.git] / src / buildvm_ppcspe.dasc
blobb9ee5b01e50624e9ec19275a855d29aaa170ea8f
1 |// Low-level VM code for PowerPC/e500 CPUs.
2 |// Bytecode interpreter, fast functions and helper functions.
3 |// Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
5 |.arch ppc
6 |.section code_op, code_sub
8 |.actionlist build_actionlist
9 |.globals GLOB_
10 |.globalnames globnames
11 |.externnames extnames
13 |// Note: The ragged indentation of the instructions is intentional.
14 |//       The starting columns indicate data dependencies.
16 |//-----------------------------------------------------------------------
18 |// Fixed register assignments for the interpreter.
19 |// Don't use: r1 = sp, r2 and r13 = reserved and/or small data area ptr
21 |// The following must be C callee-save (but BASE is often refetched).
22 |.define BASE,          r14     // Base of current Lua stack frame.
23 |.define KBASE,         r15     // Constants of current Lua function.
24 |.define PC,            r16     // Next PC.
25 |.define DISPATCH,      r17     // Opcode dispatch table.
26 |.define LREG,          r18     // Register holding lua_State (also in SAVE_L).
27 |.define MULTRES,       r19     // Size of multi-result: (nresults+1)*8.
29 |// Constants for vectorized type-comparisons (hi+low GPR). C callee-save.
30 |.define TISNUM,        r22
31 |.define TISSTR,        r23
32 |.define TISTAB,        r24
33 |.define TISFUNC,       r25
34 |.define TISNIL,        r26
35 |.define TOBIT,         r27
36 |.define ZERO,          TOBIT   // Zero in lo word.
38 |// The following temporaries are not saved across C calls, except for RA.
39 |.define RA,            r20     // Callee-save.
40 |.define RB,            r10
41 |.define RC,            r11
42 |.define RD,            r12
43 |.define INS,           r7      // Overlaps CARG5.
45 |.define TMP0,          r0
46 |.define TMP1,          r8
47 |.define TMP2,          r9
48 |.define TMP3,          r6      // Overlaps CARG4.
50 |// Saved temporaries.
51 |.define SAVE0,         r21
53 |// Calling conventions.
54 |.define CARG1,         r3
55 |.define CARG2,         r4
56 |.define CARG3,         r5
57 |.define CARG4,         r6      // Overlaps TMP3.
58 |.define CARG5,         r7      // Overlaps INS.
60 |.define CRET1,         r3
61 |.define CRET2,         r4
63 |// Stack layout while in interpreter. Must match with lj_frame.h.
64 |.define SAVE_LR,       188(sp)
65 |.define CFRAME_SPACE,  184     // Delta for sp.
66 |// Back chain for sp:  184(sp) <-- sp entering interpreter
67 |.define SAVE_r31,      176(sp) // 64 bit register saves.
68 |.define SAVE_r30,      168(sp)
69 |.define SAVE_r29,      160(sp)
70 |.define SAVE_r28,      152(sp)
71 |.define SAVE_r27,      144(sp)
72 |.define SAVE_r26,      136(sp)
73 |.define SAVE_r25,      128(sp)
74 |.define SAVE_r24,      120(sp)
75 |.define SAVE_r23,      112(sp)
76 |.define SAVE_r22,      104(sp)
77 |.define SAVE_r21,      96(sp)
78 |.define SAVE_r20,      88(sp)
79 |.define SAVE_r19,      80(sp)
80 |.define SAVE_r18,      72(sp)
81 |.define SAVE_r17,      64(sp)
82 |.define SAVE_r16,      56(sp)
83 |.define SAVE_r15,      48(sp)
84 |.define SAVE_r14,      40(sp)
85 |.define SAVE_CR,       36(sp)
86 |.define UNUSED1,       32(sp)
87 |.define SAVE_ERRF,     28(sp)  // 32 bit C frame info.
88 |.define SAVE_NRES,     24(sp)
89 |.define SAVE_CFRAME,   20(sp)
90 |.define SAVE_L,        16(sp)
91 |.define SAVE_PC,       12(sp)
92 |.define SAVE_MULTRES,  8(sp)
93 |// Next frame lr:      4(sp)
94 |// Back chain for sp:  0(sp)   <-- sp while in interpreter
96 |.macro save_, reg; evstdd reg, SAVE_..reg; .endmacro
97 |.macro rest_, reg; evldd reg, SAVE_..reg; .endmacro
99 |.macro saveregs
100 |  stwu sp, -CFRAME_SPACE(sp)
101 |  save_ r14; save_ r15; save_ r16; save_ r17; save_ r18; save_ r19
102 |  mflr r0; mfcr r12
103 |  save_ r20; save_ r21; save_ r22; save_ r23; save_ r24; save_ r25
104 |  stw  r0, SAVE_LR; stw r12, SAVE_CR
105 |  save_ r26; save_ r27; save_ r28; save_ r29; save_ r30; save_ r31
106 |.endmacro
108 |.macro restoreregs
109 |  lwz r0, SAVE_LR; lwz r12, SAVE_CR
110 |  rest_ r14; rest_ r15; rest_ r16; rest_ r17; rest_ r18; rest_ r19
111 |  mtlr r0; mtcrf 0x38, r12
112 |  rest_ r20; rest_ r21; rest_ r22; rest_ r23; rest_ r24; rest_ r25
113 |  rest_ r26; rest_ r27; rest_ r28; rest_ r29; rest_ r30; rest_ r31
114 |  addi sp, sp, CFRAME_SPACE
115 |.endmacro
117 |// Type definitions. Some of these are only used for documentation.
118 |.type L,               lua_State,      LREG
119 |.type GL,              global_State
120 |.type TVALUE,          TValue
121 |.type GCOBJ,           GCobj
122 |.type STR,             GCstr
123 |.type TAB,             GCtab
124 |.type LFUNC,           GCfuncL
125 |.type CFUNC,           GCfuncC
126 |.type PROTO,           GCproto
127 |.type UPVAL,           GCupval
128 |.type NODE,            Node
129 |.type NARGS8,          int
130 |.type TRACE,           GCtrace
132 |//-----------------------------------------------------------------------
134 |// These basic macros should really be part of DynASM.
135 |.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro
136 |.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro
137 |.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro
138 |.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro
139 |.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro
141 |// Trap for not-yet-implemented parts.
142 |.macro NYI; tw 4, sp, sp; .endmacro
144 |//-----------------------------------------------------------------------
146 |// Access to frame relative to BASE.
147 |.define FRAME_PC,      -8
148 |.define FRAME_FUNC,    -4
150 |// Instruction decode.
151 |.macro decode_OP4, dst, ins; rlwinm dst, ins, 2, 22, 29; .endmacro
152 |.macro decode_RA8, dst, ins; rlwinm dst, ins, 27, 21, 28; .endmacro
153 |.macro decode_RB8, dst, ins; rlwinm dst, ins, 11, 21, 28; .endmacro
154 |.macro decode_RC8, dst, ins; rlwinm dst, ins, 19, 21, 28; .endmacro
155 |.macro decode_RD8, dst, ins; rlwinm dst, ins, 19, 13, 28; .endmacro
157 |.macro decode_OP1, dst, ins; rlwinm dst, ins, 0, 24, 31; .endmacro
158 |.macro decode_RD4, dst, ins; rlwinm dst, ins, 18, 14, 29; .endmacro
160 |// Instruction fetch.
161 |.macro ins_NEXT1
162 |  lwz INS, 0(PC)
163 |   addi PC, PC, 4
164 |.endmacro
165 |// Instruction decode+dispatch.
166 |.macro ins_NEXT2
167 |  decode_OP4 TMP1, INS
168 |   decode_RB8 RB, INS
169 |   decode_RD8 RD, INS
170 |  lwzx TMP0, DISPATCH, TMP1
171 |   decode_RA8 RA, INS
172 |   decode_RC8 RC, INS
173 |  mtctr TMP0
174 |  bctr
175 |.endmacro
176 |.macro ins_NEXT
177 |  ins_NEXT1
178 |  ins_NEXT2
179 |.endmacro
181 |// Instruction footer.
182 |.if 1
183 |  // Replicated dispatch. Less unpredictable branches, but higher I-Cache use.
184 |  .define ins_next, ins_NEXT
185 |  .define ins_next_, ins_NEXT
186 |  .define ins_next1, ins_NEXT1
187 |  .define ins_next2, ins_NEXT2
188 |.else
189 |  // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch.
190 |  // Affects only certain kinds of benchmarks (and only with -j off).
191 |  .macro ins_next
192 |    b ->ins_next
193 |  .endmacro
194 |  .macro ins_next1
195 |  .endmacro
196 |  .macro ins_next2
197 |    b ->ins_next
198 |  .endmacro
199 |  .macro ins_next_
200 |  ->ins_next:
201 |    ins_NEXT
202 |  .endmacro
203 |.endif
205 |// Call decode and dispatch.
206 |.macro ins_callt
207 |  // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
208 |  lwz PC, LFUNC:RB->pc
209 |  lwz INS, 0(PC)
210 |   addi PC, PC, 4
211 |  decode_OP4 TMP1, INS
212 |   decode_RA8 RA, INS
213 |  lwzx TMP0, DISPATCH, TMP1
214 |   add RA, RA, BASE
215 |  mtctr TMP0
216 |  bctr
217 |.endmacro
219 |.macro ins_call
220 |  // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC
221 |  stw PC, FRAME_PC(BASE)
222 |  ins_callt
223 |.endmacro
225 |//-----------------------------------------------------------------------
227 |// Macros to test operand types.
228 |.macro checknum, reg; evcmpltu reg, TISNUM; .endmacro
229 |.macro checkstr, reg; evcmpeq reg, TISSTR; .endmacro
230 |.macro checktab, reg; evcmpeq reg, TISTAB; .endmacro
231 |.macro checkfunc, reg; evcmpeq reg, TISFUNC; .endmacro
232 |.macro checknil, reg; evcmpeq reg, TISNIL; .endmacro
233 |.macro checkok, label; blt label; .endmacro
234 |.macro checkfail, label; bge label; .endmacro
235 |.macro checkanyfail, label; bns label; .endmacro
236 |.macro checkallok, label; bso label; .endmacro
238 |.macro branch_RD
239 |  srwi TMP0, RD, 1
240 |  add PC, PC, TMP0
241 |  addis PC, PC, -(BCBIAS_J*4 >> 16)
242 |.endmacro
244 |// Assumes DISPATCH is relative to GL.
245 #define DISPATCH_GL(field)      (GG_DISP2G + (int)offsetof(global_State, field))
246 #define DISPATCH_J(field)       (GG_DISP2J + (int)offsetof(jit_State, field))
248 #define PC2PROTO(field)  ((int)offsetof(GCproto, field)-(int)sizeof(GCproto))
250 |.macro hotloop
251 |  NYI
252 |.endmacro
254 |.macro hotcall
255 |  NYI
256 |.endmacro
258 |// Set current VM state. Uses TMP0.
259 |.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro
260 |.macro st_vmstate; stw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro
262 |// Move table write barrier back. Overwrites mark and tmp.
263 |.macro barrierback, tab, mark, tmp
264 |  lwz tmp, DISPATCH_GL(gc.grayagain)(DISPATCH)
265 |  // Assumes LJ_GC_BLACK is 0x04.
266 |   rlwinm mark, mark, 0, 30, 28                // black2gray(tab)
267 |  stw tab, DISPATCH_GL(gc.grayagain)(DISPATCH)
268 |   stb mark, tab->marked
269 |  stw tmp, tab->gclist
270 |.endmacro
272 |//-----------------------------------------------------------------------
274 /* Generate subroutines used by opcodes and other parts of the VM. */
275 /* The .code_sub section should be last to help static branch prediction. */
276 static void build_subroutines(BuildCtx *ctx)
278   |.code_sub
279   |
280   |//-----------------------------------------------------------------------
281   |//-- Return handling ----------------------------------------------------
282   |//-----------------------------------------------------------------------
283   |
284   |->vm_returnp:
285   |  // See vm_return. Also: TMP2 = previous base.
286   |  andi. TMP0, PC, FRAME_P
287   |   evsplati TMP1, LJ_TTRUE
288   |  beq ->cont_dispatch
289   |
290   |  // Return from pcall or xpcall fast func.
291   |  lwz PC, FRAME_PC(TMP2)             // Fetch PC of previous frame.
292   |  mr BASE, TMP2                      // Restore caller base.
293   |  // Prepending may overwrite the pcall frame, so do it at the end.
294   |   stwu TMP1, FRAME_PC(RA)           // Prepend true to results.
295   |
296   |->vm_returnc:
297   |  andi. TMP0, PC, FRAME_TYPE
298   |   addi RD, RD, 8                    // RD = (nresults+1)*8.
299   |   mr MULTRES, RD
300   |  beq ->BC_RET_Z                     // Handle regular return to Lua.
301   |
302   |->vm_return:
303   |  // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return
304   |  // TMP0 = PC & FRAME_TYPE
305   |  cmpwi TMP0, FRAME_C
306   |   rlwinm TMP2, PC, 0, 0, 28
307   |    li_vmstate C
308   |   sub TMP2, BASE, TMP2              // TMP2 = previous base.
309   |  bne ->vm_returnp
310   |
311   |  addic. TMP1, RD, -8
312   |   stw TMP2, L->base
313   |   lwz TMP2, SAVE_NRES
314   |    subi BASE, BASE, 8
315   |    st_vmstate
316   |   slwi TMP2, TMP2, 3
317   |  beq >2
318   |1:
319   |  addic. TMP1, TMP1, -8
320   |   evldd TMP0, 0(RA)
321   |    addi RA, RA, 8
322   |   evstdd TMP0, 0(BASE)
323   |    addi BASE, BASE, 8
324   |  bne <1
325   |
326   |2:
327   |  cmpw TMP2, RD                      // More/less results wanted?
328   |  bne >6
329   |3:
330   |  stw BASE, L->top                   // Store new top.
331   |
332   |->vm_leave_cp:
333   |  lwz TMP0, SAVE_CFRAME              // Restore previous C frame.
334   |   li CRET1, 0                       // Ok return status for vm_pcall.
335   |  stw TMP0, L->cframe
336   |
337   |->vm_leave_unw:
338   |  restoreregs
339   |  blr
340   |
341   |6:
342   |  ble >7                             // Less results wanted?
343   |  // More results wanted. Check stack size and fill up results with nil.
344   |  lwz TMP1, L->maxstack
345   |  cmplw BASE, TMP1
346   |  bge >8
347   |  evstdd TISNIL, 0(BASE)
348   |  addi RD, RD, 8
349   |  addi BASE, BASE, 8
350   |  b <2
351   |
352   |7:  // Less results wanted.
353   |   sub TMP0, RD, TMP2
354   |  cmpwi TMP2, 0                      // LUA_MULTRET+1 case?
355   |   sub TMP0, BASE, TMP0              // Subtract the difference.
356   |  iseleq BASE, BASE, TMP0            // Either keep top or shrink it.
357   |  b <3
358   |
359   |8:  // Corner case: need to grow stack for filling up results.
360   |  // This can happen if:
361   |  // - A C function grows the stack (a lot).
362   |  // - The GC shrinks the stack in between.
363   |  // - A return back from a lua_call() with (high) nresults adjustment.
364   |  stw BASE, L->top                   // Save current top held in BASE (yes).
365   |   mr SAVE0, RD
366   |  mr CARG2, TMP2
367   |  mr CARG1, L
368   |  bl extern lj_state_growstack       // (lua_State *L, int n)
369   |    lwz TMP2, SAVE_NRES
370   |   mr RD, SAVE0
371   |    slwi TMP2, TMP2, 3
372   |  lwz BASE, L->top                   // Need the (realloced) L->top in BASE.
373   |  b <2
374   |
375   |->vm_unwind_c:                       // Unwind C stack, return from vm_pcall.
376   |  // (void *cframe, int errcode)
377   |  mr sp, CARG1
378   |  mr CRET1, CARG2
379   |->vm_unwind_c_eh:                    // Landing pad for external unwinder.
380   |  lwz L, SAVE_L
381   |   li TMP0, ~LJ_VMST_C
382   |  lwz GL:TMP1, L->glref
383   |   stw TMP0, GL:TMP1->vmstate
384   |  b ->vm_leave_unw
385   |
386   |->vm_unwind_ff:                      // Unwind C stack, return from ff pcall.
387   |  // (void *cframe)
388   |  rlwinm sp, CARG1, 0, 0, 29
389   |->vm_unwind_ff_eh:                   // Landing pad for external unwinder.
390   |  lwz L, SAVE_L
391   |     evsplati TISNUM, LJ_TISNUM+1    // Setup type comparison constants.
392   |     evsplati TISFUNC, LJ_TFUNC
393   |     lus TOBIT, 0x4338
394   |     evsplati TISTAB, LJ_TTAB
395   |     li TMP0, 0
396   |  lwz BASE, L->base
397   |     evmergelo TOBIT, TOBIT, TMP0
398   |   lwz DISPATCH, L->glref            // Setup pointer to dispatch table.
399   |     evsplati TISSTR, LJ_TSTR
400   |  li TMP1, LJ_TFALSE
401   |     evsplati TISNIL, LJ_TNIL
402   |    li_vmstate INTERP
403   |  lwz PC, FRAME_PC(BASE)             // Fetch PC of previous frame.
404   |  la RA, -8(BASE)                    // Results start at BASE-8.
405   |   addi DISPATCH, DISPATCH, GG_G2DISP
406   |  stw TMP1, 0(RA)                    // Prepend false to error message.
407   |  li RD, 16                          // 2 results: false + error message.
408   |    st_vmstate
409   |  b ->vm_returnc
410   |
411   |//-----------------------------------------------------------------------
412   |//-- Grow stack for calls -----------------------------------------------
413   |//-----------------------------------------------------------------------
414   |
415   |->vm_growstack_c:                    // Grow stack for C function.
416   |  li CARG2, LUA_MINSTACK
417   |  b >2
418   |
419   |->vm_growstack_l:                    // Grow stack for Lua function.
420   |  // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC
421   |  add RC, BASE, RC
422   |   sub RA, RA, BASE
423   |  stw BASE, L->base
424   |   addi PC, PC, 4                    // Must point after first instruction.
425   |  stw RC, L->top
426   |   srwi CARG2, RA, 3
427   |2:
428   |  // L->base = new base, L->top = top
429   |   stw PC, SAVE_PC
430   |  mr CARG1, L
431   |  bl extern lj_state_growstack       // (lua_State *L, int n)
432   |  lwz BASE, L->base
433   |  lwz RC, L->top
434   |  lwz LFUNC:RB, FRAME_FUNC(BASE)
435   |  sub RC, RC, BASE
436   |  // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
437   |  ins_callt                          // Just retry the call.
438   |
439   |//-----------------------------------------------------------------------
440   |//-- Entry points into the assembler VM ---------------------------------
441   |//-----------------------------------------------------------------------
442   |
443   |->vm_resume:                         // Setup C frame and resume thread.
444   |  // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0)
445   |  saveregs
446   |  mr L, CARG1
447   |    lwz DISPATCH, L->glref           // Setup pointer to dispatch table.
448   |  mr BASE, CARG2
449   |    lbz TMP1, L->status
450   |   stw L, SAVE_L
451   |  li PC, FRAME_CP
452   |  addi TMP0, sp, CFRAME_RESUME
453   |    addi DISPATCH, DISPATCH, GG_G2DISP
454   |   stw CARG3, SAVE_NRES
455   |    cmplwi TMP1, 0
456   |   stw CARG3, SAVE_ERRF
457   |  stw TMP0, L->cframe
458   |   stw CARG3, SAVE_CFRAME
459   |   stw CARG1, SAVE_PC                // Any value outside of bytecode is ok.
460   |    beq >3
461   |
462   |  // Resume after yield (like a return).
463   |  mr RA, BASE
464   |   lwz BASE, L->base
465   |    evsplati TISNUM, LJ_TISNUM+1     // Setup type comparison constants.
466   |   lwz TMP1, L->top
467   |    evsplati TISFUNC, LJ_TFUNC
468   |    lus TOBIT, 0x4338
469   |    evsplati TISTAB, LJ_TTAB
470   |  lwz PC, FRAME_PC(BASE)
471   |    li TMP2, 0
472   |    evsplati TISSTR, LJ_TSTR
473   |   sub RD, TMP1, BASE
474   |    evmergelo TOBIT, TOBIT, TMP2
475   |    stb CARG3, L->status
476   |  andi. TMP0, PC, FRAME_TYPE
477   |    li_vmstate INTERP
478   |   addi RD, RD, 8
479   |    evsplati TISNIL, LJ_TNIL
480   |   mr MULTRES, RD
481   |    st_vmstate
482   |  beq ->BC_RET_Z
483   |  b ->vm_return
484   |
485   |->vm_pcall:                          // Setup protected C frame and enter VM.
486   |  // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef)
487   |  saveregs
488   |  li PC, FRAME_CP
489   |  stw CARG4, SAVE_ERRF
490   |  b >1
491   |
492   |->vm_call:                           // Setup C frame and enter VM.
493   |  // (lua_State *L, TValue *base, int nres1)
494   |  saveregs
495   |  li PC, FRAME_C
496   |
497   |1:  // Entry point for vm_pcall above (PC = ftype).
498   |  lwz TMP1, L:CARG1->cframe
499   |   stw CARG3, SAVE_NRES
500   |    mr L, CARG1
501   |   stw CARG1, SAVE_L
502   |    mr BASE, CARG2
503   |  stw sp, L->cframe                  // Add our C frame to cframe chain.
504   |    lwz DISPATCH, L->glref           // Setup pointer to dispatch table.
505   |   stw CARG1, SAVE_PC                // Any value outside of bytecode is ok.
506   |  stw TMP1, SAVE_CFRAME
507   |    addi DISPATCH, DISPATCH, GG_G2DISP
508   |
509   |3:  // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
510   |  lwz TMP2, L->base                  // TMP2 = old base (used in vmeta_call).
511   |    evsplati TISNUM, LJ_TISNUM+1     // Setup type comparison constants.
512   |   lwz TMP1, L->top
513   |    evsplati TISFUNC, LJ_TFUNC
514   |  add PC, PC, BASE
515   |    evsplati TISTAB, LJ_TTAB
516   |    lus TOBIT, 0x4338
517   |    li TMP0, 0
518   |  sub PC, PC, TMP2                   // PC = frame delta + frame type
519   |    evsplati TISSTR, LJ_TSTR
520   |   sub NARGS8:RC, TMP1, BASE
521   |    evmergelo TOBIT, TOBIT, TMP0
522   |    li_vmstate INTERP
523   |    evsplati TISNIL, LJ_TNIL
524   |    st_vmstate
525   |
526   |->vm_call_dispatch:
527   |  // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC
528   |  li TMP0, -8
529   |  evlddx LFUNC:RB, BASE, TMP0
530   |  checkfunc LFUNC:RB
531   |  checkfail ->vmeta_call
532   |
533   |->vm_call_dispatch_f:
534   |  ins_call
535   |  // BASE = new base, RB = func, RC = nargs*8, PC = caller PC
536   |
537   |->vm_cpcall:                         // Setup protected C frame, call C.
538   |  // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp)
539   |  saveregs
540   |  mr L, CARG1
541   |   lwz TMP0, L:CARG1->stack
542   |  stw CARG1, SAVE_L
543   |   lwz TMP1, L->top
544   |  stw CARG1, SAVE_PC                 // Any value outside of bytecode is ok.
545   |   sub TMP0, TMP0, TMP1              // Compute -savestack(L, L->top).
546   |    lwz TMP1, L->cframe
547   |    stw sp, L->cframe                // Add our C frame to cframe chain.
548   |  li TMP2, 0
549   |   stw TMP0, SAVE_NRES               // Neg. delta means cframe w/o frame.
550   |  stw TMP2, SAVE_ERRF                // No error function.
551   |    stw TMP1, SAVE_CFRAME
552   |  mtctr CARG4
553   |  bctrl                      // (lua_State *L, lua_CFunction func, void *ud)
554   |  mr. BASE, CRET1
555   |   lwz DISPATCH, L->glref            // Setup pointer to dispatch table.
556   |    li PC, FRAME_CP
557   |   addi DISPATCH, DISPATCH, GG_G2DISP
558   |  bne <3                             // Else continue with the call.
559   |  b ->vm_leave_cp                    // No base? Just remove C frame.
560   |
561   |//-----------------------------------------------------------------------
562   |//-- Metamethod handling ------------------------------------------------
563   |//-----------------------------------------------------------------------
564   |
565   |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the
566   |// stack, so BASE doesn't need to be reloaded across these calls.
567   |
568   |//-- Continuation dispatch ----------------------------------------------
569   |
570   |->cont_dispatch:
571   |  // BASE = meta base, RA = resultptr, RD = (nresults+1)*8
572   |  lwz TMP0, -12(BASE)                // Continuation.
573   |   mr RB, BASE
574   |   mr BASE, TMP2                     // Restore caller BASE.
575   |    lwz LFUNC:TMP1, FRAME_FUNC(TMP2)
576   |  cmplwi TMP0, 0
577   |     lwz PC, -16(RB)                 // Restore PC from [cont|PC].
578   |  beq >1
579   |   subi TMP2, RD, 8
580   |    lwz TMP1, LFUNC:TMP1->pc
581   |   evstddx TISNIL, RA, TMP2          // Ensure one valid arg.
582   |    lwz KBASE, PC2PROTO(k)(TMP1)
583   |  // BASE = base, RA = resultptr, RB = meta base
584   |  mtctr TMP0
585   |  bctr                               // Jump to continuation.
586   |
587   |1:  // Tail call from C function.
588   |  subi TMP1, RB, 16
589   |  sub RC, TMP1, BASE
590   |  b ->vm_call_tail
591   |
592   |->cont_cat:                          // RA = resultptr, RB = meta base
593   |  lwz INS, -4(PC)
594   |   subi CARG2, RB, 16
595   |  decode_RB8 SAVE0, INS
596   |   evldd TMP0, 0(RA)
597   |  add TMP1, BASE, SAVE0
598   |   stw BASE, L->base
599   |  cmplw TMP1, CARG2
600   |   sub CARG3, CARG2, TMP1
601   |  decode_RA8 RA, INS
602   |   evstdd TMP0, 0(CARG2)
603   |  bne ->BC_CAT_Z
604   |   evstddx TMP0, BASE, RA
605   |  b ->cont_nop
606   |
607   |//-- Table indexing metamethods -----------------------------------------
608   |
609   |->vmeta_tgets1:
610   |  evmergelo STR:RC, TISSTR, STR:RC
611   |  la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
612   |   decode_RB8 RB, INS
613   |  evstdd STR:RC, 0(CARG3)
614   |   add CARG2, BASE, RB
615   |  b >1
616   |
617   |->vmeta_tgets:
618   |  evmergelo TAB:RB, TISTAB, TAB:RB
619   |  la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
620   |   evmergelo STR:RC, TISSTR, STR:RC
621   |  evstdd TAB:RB, 0(CARG2)
622   |   la CARG3, DISPATCH_GL(tmptv2)(DISPATCH)
623   |   evstdd STR:RC, 0(CARG3)
624   |  b >1
625   |
626   |->vmeta_tgetb:                       // TMP0 = index
627   |  efdcfsi TMP0, TMP0
628   |   decode_RB8 RB, INS
629   |  la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
630   |   add CARG2, BASE, RB
631   |  evstdd TMP0, 0(CARG3)
632   |  b >1
633   |
634   |->vmeta_tgetv:
635   |  decode_RB8 RB, INS
636   |   decode_RC8 RC, INS
637   |  add CARG2, BASE, RB
638   |   add CARG3, BASE, RC
639   |1:
640   |  stw BASE, L->base
641   |  mr CARG1, L
642   |  stw PC, SAVE_PC
643   |  bl extern lj_meta_tget             // (lua_State *L, TValue *o, TValue *k)
644   |  // Returns TValue * (finished) or NULL (metamethod).
645   |  cmplwi CRET1, 0
646   |  beq >3
647   |  evldd TMP0, 0(CRET1)
648   |  evstddx TMP0, BASE, RA
649   |  ins_next
650   |
651   |3:  // Call __index metamethod.
652   |  // BASE = base, L->top = new base, stack = cont/func/t/k
653   |  subfic TMP1, BASE, FRAME_CONT
654   |  lwz BASE, L->top
655   |  stw PC, -16(BASE)                  // [cont|PC]
656   |   add PC, TMP1, BASE
657   |  lwz LFUNC:RB, FRAME_FUNC(BASE)     // Guaranteed to be a function here.
658   |   li NARGS8:RC, 16                  // 2 args for func(t, k).
659   |  b ->vm_call_dispatch_f
660   |
661   |//-----------------------------------------------------------------------
662   |
663   |->vmeta_tsets1:
664   |  evmergelo STR:RC, TISSTR, STR:RC
665   |  la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
666   |   decode_RB8 RB, INS
667   |  evstdd STR:RC, 0(CARG3)
668   |   add CARG2, BASE, RB
669   |  b >1
670   |
671   |->vmeta_tsets:
672   |  evmergelo TAB:RB, TISTAB, TAB:RB
673   |  la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
674   |   evmergelo STR:RC, TISSTR, STR:RC
675   |  evstdd TAB:RB, 0(CARG2)
676   |   la CARG3, DISPATCH_GL(tmptv2)(DISPATCH)
677   |   evstdd STR:RC, 0(CARG3)
678   |  b >1
679   |
680   |->vmeta_tsetb:                       // TMP0 = index
681   |  efdcfsi TMP0, TMP0
682   |   decode_RB8 RB, INS
683   |  la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
684   |   add CARG2, BASE, RB
685   |  evstdd TMP0, 0(CARG3)
686   |  b >1
687   |
688   |->vmeta_tsetv:
689   |  decode_RB8 RB, INS
690   |   decode_RC8 RC, INS
691   |  add CARG2, BASE, RB
692   |   add CARG3, BASE, RC
693   |1:
694   |  stw BASE, L->base
695   |  mr CARG1, L
696   |  stw PC, SAVE_PC
697   |  bl extern lj_meta_tset             // (lua_State *L, TValue *o, TValue *k)
698   |  // Returns TValue * (finished) or NULL (metamethod).
699   |  cmplwi CRET1, 0
700   |   evlddx TMP0, BASE, RA
701   |  beq >3
702   |  // NOBARRIER: lj_meta_tset ensures the table is not black.
703   |   evstdd TMP0, 0(CRET1)
704   |  ins_next
705   |
706   |3:  // Call __newindex metamethod.
707   |  // BASE = base, L->top = new base, stack = cont/func/t/k/(v)
708   |  subfic TMP1, BASE, FRAME_CONT
709   |  lwz BASE, L->top
710   |  stw PC, -16(BASE)                  // [cont|PC]
711   |   add PC, TMP1, BASE
712   |  lwz LFUNC:RB, FRAME_FUNC(BASE)     // Guaranteed to be a function here.
713   |   li NARGS8:RC, 24                  // 3 args for func(t, k, v)
714   |  evstdd TMP0, 16(BASE)              // Copy value to third argument.
715   |  b ->vm_call_dispatch_f
716   |
717   |//-- Comparison metamethods ---------------------------------------------
718   |
719   |->vmeta_comp:
720   |  mr CARG1, L
721   |   subi PC, PC, 4
722   |  add CARG2, BASE, RA
723   |   stw PC, SAVE_PC
724   |  add CARG3, BASE, RD
725   |   stw BASE, L->base
726   |  decode_OP1 CARG4, INS
727   |  bl extern lj_meta_comp  // (lua_State *L, TValue *o1, *o2, int op)
728   |  // Returns 0/1 or TValue * (metamethod).
729   |3:
730   |  cmplwi CRET1, 1
731   |  bgt ->vmeta_binop
732   |4:
733   |  lwz INS, 0(PC)
734   |   addi PC, PC, 4
735   |  decode_RD4 TMP2, INS
736   |  addis TMP3, PC, -(BCBIAS_J*4 >> 16)
737   |  add TMP2, TMP2, TMP3
738   |  isellt PC, PC, TMP2
739   |->cont_nop:
740   |  ins_next
741   |
742   |->cont_ra:                           // RA = resultptr
743   |  lwz INS, -4(PC)
744   |   evldd TMP0, 0(RA)
745   |  decode_RA8 TMP1, INS
746   |   evstddx TMP0, BASE, TMP1
747   |  b ->cont_nop
748   |
749   |->cont_condt:                        // RA = resultptr
750   |  lwz TMP0, 0(RA)
751   |   li TMP1, LJ_TTRUE
752   |  cmplw TMP1, TMP0                   // Branch if result is true.
753   |  b <4
754   |
755   |->cont_condf:                        // RA = resultptr
756   |  lwz TMP0, 0(RA)
757   |   li TMP1, LJ_TFALSE
758   |  cmplw TMP0, TMP1                   // Branch if result is false.
759   |  b <4
760   |
761   |->vmeta_equal:
762   |  // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV.
763   |  subi PC, PC, 4
764   |   stw BASE, L->base
765   |  mr CARG1, L
766   |   stw PC, SAVE_PC
767   |  bl extern lj_meta_equal  // (lua_State *L, GCobj *o1, *o2, int ne)
768   |  // Returns 0/1 or TValue * (metamethod).
769   |  b <3
770   |
771   |//-- Arithmetic metamethods ---------------------------------------------
772   |
773   |->vmeta_arith_vn:
774   |  add CARG3, BASE, RB
775   |  add CARG4, KBASE, RC
776   |  b >1
777   |
778   |->vmeta_arith_nv:
779   |  add CARG3, KBASE, RC
780   |  add CARG4, BASE, RB
781   |  b >1
782   |
783   |->vmeta_unm:
784   |  add CARG3, BASE, RD
785   |  mr CARG4, CARG3
786   |  b >1
787   |
788   |->vmeta_arith_vv:
789   |  add CARG3, BASE, RB
790   |  add CARG4, BASE, RC
791   |1:
792   |  add CARG2, BASE, RA
793   |   stw BASE, L->base
794   |  mr CARG1, L
795   |   stw PC, SAVE_PC
796   |  decode_OP1 CARG5, INS              // Caveat: CARG5 overlaps INS.
797   |  bl extern lj_meta_arith  // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
798   |  // Returns NULL (finished) or TValue * (metamethod).
799   |  cmplwi CRET1, 0
800   |  beq ->cont_nop
801   |
802   |  // Call metamethod for binary op.
803   |->vmeta_binop:
804   |  // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2
805   |  sub TMP1, CRET1, BASE
806   |   stw PC, -16(CRET1)                // [cont|PC]
807   |   mr TMP2, BASE
808   |  addi PC, TMP1, FRAME_CONT
809   |   mr BASE, CRET1
810   |  li NARGS8:RC, 16                   // 2 args for func(o1, o2).
811   |  b ->vm_call_dispatch
812   |
813   |->vmeta_len:
814 #ifdef LUAJIT_ENABLE_LUA52COMPAT
815   |  mr SAVE0, CARG1
816 #endif
817   |  add CARG2, BASE, RD
818   |   stw BASE, L->base
819   |  mr CARG1, L
820   |   stw PC, SAVE_PC
821   |  bl extern lj_meta_len              // (lua_State *L, TValue *o)
822   |  // Returns NULL (retry) or TValue * (metamethod base).
823 #ifdef LUAJIT_ENABLE_LUA52COMPAT
824   |  cmplwi CRET1, 0
825   |  bne ->vmeta_binop                  // Binop call for compatibility.
826   |  mr CARG1, SAVE0
827   |  b ->BC_LEN_Z
828 #else
829   |  b ->vmeta_binop                    // Binop call for compatibility.
830 #endif
831   |
832   |//-- Call metamethod ----------------------------------------------------
833   |
834   |->vmeta_call:                        // Resolve and call __call metamethod.
835   |  // TMP2 = old base, BASE = new base, RC = nargs*8
836   |  mr CARG1, L
837   |   stw TMP2, L->base                 // This is the callers base!
838   |  subi CARG2, BASE, 8
839   |   stw PC, SAVE_PC
840   |  add CARG3, BASE, RC
841   |   mr SAVE0, NARGS8:RC
842   |  bl extern lj_meta_call     // (lua_State *L, TValue *func, TValue *top)
843   |  lwz LFUNC:RB, FRAME_FUNC(BASE)     // Guaranteed to be a function here.
844   |   addi NARGS8:RC, SAVE0, 8          // Got one more argument now.
845   |  ins_call
846   |
847   |->vmeta_callt:                       // Resolve __call for BC_CALLT.
848   |  // BASE = old base, RA = new base, RC = nargs*8
849   |  mr CARG1, L
850   |   stw BASE, L->base
851   |  subi CARG2, RA, 8
852   |   stw PC, SAVE_PC
853   |  add CARG3, RA, RC
854   |   mr SAVE0, NARGS8:RC
855   |  bl extern lj_meta_call     // (lua_State *L, TValue *func, TValue *top)
856   |  lwz TMP1, FRAME_PC(BASE)
857   |   addi NARGS8:RC, SAVE0, 8          // Got one more argument now.
858   |   lwz LFUNC:RB, FRAME_FUNC(RA)      // Guaranteed to be a function here.
859   |  b ->BC_CALLT_Z
860   |
861   |//-- Argument coercion for 'for' statement ------------------------------
862   |
863   |->vmeta_for:
864   |  mr CARG1, L
865   |   stw BASE, L->base
866   |  mr CARG2, RA
867   |   stw PC, SAVE_PC
868   |  mr SAVE0, INS
869   |  bl extern lj_meta_for      // (lua_State *L, TValue *base)
870 #if LJ_HASJIT
871   |   decode_OP1 TMP0, SAVE0
872 #endif
873   |  decode_RA8 RA, SAVE0
874 #if LJ_HASJIT
875   |   cmpwi TMP0, BC_JFORI
876 #endif
877   |  decode_RD8 RD, SAVE0
878 #if LJ_HASJIT
879   |   beq =>BC_JFORI
880 #endif
881   |  b =>BC_FORI
882   |
883   |//-----------------------------------------------------------------------
884   |//-- Fast functions -----------------------------------------------------
885   |//-----------------------------------------------------------------------
886   |
887   |.macro .ffunc, name
888   |->ff_ .. name:
889   |.endmacro
890   |
891   |.macro .ffunc_1, name
892   |->ff_ .. name:
893   |  cmplwi NARGS8:RC, 8
894   |   evldd CARG1, 0(BASE)
895   |  blt ->fff_fallback
896   |.endmacro
897   |
898   |.macro .ffunc_2, name
899   |->ff_ .. name:
900   |  cmplwi NARGS8:RC, 16
901   |   evldd CARG1, 0(BASE)
902   |   evldd CARG2, 8(BASE)
903   |  blt ->fff_fallback
904   |.endmacro
905   |
906   |.macro .ffunc_n, name
907   |  .ffunc_1 name
908   |  checknum CARG1
909   |  checkfail ->fff_fallback
910   |.endmacro
911   |
912   |.macro .ffunc_nn, name
913   |  .ffunc_2 name
914   |  evmergehi TMP0, CARG1, CARG2
915   |  checknum TMP0
916   |  checkanyfail ->fff_fallback
917   |.endmacro
918   |
919   |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1.
920   |.macro ffgccheck
921   |  lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH)
922   |  lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
923   |  cmplw TMP0, TMP1
924   |  bgel ->fff_gcstep
925   |.endmacro
926   |
927   |//-- Base library: checks -----------------------------------------------
928   |
929   |.ffunc assert
930   |  cmplwi NARGS8:RC, 8
931   |   evldd TMP0, 0(BASE)
932   |  blt ->fff_fallback
933   |  evaddw TMP1, TISNIL, TISNIL        // Synthesize LJ_TFALSE.
934   |  la RA, -8(BASE)
935   |   evcmpltu cr1, TMP0, TMP1
936   |    lwz PC, FRAME_PC(BASE)
937   |  bge cr1, ->fff_fallback
938   |   evstdd TMP0, 0(RA)
939   |  addi RD, NARGS8:RC, 8              // Compute (nresults+1)*8.
940   |   beq ->fff_res                     // Done if exactly 1 argument.
941   |  li TMP1, 8
942   |  subi RC, RC, 8
943   |1:
944   |  cmplw TMP1, RC
945   |   evlddx TMP0, BASE, TMP1
946   |   evstddx TMP0, RA, TMP1
947   |    addi TMP1, TMP1, 8
948   |  bne <1
949   |  b ->fff_res
950   |
951   |.ffunc type
952   |  cmplwi NARGS8:RC, 8
953   |   lwz CARG1, 0(BASE)
954   |  blt ->fff_fallback
955   |    li TMP2, ~LJ_TNUMX
956   |  cmplw CARG1, TISNUM
957   |  not TMP1, CARG1
958   |  isellt TMP1, TMP2, TMP1
959   |  slwi TMP1, TMP1, 3
960   |   la TMP2, CFUNC:RB->upvalue
961   |  evlddx STR:CRET1, TMP2, TMP1
962   |  b ->fff_restv
963   |
964   |//-- Base library: getters and setters ---------------------------------
965   |
966   |.ffunc_1 getmetatable
967   |  checktab CARG1
968   |   evmergehi TMP1, CARG1, CARG1
969   |  checkfail >6
970   |1:  // Field metatable must be at same offset for GCtab and GCudata!
971   |  lwz TAB:RB, TAB:CARG1->metatable
972   |2:
973   |  evmr CRET1, TISNIL
974   |   cmplwi TAB:RB, 0
975   |  lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH)
976   |   beq ->fff_restv
977   |  lwz TMP0, TAB:RB->hmask
978   |   evmergelo CRET1, TISTAB, TAB:RB   // Use metatable as default result.
979   |  lwz TMP1, STR:RC->hash
980   |  lwz NODE:TMP2, TAB:RB->node
981   |   evmergelo STR:RC, TISSTR, STR:RC
982   |  and TMP1, TMP1, TMP0               // idx = str->hash & tab->hmask
983   |  slwi TMP0, TMP1, 5
984   |  slwi TMP1, TMP1, 3
985   |  sub TMP1, TMP0, TMP1
986   |  add NODE:TMP2, NODE:TMP2, TMP1     // node = tab->node + (idx*32-idx*8)
987   |3:  // Rearranged logic, because we expect _not_ to find the key.
988   |  evldd TMP0, NODE:TMP2->key
989   |   evldd TMP1, NODE:TMP2->val
990   |  evcmpeq TMP0, STR:RC
991   |   lwz NODE:TMP2, NODE:TMP2->next
992   |  checkallok >5
993   |   cmplwi NODE:TMP2, 0
994   |   beq ->fff_restv                   // Not found, keep default result.
995   |   b <3
996   |5:
997   |  checknil TMP1
998   |  checkok ->fff_restv                // Ditto for nil value.
999   |  evmr CRET1, TMP1                   // Return value of mt.__metatable.
1000   |  b ->fff_restv
1001   |
1002   |6:
1003   |  cmpwi TMP1, LJ_TUDATA
1004   |   not TMP1, TMP1
1005   |  beq <1
1006   |  checknum CARG1
1007   |   slwi TMP1, TMP1, 2
1008   |   li TMP2, 4*~LJ_TNUMX
1009   |  isellt TMP1, TMP2, TMP1
1010   |   la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH)
1011   |  lwzx TAB:RB, TMP2, TMP1
1012   |  b <2
1013   |
1014   |.ffunc_2 setmetatable
1015   |  // Fast path: no mt for table yet and not clearing the mt.
1016   |  evmergehi TMP0, TAB:CARG1, TAB:CARG2
1017   |  checktab TMP0
1018   |  checkanyfail ->fff_fallback
1019   |  lwz TAB:TMP1, TAB:CARG1->metatable
1020   |  cmplwi TAB:TMP1, 0
1021   |   lbz TMP3, TAB:CARG1->marked
1022   |  bne ->fff_fallback
1023   |   andi. TMP0, TMP3, LJ_GC_BLACK     // isblack(table)
1024   |    stw TAB:CARG2, TAB:CARG1->metatable
1025   |   beq ->fff_restv
1026   |  barrierback TAB:CARG1, TMP3, TMP0
1027   |  b ->fff_restv
1028   |
1029   |.ffunc rawget
1030   |  cmplwi NARGS8:RC, 16
1031   |   evldd CARG2, 0(BASE)
1032   |  blt ->fff_fallback
1033   |  checktab CARG2
1034   |   la CARG3, 8(BASE)
1035   |  checkfail ->fff_fallback
1036   |   mr CARG1, L
1037   |  bl extern lj_tab_get  // (lua_State *L, GCtab *t, cTValue *key)
1038   |  // Returns cTValue *.
1039   |  evldd CRET1, 0(CRET1)
1040   |  b ->fff_restv
1041   |
1042   |//-- Base library: conversions ------------------------------------------
1043   |
1044   |.ffunc tonumber
1045   |  // Only handles the number case inline (without a base argument).
1046   |  cmplwi NARGS8:RC, 8
1047   |   evldd CARG1, 0(BASE)
1048   |  bne ->fff_fallback                 // Exactly one argument.
1049   |  checknum CARG1
1050   |  checkok ->fff_restv
1051   |  b ->fff_fallback
1052   |
1053   |.ffunc_1 tostring
1054   |  // Only handles the string or number case inline.
1055   |  checkstr CARG1
1056   |  // A __tostring method in the string base metatable is ignored.
1057   |  checkok ->fff_restv                // String key?
1058   |  // Handle numbers inline, unless a number base metatable is present.
1059   |  lwz TMP0, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH)
1060   |  checknum CARG1
1061   |  cmplwi cr1, TMP0, 0
1062   |   stw BASE, L->base                 // Add frame since C call can throw.
1063   |  crand 4*cr0+eq, 4*cr0+lt, 4*cr1+eq
1064   |   stw PC, SAVE_PC                   // Redundant (but a defined value).
1065   |  bne ->fff_fallback
1066   |  ffgccheck
1067   |  mr CARG1, L
1068   |  mr CARG2, BASE
1069   |  bl extern lj_str_fromnum           // (lua_State *L, lua_Number *np)
1070   |  // Returns GCstr *.
1071   |  evmergelo STR:CRET1, TISSTR, STR:CRET1
1072   |  b ->fff_restv
1073   |
1074   |//-- Base library: iterators -------------------------------------------
1075   |
1076   |.ffunc next
1077   |  cmplwi NARGS8:RC, 8
1078   |   evldd CARG2, 0(BASE)
1079   |  blt ->fff_fallback
1080   |   evstddx TISNIL, BASE, NARGS8:RC   // Set missing 2nd arg to nil.
1081   |  checktab TAB:CARG2
1082   |   lwz PC, FRAME_PC(BASE)
1083   |  checkfail ->fff_fallback
1084   |   stw BASE, L->base                 // Add frame since C call can throw.
1085   |  mr CARG1, L
1086   |   stw BASE, L->top                  // Dummy frame length is ok.
1087   |  la CARG3, 8(BASE)
1088   |   stw PC, SAVE_PC
1089   |  bl extern lj_tab_next      // (lua_State *L, GCtab *t, TValue *key)
1090   |  // Returns 0 at end of traversal.
1091   |  cmplwi CRET1, 0
1092   |   evmr CRET1, TISNIL
1093   |  beq ->fff_restv                    // End of traversal: return nil.
1094   |  evldd TMP0, 8(BASE)                // Copy key and value to results.
1095   |   la RA, -8(BASE)
1096   |  evldd TMP1, 16(BASE)
1097   |  evstdd TMP0, 0(RA)
1098   |   li RD, (2+1)*8
1099   |  evstdd TMP1, 8(RA)
1100   |  b ->fff_res
1101   |
1102   |.ffunc_1 pairs
1103   |  checktab TAB:CARG1
1104   |   lwz PC, FRAME_PC(BASE)
1105   |  checkfail ->fff_fallback
1106 #ifdef LUAJIT_ENABLE_LUA52COMPAT
1107   |   lwz TAB:TMP2, TAB:CARG1->metatable
1108   |  evldd CFUNC:TMP0, CFUNC:RB->upvalue[0]
1109   |   cmplwi TAB:TMP2, 0
1110   |  la RA, -8(BASE)
1111   |   bne ->fff_fallback
1112 #else
1113   |  evldd CFUNC:TMP0, CFUNC:RB->upvalue[0]
1114   |  la RA, -8(BASE)
1115 #endif
1116   |   evstdd TISNIL, 8(BASE)
1117   |  li RD, (3+1)*8
1118   |  evstdd CFUNC:TMP0, 0(RA)
1119   |  b ->fff_res
1120   |
1121   |.ffunc_2 ipairs_aux
1122   |  checktab TAB:CARG1
1123   |   lwz PC, FRAME_PC(BASE)
1124   |  checkfail ->fff_fallback
1125   |  checknum CARG2
1126   |    lus TMP3, 0x3ff0
1127   |  checkfail ->fff_fallback
1128   |  efdctsi TMP2, CARG2
1129   |   lwz TMP0, TAB:CARG1->asize
1130   |    evmergelo TMP3, TMP3, ZERO
1131   |   lwz TMP1, TAB:CARG1->array
1132   |  efdadd CARG2, CARG2, TMP3
1133   |  addi TMP2, TMP2, 1
1134   |   la RA, -8(BASE)
1135   |  cmplw TMP0, TMP2
1136   |   slwi TMP3, TMP2, 3
1137   |  evstdd CARG2, 0(RA)
1138   |  ble >2                             // Not in array part?
1139   |  evlddx TMP1, TMP1, TMP3
1140   |1:
1141   |  checknil TMP1
1142   |   li RD, (0+1)*8
1143   |  checkok ->fff_res                  // End of iteration, return 0 results.
1144   |   li RD, (2+1)*8
1145   |  evstdd TMP1, 8(RA)
1146   |  b ->fff_res
1147   |2:  // Check for empty hash part first. Otherwise call C function.
1148   |  lwz TMP0, TAB:CARG1->hmask
1149   |  cmplwi TMP0, 0
1150   |   li RD, (0+1)*8
1151   |  beq ->fff_res
1152   |   mr CARG2, TMP2
1153   |  bl extern lj_tab_getinth           // (GCtab *t, int32_t key)
1154   |  // Returns cTValue * or NULL.
1155   |  cmplwi CRET1, 0
1156   |   li RD, (0+1)*8
1157   |  beq ->fff_res
1158   |  evldd TMP1, 0(CRET1)
1159   |  b <1
1160   |
1161   |.ffunc_1 ipairs
1162   |  checktab TAB:CARG1
1163   |   lwz PC, FRAME_PC(BASE)
1164   |  checkfail ->fff_fallback
1165 #ifdef LUAJIT_ENABLE_LUA52COMPAT
1166   |   lwz TAB:TMP2, TAB:CARG1->metatable
1167   |  evldd CFUNC:TMP0, CFUNC:RB->upvalue[0]
1168   |   cmplwi TAB:TMP2, 0
1169   |  la RA, -8(BASE)
1170   |   bne ->fff_fallback
1171 #else
1172   |  evldd CFUNC:TMP0, CFUNC:RB->upvalue[0]
1173   |  la RA, -8(BASE)
1174 #endif
1175   |    evsplati TMP1, 0
1176   |  li RD, (3+1)*8
1177   |    evstdd TMP1, 8(BASE)
1178   |  evstdd CFUNC:TMP0, 0(RA)
1179   |  b ->fff_res
1180   |
1181   |//-- Base library: catch errors ----------------------------------------
1182   |
1183   |.ffunc pcall
1184   |  cmplwi NARGS8:RC, 8
1185   |   lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1186   |  blt ->fff_fallback
1187   |   mr TMP2, BASE
1188   |   la BASE, 8(BASE)
1189   |  // Remember active hook before pcall.
1190   |  rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31
1191   |   subi NARGS8:RC, NARGS8:RC, 8
1192   |  addi PC, TMP3, 8+FRAME_PCALL
1193   |  b ->vm_call_dispatch
1194   |
1195   |.ffunc_2 xpcall
1196   |  lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1197   |   mr TMP2, BASE
1198   |  checkfunc CARG2                    // Traceback must be a function.
1199   |  checkfail ->fff_fallback
1200   |   la BASE, 16(BASE)
1201   |  // Remember active hook before pcall.
1202   |  rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31
1203   |   evstdd CARG2, 0(TMP2)             // Swap function and traceback.
1204   |  subi NARGS8:RC, NARGS8:RC, 16
1205   |   evstdd CARG1, 8(TMP2)
1206   |  addi PC, TMP3, 16+FRAME_PCALL
1207   |  b ->vm_call_dispatch
1208   |
1209   |//-- Coroutine library --------------------------------------------------
1210   |
1211   |.macro coroutine_resume_wrap, resume
1212   |.if resume
1213   |.ffunc_1 coroutine_resume
1214   |  evmergehi TMP0, L:CARG1, L:CARG1
1215   |.else
1216   |.ffunc coroutine_wrap_aux
1217   |  lwz L:CARG1, CFUNC:RB->upvalue[0].gcr
1218   |.endif
1219   |.if resume
1220   |  cmpwi TMP0, LJ_TTHREAD
1221   |  bne ->fff_fallback
1222   |.endif
1223   |  lbz TMP0, L:CARG1->status
1224   |   lwz TMP1, L:CARG1->cframe
1225   |    lwz CARG2, L:CARG1->top
1226   |  cmplwi cr0, TMP0, LUA_YIELD
1227   |    lwz TMP2, L:CARG1->base
1228   |   cmplwi cr1, TMP1, 0
1229   |   lwz TMP0, L:CARG1->maxstack
1230   |    cmplw cr7, CARG2, TMP2
1231   |   lwz PC, FRAME_PC(BASE)
1232   |  crorc 4*cr6+lt, 4*cr0+gt, 4*cr1+eq         // st>LUA_YIELD || cframe!=0
1233   |   add TMP2, CARG2, NARGS8:RC
1234   |  crandc 4*cr6+gt, 4*cr7+eq, 4*cr0+eq        // base==top && st!=LUA_YIELD
1235   |   cmplw cr1, TMP2, TMP0
1236   |  cror 4*cr6+lt, 4*cr6+lt, 4*cr6+gt
1237   |   stw PC, SAVE_PC
1238   |  cror 4*cr6+lt, 4*cr6+lt, 4*cr1+gt          // cond1 || cond2 || stackov
1239   |   stw BASE, L->base
1240   |  blt cr6, ->fff_fallback
1241   |1:
1242   |.if resume
1243   |  addi BASE, BASE, 8                 // Keep resumed thread in stack for GC.
1244   |  subi NARGS8:RC, NARGS8:RC, 8
1245   |  subi TMP2, TMP2, 8
1246   |.endif
1247   |  stw TMP2, L:CARG1->top
1248   |  li TMP1, 0
1249   |  stw BASE, L->top
1250   |2:  // Move args to coroutine.
1251   |  cmpw TMP1, NARGS8:RC
1252   |   evlddx TMP0, BASE, TMP1
1253   |  beq >3
1254   |   evstddx TMP0, CARG2, TMP1
1255   |  addi TMP1, TMP1, 8
1256   |  b <2
1257   |3:
1258   |  li CARG3, 0
1259   |   mr L:SAVE0, L:CARG1
1260   |  li CARG4, 0
1261   |  bl ->vm_resume                     // (lua_State *L, TValue *base, 0, 0)
1262   |  // Returns thread status.
1263   |4:
1264   |  lwz TMP2, L:SAVE0->base
1265   |   cmplwi CRET1, LUA_YIELD
1266   |  lwz TMP3, L:SAVE0->top
1267   |    li_vmstate INTERP
1268   |  lwz BASE, L->base
1269   |    st_vmstate
1270   |   bgt >8
1271   |  sub RD, TMP3, TMP2
1272   |   lwz TMP0, L->maxstack
1273   |  cmplwi RD, 0
1274   |   add TMP1, BASE, RD
1275   |  beq >6                             // No results?
1276   |  cmplw TMP1, TMP0
1277   |   li TMP1, 0
1278   |  bgt >9                             // Need to grow stack?
1279   |
1280   |  subi TMP3, RD, 8
1281   |   stw TMP2, L:SAVE0->top            // Clear coroutine stack.
1282   |5:  // Move results from coroutine.
1283   |  cmplw TMP1, TMP3
1284   |   evlddx TMP0, TMP2, TMP1
1285   |   evstddx TMP0, BASE, TMP1
1286   |    addi TMP1, TMP1, 8
1287   |  bne <5
1288   |6:
1289   |  andi. TMP0, PC, FRAME_TYPE
1290   |.if resume
1291   |  li TMP1, LJ_TTRUE
1292   |   la RA, -8(BASE)
1293   |  stw TMP1, -8(BASE)                 // Prepend true to results.
1294   |  addi RD, RD, 16
1295   |.else
1296   |  mr RA, BASE
1297   |  addi RD, RD, 8
1298   |.endif
1299   |7:
1300   |    stw PC, SAVE_PC
1301   |   mr MULTRES, RD
1302   |  beq ->BC_RET_Z
1303   |  b ->vm_return
1304   |
1305   |8:  // Coroutine returned with error (at co->top-1).
1306   |.if resume
1307   |  andi. TMP0, PC, FRAME_TYPE
1308   |  la TMP3, -8(TMP3)
1309   |   li TMP1, LJ_TFALSE
1310   |  evldd TMP0, 0(TMP3)
1311   |   stw TMP3, L:SAVE0->top            // Remove error from coroutine stack.
1312   |    li RD, (2+1)*8
1313   |   stw TMP1, -8(BASE)                // Prepend false to results.
1314   |    la RA, -8(BASE)
1315   |  evstdd TMP0, 0(BASE)               // Copy error message.
1316   |  b <7
1317   |.else
1318   |  mr CARG1, L
1319   |  mr CARG2, L:SAVE0
1320   |  bl extern lj_ffh_coroutine_wrap_err  // (lua_State *L, lua_State *co)
1321   |.endif
1322   |
1323   |9:  // Handle stack expansion on return from yield.
1324   |  mr CARG1, L
1325   |  srwi CARG2, RD, 3
1326   |  bl extern lj_state_growstack       // (lua_State *L, int n)
1327   |  li CRET1, 0
1328   |  b <4
1329   |.endmacro
1330   |
1331   |  coroutine_resume_wrap 1            // coroutine.resume
1332   |  coroutine_resume_wrap 0            // coroutine.wrap
1333   |
1334   |.ffunc coroutine_yield
1335   |  lwz TMP0, L->cframe
1336   |   add TMP1, BASE, NARGS8:RC
1337   |   stw BASE, L->base
1338   |  andi. TMP0, TMP0, CFRAME_RESUME
1339   |   stw TMP1, L->top
1340   |    li CRET1, LUA_YIELD
1341   |  beq ->fff_fallback
1342   |   stw ZERO, L->cframe
1343   |    stb CRET1, L->status
1344   |  b ->vm_leave_unw
1345   |
1346   |//-- Math library -------------------------------------------------------
1347   |
1348   |.ffunc_n math_abs
1349   |  efdabs CRET1, CARG1
1350   |  // Fallthrough.
1351   |
1352   |->fff_restv:
1353   |  // CRET1 = TValue result.
1354   |  lwz PC, FRAME_PC(BASE)
1355   |   la RA, -8(BASE)
1356   |  evstdd CRET1, 0(RA)
1357   |->fff_res1:
1358   |  // RA = results, PC = return.
1359   |  li RD, (1+1)*8
1360   |->fff_res:
1361   |  // RA = results, RD = (nresults+1)*8, PC = return.
1362   |  andi. TMP0, PC, FRAME_TYPE
1363   |   mr MULTRES, RD
1364   |  bne ->vm_return
1365   |  lwz INS, -4(PC)
1366   |  decode_RB8 RB, INS
1367   |5:
1368   |  cmplw RB, RD                       // More results expected?
1369   |   decode_RA8 TMP0, INS
1370   |  bgt >6
1371   |  ins_next1
1372   |  // Adjust BASE. KBASE is assumed to be set for the calling frame.
1373   |   sub BASE, RA, TMP0
1374   |  ins_next2
1375   |
1376   |6:  // Fill up results with nil.
1377   |  subi TMP1, RD, 8
1378   |   addi RD, RD, 8
1379   |  evstddx TISNIL, RA, TMP1
1380   |  b <5
1381   |
1382   |.macro math_extern, func
1383   |  .ffunc math_ .. func
1384   |  cmplwi NARGS8:RC, 8
1385   |   evldd CARG2, 0(BASE)
1386   |  blt ->fff_fallback
1387   |  checknum CARG2
1388   |   evmergehi CARG1, CARG2, CARG2
1389   |  checkfail ->fff_fallback
1390   |  bl extern func
1391   |  evmergelo CRET1, CRET1, CRET2
1392   |  b ->fff_restv
1393   |.endmacro
1394   |
1395   |.macro math_extern2, func
1396   |  .ffunc math_ .. func
1397   |  cmplwi NARGS8:RC, 16
1398   |   evldd CARG2, 0(BASE)
1399   |   evldd CARG4, 8(BASE)
1400   |  blt ->fff_fallback
1401   |  evmergehi CARG1, CARG4, CARG2
1402   |  checknum CARG1
1403   |   evmergehi CARG3, CARG4, CARG4
1404   |  checkanyfail ->fff_fallback
1405   |  bl extern func
1406   |  evmergelo CRET1, CRET1, CRET2
1407   |  b ->fff_restv
1408   |.endmacro
1409   |
1410   |.macro math_round, func
1411   |  .ffunc math_ .. func
1412   |  cmplwi NARGS8:RC, 8
1413   |   evldd CARG2, 0(BASE)
1414   |  blt ->fff_fallback
1415   |  checknum CARG2
1416   |   evmergehi CARG1, CARG2, CARG2
1417   |  checkfail ->fff_fallback
1418   |   lwz PC, FRAME_PC(BASE)
1419   |  bl ->vm_..func.._hilo;
1420   |  la RA, -8(BASE)
1421   |  evstdd CRET2, 0(RA)
1422   |  b ->fff_res1
1423   |.endmacro
1424   |
1425   |  math_round floor
1426   |  math_round ceil
1427   |
1428   |  math_extern sqrt
1429   |  math_extern log
1430   |  math_extern log10
1431   |  math_extern exp
1432   |  math_extern sin
1433   |  math_extern cos
1434   |  math_extern tan
1435   |  math_extern asin
1436   |  math_extern acos
1437   |  math_extern atan
1438   |  math_extern sinh
1439   |  math_extern cosh
1440   |  math_extern tanh
1441   |  math_extern2 pow
1442   |  math_extern2 atan2
1443   |  math_extern2 fmod
1444   |
1445   |->ff_math_deg:
1446   |.ffunc_n math_rad
1447   |  evldd CARG2, CFUNC:RB->upvalue[0]
1448   |  efdmul CRET1, CARG1, CARG2
1449   |  b ->fff_restv
1450   |
1451   |.ffunc math_ldexp
1452   |  cmplwi NARGS8:RC, 16
1453   |   evldd CARG2, 0(BASE)
1454   |   evldd CARG4, 8(BASE)
1455   |  blt ->fff_fallback
1456   |  evmergehi CARG1, CARG4, CARG2
1457   |  checknum CARG1
1458   |  checkanyfail ->fff_fallback
1459   |  efdctsi CARG3, CARG4
1460   |  bl extern ldexp
1461   |  evmergelo CRET1, CRET1, CRET2
1462   |  b ->fff_restv
1463   |
1464   |.ffunc math_frexp
1465   |  cmplwi NARGS8:RC, 8
1466   |   evldd CARG2, 0(BASE)
1467   |  blt ->fff_fallback
1468   |  checknum CARG2
1469   |   evmergehi CARG1, CARG2, CARG2
1470   |  checkfail ->fff_fallback
1471   |  la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
1472   |   lwz PC, FRAME_PC(BASE)
1473   |  bl extern frexp
1474   |   lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH)
1475   |  evmergelo CRET1, CRET1, CRET2
1476   |   efdcfsi CRET2, TMP1
1477   |   la RA, -8(BASE)
1478   |  evstdd CRET1, 0(RA)
1479   |  li RD, (2+1)*8
1480   |   evstdd CRET2, 8(RA)
1481   |  b ->fff_res
1482   |
1483   |.ffunc math_modf
1484   |  cmplwi NARGS8:RC, 8
1485   |   evldd CARG2, 0(BASE)
1486   |  blt ->fff_fallback
1487   |  checknum CARG2
1488   |   evmergehi CARG1, CARG2, CARG2
1489   |  checkfail ->fff_fallback
1490   |  la CARG3, -8(BASE)
1491   |   lwz PC, FRAME_PC(BASE)
1492   |  bl extern modf
1493   |  evmergelo CRET1, CRET1, CRET2
1494   |   la RA, -8(BASE)
1495   |  evstdd CRET1, 0(BASE)
1496   |  li RD, (2+1)*8
1497   |  b ->fff_res
1498   |
1499   |.macro math_minmax, name, cmpop
1500   |  .ffunc_1 name
1501   |  checknum CARG1
1502   |   li TMP1, 8
1503   |  checkfail ->fff_fallback
1504   |1:
1505   |  evlddx CARG2, BASE, TMP1
1506   |  cmplw cr1, TMP1, NARGS8:RC
1507   |   checknum CARG2
1508   |  bge cr1, ->fff_restv               // Ok, since CRET1 = CARG1.
1509   |   checkfail ->fff_fallback
1510   |  cmpop CARG2, CARG1
1511   |   addi TMP1, TMP1, 8
1512   |  crmove 4*cr0+lt, 4*cr0+gt
1513   |  evsel CARG1, CARG2, CARG1
1514   |  b <1
1515   |.endmacro
1516   |
1517   |  math_minmax math_min, efdtstlt
1518   |  math_minmax math_max, efdtstgt
1519   |
1520   |//-- String library -----------------------------------------------------
1521   |
1522   |.ffunc_1 string_len
1523   |  checkstr STR:CARG1
1524   |  checkfail ->fff_fallback
1525   |  lwz TMP0, STR:CARG1->len
1526   |  efdcfsi CRET1, TMP0
1527   |  b ->fff_restv
1528   |
1529   |.ffunc string_byte                   // Only handle the 1-arg case here.
1530   |  cmplwi NARGS8:RC, 8
1531   |   evldd STR:CARG1, 0(BASE)
1532   |  bne ->fff_fallback                 // Need exactly 1 argument.
1533   |  checkstr STR:CARG1
1534   |   la RA, -8(BASE)
1535   |  checkfail ->fff_fallback
1536   |  lwz TMP0, STR:CARG1->len
1537   |   li RD, (0+1)*8
1538   |    lbz TMP1, STR:CARG1[1]           // Access is always ok (NUL at end).
1539   |   li TMP2, (1+1)*8
1540   |  cmplwi TMP0, 0
1541   |   lwz PC, FRAME_PC(BASE)
1542   |    efdcfsi CRET1, TMP1
1543   |  iseleq RD, RD, TMP2
1544   |    evstdd CRET1, 0(RA)
1545   |  b ->fff_res
1546   |
1547   |.ffunc string_char                   // Only handle the 1-arg case here.
1548   |  ffgccheck
1549   |  cmplwi NARGS8:RC, 8
1550   |   evldd CARG1, 0(BASE)
1551   |  bne ->fff_fallback                 // Exactly 1 argument.
1552   |  checknum CARG1
1553   |   la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
1554   |  checkfail ->fff_fallback
1555   |  efdctsiz TMP0, CARG1
1556   |   li CARG3, 1
1557   |  cmplwi TMP0, 255
1558   |   stb TMP0, 0(CARG2)
1559   |  bgt ->fff_fallback
1560   |->fff_newstr:
1561   |  mr CARG1, L
1562   |  stw BASE, L->base
1563   |  stw PC, SAVE_PC
1564   |  bl extern lj_str_new               // (lua_State *L, char *str, size_t l)
1565   |  // Returns GCstr *.
1566   |  lwz BASE, L->base
1567   |   evmergelo STR:CRET1, TISSTR, STR:CRET1
1568   |  b ->fff_restv
1569   |
1570   |.ffunc string_sub
1571   |  ffgccheck
1572   |  cmplwi NARGS8:RC, 16
1573   |   evldd CARG3, 16(BASE)
1574   |   evldd STR:CARG1, 0(BASE)
1575   |  blt ->fff_fallback
1576   |   evldd CARG2, 8(BASE)
1577   |   li TMP2, -1
1578   |  beq >1
1579   |  checknum CARG3
1580   |  checkfail ->fff_fallback
1581   |  efdctsiz TMP2, CARG3
1582   |1:
1583   |  checknum CARG2
1584   |  checkfail ->fff_fallback
1585   |  checkstr STR:CARG1
1586   |   efdctsiz TMP1, CARG2
1587   |  checkfail ->fff_fallback
1588   |   lwz TMP0, STR:CARG1->len
1589   |  cmplw TMP0, TMP2                   // len < end? (unsigned compare)
1590   |   add TMP3, TMP2, TMP0
1591   |  blt >5
1592   |2:
1593   |  cmpwi TMP1, 0                      // start <= 0?
1594   |   add TMP3, TMP1, TMP0
1595   |  ble >7
1596   |3:
1597   |  sub. CARG3, TMP2, TMP1
1598   |    addi CARG2, STR:CARG1, #STR-1
1599   |   addi CARG3, CARG3, 1
1600   |    add CARG2, CARG2, TMP1
1601   |  isellt CARG3, r0, CARG3
1602   |  b ->fff_newstr
1603   |
1604   |5:  // Negative end or overflow.
1605   |  cmpw TMP0, TMP2
1606   |   addi TMP3, TMP3, 1
1607   |  iselgt TMP2, TMP3, TMP0            // end = end > len ? len : end+len+1
1608   |  b <2
1609   |
1610   |7:  // Negative start or underflow.
1611   |   cmpwi cr1, TMP3, 0
1612   |  iseleq TMP1, r0, TMP3
1613   |   isel TMP1, r0, TMP1, 4*cr1+lt
1614   |  addi TMP1, TMP1, 1                 // start = 1 + (start ? start+len : 0)
1615   |  b <3
1616   |
1617   |.ffunc string_rep                    // Only handle the 1-char case inline.
1618   |  ffgccheck
1619   |  cmplwi NARGS8:RC, 16
1620   |   evldd CARG1, 0(BASE)
1621   |   evldd CARG2, 8(BASE)
1622   |  blt ->fff_fallback
1623   |  checknum CARG2
1624   |  checkfail ->fff_fallback
1625   |  checkstr STR:CARG1
1626   |   efdctsiz CARG3, CARG2
1627   |  checkfail ->fff_fallback
1628   |   lwz TMP0, STR:CARG1->len
1629   |  cmpwi CARG3, 0
1630   |   lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
1631   |  ble >2                             // Count <= 0? (or non-int)
1632   |   cmplwi TMP0, 1
1633   |  subi TMP2, CARG3, 1
1634   |   blt >2                            // Zero length string?
1635   |  cmplw cr1, TMP1, CARG3
1636   |   bne ->fff_fallback                // Fallback for > 1-char strings.
1637   |   lbz TMP0, STR:CARG1[1]
1638   |   lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
1639   |  blt cr1, ->fff_fallback
1640   |1:  // Fill buffer with char. Yes, this is suboptimal code (do you care?).
1641   |  cmplwi TMP2, 0
1642   |   stbx TMP0, CARG2, TMP2
1643   |   subi TMP2, TMP2, 1
1644   |  bne <1
1645   |  b ->fff_newstr
1646   |2:  // Return empty string.
1647   |  la STR:CRET1, DISPATCH_GL(strempty)(DISPATCH)
1648   |  evmergelo CRET1, TISSTR, STR:CRET1
1649   |  b ->fff_restv
1650   |
1651   |.ffunc string_reverse
1652   |  ffgccheck
1653   |  cmplwi NARGS8:RC, 8
1654   |   evldd CARG1, 0(BASE)
1655   |  blt ->fff_fallback
1656   |  checkstr STR:CARG1
1657   |   lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
1658   |  checkfail ->fff_fallback
1659   |  lwz CARG3, STR:CARG1->len
1660   |   la CARG1, #STR(STR:CARG1)
1661   |   lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
1662   |   li TMP2, 0
1663   |  cmplw TMP1, CARG3
1664   |   subi TMP3, CARG3, 1
1665   |  blt ->fff_fallback
1666   |1:  // Reverse string copy.
1667   |  cmpwi TMP3, 0
1668   |   lbzx TMP1, CARG1, TMP2
1669   |  blt ->fff_newstr
1670   |   stbx TMP1, CARG2, TMP3
1671   |  subi TMP3, TMP3, 1
1672   |  addi TMP2, TMP2, 1
1673   |  b <1
1674   |
1675   |.macro ffstring_case, name, lo
1676   |  .ffunc name
1677   |  ffgccheck
1678   |  cmplwi NARGS8:RC, 8
1679   |   evldd CARG1, 0(BASE)
1680   |  blt ->fff_fallback
1681   |  checkstr STR:CARG1
1682   |   lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
1683   |  checkfail ->fff_fallback
1684   |  lwz CARG3, STR:CARG1->len
1685   |   la CARG1, #STR(STR:CARG1)
1686   |   lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
1687   |  cmplw TMP1, CARG3
1688   |   li TMP2, 0
1689   |  blt ->fff_fallback
1690   |1:  // ASCII case conversion.
1691   |  cmplw TMP2, CARG3
1692   |   lbzx TMP1, CARG1, TMP2
1693   |  bge ->fff_newstr
1694   |   subi TMP0, TMP1, lo
1695   |    xori TMP3, TMP1, 0x20
1696   |   cmplwi TMP0, 26
1697   |   isellt TMP1, TMP3, TMP1
1698   |   stbx TMP1, CARG2, TMP2
1699   |  addi TMP2, TMP2, 1
1700   |  b <1
1701   |.endmacro
1702   |
1703   |ffstring_case string_lower, 65
1704   |ffstring_case string_upper, 97
1705   |
1706   |//-- Table library ------------------------------------------------------
1707   |
1708   |.ffunc_1 table_getn
1709   |  checktab CARG1
1710   |  checkfail ->fff_fallback
1711   |  bl extern lj_tab_len               // (GCtab *t)
1712   |  // Returns uint32_t (but less than 2^31).
1713   |  efdcfsi CRET1, CRET1
1714   |  b ->fff_restv
1715   |
1716   |//-- Bit library --------------------------------------------------------
1717   |
1718   |.macro .ffunc_bit, name
1719   |  .ffunc_n bit_..name
1720   |  efdadd CARG1, CARG1, TOBIT
1721   |.endmacro
1722   |
1723   |.ffunc_bit tobit
1724   |->fff_resbit:
1725   |  efdcfsi CRET1, CARG1
1726   |  b ->fff_restv
1727   |
1728   |.macro .ffunc_bit_op, name, ins
1729   |  .ffunc_bit name
1730   |   li TMP1, 8
1731   |1:
1732   |  evlddx CARG2, BASE, TMP1
1733   |  cmplw cr1, TMP1, NARGS8:RC
1734   |   checknum CARG2
1735   |  bge cr1, ->fff_resbit
1736   |   checkfail ->fff_fallback
1737   |  efdadd CARG2, CARG2, TOBIT
1738   |  ins CARG1, CARG1, CARG2
1739   |   addi TMP1, TMP1, 8
1740   |  b <1
1741   |.endmacro
1742   |
1743   |.ffunc_bit_op band, and
1744   |.ffunc_bit_op bor, or
1745   |.ffunc_bit_op bxor, xor
1746   |
1747   |.ffunc_bit bswap
1748   |  rotlwi TMP0, CARG1, 8
1749   |  rlwimi TMP0, CARG1, 24, 0, 7
1750   |  rlwimi TMP0, CARG1, 24, 16, 23
1751   |  efdcfsi CRET1, TMP0
1752   |  b ->fff_restv
1753   |
1754   |.ffunc_bit bnot
1755   |  not TMP0, CARG1
1756   |  efdcfsi CRET1, TMP0
1757   |  b ->fff_restv
1758   |
1759   |.macro .ffunc_bit_sh, name, ins, shmod
1760   |  .ffunc_nn bit_..name
1761   |  efdadd CARG2, CARG2, TOBIT
1762   |   efdadd CARG1, CARG1, TOBIT
1763   |.if shmod == 1
1764   |  rlwinm CARG2, CARG2, 0, 27, 31
1765   |.elif shmod == 2
1766   |  neg CARG2, CARG2
1767   |.endif
1768   |  ins TMP0, CARG1, CARG2
1769   |  efdcfsi CRET1, TMP0
1770   |  b ->fff_restv
1771   |.endmacro
1772   |
1773   |.ffunc_bit_sh lshift, slw, 1
1774   |.ffunc_bit_sh rshift, srw, 1
1775   |.ffunc_bit_sh arshift, sraw, 1
1776   |.ffunc_bit_sh rol, rotlw, 0
1777   |.ffunc_bit_sh ror, rotlw, 2
1778   |
1779   |//-----------------------------------------------------------------------
1780   |
1781   |->fff_fallback:                      // Call fast function fallback handler.
1782   |  // BASE = new base, RB = CFUNC, RC = nargs*8
1783   |  lwz TMP3, CFUNC:RB->f
1784   |    add TMP1, BASE, NARGS8:RC
1785   |   lwz PC, FRAME_PC(BASE)            // Fallback may overwrite PC.
1786   |    addi TMP0, TMP1, 8*LUA_MINSTACK
1787   |     lwz TMP2, L->maxstack
1788   |   stw PC, SAVE_PC                   // Redundant (but a defined value).
1789   |  cmplw TMP0, TMP2
1790   |     stw BASE, L->base
1791   |    stw TMP1, L->top
1792   |   mr CARG1, L
1793   |  bgt >5                             // Need to grow stack.
1794   |  mtctr TMP3
1795   |  bctrl                              // (lua_State *L)
1796   |  // Either throws an error, or recovers and returns -1, 0 or nresults+1.
1797   |  lwz BASE, L->base
1798   |  cmpwi CRET1, 0
1799   |   slwi RD, CRET1, 3
1800   |   la RA, -8(BASE)
1801   |  bgt ->fff_res                      // Returned nresults+1?
1802   |1:  // Returned 0 or -1: retry fast path.
1803   |  lwz TMP0, L->top
1804   |   lwz LFUNC:RB, FRAME_FUNC(BASE)
1805   |  sub NARGS8:RC, TMP0, BASE
1806   |  bne ->vm_call_tail                 // Returned -1?
1807   |  ins_callt                          // Returned 0: retry fast path.
1808   |
1809   |// Reconstruct previous base for vmeta_call during tailcall.
1810   |->vm_call_tail:
1811   |  andi. TMP0, PC, FRAME_TYPE
1812   |   rlwinm TMP1, PC, 0, 0, 28
1813   |  bne >3
1814   |  lwz INS, -4(PC)
1815   |  decode_RA8 TMP1, INS
1816   |3:
1817   |  sub TMP2, BASE, TMP1
1818   |  b ->vm_call_dispatch               // Resolve again for tailcall.
1819   |
1820   |5:  // Grow stack for fallback handler.
1821   |  li CARG2, LUA_MINSTACK
1822   |  bl extern lj_state_growstack       // (lua_State *L, int n)
1823   |  lwz BASE, L->base
1824   |  cmpw TMP0, TMP0                    // Set 4*cr0+eq to force retry.
1825   |  b <1
1826   |
1827   |->fff_gcstep:                        // Call GC step function.
1828   |  // BASE = new base, RC = nargs*8
1829   |  mflr SAVE0
1830   |   stw BASE, L->base
1831   |  add TMP0, BASE, NARGS8:RC
1832   |   stw PC, SAVE_PC                   // Redundant (but a defined value).
1833   |  stw TMP0, L->top
1834   |  mr CARG1, L
1835   |  bl extern lj_gc_step               // (lua_State *L)
1836   |   lwz BASE, L->base
1837   |  mtlr SAVE0
1838   |    lwz TMP0, L->top
1839   |   sub NARGS8:RC, TMP0, BASE
1840   |   lwz CFUNC:RB, FRAME_FUNC(BASE)
1841   |  blr
1842   |
1843   |//-----------------------------------------------------------------------
1844   |//-- Special dispatch targets -------------------------------------------
1845   |//-----------------------------------------------------------------------
1846   |
1847   |->vm_record:                         // Dispatch target for recording phase.
1848 #if LJ_HASJIT
1849   |  NYI
1850 #endif
1851   |
1852   |->vm_rethook:                        // Dispatch target for return hooks.
1853   |  lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1854   |  andi. TMP0, TMP3, HOOK_ACTIVE      // Hook already active?
1855   |  beq >1
1856   |5:  // Re-dispatch to static ins.
1857   |  addi TMP1, TMP1, GG_DISP2STATIC    // Assumes decode_OP4 TMP1, INS.
1858   |  lwzx TMP0, DISPATCH, TMP1
1859   |  mtctr TMP0
1860   |  bctr
1861   |
1862   |->vm_inshook:                        // Dispatch target for instr/line hooks.
1863   |  lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1864   |  lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH)
1865   |  andi. TMP0, TMP3, HOOK_ACTIVE      // Hook already active?
1866   |   rlwinm TMP0, TMP3, 31-LUA_HOOKLINE, 31, 0
1867   |  bne <5
1868   |
1869   |   cmpwi cr1, TMP0, 0
1870   |  addic. TMP2, TMP2, -1
1871   |   beq cr1, <5
1872   |  stw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
1873   |  beq >1
1874   |   bge cr1, <5
1875   |1:
1876   |  mr CARG1, L
1877   |   stw MULTRES, SAVE_MULTRES
1878   |  mr CARG2, PC
1879   |   stw BASE, L->base
1880   |  // SAVE_PC must hold the _previous_ PC. The callee updates it with PC.
1881   |  bl extern lj_dispatch_ins          // (lua_State *L, const BCIns *pc)
1882   |3:
1883   |  lwz BASE, L->base
1884   |4:  // Re-dispatch to static ins.
1885   |  lwz INS, -4(PC)
1886   |  decode_OP4 TMP1, INS
1887   |   decode_RB8 RB, INS
1888   |  addi TMP1, TMP1, GG_DISP2STATIC
1889   |   decode_RD8 RD, INS
1890   |  lwzx TMP0, DISPATCH, TMP1
1891   |   decode_RA8 RA, INS
1892   |   decode_RC8 RC, INS
1893   |  mtctr TMP0
1894   |  bctr
1895   |
1896   |->cont_hook:                         // Continue from hook yield.
1897   |  addi PC, PC, 4
1898   |  lwz MULTRES, -20(RB)               // Restore MULTRES for *M ins.
1899   |  b <4
1900   |
1901   |->vm_hotloop:                        // Hot loop counter underflow.
1902 #if LJ_HASJIT
1903   |  NYI
1904 #endif
1905   |
1906   |->vm_callhook:                       // Dispatch target for call hooks.
1907   |  mr CARG2, PC
1908 #if LJ_HASJIT
1909   |  b >1
1910 #endif
1911   |
1912   |->vm_hotcall:                        // Hot call counter underflow.
1913 #if LJ_HASJIT
1914   |  ori CARG2, PC, 1
1915   |1:
1916 #endif
1917   |  add TMP0, BASE, RC
1918   |   stw PC, SAVE_PC
1919   |  mr CARG1, L
1920   |   stw BASE, L->base
1921   |  sub RA, RA, BASE
1922   |   stw TMP0, L->top
1923   |  bl extern lj_dispatch_call         // (lua_State *L, const BCIns *pc)
1924   |  // Returns ASMFunction.
1925   |  lwz BASE, L->base
1926   |   lwz TMP0, L->top
1927   |   stw ZERO, SAVE_PC                 // Invalidate for subsequent line hook.
1928   |  sub NARGS8:RC, TMP0, BASE
1929   |  add RA, BASE, RA
1930   |  lwz LFUNC:RB, FRAME_FUNC(BASE)
1931   |  mtctr CRET1
1932   |  bctr
1933   |
1934   |//-----------------------------------------------------------------------
1935   |//-- Trace exit handler -------------------------------------------------
1936   |//-----------------------------------------------------------------------
1937   |
1938   |->vm_exit_handler:
1939 #if LJ_HASJIT
1940   |  NYI
1941 #endif
1942   |->vm_exit_interp:
1943 #if LJ_HASJIT
1944   |  NYI
1945 #endif
1946   |
1947   |//-----------------------------------------------------------------------
1948   |//-- Math helper functions ----------------------------------------------
1949   |//-----------------------------------------------------------------------
1950   |
1951   |// FP value rounding. Called by math.floor/math.ceil fast functions
1952   |// and from JIT code.
1953   |//
1954   |// This can be inlined if the CPU has the frin/friz/frip/frim instructions.
1955   |// The alternative hard-float approaches have a deep dependency chain.
1956   |// The resulting latency is at least 3x-7x the double-precision FP latency
1957   |// (e500v2: 6cy, e600: 5cy, Cell: 10cy) or around 20-70 cycles.
1958   |//
1959   |// The soft-float approach is tedious, but much faster (e500v2: ~11cy/~6cy).
1960   |// However it relies on a fast way to transfer the FP value to GPRs
1961   |// (e500v2: 0cy for lo-word, 1cy for hi-word).
1962   |//
1963   |.macro vm_round, name, mode
1964   |  // Used temporaries: TMP0, TMP1, TMP2, TMP3.
1965   |->name.._efd:                        // Input: CARG2, output: CRET2
1966   |  evmergehi CARG1, CARG2, CARG2
1967   |->name.._hilo:
1968   |  // Input: CARG1 (hi), CARG2 (hi, lo), output: CRET2
1969   |  rlwinm TMP2, CARG1, 12, 21, 31
1970   |  addic. TMP2, TMP2, -1023           // exp = exponent(x) - 1023
1971   |   li TMP1, -1
1972   |  cmplwi cr1, TMP2, 51               // 0 <= exp <= 51?
1973   |   subfic TMP0, TMP2, 52
1974   |  bgt cr1, >1
1975   |   lus TMP3, 0xfff0
1976   |  slw TMP0, TMP1, TMP0               // lomask = -1 << (52-exp)
1977   |   sraw TMP1, TMP3, TMP2             // himask = (int32_t)0xfff00000 >> exp
1978   |.if mode == 2                // trunc(x):
1979   |  evmergelo TMP0, TMP1, TMP0
1980   |  evand CRET2, CARG2, TMP0           // hi &= himask, lo &= lomask
1981   |.else
1982   |  andc TMP2, CARG2, TMP0
1983   |   andc TMP3, CARG1, TMP1
1984   |  or TMP2, TMP2, TMP3                // ztest = (hi&~himask) | (lo&~lomask)
1985   |   srawi TMP3, CARG1, 31             // signmask = (int32_t)hi >> 31
1986   |.if mode == 0                // floor(x):
1987   |  and. TMP2, TMP2, TMP3              // iszero = ((ztest & signmask) == 0)
1988   |.else                        // ceil(x):
1989   |  andc. TMP2, TMP2, TMP3             // iszero = ((ztest & ~signmask) == 0)
1990   |.endif
1991   |  and CARG2, CARG2, TMP0             // lo &= lomask
1992   |  and CARG1, CARG1, TMP1             // hi &= himask
1993   |   subc TMP0, CARG2, TMP0
1994   |  iseleq TMP0, CARG2, TMP0           // lo = iszero ? lo : lo-lomask
1995   |   sube TMP1, CARG1, TMP1
1996   |  iseleq TMP1, CARG1, TMP1           // hi = iszero ? hi : hi-himask+carry
1997   |  evmergelo CRET2, TMP1, TMP0
1998   |.endif
1999   |  blr
2000   |1:
2001   |  bgtlr                              // Already done if >=2^52, +-inf or nan.
2002   |.if mode == 2                // trunc(x):
2003   |  rlwinm TMP1, CARG1, 0, 0, 0        // hi = sign(x)
2004   |  li TMP0, 0
2005   |  evmergelo CRET2, TMP1, TMP0
2006   |.else
2007   |  rlwinm TMP2, CARG1, 0, 1, 31
2008   |  srawi TMP0, CARG1, 31              // signmask = (int32_t)hi >> 31
2009   |  or TMP2, TMP2, CARG2               // ztest = abs(hi) | lo
2010   |   lus TMP1, 0x3ff0
2011   |.if mode == 0                // floor(x):
2012   |  and. TMP2, TMP2, TMP0              // iszero = ((ztest & signmask) == 0)
2013   |.else                        // ceil(x):
2014   |  andc. TMP2, TMP2, TMP0             // iszero = ((ztest & ~signmask) == 0)
2015   |.endif
2016   |   li TMP0, 0
2017   |  iseleq TMP1, r0, TMP1
2018   |  rlwimi CARG1, TMP1, 0, 1, 31       // hi = sign(x) | (iszero ? 0.0 : 1.0)
2019   |  evmergelo CRET2, CARG1, TMP0
2020   |.endif
2021   |  blr
2022   |.endmacro
2023   |
2024   |->vm_floor:
2025   |  mflr CARG3
2026   |  bl ->vm_floor_hilo
2027   |  mtlr CARG3
2028   |  evmergehi CRET1, CRET2, CRET2
2029   |  blr
2030   |
2031   |  vm_round vm_floor, 0
2032   |  vm_round vm_ceil,  1
2033 #if LJ_HASJIT
2034   |  vm_round vm_trunc, 2
2035 #else
2036   |->vm_trunc_efd:
2037   |->vm_trunc_hilo:
2038 #endif
2039   |
2040   |// Callable from C: double lj_vm_foldarith(double x, double y, int op)
2041   |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -)
2042   |// and basic math functions. ORDER ARITH
2043   |->vm_foldarith:
2044   |  evmergelo CARG2, CARG1, CARG2
2045   |   cmplwi CARG5, 1
2046   |  evmergelo CARG4, CARG3, CARG4
2047   |   beq >1; bgt >2
2048   |  efdadd CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr
2049   |1:
2050   |  efdsub CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr
2051   |2:
2052   |   cmplwi CARG5, 3; beq >1; bgt >2
2053   |  efdmul CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr
2054   |1:
2055   |  efddiv CRET2, CARG2, CARG4; evmergehi CRET1, CRET2, CRET2; blr
2056   |2:
2057   |   cmplwi CARG5, 5; beq >1; bgt >2
2058   |  evmr CARG3, CARG2; efddiv CRET2, CARG2, CARG4; evmr RB, CARG4
2059   |  mflr RC; bl ->vm_floor_efd; mtlr RC
2060   |  efdmul CRET2, CRET2, RB; efdsub CRET2, CARG3, CRET2
2061   |  evmergehi CRET1, CRET2, CRET2; blr
2062   |1:
2063   |  b extern pow
2064   |2:
2065   |   cmplwi CARG5, 7; beq >1; bgt >2
2066   |  xoris CARG1, CARG1, 0x8000; blr
2067   |1:
2068   |  rlwinm CARG1, CARG1, 0, 1, 31; blr
2069   |2:
2070   |  NYI  // Other operations only needed by JIT compiler.
2071   |
2072   |//-----------------------------------------------------------------------
2073   |//-- Miscellaneous functions --------------------------------------------
2074   |//-----------------------------------------------------------------------
2075   |
2076   |//-----------------------------------------------------------------------
2077   |//-- FFI helper functions -----------------------------------------------
2078   |//-----------------------------------------------------------------------
2079   |
2080   |->vm_ffi_call:
2081 #if LJ_HASFFI
2082   |  NYI
2083 #endif
2084   |
2085   |//-----------------------------------------------------------------------
2088 /* Generate the code for a single instruction. */
2089 static void build_ins(BuildCtx *ctx, BCOp op, int defop)
2091   int vk = 0;
2092   |=>defop:
2094   switch (op) {
2096   /* -- Comparison ops ---------------------------------------------------- */
2098   /* Remember: all ops branch for a true comparison, fall through otherwise. */
2100   case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
2101     |  // RA = src1*8, RD = src2*8, JMP with RD = target
2102     |  evlddx TMP0, BASE, RA
2103     |   addi PC, PC, 4
2104     |  evlddx TMP1, BASE, RD
2105     |   addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2106     |   lwz TMP2, -4(PC)
2107     |  evmergehi RB, TMP0, TMP1
2108     |   decode_RD4 TMP2, TMP2
2109     |  checknum RB
2110     |   add TMP2, TMP2, TMP3
2111     |  checkanyfail ->vmeta_comp
2112     |  efdcmplt TMP0, TMP1
2113     if (op == BC_ISLE || op == BC_ISGT) {
2114       |  efdcmpeq cr1, TMP0, TMP1
2115       |  cror 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
2116     }
2117     if (op == BC_ISLT || op == BC_ISLE) {
2118       |  iselgt PC, TMP2, PC
2119     } else {
2120       |  iselgt PC, PC, TMP2
2121     }
2122     |  ins_next
2123     break;
2125   case BC_ISEQV: case BC_ISNEV:
2126     vk = op == BC_ISEQV;
2127     |  // RA = src1*8, RD = src2*8, JMP with RD = target
2128     |  evlddx CARG2, BASE, RA
2129     |   addi PC, PC, 4
2130     |  evlddx CARG3, BASE, RD
2131     |   addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2132     |   lwz TMP2, -4(PC)
2133     |  evmergehi RB, CARG2, CARG3
2134     |   decode_RD4 TMP2, TMP2
2135     |  checknum RB
2136     |   add TMP2, TMP2, TMP3
2137     |  checkanyfail >5
2138     |  efdcmpeq CARG2, CARG3
2139     if (vk) {
2140       |  iselgt PC, TMP2, PC
2141     } else {
2142       |  iselgt PC, PC, TMP2
2143     }
2144     |1:
2145     |  ins_next
2146     |
2147     |5:  // Either or both types are not numbers.
2148     |  evcmpeq CARG2, CARG3
2149     |   not TMP3, RB
2150     |   cmplwi cr1, TMP3, ~LJ_TISPRI            // Primitive?
2151     |  crorc 4*cr7+lt, 4*cr0+so, 4*cr0+lt       // 1: Same tv or different type.
2152     |   cmplwi cr6, TMP3, ~LJ_TISTABUD          // Table or userdata?
2153     |  crandc 4*cr7+gt, 4*cr0+lt, 4*cr1+gt      // 2: Same type and primitive.
2154     |   mr SAVE0, PC
2155     if (vk) {
2156       |  isel PC, TMP2, PC, 4*cr7+gt
2157     } else {
2158       |  isel TMP2, PC, TMP2, 4*cr7+gt
2159     }
2160     |  cror 4*cr7+lt, 4*cr7+lt, 4*cr7+gt        // 1 or 2.
2161     if (vk) {
2162       |  isel PC, TMP2, PC, 4*cr0+so
2163     } else {
2164       |  isel PC, PC, TMP2, 4*cr0+so
2165     }
2166     |  blt cr7, <1                      // Done if 1 or 2.
2167     |  blt cr6, <1                      // Done if not tab/ud.
2168     |
2169     |  // Different tables or userdatas. Need to check __eq metamethod.
2170     |  // Field metatable must be at same offset for GCtab and GCudata!
2171     |  lwz TAB:TMP2, TAB:CARG2->metatable
2172     |   li CARG4, 1-vk                  // ne = 0 or 1.
2173     |  cmplwi TAB:TMP2, 0
2174     |  beq <1                           // No metatable?
2175     |  lbz TMP2, TAB:TMP2->nomm
2176     |  andi. TMP2, TMP2, 1<<MM_eq
2177     |  bne <1                           // Or 'no __eq' flag set?
2178     |  mr PC, SAVE0                     // Restore old PC.
2179     |  b ->vmeta_equal                  // Handle __eq metamethod.
2180     break;
2182   case BC_ISEQS: case BC_ISNES:
2183     vk = op == BC_ISEQS;
2184     |  // RA = src*8, RD = str_const*8 (~), JMP with RD = target
2185     |  evlddx TMP0, BASE, RA
2186     |   srwi RD, RD, 1
2187     |    lwz INS, 0(PC)
2188     |   subfic RD, RD, -4
2189     |    addi PC, PC, 4
2190     |   lwzx STR:TMP1, KBASE, RD        // KBASE-4-str_const*4
2191     |    addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2192     |    decode_RD4 TMP2, INS
2193     |   evmergelo STR:TMP1, TISSTR, STR:TMP1
2194     |    add TMP2, TMP2, TMP3
2195     |  evcmpeq TMP0, STR:TMP1
2196     if (vk) {
2197       |  isel PC, TMP2, PC, 4*cr0+so
2198     } else {
2199       |  isel PC, PC, TMP2, 4*cr0+so
2200     }
2201     |  ins_next
2202     break;
2204   case BC_ISEQN: case BC_ISNEN:
2205     vk = op == BC_ISEQN;
2206     |  // RA = src*8, RD = num_const*8, JMP with RD = target
2207     |  evlddx TMP0, BASE, RA
2208     |   addi PC, PC, 4
2209     |  evlddx TMP1, KBASE, RD
2210     |   addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2211     |   lwz INS, -4(PC)
2212     |  checknum TMP0
2213     |  checkfail >5
2214     |  efdcmpeq TMP0, TMP1
2215     |1:
2216     |   decode_RD4 TMP2, INS
2217     |   add TMP2, TMP2, TMP3
2218     if (vk) {
2219       |  iselgt PC, TMP2, PC
2220       |5:
2221     } else {
2222       |  iselgt PC, PC, TMP2
2223     }
2224     |3:
2225     |  ins_next
2226     if (!vk) {
2227       |5:
2228       |  decode_RD4 TMP2, INS
2229       |  add PC, TMP2, TMP3
2230       |  b <3
2231     }
2232     break;
2234   case BC_ISEQP: case BC_ISNEP:
2235     vk = op == BC_ISEQP;
2236     |  // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target
2237     |  lwzx TMP0, BASE, RA
2238     |   srwi TMP1, RD, 3
2239     |    lwz INS, 0(PC)
2240     |    addi PC, PC, 4
2241     |   not TMP1, TMP1
2242     |    addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2243     |  cmplw TMP0, TMP1
2244     |    decode_RD4 TMP2, INS
2245     |    add TMP2, TMP2, TMP3
2246     if (vk) {
2247       |  iseleq PC, TMP2, PC
2248     } else {
2249       |  iseleq PC, PC, TMP2
2250     }
2251     |  ins_next
2252     break;
2254   /* -- Unary test and copy ops ------------------------------------------- */
2256   case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF:
2257     |  // RA = dst*8 or unused, RD = src*8, JMP with RD = target
2258     |  evlddx TMP0, BASE, RD
2259     |   evaddw TMP1, TISNIL, TISNIL     // Synthesize LJ_TFALSE.
2260     |   lwz INS, 0(PC)
2261     |  evcmpltu TMP0, TMP1
2262     |   addi PC, PC, 4
2263     if (op == BC_IST || op == BC_ISF) {
2264       |  addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2265       |  decode_RD4 TMP2, INS
2266       |  add TMP2, TMP2, TMP3
2267       if (op == BC_IST) {
2268         |  isellt PC, TMP2, PC
2269       } else {
2270         |  isellt PC, PC, TMP2
2271       }
2272     } else {
2273       if (op == BC_ISTC) {
2274         |  checkfail >1
2275       } else {
2276         |  checkok >1
2277       }
2278       |  addis PC, PC, -(BCBIAS_J*4 >> 16)
2279       |  decode_RD4 TMP2, INS
2280       |   evstddx TMP0, BASE, RA
2281       |  add PC, PC, TMP2
2282       |1:
2283     }
2284     |  ins_next
2285     break;
2287   /* -- Unary ops --------------------------------------------------------- */
2289   case BC_MOV:
2290     |  // RA = dst*8, RD = src*8
2291     |  ins_next1
2292     |  evlddx TMP0, BASE, RD
2293     |  evstddx TMP0, BASE, RA
2294     |  ins_next2
2295     break;
2296   case BC_NOT:
2297     |  // RA = dst*8, RD = src*8
2298     |  ins_next1
2299     |  lwzx TMP0, BASE, RD
2300     |  subfic TMP1, TMP0, LJ_TTRUE
2301     |  adde TMP0, TMP0, TMP1
2302     |  stwx TMP0, BASE, RA
2303     |  ins_next2
2304     break;
2305   case BC_UNM:
2306     |  // RA = dst*8, RD = src*8
2307     |  evlddx TMP0, BASE, RD
2308     |  checknum TMP0
2309     |  checkfail ->vmeta_unm
2310     |  efdneg TMP0, TMP0
2311     |  ins_next1
2312     |  evstddx TMP0, BASE, RA
2313     |  ins_next2
2314     break;
2315   case BC_LEN:
2316     |  // RA = dst*8, RD = src*8
2317     |  evlddx CARG1, BASE, RD
2318     |  checkstr CARG1
2319     |  checkfail >2
2320     |  lwz CRET1, STR:CARG1->len
2321     |1:
2322     |  ins_next1
2323     |  efdcfsi TMP0, CRET1
2324     |  evstddx TMP0, BASE, RA
2325     |  ins_next2
2326     |2:
2327     |  checktab CARG1
2328     |  checkfail ->vmeta_len
2329 #ifdef LUAJIT_ENABLE_LUA52COMPAT
2330     |  lwz TAB:TMP2, TAB:CARG1->metatable
2331     |  cmplwi TAB:TMP2, 0
2332     |  bne >9
2333     |3:
2334 #endif
2335     |->BC_LEN_Z:
2336     |  bl extern lj_tab_len             // (GCtab *t)
2337     |  // Returns uint32_t (but less than 2^31).
2338     |  b <1
2339 #ifdef LUAJIT_ENABLE_LUA52COMPAT
2340     |9:
2341     |  lbz TMP0, TAB:TMP2->nomm
2342     |  andi. TMP0, TMP0, 1<<MM_len
2343     |  bne <3                           // 'no __len' flag set: done.
2344     |  b ->vmeta_len
2345 #endif
2346     break;
2348   /* -- Binary ops -------------------------------------------------------- */
2350     |.macro ins_arithpre, t0, t1
2351     |  // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
2352     ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
2353     ||switch (vk) {
2354     ||case 0:
2355     |   evlddx t0, BASE, RB
2356     |    checknum t0
2357     |   evlddx t1, KBASE, RC
2358     |    checkfail ->vmeta_arith_vn
2359     ||  break;
2360     ||case 1:
2361     |   evlddx t1, BASE, RB
2362     |    checknum t1
2363     |   evlddx t0, KBASE, RC
2364     |    checkfail ->vmeta_arith_nv
2365     ||  break;
2366     ||default:
2367     |   evlddx t0, BASE, RB
2368     |   evlddx t1, BASE, RC
2369     |    evmergehi TMP2, t0, t1
2370     |    checknum TMP2
2371     |    checkanyfail ->vmeta_arith_vv
2372     ||  break;
2373     ||}
2374     |.endmacro
2375     |
2376     |.macro ins_arith, ins
2377     |  ins_arithpre TMP0, TMP1
2378     |  ins_next1
2379     |  ins TMP0, TMP0, TMP1
2380     |  evstddx TMP0, BASE, RA
2381     |  ins_next2
2382     |.endmacro
2384   case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
2385     |  ins_arith efdadd
2386     break;
2387   case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
2388     |  ins_arith efdsub
2389     break;
2390   case BC_MULVN: case BC_MULNV: case BC_MULVV:
2391     |  ins_arith efdmul
2392     break;
2393   case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
2394     |  ins_arith efddiv
2395     break;
2396   case BC_MODVN:
2397     |  ins_arithpre RD, SAVE0
2398     |->BC_MODVN_Z:
2399     |  efddiv CARG2, RD, SAVE0
2400     |  bl ->vm_floor_efd                // floor(b/c)
2401     |  efdmul TMP0, CRET2, SAVE0
2402     |  ins_next1
2403     |  efdsub TMP0, RD, TMP0            // b - floor(b/c)*c
2404     |  evstddx TMP0, BASE, RA
2405     |  ins_next2
2406     break;
2407   case BC_MODNV: case BC_MODVV:
2408     |  ins_arithpre RD, SAVE0
2409     |  b ->BC_MODVN_Z                   // Avoid 3 copies. It's slow anyway.
2410     break;
2411   case BC_POW:
2412     |  evlddx CARG2, BASE, RB
2413     |  evlddx CARG4, BASE, RC
2414     |  evmergehi CARG1, CARG4, CARG2
2415     |  checknum CARG1
2416     |   evmergehi CARG3, CARG4, CARG4
2417     |  checkanyfail ->vmeta_arith_vv
2418     |  bl extern pow
2419     |  evmergelo CRET2, CRET1, CRET2
2420     |  evstddx CRET2, BASE, RA
2421     |  ins_next
2422     break;
2424   case BC_CAT:
2425     |  // RA = dst*8, RB = src_start*8, RC = src_end*8
2426     |  sub CARG3, RC, RB
2427     |   stw BASE, L->base
2428     |  add CARG2, BASE, RC
2429     |  mr SAVE0, RB
2430     |->BC_CAT_Z:
2431     |   stw PC, SAVE_PC
2432     |  mr CARG1, L
2433     |  srwi CARG3, CARG3, 3
2434     |  bl extern lj_meta_cat            // (lua_State *L, TValue *top, int left)
2435     |  // Returns NULL (finished) or TValue * (metamethod).
2436     |  cmplwi CRET1, 0
2437     |   lwz BASE, L->base
2438     |  bne ->vmeta_binop
2439     |  evlddx TMP0, BASE, SAVE0         // Copy result from RB to RA.
2440     |  evstddx TMP0, BASE, RA
2441     |  ins_next
2442     break;
2444   /* -- Constant ops ------------------------------------------------------ */
2446   case BC_KSTR:
2447     |  // RA = dst*8, RD = str_const*8 (~)
2448     |  ins_next1
2449     |  srwi TMP1, RD, 1
2450     |  subfic TMP1, TMP1, -4
2451     |  lwzx TMP0, KBASE, TMP1           // KBASE-4-str_const*4
2452     |  evmergelo TMP0, TISSTR, TMP0
2453     |  evstddx TMP0, BASE, RA
2454     |  ins_next2
2455     break;
2456   case BC_KCDATA:
2457 #if LJ_HASFFI
2458     |  // RA = dst*8, RD = cdata_const*8 (~)
2459     |  ins_next1
2460     |  srwi TMP1, RD, 1
2461     |  subfic TMP1, TMP1, -4
2462     |  lwzx TMP0, KBASE, TMP1           // KBASE-4-cdata_const*4
2463     |  li TMP2, LJ_TCDATA
2464     |  evmergelo TMP0, TMP2, TMP0
2465     |  evstddx TMP0, BASE, RA
2466     |  ins_next2
2467 #endif
2468     break;
2469   case BC_KSHORT:
2470     |  // RA = dst*8, RD = int16_literal*8
2471     |  srwi TMP1, RD, 3
2472     |  extsh TMP1, TMP1
2473     |  ins_next1
2474     |  efdcfsi TMP0, TMP1
2475     |  evstddx TMP0, BASE, RA
2476     |  ins_next2
2477     break;
2478   case BC_KNUM:
2479     |  // RA = dst*8, RD = num_const*8
2480     |  evlddx TMP0, KBASE, RD
2481     |  ins_next1
2482     |  evstddx TMP0, BASE, RA
2483     |  ins_next2
2484     break;
2485   case BC_KPRI:
2486     |  // RA = dst*8, RD = primitive_type*8 (~)
2487     |  srwi TMP1, RD, 3
2488     |  not TMP0, TMP1
2489     |  ins_next1
2490     |  stwx TMP0, BASE, RA
2491     |  ins_next2
2492     break;
2493   case BC_KNIL:
2494     |  // RA = base*8, RD = end*8
2495     |  evstddx TISNIL, BASE, RA
2496     |   addi RA, RA, 8
2497     |1:
2498     |  evstddx TISNIL, BASE, RA
2499     |  cmpw RA, RD
2500     |   addi RA, RA, 8
2501     |  blt <1
2502     |  ins_next_
2503     break;
2505   /* -- Upvalue and function ops ------------------------------------------ */
2507   case BC_UGET:
2508     |  // RA = dst*8, RD = uvnum*8
2509     |  ins_next1
2510     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2511     |   srwi RD, RD, 1
2512     |   addi RD, RD, offsetof(GCfuncL, uvptr)
2513     |  lwzx UPVAL:RB, LFUNC:RB, RD
2514     |  lwz TMP1, UPVAL:RB->v
2515     |  evldd TMP0, 0(TMP1)
2516     |  evstddx TMP0, BASE, RA
2517     |  ins_next2
2518     break;
2519   case BC_USETV:
2520     |  // RA = uvnum*8, RD = src*8
2521     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2522     |    srwi RA, RA, 1
2523     |    addi RA, RA, offsetof(GCfuncL, uvptr)
2524     |   evlddx TMP1, BASE, RD
2525     |  lwzx UPVAL:RB, LFUNC:RB, RA
2526     |  lbz TMP3, UPVAL:RB->marked
2527     |   lwz CARG2, UPVAL:RB->v
2528     |  andi. TMP3, TMP3, LJ_GC_BLACK    // isblack(uv)
2529     |    lbz TMP0, UPVAL:RB->closed
2530     |   evmergehi TMP2, TMP1, TMP1
2531     |   evstdd TMP1, 0(CARG2)
2532     |    cmplwi cr1, TMP0, 0
2533     |  cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
2534     |   subi TMP2, TMP2, (LJ_TISNUM+1)
2535     |  bne >2                           // Upvalue is closed and black?
2536     |1:
2537     |  ins_next
2538     |
2539     |2:  // Check if new value is collectable.
2540     |  cmplwi TMP2, LJ_TISGCV - (LJ_TISNUM+1)
2541     |  bge <1                           // tvisgcv(v)
2542     |  lbz TMP3, GCOBJ:TMP1->gch.marked
2543     |  andi. TMP3, TMP3, LJ_GC_WHITES   // iswhite(v)
2544     |   la CARG1, GG_DISP2G(DISPATCH)
2545     |  // Crossed a write barrier. Move the barrier forward.
2546     |  beq <1
2547     |  bl extern lj_gc_barrieruv        // (global_State *g, TValue *tv)
2548     |  b <1
2549     break;
2550   case BC_USETS:
2551     |  // RA = uvnum*8, RD = str_const*8 (~)
2552     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2553     |   srwi TMP1, RD, 1
2554     |    srwi RA, RA, 1
2555     |   subfic TMP1, TMP1, -4
2556     |    addi RA, RA, offsetof(GCfuncL, uvptr)
2557     |   lwzx STR:TMP1, KBASE, TMP1      // KBASE-4-str_const*4
2558     |  lwzx UPVAL:RB, LFUNC:RB, RA
2559     |   evmergelo STR:TMP1, TISSTR, STR:TMP1
2560     |  lbz TMP3, UPVAL:RB->marked
2561     |   lwz CARG2, UPVAL:RB->v
2562     |  andi. TMP3, TMP3, LJ_GC_BLACK    // isblack(uv)
2563     |   lbz TMP3, STR:TMP1->marked
2564     |   lbz TMP2, UPVAL:RB->closed
2565     |   evstdd STR:TMP1, 0(CARG2)
2566     |  bne >2
2567     |1:
2568     |  ins_next
2569     |
2570     |2:  // Check if string is white and ensure upvalue is closed.
2571     |  andi. TMP3, TMP3, LJ_GC_WHITES   // iswhite(str)
2572     |   cmplwi cr1, TMP2, 0
2573     |  cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
2574     |   la CARG1, GG_DISP2G(DISPATCH)
2575     |  // Crossed a write barrier. Move the barrier forward.
2576     |  beq <1
2577     |  bl extern lj_gc_barrieruv        // (global_State *g, TValue *tv)
2578     |  b <1
2579     break;
2580   case BC_USETN:
2581     |  // RA = uvnum*8, RD = num_const*8
2582     |  ins_next1
2583     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2584     |   srwi RA, RA, 1
2585     |   addi RA, RA, offsetof(GCfuncL, uvptr)
2586     |    evlddx TMP0, KBASE, RD
2587     |  lwzx UPVAL:RB, LFUNC:RB, RA
2588     |  lwz TMP1, UPVAL:RB->v
2589     |  evstdd TMP0, 0(TMP1)
2590     |  ins_next2
2591     break;
2592   case BC_USETP:
2593     |  // RA = uvnum*8, RD = primitive_type*8 (~)
2594     |  ins_next1
2595     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2596     |   srwi RA, RA, 1
2597     |   addi RA, RA, offsetof(GCfuncL, uvptr)
2598     |    srwi TMP0, RD, 3
2599     |  lwzx UPVAL:RB, LFUNC:RB, RA
2600     |    not TMP0, TMP0
2601     |  lwz TMP1, UPVAL:RB->v
2602     |  stw TMP0, 0(TMP1)
2603     |  ins_next2
2604     break;
2606   case BC_UCLO:
2607     |  // RA = level*8, RD = target
2608     |  lwz TMP1, L->openupval
2609     |  branch_RD                        // Do this first since RD is not saved.
2610     |   stw BASE, L->base
2611     |  cmplwi TMP1, 0
2612     |   mr CARG1, L
2613     |  beq >1
2614     |   add CARG2, BASE, RA
2615     |  bl extern lj_func_closeuv        // (lua_State *L, TValue *level)
2616     |  lwz BASE, L->base
2617     |1:
2618     |  ins_next
2619     break;
2621   case BC_FNEW:
2622     |  // RA = dst*8, RD = proto_const*8 (~) (holding function prototype)
2623     |  srwi TMP1, RD, 1
2624     |   stw BASE, L->base
2625     |  subfic TMP1, TMP1, -4
2626     |   stw PC, SAVE_PC
2627     |  lwzx CARG2, KBASE, TMP1          // KBASE-4-tab_const*4
2628     |   mr CARG1, L
2629     |  lwz CARG3, FRAME_FUNC(BASE)
2630     |  // (lua_State *L, GCproto *pt, GCfuncL *parent)
2631     |  bl extern lj_func_newL_gc
2632     |  // Returns GCfuncL *.
2633     |  lwz BASE, L->base
2634     |  evmergelo LFUNC:CRET1, TISFUNC, LFUNC:CRET1
2635     |  evstddx LFUNC:CRET1, BASE, RA
2636     |  ins_next
2637     break;
2639   /* -- Table ops --------------------------------------------------------- */
2641   case BC_TNEW:
2642   case BC_TDUP:
2643     |  // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~)
2644     |  lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH)
2645     |   mr CARG1, L
2646     |  lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
2647     |   stw BASE, L->base
2648     |  cmplw TMP0, TMP1
2649     |   stw PC, SAVE_PC
2650     |  bge >5
2651     |1:
2652     if (op == BC_TNEW) {
2653       |  rlwinm CARG2, RD, 29, 21, 31
2654       |  rlwinm CARG3, RD, 18, 27, 31
2655       |  cmpwi CARG2, 0x7ff
2656       |   li TMP1, 0x801
2657       |  iseleq CARG2, TMP1, CARG2
2658       |  bl extern lj_tab_new  // (lua_State *L, int32_t asize, uint32_t hbits)
2659       |  // Returns Table *.
2660     } else {
2661       |  srwi TMP1, RD, 1
2662       |  subfic TMP1, TMP1, -4
2663       |  lwzx CARG2, KBASE, TMP1                // KBASE-4-tab_const*4
2664       |  bl extern lj_tab_dup  // (lua_State *L, Table *kt)
2665       |  // Returns Table *.
2666     }
2667     |  lwz BASE, L->base
2668     |  evmergelo TAB:CRET1, TISTAB, TAB:CRET1
2669     |  evstddx TAB:CRET1, BASE, RA
2670     |  ins_next
2671     |5:
2672     |  mr SAVE0, RD
2673     |  bl extern lj_gc_step_fixtop  // (lua_State *L)
2674     |  mr RD, SAVE0
2675     |  mr CARG1, L
2676     |  b <1
2677     break;
2679   case BC_GGET:
2680     |  // RA = dst*8, RD = str_const*8 (~)
2681   case BC_GSET:
2682     |  // RA = src*8, RD = str_const*8 (~)
2683     |  lwz LFUNC:TMP2, FRAME_FUNC(BASE)
2684     |   srwi TMP1, RD, 1
2685     |  lwz TAB:RB, LFUNC:TMP2->env
2686     |   subfic TMP1, TMP1, -4
2687     |   lwzx STR:RC, KBASE, TMP1        // KBASE-4-str_const*4
2688     if (op == BC_GGET) {
2689       |  b ->BC_TGETS_Z
2690     } else {
2691       |  b ->BC_TSETS_Z
2692     }
2693     break;
2695   case BC_TGETV:
2696     |  // RA = dst*8, RB = table*8, RC = key*8
2697     |  evlddx TAB:RB, BASE, RB
2698     |   evlddx RC, BASE, RC
2699     |  checktab TAB:RB
2700     |  checkfail ->vmeta_tgetv
2701     |  checknum RC
2702     |  checkfail >5
2703     |  // Convert number key to integer
2704     |  efdctsi TMP2, RC
2705     |   lwz TMP0, TAB:RB->asize
2706     |  efdcfsi TMP1, TMP2
2707     |   cmplw cr0, TMP0, TMP2
2708     |  efdcmpeq cr1, RC, TMP1
2709     |   lwz TMP1, TAB:RB->array
2710     |  crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
2711     |   slwi TMP2, TMP2, 3
2712     |  ble ->vmeta_tgetv                // Integer key and in array part?
2713     |  evlddx TMP1, TMP1, TMP2
2714     |  checknil TMP1
2715     |  checkok >2
2716     |1:
2717     |  evstddx TMP1, BASE, RA
2718     |  ins_next
2719     |
2720     |2:  // Check for __index if table value is nil.
2721     |  lwz TAB:TMP2, TAB:RB->metatable
2722     |  cmplwi TAB:TMP2, 0
2723     |  beq <1                           // No metatable: done.
2724     |  lbz TMP0, TAB:TMP2->nomm
2725     |  andi. TMP0, TMP0, 1<<MM_index
2726     |  bne <1                           // 'no __index' flag set: done.
2727     |  b ->vmeta_tgetv
2728     |
2729     |5:
2730     |  checkstr STR:RC                  // String key?
2731     |  checkok ->BC_TGETS_Z
2732     |  b ->vmeta_tgetv
2733     break;
2734   case BC_TGETS:
2735     |  // RA = dst*8, RB = table*8, RC = str_const*8 (~)
2736     |  evlddx TAB:RB, BASE, RB
2737     |   srwi TMP1, RC, 1
2738     |  checktab TAB:RB
2739     |   subfic TMP1, TMP1, -4
2740     |   lwzx STR:RC, KBASE, TMP1        // KBASE-4-str_const*4
2741     |  checkfail ->vmeta_tgets1
2742     |->BC_TGETS_Z:
2743     |  // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8
2744     |  lwz TMP0, TAB:RB->hmask
2745     |  lwz TMP1, STR:RC->hash
2746     |  lwz NODE:TMP2, TAB:RB->node
2747     |   evmergelo STR:RC, TISSTR, STR:RC
2748     |  and TMP1, TMP1, TMP0             // idx = str->hash & tab->hmask
2749     |  slwi TMP0, TMP1, 5
2750     |  slwi TMP1, TMP1, 3
2751     |  sub TMP1, TMP0, TMP1
2752     |  add NODE:TMP2, NODE:TMP2, TMP1   // node = tab->node + (idx*32-idx*8)
2753     |1:
2754     |  evldd TMP0, NODE:TMP2->key
2755     |   evldd TMP1, NODE:TMP2->val
2756     |  evcmpeq TMP0, STR:RC
2757     |  checkanyfail >4
2758     |   checknil TMP1
2759     |   checkok >5                      // Key found, but nil value?
2760     |3:
2761     |   evstddx TMP1, BASE, RA
2762     |  ins_next
2763     |
2764     |4:  // Follow hash chain.
2765     |  lwz NODE:TMP2, NODE:TMP2->next
2766     |  cmplwi NODE:TMP2, 0
2767     |  bne <1
2768     |  // End of hash chain: key not found, nil result.
2769     |   evmr TMP1, TISNIL
2770     |
2771     |5:  // Check for __index if table value is nil.
2772     |  lwz TAB:TMP2, TAB:RB->metatable
2773     |  cmplwi TAB:TMP2, 0
2774     |  beq <3                           // No metatable: done.
2775     |  lbz TMP0, TAB:TMP2->nomm
2776     |  andi. TMP0, TMP0, 1<<MM_index
2777     |  bne <3                           // 'no __index' flag set: done.
2778     |  b ->vmeta_tgets
2779     break;
2780   case BC_TGETB:
2781     |  // RA = dst*8, RB = table*8, RC = index*8
2782     |  evlddx TAB:RB, BASE, RB
2783     |   srwi TMP0, RC, 3
2784     |  checktab TAB:RB
2785     |  checkfail ->vmeta_tgetb
2786     |  lwz TMP1, TAB:RB->asize
2787     |   lwz TMP2, TAB:RB->array
2788     |  cmplw TMP0, TMP1
2789     |  bge ->vmeta_tgetb
2790     |  evlddx TMP1, TMP2, RC
2791     |  checknil TMP1
2792     |  checkok >5
2793     |1:
2794     |  ins_next1
2795     |  evstddx TMP1, BASE, RA
2796     |  ins_next2
2797     |
2798     |5:  // Check for __index if table value is nil.
2799     |  lwz TAB:TMP2, TAB:RB->metatable
2800     |  cmplwi TAB:TMP2, 0
2801     |  beq <1                           // No metatable: done.
2802     |  lbz TMP2, TAB:TMP2->nomm
2803     |  andi. TMP2, TMP2, 1<<MM_index
2804     |  bne <1                           // 'no __index' flag set: done.
2805     |  b ->vmeta_tgetb                  // Caveat: preserve TMP0!
2806     break;
2808   case BC_TSETV:
2809     |  // RA = src*8, RB = table*8, RC = key*8
2810     |  evlddx TAB:RB, BASE, RB
2811     |   evlddx RC, BASE, RC
2812     |  checktab TAB:RB
2813     |  checkfail ->vmeta_tsetv
2814     |  checknum RC
2815     |  checkfail >5
2816     |  // Convert number key to integer
2817     |  efdctsi TMP2, RC
2818     |    evlddx SAVE0, BASE, RA
2819     |   lwz TMP0, TAB:RB->asize
2820     |  efdcfsi TMP1, TMP2
2821     |   cmplw cr0, TMP0, TMP2
2822     |  efdcmpeq cr1, RC, TMP1
2823     |   lwz TMP1, TAB:RB->array
2824     |  crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
2825     |   slwi TMP0, TMP2, 3
2826     |  ble ->vmeta_tsetv                // Integer key and in array part?
2827     |   lbz TMP3, TAB:RB->marked
2828     |  evlddx TMP2, TMP1, TMP0
2829     |  checknil TMP2
2830     |  checkok >3
2831     |1:
2832     |  andi. TMP2, TMP3, LJ_GC_BLACK    // isblack(table)
2833     |   evstddx SAVE0, TMP1, TMP0
2834     |  bne >7
2835     |2:
2836     |  ins_next
2837     |
2838     |3:  // Check for __newindex if previous value is nil.
2839     |  lwz TAB:TMP2, TAB:RB->metatable
2840     |  cmplwi TAB:TMP2, 0
2841     |  beq <1                           // No metatable: done.
2842     |  lbz TMP2, TAB:TMP2->nomm
2843     |  andi. TMP2, TMP2, 1<<MM_newindex
2844     |  bne <1                           // 'no __newindex' flag set: done.
2845     |  b ->vmeta_tsetv
2846     |
2847     |5:
2848     |  checkstr STR:RC                  // String key?
2849     |  checkok ->BC_TSETS_Z
2850     |  b ->vmeta_tsetv
2851     |
2852     |7:  // Possible table write barrier for the value. Skip valiswhite check.
2853     |  barrierback TAB:RB, TMP3, TMP0
2854     |  b <2
2855     break;
2856   case BC_TSETS:
2857     |  // RA = src*8, RB = table*8, RC = str_const*8 (~)
2858     |  evlddx TAB:RB, BASE, RB
2859     |   srwi TMP1, RC, 1
2860     |  checktab TAB:RB
2861     |   subfic TMP1, TMP1, -4
2862     |   lwzx STR:RC, KBASE, TMP1        // KBASE-4-str_const*4
2863     |  checkfail ->vmeta_tsets1
2864     |->BC_TSETS_Z:
2865     |  // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8
2866     |  lwz TMP0, TAB:RB->hmask
2867     |  lwz TMP1, STR:RC->hash
2868     |  lwz NODE:TMP2, TAB:RB->node
2869     |   evmergelo STR:RC, TISSTR, STR:RC
2870     |    stb ZERO, TAB:RB->nomm         // Clear metamethod cache.
2871     |  and TMP1, TMP1, TMP0             // idx = str->hash & tab->hmask
2872     |    evlddx SAVE0, BASE, RA
2873     |  slwi TMP0, TMP1, 5
2874     |  slwi TMP1, TMP1, 3
2875     |  sub TMP1, TMP0, TMP1
2876     |    lbz TMP3, TAB:RB->marked
2877     |  add NODE:TMP2, NODE:TMP2, TMP1   // node = tab->node + (idx*32-idx*8)
2878     |1:
2879     |  evldd TMP0, NODE:TMP2->key
2880     |   evldd TMP1, NODE:TMP2->val
2881     |  evcmpeq TMP0, STR:RC
2882     |  checkanyfail >5
2883     |   checknil TMP1
2884     |   checkok >4                      // Key found, but nil value?
2885     |2:
2886     |  andi. TMP0, TMP3, LJ_GC_BLACK    // isblack(table)
2887     |    evstdd SAVE0, NODE:TMP2->val
2888     |  bne >7
2889     |3:
2890     |  ins_next
2891     |
2892     |4:  // Check for __newindex if previous value is nil.
2893     |  lwz TAB:TMP1, TAB:RB->metatable
2894     |  cmplwi TAB:TMP1, 0
2895     |  beq <2                           // No metatable: done.
2896     |  lbz TMP0, TAB:TMP1->nomm
2897     |  andi. TMP0, TMP0, 1<<MM_newindex
2898     |  bne <2                           // 'no __newindex' flag set: done.
2899     |  b ->vmeta_tsets
2900     |
2901     |5:  // Follow hash chain.
2902     |  lwz NODE:TMP2, NODE:TMP2->next
2903     |  cmplwi NODE:TMP2, 0
2904     |  bne <1
2905     |  // End of hash chain: key not found, add a new one.
2906     |
2907     |  // But check for __newindex first.
2908     |  lwz TAB:TMP1, TAB:RB->metatable
2909     |   la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
2910     |   stw PC, SAVE_PC
2911     |   mr CARG1, L
2912     |  cmplwi TAB:TMP1, 0
2913     |   stw BASE, L->base
2914     |  beq >6                           // No metatable: continue.
2915     |  lbz TMP0, TAB:TMP1->nomm
2916     |  andi. TMP0, TMP0, 1<<MM_newindex
2917     |  beq ->vmeta_tsets                // 'no __newindex' flag NOT set: check.
2918     |6:
2919     |  mr CARG2, TAB:RB
2920     |  evstdd STR:RC, 0(CARG3)
2921     |  bl extern lj_tab_newkey          // (lua_State *L, GCtab *t, TValue *k)
2922     |  // Returns TValue *.
2923     |  lwz BASE, L->base
2924     |  evstdd SAVE0, 0(CRET1)
2925     |  b <3                             // No 2nd write barrier needed.
2926     |
2927     |7:  // Possible table write barrier for the value. Skip valiswhite check.
2928     |  barrierback TAB:RB, TMP3, TMP0
2929     |  b <3
2930     break;
2931   case BC_TSETB:
2932     |  // RA = src*8, RB = table*8, RC = index*8
2933     |  evlddx TAB:RB, BASE, RB
2934     |   srwi TMP0, RC, 3
2935     |  checktab TAB:RB
2936     |  checkfail ->vmeta_tsetb
2937     |  lwz TMP1, TAB:RB->asize
2938     |   lwz TMP2, TAB:RB->array
2939     |    lbz TMP3, TAB:RB->marked
2940     |  cmplw TMP0, TMP1
2941     |   evlddx SAVE0, BASE, RA
2942     |  bge ->vmeta_tsetb
2943     |  evlddx TMP1, TMP2, RC
2944     |  checknil TMP1
2945     |  checkok >5
2946     |1:
2947     |  andi. TMP0, TMP3, LJ_GC_BLACK    // isblack(table)
2948     |   evstddx SAVE0, TMP2, RC
2949     |  bne >7
2950     |2:
2951     |  ins_next
2952     |
2953     |5:  // Check for __newindex if previous value is nil.
2954     |  lwz TAB:TMP1, TAB:RB->metatable
2955     |  cmplwi TAB:TMP1, 0
2956     |  beq <1                           // No metatable: done.
2957     |  lbz TMP1, TAB:TMP1->nomm
2958     |  andi. TMP1, TMP1, 1<<MM_newindex
2959     |  bne <1                           // 'no __newindex' flag set: done.
2960     |  b ->vmeta_tsetb                  // Caveat: preserve TMP0!
2961     |
2962     |7:  // Possible table write barrier for the value. Skip valiswhite check.
2963     |  barrierback TAB:RB, TMP3, TMP0
2964     |  b <2
2965     break;
2967   case BC_TSETM:
2968     |  // RA = base*8 (table at base-1), RD = num_const*8 (start index)
2969     |  add RA, BASE, RA
2970     |1:
2971     |   add TMP3, KBASE, RD
2972     |  lwz TAB:CARG2, -4(RA)            // Guaranteed to be a table.
2973     |    addic. TMP0, MULTRES, -8
2974     |   lwz TMP3, 4(TMP3)               // Integer constant is in lo-word.
2975     |    srwi CARG3, TMP0, 3
2976     |    beq >4                         // Nothing to copy?
2977     |  add CARG3, CARG3, TMP3
2978     |  lwz TMP2, TAB:CARG2->asize
2979     |   slwi TMP1, TMP3, 3
2980     |    lbz TMP3, TAB:CARG2->marked
2981     |  cmplw CARG3, TMP2
2982     |   add TMP2, RA, TMP0
2983     |   lwz TMP0, TAB:CARG2->array
2984     |  bgt >5
2985     |   add TMP1, TMP1, TMP0
2986     |    andi. TMP0, TMP3, LJ_GC_BLACK  // isblack(table)
2987     |3:  // Copy result slots to table.
2988     |   evldd TMP0, 0(RA)
2989     |  addi RA, RA, 8
2990     |  cmpw cr1, RA, TMP2
2991     |   evstdd TMP0, 0(TMP1)
2992     |    addi TMP1, TMP1, 8
2993     |  blt cr1, <3
2994     |  bne >7
2995     |4:
2996     |  ins_next
2997     |
2998     |5:  // Need to resize array part.
2999     |   stw BASE, L->base
3000     |  mr CARG1, L
3001     |   stw PC, SAVE_PC
3002     |  mr SAVE0, RD
3003     |  bl extern lj_tab_reasize         // (lua_State *L, GCtab *t, int nasize)
3004     |  // Must not reallocate the stack.
3005     |  mr RD, SAVE0
3006     |  b <1
3007     |
3008     |7:  // Possible table write barrier for any value. Skip valiswhite check.
3009     |  barrierback TAB:CARG2, TMP3, TMP0
3010     |  b <4
3011     break;
3013   /* -- Calls and vararg handling ----------------------------------------- */
3015   case BC_CALLM:
3016     |  // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8
3017     |  add NARGS8:RC, NARGS8:RC, MULTRES
3018     |  // Fall through. Assumes BC_CALL follows.
3019     break;
3020   case BC_CALL:
3021     |  // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8
3022     |  evlddx LFUNC:RB, BASE, RA
3023     |   mr TMP2, BASE
3024     |   add BASE, BASE, RA
3025     |    subi NARGS8:RC, NARGS8:RC, 8
3026     |  checkfunc LFUNC:RB
3027     |   addi BASE, BASE, 8
3028     |  checkfail ->vmeta_call
3029     |  ins_call
3030     break;
3032   case BC_CALLMT:
3033     |  // RA = base*8, (RB = 0,) RC = extra_nargs*8
3034     |  add NARGS8:RC, NARGS8:RC, MULTRES
3035     |  // Fall through. Assumes BC_CALLT follows.
3036     break;
3037   case BC_CALLT:
3038     |  // RA = base*8, (RB = 0,) RC = (nargs+1)*8
3039     |  evlddx LFUNC:RB, BASE, RA
3040     |   add RA, BASE, RA
3041     |    lwz TMP1, FRAME_PC(BASE)
3042     |    subi NARGS8:RC, NARGS8:RC, 8
3043     |  checkfunc LFUNC:RB
3044     |   addi RA, RA, 8
3045     |  checkfail ->vmeta_callt
3046     |->BC_CALLT_Z:
3047     |  andi. TMP0, TMP1, FRAME_TYPE     // Caveat: preserve cr0 until the crand.
3048     |   lbz TMP3, LFUNC:RB->ffid
3049     |    xori TMP2, TMP1, FRAME_VARG
3050     |    cmplwi cr1, NARGS8:RC, 0
3051     |  bne >7
3052     |1:
3053     |  stw LFUNC:RB, FRAME_FUNC(BASE)   // Copy function down, but keep PC.
3054     |  li TMP2, 0
3055     |   cmplwi cr7, TMP3, 1             // (> FF_C) Calling a fast function?
3056     |    beq cr1, >3
3057     |2:
3058     |  addi TMP3, TMP2, 8
3059     |   evlddx TMP0, RA, TMP2
3060     |  cmplw cr1, TMP3, NARGS8:RC
3061     |   evstddx TMP0, BASE, TMP2
3062     |  mr TMP2, TMP3
3063     |  bne cr1, <2
3064     |3:
3065     |  crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt
3066     |  beq >5
3067     |4:
3068     |  ins_callt
3069     |
3070     |5:  // Tailcall to a fast function with a Lua frame below.
3071     |  lwz INS, -4(TMP1)
3072     |  decode_RA8 RA, INS
3073     |  sub TMP1, BASE, RA
3074     |  lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1)
3075     |  lwz TMP1, LFUNC:TMP1->pc
3076     |  lwz KBASE, PC2PROTO(k)(TMP1)     // Need to prepare KBASE.
3077     |  b <4
3078     |
3079     |7:  // Tailcall from a vararg function.
3080     |  andi. TMP0, TMP2, FRAME_TYPEP
3081     |  bne <1                           // Vararg frame below?
3082     |  sub BASE, BASE, TMP2             // Relocate BASE down.
3083     |  lwz TMP1, FRAME_PC(BASE)
3084     |  andi. TMP0, TMP1, FRAME_TYPE
3085     |  b <1
3086     break;
3088   case BC_ITERC:
3089     |  // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8))
3090     |  subi RA, RA, 24                  // evldd doesn't support neg. offsets.
3091     |   mr TMP2, BASE
3092     |  evlddx LFUNC:RB, BASE, RA
3093     |   add BASE, BASE, RA
3094     |   evldd TMP0, 8(BASE)
3095     |    evldd TMP1, 16(BASE)
3096     |  evstdd LFUNC:RB, 24(BASE)        // Copy callable.
3097     |  checkfunc LFUNC:RB
3098     |   evstdd TMP0, 32(BASE)           // Copy state.
3099     |     li NARGS8:RC, 16              // Iterators get 2 arguments.
3100     |    evstdd TMP1, 40(BASE)          // Copy control var.
3101     |     addi BASE, BASE, 32
3102     |  checkfail ->vmeta_call
3103     |  ins_call
3104     break;
3106   case BC_ITERN:
3107     |  // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8)
3108 #if LJ_HASJIT
3109     |  // NYI: add hotloop, record BC_ITERN.
3110 #endif
3111     |  add RA, BASE, RA
3112     |  lwz TAB:RB, -12(RA)
3113     |  lwz RC, -4(RA)                   // Get index from control var.
3114     |  lwz TMP0, TAB:RB->asize
3115     |  lwz TMP1, TAB:RB->array
3116     |   addi PC, PC, 4
3117     |1:  // Traverse array part.
3118     |  cmplw RC, TMP0
3119     |   slwi TMP3, RC, 3
3120     |  bge >5                           // Index points after array part?
3121     |  evlddx TMP2, TMP1, TMP3
3122     |  checknil TMP2
3123     |     lwz INS, -4(PC)
3124     |  checkok >4
3125     |   efdcfsi TMP0, RC
3126     |    addi RC, RC, 1
3127     |     addis TMP3, PC, -(BCBIAS_J*4 >> 16)
3128     |  evstdd TMP2, 8(RA)
3129     |     decode_RD4 TMP1, INS
3130     |    stw RC, -4(RA)                 // Update control var.
3131     |     add PC, TMP1, TMP3
3132     |   evstdd TMP0, 0(RA)
3133     |3:
3134     |  ins_next
3135     |
3136     |4:  // Skip holes in array part.
3137     |  addi RC, RC, 1
3138     |  b <1
3139     |
3140     |5:  // Traverse hash part.
3141     |  lwz TMP1, TAB:RB->hmask
3142     |  sub RC, RC, TMP0
3143     |   lwz TMP2, TAB:RB->node
3144     |6:
3145     |  cmplw RC, TMP1                   // End of iteration? Branch to ITERL+1.
3146     |   slwi TMP3, RC, 5
3147     |  bgt <3
3148     |   slwi RB, RC, 3
3149     |   sub TMP3, TMP3, RB
3150     |  evlddx RB, TMP2, TMP3
3151     |   add NODE:TMP3, TMP2, TMP3
3152     |  checknil RB
3153     |     lwz INS, -4(PC)
3154     |  checkok >7
3155     |   evldd TMP3, NODE:TMP3->key
3156     |     addis TMP2, PC, -(BCBIAS_J*4 >> 16)
3157     |  evstdd RB, 8(RA)
3158     |    add RC, RC, TMP0
3159     |     decode_RD4 TMP1, INS
3160     |   evstdd TMP3, 0(RA)
3161     |    addi RC, RC, 1
3162     |     add PC, TMP1, TMP2
3163     |    stw RC, -4(RA)                 // Update control var.
3164     |  b <3
3165     |
3166     |7:  // Skip holes in hash part.
3167     |  addi RC, RC, 1
3168     |  b <6
3169     break;
3171   case BC_ISNEXT:
3172     |  // RA = base*8, RD = target (points to ITERN)
3173     |  add RA, BASE, RA
3174     |   li TMP2, -24
3175     |  evlddx CFUNC:TMP1, RA, TMP2
3176     |   lwz TMP2, -16(RA)
3177     |    lwz TMP3, -8(RA)
3178     |  evmergehi TMP0, CFUNC:TMP1, CFUNC:TMP1
3179     |   cmpwi cr0, TMP2, LJ_TTAB
3180     |  cmpwi cr1, TMP0, LJ_TFUNC
3181     |    cmpwi cr6, TMP3, LJ_TNIL
3182     |  bne cr1, >5
3183     |  lbz TMP1, CFUNC:TMP1->ffid
3184     |   crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq
3185     |  cmpwi cr7, TMP1, FF_next_N
3186     |    srwi TMP0, RD, 1
3187     |  crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq
3188     |    add TMP3, PC, TMP0
3189     |  bne cr0, >5
3190     |  stw ZERO, -4(RA)                 // Initialize control var.
3191     |    addis PC, TMP3, -(BCBIAS_J*4 >> 16)
3192     |1:
3193     |  ins_next
3194     |5:  // Despecialize bytecode if any of the checks fail.
3195     |  li TMP0, BC_JMP
3196     |   li TMP1, BC_ITERC
3197     |  stb TMP0, -1(PC)
3198     |    addis PC, TMP3, -(BCBIAS_J*4 >> 16)
3199     |   stb TMP1, 3(PC)
3200     |  b <1
3201     break;
3203   case BC_VARG:
3204     |  // RA = base*8, RB = (nresults+1)*8, RC = numparams*8
3205     |  lwz TMP0, FRAME_PC(BASE)
3206     |  add RC, BASE, RC
3207     |   add RA, BASE, RA
3208     |  addi RC, RC, FRAME_VARG
3209     |   add TMP2, RA, RB
3210     |  subi TMP3, BASE, 8               // TMP3 = vtop
3211     |  sub RC, RC, TMP0                 // RC = vbase
3212     |  // Note: RC may now be even _above_ BASE if nargs was < numparams.
3213     |  cmplwi cr1, RB, 0
3214     |   sub. TMP1, TMP3, RC
3215     |  beq cr1, >5                      // Copy all varargs?
3216     |   subi TMP2, TMP2, 16
3217     |   ble >2                          // No vararg slots?
3218     |1:  // Copy vararg slots to destination slots.
3219     |  evldd TMP0, 0(RC)
3220     |   addi RC, RC, 8
3221     |  evstdd TMP0, 0(RA)
3222     |  cmplw RA, TMP2
3223     |   cmplw cr1, RC, TMP3
3224     |  bge >3                           // All destination slots filled?
3225     |    addi RA, RA, 8
3226     |   blt cr1, <1                     // More vararg slots?
3227     |2:  // Fill up remainder with nil.
3228     |  evstdd TISNIL, 0(RA)
3229     |  cmplw RA, TMP2
3230     |   addi RA, RA, 8
3231     |  blt <2
3232     |3:
3233     |  ins_next
3234     |
3235     |5:  // Copy all varargs.
3236     |  lwz TMP0, L->maxstack
3237     |   li MULTRES, 8                   // MULTRES = (0+1)*8
3238     |  ble <3                           // No vararg slots?
3239     |  add TMP2, RA, TMP1
3240     |  cmplw TMP2, TMP0
3241     |   addi MULTRES, TMP1, 8
3242     |  bgt >7
3243     |6:
3244     |  evldd TMP0, 0(RC)
3245     |   addi RC, RC, 8
3246     |  evstdd TMP0, 0(RA)
3247     |  cmplw RC, TMP3
3248     |   addi RA, RA, 8
3249     |  blt <6                           // More vararg slots?
3250     |  b <3
3251     |
3252     |7:  // Grow stack for varargs.
3253     |  mr CARG1, L
3254     |   stw RA, L->top
3255     |  sub SAVE0, RC, BASE              // Need delta, because BASE may change.
3256     |   stw BASE, L->base
3257     |  sub RA, RA, BASE
3258     |   stw PC, SAVE_PC
3259     |  srwi CARG2, TMP1, 3
3260     |  bl extern lj_state_growstack     // (lua_State *L, int n)
3261     |  lwz BASE, L->base
3262     |  add RA, BASE, RA
3263     |  add RC, BASE, SAVE0
3264     |  subi TMP3, BASE, 8
3265     |  b <6
3266     break;
3268   /* -- Returns ----------------------------------------------------------- */
3270   case BC_RETM:
3271     |  // RA = results*8, RD = extra_nresults*8
3272     |  add RD, RD, MULTRES              // MULTRES >= 8, so RD >= 8.
3273     |  // Fall through. Assumes BC_RET follows.
3274     break;
3276   case BC_RET:
3277     |  // RA = results*8, RD = (nresults+1)*8
3278     |  lwz PC, FRAME_PC(BASE)
3279     |   add RA, BASE, RA
3280     |    mr MULTRES, RD
3281     |1:
3282     |  andi. TMP0, PC, FRAME_TYPE
3283     |   xori TMP1, PC, FRAME_VARG
3284     |  bne ->BC_RETV_Z
3285     |
3286     |->BC_RET_Z:
3287     |  // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return
3288     |   lwz INS, -4(PC)
3289     |  cmpwi RD, 8
3290     |   subi TMP2, BASE, 8
3291     |   subi RC, RD, 8
3292     |   decode_RB8 RB, INS
3293     |  beq >3
3294     |   li TMP1, 0
3295     |2:
3296     |  addi TMP3, TMP1, 8
3297     |   evlddx TMP0, RA, TMP1
3298     |  cmpw TMP3, RC
3299     |   evstddx TMP0, TMP2, TMP1
3300     |  beq >3
3301     |  addi TMP1, TMP3, 8
3302     |   evlddx TMP0, RA, TMP3
3303     |  cmpw TMP1, RC
3304     |   evstddx TMP0, TMP2, TMP3
3305     |  bne <2
3306     |3:
3307     |5:
3308     |  cmplw RB, RD
3309     |   decode_RA8 RA, INS
3310     |  bgt >6
3311     |   sub BASE, TMP2, RA
3312     |  lwz LFUNC:TMP1, FRAME_FUNC(BASE)
3313     |  ins_next1
3314     |  lwz TMP1, LFUNC:TMP1->pc
3315     |  lwz KBASE, PC2PROTO(k)(TMP1)
3316     |  ins_next2
3317     |
3318     |6:  // Fill up results with nil.
3319     |  subi TMP1, RD, 8
3320     |   addi RD, RD, 8
3321     |  evstddx TISNIL, TMP2, TMP1
3322     |  b <5
3323     |
3324     |->BC_RETV_Z:  // Non-standard return case.
3325     |  andi. TMP2, TMP1, FRAME_TYPEP
3326     |  bne ->vm_return
3327     |  // Return from vararg function: relocate BASE down.
3328     |  sub BASE, BASE, TMP1
3329     |  lwz PC, FRAME_PC(BASE)
3330     |  b <1
3331     break;
3333   case BC_RET0: case BC_RET1:
3334     |  // RA = results*8, RD = (nresults+1)*8
3335     |  lwz PC, FRAME_PC(BASE)
3336     |   add RA, BASE, RA
3337     |    mr MULTRES, RD
3338     |  andi. TMP0, PC, FRAME_TYPE
3339     |   xori TMP1, PC, FRAME_VARG
3340     |  bne ->BC_RETV_Z
3341     |
3342     |  lwz INS, -4(PC)
3343     |   subi TMP2, BASE, 8
3344     |  decode_RB8 RB, INS
3345     if (op == BC_RET1) {
3346       |  evldd TMP0, 0(RA)
3347       |  evstdd TMP0, 0(TMP2)
3348     }
3349     |5:
3350     |  cmplw RB, RD
3351     |   decode_RA8 RA, INS
3352     |  bgt >6
3353     |   sub BASE, TMP2, RA
3354     |  lwz LFUNC:TMP1, FRAME_FUNC(BASE)
3355     |  ins_next1
3356     |  lwz TMP1, LFUNC:TMP1->pc
3357     |  lwz KBASE, PC2PROTO(k)(TMP1)
3358     |  ins_next2
3359     |
3360     |6:  // Fill up results with nil.
3361     |  subi TMP1, RD, 8
3362     |   addi RD, RD, 8
3363     |  evstddx TISNIL, TMP2, TMP1
3364     |  b <5
3365     break;
3367   /* -- Loops and branches ------------------------------------------------ */
3369   case BC_FORL:
3370 #if LJ_HASJIT
3371     |  hotloop
3372 #endif
3373     |  // Fall through. Assumes BC_IFORL follows.
3374     break;
3376   case BC_JFORI:
3377   case BC_JFORL:
3378 #if !LJ_HASJIT
3379     break;
3380 #endif
3381   case BC_FORI:
3382   case BC_IFORL:
3383     |  // RA = base*8, RD = target (after end of loop or start of loop)
3384     vk = (op == BC_IFORL || op == BC_JFORL);
3385     |  add RA, BASE, RA
3386     |  evldd TMP1, FORL_IDX*8(RA)
3387     |  evldd TMP3, FORL_STEP*8(RA)
3388     |  evldd TMP2, FORL_STOP*8(RA)
3389     if (!vk) {
3390       |  evcmpgtu cr0, TMP1, TISNUM
3391       |  evcmpgtu cr7, TMP3, TISNUM
3392       |  evcmpgtu cr1, TMP2, TISNUM
3393       |  cror 4*cr0+lt, 4*cr0+lt, 4*cr7+lt
3394       |  cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3395       |  blt ->vmeta_for
3396     }
3397     if (vk) {
3398       |  efdadd TMP1, TMP1, TMP3
3399       |  evstdd TMP1, FORL_IDX*8(RA)
3400     }
3401     |   evcmpgts TMP3, TISNIL
3402     |  evstdd TMP1, FORL_EXT*8(RA)
3403     |   bge >2
3404     |  efdcmpgt TMP1, TMP2
3405     |1:
3406     if (op != BC_JFORL) {
3407       |  srwi RD, RD, 1
3408       |  add RD, PC, RD
3409       if (op == BC_JFORI) {
3410         |  addis PC, RD, -(BCBIAS_J*4 >> 16)
3411       } else {
3412         |  addis RD, RD, -(BCBIAS_J*4 >> 16)
3413       }
3414     }
3415     if (op == BC_FORI) {
3416       |  iselgt PC, RD, PC
3417     } else if (op == BC_IFORL) {
3418       |  iselgt PC, PC, RD
3419     } else {
3420       |  ble =>BC_JLOOP
3421     }
3422     |  ins_next
3423     |2:
3424     |  efdcmpgt TMP2, TMP1
3425     |  b <1
3426     break;
3428   case BC_ITERL:
3429 #if LJ_HASJIT
3430     |  hotloop
3431 #endif
3432     |  // Fall through. Assumes BC_IITERL follows.
3433     break;
3435   case BC_JITERL:
3436 #if !LJ_HASJIT
3437     break;
3438 #endif
3439   case BC_IITERL:
3440     |  // RA = base*8, RD = target
3441     |  evlddx TMP1, BASE, RA
3442     |   subi RA, RA, 8
3443     |  checknil TMP1
3444     |  checkok >1                       // Stop if iterator returned nil.
3445     if (op == BC_JITERL) {
3446       |  NYI
3447     } else {
3448       |  branch_RD                      // Otherwise save control var + branch.
3449       |  evstddx TMP1, BASE, RA
3450     }
3451     |1:
3452     |  ins_next
3453     break;
3455   case BC_LOOP:
3456     |  // RA = base*8, RD = target (loop extent)
3457     |  // Note: RA/RD is only used by trace recorder to determine scope/extent
3458     |  // This opcode does NOT jump, it's only purpose is to detect a hot loop.
3459 #if LJ_HASJIT
3460     |  hotloop
3461 #endif
3462     |  // Fall through. Assumes BC_ILOOP follows.
3463     break;
3465   case BC_ILOOP:
3466     |  // RA = base*8, RD = target (loop extent)
3467     |  ins_next
3468     break;
3470   case BC_JLOOP:
3471 #if LJ_HASJIT
3472     |  NYI
3473 #endif
3474     break;
3476   case BC_JMP:
3477     |  // RA = base*8 (only used by trace recorder), RD = target
3478     |  branch_RD
3479     |  ins_next
3480     break;
3482   /* -- Function headers -------------------------------------------------- */
3484   case BC_FUNCF:
3485 #if LJ_HASJIT
3486     |  hotcall
3487 #endif
3488   case BC_FUNCV:  /* NYI: compiled vararg functions. */
3489     |  // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow.
3490     break;
3492   case BC_JFUNCF:
3493 #if !LJ_HASJIT
3494     break;
3495 #endif
3496   case BC_IFUNCF:
3497     |  // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
3498     |  lwz TMP2, L->maxstack
3499     |   lbz TMP1, -4+PC2PROTO(numparams)(PC)
3500     |    lwz KBASE, -4+PC2PROTO(k)(PC)
3501     |  cmplw RA, TMP2
3502     |   slwi TMP1, TMP1, 3
3503     |  bgt ->vm_growstack_l
3504     |  ins_next1
3505     |2:
3506     |  cmplw NARGS8:RC, TMP1            // Check for missing parameters.
3507     |  ble >3
3508     if (op == BC_JFUNCF) {
3509       |  NYI
3510     } else {
3511       |  ins_next2
3512     }
3513     |
3514     |3:  // Clear missing parameters.
3515     |  evstddx TISNIL, BASE, NARGS8:RC
3516     |  addi NARGS8:RC, NARGS8:RC, 8
3517     |  b <2
3518     break;
3520   case BC_JFUNCV:
3521 #if !LJ_HASJIT
3522     break;
3523 #endif
3524     |  NYI  // NYI: compiled vararg functions
3525     break;  /* NYI: compiled vararg functions. */
3527   case BC_IFUNCV:
3528     |  // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
3529     |  lwz TMP2, L->maxstack
3530     |   add TMP1, BASE, RC
3531     |  add TMP0, RA, RC
3532     |   stw LFUNC:RB, 4(TMP1)           // Store copy of LFUNC.
3533     |   addi TMP3, RC, 8+FRAME_VARG
3534     |    lwz KBASE, -4+PC2PROTO(k)(PC)
3535     |  cmplw TMP0, TMP2
3536     |   stw TMP3, 0(TMP1)               // Store delta + FRAME_VARG.
3537     |  bge ->vm_growstack_l
3538     |  lbz TMP2, -4+PC2PROTO(numparams)(PC)
3539     |   mr RA, BASE
3540     |   mr RC, TMP1
3541     |  ins_next1
3542     |  cmpwi TMP2, 0
3543     |   addi BASE, TMP1, 8
3544     |  beq >3
3545     |1:
3546     |  cmplw RA, RC                     // Less args than parameters?
3547     |   evldd TMP0, 0(RA)
3548     |  bge >4
3549     |    evstdd TISNIL, 0(RA)           // Clear old fixarg slot (help the GC).
3550     |    addi RA, RA, 8
3551     |2:
3552     |  addic. TMP2, TMP2, -1
3553     |   evstdd TMP0, 8(TMP1)
3554     |    addi TMP1, TMP1, 8
3555     |  bne <1
3556     |3:
3557     |  ins_next2
3558     |
3559     |4:  // Clear missing parameters.
3560     |  evmr TMP0, TISNIL
3561     |  b <2
3562     break;
3564   case BC_FUNCC:
3565   case BC_FUNCCW:
3566     |  // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8
3567     if (op == BC_FUNCC) {
3568       |  lwz TMP3, CFUNC:RB->f
3569     } else {
3570       |  lwz TMP3, DISPATCH_GL(wrapf)(DISPATCH)
3571     }
3572     |   add TMP1, RA, NARGS8:RC
3573     |   lwz TMP2, L->maxstack
3574     |    add RC, BASE, NARGS8:RC
3575     |   stw BASE, L->base
3576     |   cmplw TMP1, TMP2
3577     |    stw RC, L->top
3578     |     li_vmstate C
3579     |  mtctr TMP3
3580     if (op == BC_FUNCCW) {
3581       |  lwz CARG2, CFUNC:RB->f
3582     }
3583     |  mr CARG1, L
3584     |   bgt ->vm_growstack_c            // Need to grow stack.
3585     |     st_vmstate
3586     |  bctrl                            // (lua_State *L [, lua_CFunction f])
3587     |  // Returns nresults.
3588     |  lwz TMP1, L->top
3589     |   slwi RD, CRET1, 3
3590     |  lwz BASE, L->base
3591     |    li_vmstate INTERP
3592     |  lwz PC, FRAME_PC(BASE)           // Fetch PC of caller.
3593     |   sub RA, TMP1, RD                // RA = L->top - nresults*8
3594     |    st_vmstate
3595     |  b ->vm_returnc
3596     break;
3598   /* ---------------------------------------------------------------------- */
3600   default:
3601     fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]);
3602     exit(2);
3603     break;
3604   }
3607 static int build_backend(BuildCtx *ctx)
3609   int op;
3611   dasm_growpc(Dst, BC__MAX);
3613   build_subroutines(ctx);
3615   |.code_op
3616   for (op = 0; op < BC__MAX; op++)
3617     build_ins(ctx, (BCOp)op, op);
3619   return BC__MAX;
3622 /* Emit pseudo frame-info for all assembler functions. */
3623 static void emit_asm_debug(BuildCtx *ctx)
3625   int i;
3626   switch (ctx->mode) {
3627   case BUILD_elfasm:
3628     fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n");
3629     fprintf(ctx->fp,
3630         ".Lframe0:\n"
3631         "\t.long .LECIE0-.LSCIE0\n"
3632         ".LSCIE0:\n"
3633         "\t.long 0xffffffff\n"
3634         "\t.byte 0x1\n"
3635         "\t.string \"\"\n"
3636         "\t.uleb128 0x1\n"
3637         "\t.sleb128 -4\n"
3638         "\t.byte 65\n"
3639         "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
3640         "\t.align 2\n"
3641         ".LECIE0:\n\n");
3642     fprintf(ctx->fp,
3643         ".LSFDE0:\n"
3644         "\t.long .LEFDE0-.LASFDE0\n"
3645         ".LASFDE0:\n"
3646         "\t.long .Lframe0\n"
3647         "\t.long .Lbegin\n"
3648         "\t.long %d\n"
3649         "\t.byte 0xe\n\t.uleb128 %d\n"
3650         "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
3651         "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n",
3652         (int)ctx->codesz, CFRAME_SIZE);
3653     for (i = 14; i <= 31; i++)
3654       fprintf(ctx->fp,
3655         "\t.byte %d\n\t.uleb128 %d\n"
3656         "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n",
3657         0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i));
3658     fprintf(ctx->fp,
3659         "\t.align 2\n"
3660         ".LEFDE0:\n\n");
3661     fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
3662     fprintf(ctx->fp,
3663         ".Lframe1:\n"
3664         "\t.long .LECIE1-.LSCIE1\n"
3665         ".LSCIE1:\n"
3666         "\t.long 0\n"
3667         "\t.byte 0x1\n"
3668         "\t.string \"zPR\"\n"
3669         "\t.uleb128 0x1\n"
3670         "\t.sleb128 -4\n"
3671         "\t.byte 65\n"
3672         "\t.uleb128 6\n"                        /* augmentation length */
3673         "\t.byte 0x1b\n"                        /* pcrel|sdata4 */
3674         "\t.long lj_err_unwind_dwarf-.\n"
3675         "\t.byte 0x1b\n"                        /* pcrel|sdata4 */
3676         "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
3677         "\t.align 2\n"
3678         ".LECIE1:\n\n");
3679     fprintf(ctx->fp,
3680         ".LSFDE1:\n"
3681         "\t.long .LEFDE1-.LASFDE1\n"
3682         ".LASFDE1:\n"
3683         "\t.long .LASFDE1-.Lframe1\n"
3684         "\t.long .Lbegin-.\n"
3685         "\t.long %d\n"
3686         "\t.uleb128 0\n"                        /* augmentation length */
3687         "\t.byte 0xe\n\t.uleb128 %d\n"
3688         "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
3689         "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n",
3690         (int)ctx->codesz, CFRAME_SIZE);
3691     for (i = 14; i <= 31; i++)
3692       fprintf(ctx->fp,
3693         "\t.byte %d\n\t.uleb128 %d\n"
3694         "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n",
3695         0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i));
3696     fprintf(ctx->fp,
3697         "\t.align 2\n"
3698         ".LEFDE1:\n\n");
3699     break;
3700   default:
3701     break;
3702   }