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