Initialize uv->immutable for upvalues of loaded chunks.
[luajit-2.0.git] / src / vm_ppcspe.dasc
blob002837f8f7c560c321f60d8207bab8129633ce53
1 |// Low-level VM code for PowerPC/e500 CPUs.
2 |// Bytecode interpreter, fast functions and helper functions.
3 |// Copyright (C) 2005-2016 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@plt
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@plt
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@plt
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@plt
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@plt
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@plt
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   |  evmergelo CARG2, CARG1, CARG2
2042   |  bl ->vm_floor_hilo
2043   |  mtlr CARG3
2044   |  evmergehi CRET1, CRET2, CRET2
2045   |  blr
2046   |
2047   |  vm_round vm_floor, 0
2048   |  vm_round vm_ceil,  1
2049   |.if JIT
2050   |  vm_round vm_trunc, 2
2051   |.else
2052   |->vm_trunc_efd:
2053   |->vm_trunc_hilo:
2054   |.endif
2055   |
2056   |//-----------------------------------------------------------------------
2057   |//-- Miscellaneous functions --------------------------------------------
2058   |//-----------------------------------------------------------------------
2059   |
2060   |//-----------------------------------------------------------------------
2061   |//-- FFI helper functions -----------------------------------------------
2062   |//-----------------------------------------------------------------------
2063   |
2064   |->vm_ffi_call:
2065   |.if FFI
2066   |  NYI
2067   |.endif
2068   |
2069   |//-----------------------------------------------------------------------
2072 /* Generate the code for a single instruction. */
2073 static void build_ins(BuildCtx *ctx, BCOp op, int defop)
2075   int vk = 0;
2076   |=>defop:
2078   switch (op) {
2080   /* -- Comparison ops ---------------------------------------------------- */
2082   /* Remember: all ops branch for a true comparison, fall through otherwise. */
2084   case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
2085     |  // RA = src1*8, RD = src2*8, JMP with RD = target
2086     |  evlddx TMP0, BASE, RA
2087     |   addi PC, PC, 4
2088     |  evlddx TMP1, BASE, RD
2089     |   addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2090     |   lwz TMP2, -4(PC)
2091     |  evmergehi RB, TMP0, TMP1
2092     |   decode_RD4 TMP2, TMP2
2093     |  checknum RB
2094     |   add TMP2, TMP2, TMP3
2095     |  checkanyfail ->vmeta_comp
2096     |  efdcmplt TMP0, TMP1
2097     if (op == BC_ISLE || op == BC_ISGT) {
2098       |  efdcmpeq cr1, TMP0, TMP1
2099       |  cror 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
2100     }
2101     if (op == BC_ISLT || op == BC_ISLE) {
2102       |  iselgt PC, TMP2, PC
2103     } else {
2104       |  iselgt PC, PC, TMP2
2105     }
2106     |  ins_next
2107     break;
2109   case BC_ISEQV: case BC_ISNEV:
2110     vk = op == BC_ISEQV;
2111     |  // RA = src1*8, RD = src2*8, JMP with RD = target
2112     |  evlddx CARG2, BASE, RA
2113     |   addi PC, PC, 4
2114     |  evlddx CARG3, BASE, RD
2115     |   addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2116     |   lwz TMP2, -4(PC)
2117     |  evmergehi RB, CARG2, CARG3
2118     |   decode_RD4 TMP2, TMP2
2119     |  checknum RB
2120     |   add TMP2, TMP2, TMP3
2121     |  checkanyfail >5
2122     |  efdcmpeq CARG2, CARG3
2123     if (vk) {
2124       |  iselgt PC, TMP2, PC
2125     } else {
2126       |  iselgt PC, PC, TMP2
2127     }
2128     |1:
2129     |  ins_next
2130     |
2131     |5:  // Either or both types are not numbers.
2132     |  evcmpeq CARG2, CARG3
2133     |   not TMP3, RB
2134     |   cmplwi cr1, TMP3, ~LJ_TISPRI            // Primitive?
2135     |  crorc 4*cr7+lt, 4*cr0+so, 4*cr0+lt       // 1: Same tv or different type.
2136     |   cmplwi cr6, TMP3, ~LJ_TISTABUD          // Table or userdata?
2137     |  crandc 4*cr7+gt, 4*cr0+lt, 4*cr1+gt      // 2: Same type and primitive.
2138     |   mr SAVE0, PC
2139     if (vk) {
2140       |  isel PC, TMP2, PC, 4*cr7+gt
2141     } else {
2142       |  isel TMP2, PC, TMP2, 4*cr7+gt
2143     }
2144     |  cror 4*cr7+lt, 4*cr7+lt, 4*cr7+gt        // 1 or 2.
2145     if (vk) {
2146       |  isel PC, TMP2, PC, 4*cr0+so
2147     } else {
2148       |  isel PC, PC, TMP2, 4*cr0+so
2149     }
2150     |  blt cr7, <1                      // Done if 1 or 2.
2151     |  blt cr6, <1                      // Done if not tab/ud.
2152     |
2153     |  // Different tables or userdatas. Need to check __eq metamethod.
2154     |  // Field metatable must be at same offset for GCtab and GCudata!
2155     |  lwz TAB:TMP2, TAB:CARG2->metatable
2156     |   li CARG4, 1-vk                  // ne = 0 or 1.
2157     |  cmplwi TAB:TMP2, 0
2158     |  beq <1                           // No metatable?
2159     |  lbz TMP2, TAB:TMP2->nomm
2160     |  andi. TMP2, TMP2, 1<<MM_eq
2161     |  bne <1                           // Or 'no __eq' flag set?
2162     |  mr PC, SAVE0                     // Restore old PC.
2163     |  b ->vmeta_equal                  // Handle __eq metamethod.
2164     break;
2166   case BC_ISEQS: case BC_ISNES:
2167     vk = op == BC_ISEQS;
2168     |  // RA = src*8, RD = str_const*8 (~), JMP with RD = target
2169     |  evlddx TMP0, BASE, RA
2170     |   srwi RD, RD, 1
2171     |    lwz INS, 0(PC)
2172     |   subfic RD, RD, -4
2173     |    addi PC, PC, 4
2174     |   lwzx STR:TMP1, KBASE, RD        // KBASE-4-str_const*4
2175     |    addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2176     |    decode_RD4 TMP2, INS
2177     |   evmergelo STR:TMP1, TISSTR, STR:TMP1
2178     |    add TMP2, TMP2, TMP3
2179     |  evcmpeq TMP0, STR:TMP1
2180     if (vk) {
2181       |  isel PC, TMP2, PC, 4*cr0+so
2182     } else {
2183       |  isel PC, PC, TMP2, 4*cr0+so
2184     }
2185     |  ins_next
2186     break;
2188   case BC_ISEQN: case BC_ISNEN:
2189     vk = op == BC_ISEQN;
2190     |  // RA = src*8, RD = num_const*8, JMP with RD = target
2191     |  evlddx TMP0, BASE, RA
2192     |   addi PC, PC, 4
2193     |  evlddx TMP1, KBASE, RD
2194     |   addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2195     |   lwz INS, -4(PC)
2196     |  checknum TMP0
2197     |  checkfail >5
2198     |  efdcmpeq TMP0, TMP1
2199     |1:
2200     |   decode_RD4 TMP2, INS
2201     |   add TMP2, TMP2, TMP3
2202     if (vk) {
2203       |  iselgt PC, TMP2, PC
2204       |5:
2205     } else {
2206       |  iselgt PC, PC, TMP2
2207     }
2208     |3:
2209     |  ins_next
2210     if (!vk) {
2211       |5:
2212       |  decode_RD4 TMP2, INS
2213       |  add PC, TMP2, TMP3
2214       |  b <3
2215     }
2216     break;
2218   case BC_ISEQP: case BC_ISNEP:
2219     vk = op == BC_ISEQP;
2220     |  // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target
2221     |  lwzx TMP0, BASE, RA
2222     |   srwi TMP1, RD, 3
2223     |    lwz INS, 0(PC)
2224     |    addi PC, PC, 4
2225     |   not TMP1, TMP1
2226     |    addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2227     |  cmplw TMP0, TMP1
2228     |    decode_RD4 TMP2, INS
2229     |    add TMP2, TMP2, TMP3
2230     if (vk) {
2231       |  iseleq PC, TMP2, PC
2232     } else {
2233       |  iseleq PC, PC, TMP2
2234     }
2235     |  ins_next
2236     break;
2238   /* -- Unary test and copy ops ------------------------------------------- */
2240   case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF:
2241     |  // RA = dst*8 or unused, RD = src*8, JMP with RD = target
2242     |  evlddx TMP0, BASE, RD
2243     |   evaddw TMP1, TISNIL, TISNIL     // Synthesize LJ_TFALSE.
2244     |   lwz INS, 0(PC)
2245     |  evcmpltu TMP0, TMP1
2246     |   addi PC, PC, 4
2247     if (op == BC_IST || op == BC_ISF) {
2248       |  addis TMP3, PC, -(BCBIAS_J*4 >> 16)
2249       |  decode_RD4 TMP2, INS
2250       |  add TMP2, TMP2, TMP3
2251       if (op == BC_IST) {
2252         |  isellt PC, TMP2, PC
2253       } else {
2254         |  isellt PC, PC, TMP2
2255       }
2256     } else {
2257       if (op == BC_ISTC) {
2258         |  checkfail >1
2259       } else {
2260         |  checkok >1
2261       }
2262       |  addis PC, PC, -(BCBIAS_J*4 >> 16)
2263       |  decode_RD4 TMP2, INS
2264       |   evstddx TMP0, BASE, RA
2265       |  add PC, PC, TMP2
2266       |1:
2267     }
2268     |  ins_next
2269     break;
2271   /* -- Unary ops --------------------------------------------------------- */
2273   case BC_MOV:
2274     |  // RA = dst*8, RD = src*8
2275     |  ins_next1
2276     |  evlddx TMP0, BASE, RD
2277     |  evstddx TMP0, BASE, RA
2278     |  ins_next2
2279     break;
2280   case BC_NOT:
2281     |  // RA = dst*8, RD = src*8
2282     |  ins_next1
2283     |  lwzx TMP0, BASE, RD
2284     |  subfic TMP1, TMP0, LJ_TTRUE
2285     |  adde TMP0, TMP0, TMP1
2286     |  stwx TMP0, BASE, RA
2287     |  ins_next2
2288     break;
2289   case BC_UNM:
2290     |  // RA = dst*8, RD = src*8
2291     |  evlddx TMP0, BASE, RD
2292     |  checknum TMP0
2293     |  checkfail ->vmeta_unm
2294     |  efdneg TMP0, TMP0
2295     |  ins_next1
2296     |  evstddx TMP0, BASE, RA
2297     |  ins_next2
2298     break;
2299   case BC_LEN:
2300     |  // RA = dst*8, RD = src*8
2301     |  evlddx CARG1, BASE, RD
2302     |  checkstr CARG1
2303     |  checkfail >2
2304     |  lwz CRET1, STR:CARG1->len
2305     |1:
2306     |  ins_next1
2307     |  efdcfsi TMP0, CRET1
2308     |  evstddx TMP0, BASE, RA
2309     |  ins_next2
2310     |2:
2311     |  checktab CARG1
2312     |  checkfail ->vmeta_len
2313 #if LJ_52
2314     |  lwz TAB:TMP2, TAB:CARG1->metatable
2315     |  cmplwi TAB:TMP2, 0
2316     |  bne >9
2317     |3:
2318 #endif
2319     |->BC_LEN_Z:
2320     |  bl extern lj_tab_len             // (GCtab *t)
2321     |  // Returns uint32_t (but less than 2^31).
2322     |  b <1
2323 #if LJ_52
2324     |9:
2325     |  lbz TMP0, TAB:TMP2->nomm
2326     |  andi. TMP0, TMP0, 1<<MM_len
2327     |  bne <3                           // 'no __len' flag set: done.
2328     |  b ->vmeta_len
2329 #endif
2330     break;
2332   /* -- Binary ops -------------------------------------------------------- */
2334     |.macro ins_arithpre, t0, t1
2335     |  // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
2336     ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
2337     ||switch (vk) {
2338     ||case 0:
2339     |   evlddx t0, BASE, RB
2340     |    checknum t0
2341     |   evlddx t1, KBASE, RC
2342     |    checkfail ->vmeta_arith_vn
2343     ||  break;
2344     ||case 1:
2345     |   evlddx t1, BASE, RB
2346     |    checknum t1
2347     |   evlddx t0, KBASE, RC
2348     |    checkfail ->vmeta_arith_nv
2349     ||  break;
2350     ||default:
2351     |   evlddx t0, BASE, RB
2352     |   evlddx t1, BASE, RC
2353     |    evmergehi TMP2, t0, t1
2354     |    checknum TMP2
2355     |    checkanyfail ->vmeta_arith_vv
2356     ||  break;
2357     ||}
2358     |.endmacro
2359     |
2360     |.macro ins_arith, ins
2361     |  ins_arithpre TMP0, TMP1
2362     |  ins_next1
2363     |  ins TMP0, TMP0, TMP1
2364     |  evstddx TMP0, BASE, RA
2365     |  ins_next2
2366     |.endmacro
2368   case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
2369     |  ins_arith efdadd
2370     break;
2371   case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
2372     |  ins_arith efdsub
2373     break;
2374   case BC_MULVN: case BC_MULNV: case BC_MULVV:
2375     |  ins_arith efdmul
2376     break;
2377   case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
2378     |  ins_arith efddiv
2379     break;
2380   case BC_MODVN:
2381     |  ins_arithpre RD, SAVE0
2382     |->BC_MODVN_Z:
2383     |  efddiv CARG2, RD, SAVE0
2384     |  bl ->vm_floor_efd                // floor(b/c)
2385     |  efdmul TMP0, CRET2, SAVE0
2386     |  ins_next1
2387     |  efdsub TMP0, RD, TMP0            // b - floor(b/c)*c
2388     |  evstddx TMP0, BASE, RA
2389     |  ins_next2
2390     break;
2391   case BC_MODNV: case BC_MODVV:
2392     |  ins_arithpre RD, SAVE0
2393     |  b ->BC_MODVN_Z                   // Avoid 3 copies. It's slow anyway.
2394     break;
2395   case BC_POW:
2396     |  evlddx CARG2, BASE, RB
2397     |  evlddx CARG4, BASE, RC
2398     |  evmergehi CARG1, CARG4, CARG2
2399     |  checknum CARG1
2400     |   evmergehi CARG3, CARG4, CARG4
2401     |  checkanyfail ->vmeta_arith_vv
2402     |  bl extern pow@plt
2403     |  evmergelo CRET2, CRET1, CRET2
2404     |  evstddx CRET2, BASE, RA
2405     |  ins_next
2406     break;
2408   case BC_CAT:
2409     |  // RA = dst*8, RB = src_start*8, RC = src_end*8
2410     |  sub CARG3, RC, RB
2411     |   stw BASE, L->base
2412     |  add CARG2, BASE, RC
2413     |  mr SAVE0, RB
2414     |->BC_CAT_Z:
2415     |   stw PC, SAVE_PC
2416     |  mr CARG1, L
2417     |  srwi CARG3, CARG3, 3
2418     |  bl extern lj_meta_cat            // (lua_State *L, TValue *top, int left)
2419     |  // Returns NULL (finished) or TValue * (metamethod).
2420     |  cmplwi CRET1, 0
2421     |   lwz BASE, L->base
2422     |  bne ->vmeta_binop
2423     |  evlddx TMP0, BASE, SAVE0         // Copy result from RB to RA.
2424     |  evstddx TMP0, BASE, RA
2425     |  ins_next
2426     break;
2428   /* -- Constant ops ------------------------------------------------------ */
2430   case BC_KSTR:
2431     |  // RA = dst*8, RD = str_const*8 (~)
2432     |  ins_next1
2433     |  srwi TMP1, RD, 1
2434     |  subfic TMP1, TMP1, -4
2435     |  lwzx TMP0, KBASE, TMP1           // KBASE-4-str_const*4
2436     |  evmergelo TMP0, TISSTR, TMP0
2437     |  evstddx TMP0, BASE, RA
2438     |  ins_next2
2439     break;
2440   case BC_KCDATA:
2441     |.if FFI
2442     |  // RA = dst*8, RD = cdata_const*8 (~)
2443     |  ins_next1
2444     |  srwi TMP1, RD, 1
2445     |  subfic TMP1, TMP1, -4
2446     |  lwzx TMP0, KBASE, TMP1           // KBASE-4-cdata_const*4
2447     |  li TMP2, LJ_TCDATA
2448     |  evmergelo TMP0, TMP2, TMP0
2449     |  evstddx TMP0, BASE, RA
2450     |  ins_next2
2451     |.endif
2452     break;
2453   case BC_KSHORT:
2454     |  // RA = dst*8, RD = int16_literal*8
2455     |  srwi TMP1, RD, 3
2456     |  extsh TMP1, TMP1
2457     |  ins_next1
2458     |  efdcfsi TMP0, TMP1
2459     |  evstddx TMP0, BASE, RA
2460     |  ins_next2
2461     break;
2462   case BC_KNUM:
2463     |  // RA = dst*8, RD = num_const*8
2464     |  evlddx TMP0, KBASE, RD
2465     |  ins_next1
2466     |  evstddx TMP0, BASE, RA
2467     |  ins_next2
2468     break;
2469   case BC_KPRI:
2470     |  // RA = dst*8, RD = primitive_type*8 (~)
2471     |  srwi TMP1, RD, 3
2472     |  not TMP0, TMP1
2473     |  ins_next1
2474     |  stwx TMP0, BASE, RA
2475     |  ins_next2
2476     break;
2477   case BC_KNIL:
2478     |  // RA = base*8, RD = end*8
2479     |  evstddx TISNIL, BASE, RA
2480     |   addi RA, RA, 8
2481     |1:
2482     |  evstddx TISNIL, BASE, RA
2483     |  cmpw RA, RD
2484     |   addi RA, RA, 8
2485     |  blt <1
2486     |  ins_next_
2487     break;
2489   /* -- Upvalue and function ops ------------------------------------------ */
2491   case BC_UGET:
2492     |  // RA = dst*8, RD = uvnum*8
2493     |  ins_next1
2494     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2495     |   srwi RD, RD, 1
2496     |   addi RD, RD, offsetof(GCfuncL, uvptr)
2497     |  lwzx UPVAL:RB, LFUNC:RB, RD
2498     |  lwz TMP1, UPVAL:RB->v
2499     |  evldd TMP0, 0(TMP1)
2500     |  evstddx TMP0, BASE, RA
2501     |  ins_next2
2502     break;
2503   case BC_USETV:
2504     |  // RA = uvnum*8, RD = src*8
2505     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2506     |    srwi RA, RA, 1
2507     |    addi RA, RA, offsetof(GCfuncL, uvptr)
2508     |   evlddx TMP1, BASE, RD
2509     |  lwzx UPVAL:RB, LFUNC:RB, RA
2510     |  lbz TMP3, UPVAL:RB->marked
2511     |   lwz CARG2, UPVAL:RB->v
2512     |  andi. TMP3, TMP3, LJ_GC_BLACK    // isblack(uv)
2513     |    lbz TMP0, UPVAL:RB->closed
2514     |   evmergehi TMP2, TMP1, TMP1
2515     |   evstdd TMP1, 0(CARG2)
2516     |    cmplwi cr1, TMP0, 0
2517     |  cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
2518     |   subi TMP2, TMP2, (LJ_TISNUM+1)
2519     |  bne >2                           // Upvalue is closed and black?
2520     |1:
2521     |  ins_next
2522     |
2523     |2:  // Check if new value is collectable.
2524     |  cmplwi TMP2, LJ_TISGCV - (LJ_TISNUM+1)
2525     |  bge <1                           // tvisgcv(v)
2526     |  lbz TMP3, GCOBJ:TMP1->gch.marked
2527     |  andi. TMP3, TMP3, LJ_GC_WHITES   // iswhite(v)
2528     |   la CARG1, GG_DISP2G(DISPATCH)
2529     |  // Crossed a write barrier. Move the barrier forward.
2530     |  beq <1
2531     |  bl extern lj_gc_barrieruv        // (global_State *g, TValue *tv)
2532     |  b <1
2533     break;
2534   case BC_USETS:
2535     |  // RA = uvnum*8, RD = str_const*8 (~)
2536     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2537     |   srwi TMP1, RD, 1
2538     |    srwi RA, RA, 1
2539     |   subfic TMP1, TMP1, -4
2540     |    addi RA, RA, offsetof(GCfuncL, uvptr)
2541     |   lwzx STR:TMP1, KBASE, TMP1      // KBASE-4-str_const*4
2542     |  lwzx UPVAL:RB, LFUNC:RB, RA
2543     |   evmergelo STR:TMP1, TISSTR, STR:TMP1
2544     |  lbz TMP3, UPVAL:RB->marked
2545     |   lwz CARG2, UPVAL:RB->v
2546     |  andi. TMP3, TMP3, LJ_GC_BLACK    // isblack(uv)
2547     |   lbz TMP3, STR:TMP1->marked
2548     |   lbz TMP2, UPVAL:RB->closed
2549     |   evstdd STR:TMP1, 0(CARG2)
2550     |  bne >2
2551     |1:
2552     |  ins_next
2553     |
2554     |2:  // Check if string is white and ensure upvalue is closed.
2555     |  andi. TMP3, TMP3, LJ_GC_WHITES   // iswhite(str)
2556     |   cmplwi cr1, TMP2, 0
2557     |  cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
2558     |   la CARG1, GG_DISP2G(DISPATCH)
2559     |  // Crossed a write barrier. Move the barrier forward.
2560     |  beq <1
2561     |  bl extern lj_gc_barrieruv        // (global_State *g, TValue *tv)
2562     |  b <1
2563     break;
2564   case BC_USETN:
2565     |  // RA = uvnum*8, RD = num_const*8
2566     |  ins_next1
2567     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2568     |   srwi RA, RA, 1
2569     |   addi RA, RA, offsetof(GCfuncL, uvptr)
2570     |    evlddx TMP0, KBASE, RD
2571     |  lwzx UPVAL:RB, LFUNC:RB, RA
2572     |  lwz TMP1, UPVAL:RB->v
2573     |  evstdd TMP0, 0(TMP1)
2574     |  ins_next2
2575     break;
2576   case BC_USETP:
2577     |  // RA = uvnum*8, RD = primitive_type*8 (~)
2578     |  ins_next1
2579     |  lwz LFUNC:RB, FRAME_FUNC(BASE)
2580     |   srwi RA, RA, 1
2581     |   addi RA, RA, offsetof(GCfuncL, uvptr)
2582     |    srwi TMP0, RD, 3
2583     |  lwzx UPVAL:RB, LFUNC:RB, RA
2584     |    not TMP0, TMP0
2585     |  lwz TMP1, UPVAL:RB->v
2586     |  stw TMP0, 0(TMP1)
2587     |  ins_next2
2588     break;
2590   case BC_UCLO:
2591     |  // RA = level*8, RD = target
2592     |  lwz TMP1, L->openupval
2593     |  branch_RD                        // Do this first since RD is not saved.
2594     |   stw BASE, L->base
2595     |  cmplwi TMP1, 0
2596     |   mr CARG1, L
2597     |  beq >1
2598     |   add CARG2, BASE, RA
2599     |  bl extern lj_func_closeuv        // (lua_State *L, TValue *level)
2600     |  lwz BASE, L->base
2601     |1:
2602     |  ins_next
2603     break;
2605   case BC_FNEW:
2606     |  // RA = dst*8, RD = proto_const*8 (~) (holding function prototype)
2607     |  srwi TMP1, RD, 1
2608     |   stw BASE, L->base
2609     |  subfic TMP1, TMP1, -4
2610     |   stw PC, SAVE_PC
2611     |  lwzx CARG2, KBASE, TMP1          // KBASE-4-tab_const*4
2612     |   mr CARG1, L
2613     |  lwz CARG3, FRAME_FUNC(BASE)
2614     |  // (lua_State *L, GCproto *pt, GCfuncL *parent)
2615     |  bl extern lj_func_newL_gc
2616     |  // Returns GCfuncL *.
2617     |  lwz BASE, L->base
2618     |  evmergelo LFUNC:CRET1, TISFUNC, LFUNC:CRET1
2619     |  evstddx LFUNC:CRET1, BASE, RA
2620     |  ins_next
2621     break;
2623   /* -- Table ops --------------------------------------------------------- */
2625   case BC_TNEW:
2626   case BC_TDUP:
2627     |  // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~)
2628     |  lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH)
2629     |   mr CARG1, L
2630     |  lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
2631     |   stw BASE, L->base
2632     |  cmplw TMP0, TMP1
2633     |   stw PC, SAVE_PC
2634     |  bge >5
2635     |1:
2636     if (op == BC_TNEW) {
2637       |  rlwinm CARG2, RD, 29, 21, 31
2638       |  rlwinm CARG3, RD, 18, 27, 31
2639       |  cmpwi CARG2, 0x7ff
2640       |   li TMP1, 0x801
2641       |  iseleq CARG2, TMP1, CARG2
2642       |  bl extern lj_tab_new  // (lua_State *L, int32_t asize, uint32_t hbits)
2643       |  // Returns Table *.
2644     } else {
2645       |  srwi TMP1, RD, 1
2646       |  subfic TMP1, TMP1, -4
2647       |  lwzx CARG2, KBASE, TMP1                // KBASE-4-tab_const*4
2648       |  bl extern lj_tab_dup  // (lua_State *L, Table *kt)
2649       |  // Returns Table *.
2650     }
2651     |  lwz BASE, L->base
2652     |  evmergelo TAB:CRET1, TISTAB, TAB:CRET1
2653     |  evstddx TAB:CRET1, BASE, RA
2654     |  ins_next
2655     |5:
2656     |  mr SAVE0, RD
2657     |  bl extern lj_gc_step_fixtop  // (lua_State *L)
2658     |  mr RD, SAVE0
2659     |  mr CARG1, L
2660     |  b <1
2661     break;
2663   case BC_GGET:
2664     |  // RA = dst*8, RD = str_const*8 (~)
2665   case BC_GSET:
2666     |  // RA = src*8, RD = str_const*8 (~)
2667     |  lwz LFUNC:TMP2, FRAME_FUNC(BASE)
2668     |   srwi TMP1, RD, 1
2669     |  lwz TAB:RB, LFUNC:TMP2->env
2670     |   subfic TMP1, TMP1, -4
2671     |   lwzx STR:RC, KBASE, TMP1        // KBASE-4-str_const*4
2672     if (op == BC_GGET) {
2673       |  b ->BC_TGETS_Z
2674     } else {
2675       |  b ->BC_TSETS_Z
2676     }
2677     break;
2679   case BC_TGETV:
2680     |  // RA = dst*8, RB = table*8, RC = key*8
2681     |  evlddx TAB:RB, BASE, RB
2682     |   evlddx RC, BASE, RC
2683     |  checktab TAB:RB
2684     |  checkfail ->vmeta_tgetv
2685     |  checknum RC
2686     |  checkfail >5
2687     |  // Convert number key to integer
2688     |  efdctsi TMP2, RC
2689     |   lwz TMP0, TAB:RB->asize
2690     |  efdcfsi TMP1, TMP2
2691     |   cmplw cr0, TMP0, TMP2
2692     |  efdcmpeq cr1, RC, TMP1
2693     |   lwz TMP1, TAB:RB->array
2694     |  crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
2695     |   slwi TMP2, TMP2, 3
2696     |  ble ->vmeta_tgetv                // Integer key and in array part?
2697     |  evlddx TMP1, TMP1, TMP2
2698     |  checknil TMP1
2699     |  checkok >2
2700     |1:
2701     |  evstddx TMP1, BASE, RA
2702     |  ins_next
2703     |
2704     |2:  // Check for __index if table value is nil.
2705     |  lwz TAB:TMP2, TAB:RB->metatable
2706     |  cmplwi TAB:TMP2, 0
2707     |  beq <1                           // No metatable: done.
2708     |  lbz TMP0, TAB:TMP2->nomm
2709     |  andi. TMP0, TMP0, 1<<MM_index
2710     |  bne <1                           // 'no __index' flag set: done.
2711     |  b ->vmeta_tgetv
2712     |
2713     |5:
2714     |  checkstr STR:RC                  // String key?
2715     |  checkok ->BC_TGETS_Z
2716     |  b ->vmeta_tgetv
2717     break;
2718   case BC_TGETS:
2719     |  // RA = dst*8, RB = table*8, RC = str_const*8 (~)
2720     |  evlddx TAB:RB, BASE, RB
2721     |   srwi TMP1, RC, 1
2722     |  checktab TAB:RB
2723     |   subfic TMP1, TMP1, -4
2724     |   lwzx STR:RC, KBASE, TMP1        // KBASE-4-str_const*4
2725     |  checkfail ->vmeta_tgets1
2726     |->BC_TGETS_Z:
2727     |  // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8
2728     |  lwz TMP0, TAB:RB->hmask
2729     |  lwz TMP1, STR:RC->hash
2730     |  lwz NODE:TMP2, TAB:RB->node
2731     |   evmergelo STR:RC, TISSTR, STR:RC
2732     |  and TMP1, TMP1, TMP0             // idx = str->hash & tab->hmask
2733     |  slwi TMP0, TMP1, 5
2734     |  slwi TMP1, TMP1, 3
2735     |  sub TMP1, TMP0, TMP1
2736     |  add NODE:TMP2, NODE:TMP2, TMP1   // node = tab->node + (idx*32-idx*8)
2737     |1:
2738     |  evldd TMP0, NODE:TMP2->key
2739     |   evldd TMP1, NODE:TMP2->val
2740     |  evcmpeq TMP0, STR:RC
2741     |  checkanyfail >4
2742     |   checknil TMP1
2743     |   checkok >5                      // Key found, but nil value?
2744     |3:
2745     |   evstddx TMP1, BASE, RA
2746     |  ins_next
2747     |
2748     |4:  // Follow hash chain.
2749     |  lwz NODE:TMP2, NODE:TMP2->next
2750     |  cmplwi NODE:TMP2, 0
2751     |  bne <1
2752     |  // End of hash chain: key not found, nil result.
2753     |   evmr TMP1, TISNIL
2754     |
2755     |5:  // Check for __index if table value is nil.
2756     |  lwz TAB:TMP2, TAB:RB->metatable
2757     |  cmplwi TAB:TMP2, 0
2758     |  beq <3                           // No metatable: done.
2759     |  lbz TMP0, TAB:TMP2->nomm
2760     |  andi. TMP0, TMP0, 1<<MM_index
2761     |  bne <3                           // 'no __index' flag set: done.
2762     |  b ->vmeta_tgets
2763     break;
2764   case BC_TGETB:
2765     |  // RA = dst*8, RB = table*8, RC = index*8
2766     |  evlddx TAB:RB, BASE, RB
2767     |   srwi TMP0, RC, 3
2768     |  checktab TAB:RB
2769     |  checkfail ->vmeta_tgetb
2770     |  lwz TMP1, TAB:RB->asize
2771     |   lwz TMP2, TAB:RB->array
2772     |  cmplw TMP0, TMP1
2773     |  bge ->vmeta_tgetb
2774     |  evlddx TMP1, TMP2, RC
2775     |  checknil TMP1
2776     |  checkok >5
2777     |1:
2778     |  ins_next1
2779     |  evstddx TMP1, BASE, RA
2780     |  ins_next2
2781     |
2782     |5:  // Check for __index if table value is nil.
2783     |  lwz TAB:TMP2, TAB:RB->metatable
2784     |  cmplwi TAB:TMP2, 0
2785     |  beq <1                           // No metatable: done.
2786     |  lbz TMP2, TAB:TMP2->nomm
2787     |  andi. TMP2, TMP2, 1<<MM_index
2788     |  bne <1                           // 'no __index' flag set: done.
2789     |  b ->vmeta_tgetb                  // Caveat: preserve TMP0!
2790     break;
2792   case BC_TSETV:
2793     |  // RA = src*8, RB = table*8, RC = key*8
2794     |  evlddx TAB:RB, BASE, RB
2795     |   evlddx RC, BASE, RC
2796     |  checktab TAB:RB
2797     |  checkfail ->vmeta_tsetv
2798     |  checknum RC
2799     |  checkfail >5
2800     |  // Convert number key to integer
2801     |  efdctsi TMP2, RC
2802     |    evlddx SAVE0, BASE, RA
2803     |   lwz TMP0, TAB:RB->asize
2804     |  efdcfsi TMP1, TMP2
2805     |   cmplw cr0, TMP0, TMP2
2806     |  efdcmpeq cr1, RC, TMP1
2807     |   lwz TMP1, TAB:RB->array
2808     |  crand 4*cr0+gt, 4*cr0+gt, 4*cr1+gt
2809     |   slwi TMP0, TMP2, 3
2810     |  ble ->vmeta_tsetv                // Integer key and in array part?
2811     |   lbz TMP3, TAB:RB->marked
2812     |  evlddx TMP2, TMP1, TMP0
2813     |  checknil TMP2
2814     |  checkok >3
2815     |1:
2816     |  andi. TMP2, TMP3, LJ_GC_BLACK    // isblack(table)
2817     |   evstddx SAVE0, TMP1, TMP0
2818     |  bne >7
2819     |2:
2820     |  ins_next
2821     |
2822     |3:  // Check for __newindex if previous value is nil.
2823     |  lwz TAB:TMP2, TAB:RB->metatable
2824     |  cmplwi TAB:TMP2, 0
2825     |  beq <1                           // No metatable: done.
2826     |  lbz TMP2, TAB:TMP2->nomm
2827     |  andi. TMP2, TMP2, 1<<MM_newindex
2828     |  bne <1                           // 'no __newindex' flag set: done.
2829     |  b ->vmeta_tsetv
2830     |
2831     |5:
2832     |  checkstr STR:RC                  // String key?
2833     |  checkok ->BC_TSETS_Z
2834     |  b ->vmeta_tsetv
2835     |
2836     |7:  // Possible table write barrier for the value. Skip valiswhite check.
2837     |  barrierback TAB:RB, TMP3, TMP0
2838     |  b <2
2839     break;
2840   case BC_TSETS:
2841     |  // RA = src*8, RB = table*8, RC = str_const*8 (~)
2842     |  evlddx TAB:RB, BASE, RB
2843     |   srwi TMP1, RC, 1
2844     |  checktab TAB:RB
2845     |   subfic TMP1, TMP1, -4
2846     |   lwzx STR:RC, KBASE, TMP1        // KBASE-4-str_const*4
2847     |  checkfail ->vmeta_tsets1
2848     |->BC_TSETS_Z:
2849     |  // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8
2850     |  lwz TMP0, TAB:RB->hmask
2851     |  lwz TMP1, STR:RC->hash
2852     |  lwz NODE:TMP2, TAB:RB->node
2853     |   evmergelo STR:RC, TISSTR, STR:RC
2854     |    stb ZERO, TAB:RB->nomm         // Clear metamethod cache.
2855     |  and TMP1, TMP1, TMP0             // idx = str->hash & tab->hmask
2856     |    evlddx SAVE0, BASE, RA
2857     |  slwi TMP0, TMP1, 5
2858     |  slwi TMP1, TMP1, 3
2859     |  sub TMP1, TMP0, TMP1
2860     |    lbz TMP3, TAB:RB->marked
2861     |  add NODE:TMP2, NODE:TMP2, TMP1   // node = tab->node + (idx*32-idx*8)
2862     |1:
2863     |  evldd TMP0, NODE:TMP2->key
2864     |   evldd TMP1, NODE:TMP2->val
2865     |  evcmpeq TMP0, STR:RC
2866     |  checkanyfail >5
2867     |   checknil TMP1
2868     |   checkok >4                      // Key found, but nil value?
2869     |2:
2870     |  andi. TMP0, TMP3, LJ_GC_BLACK    // isblack(table)
2871     |    evstdd SAVE0, NODE:TMP2->val
2872     |  bne >7
2873     |3:
2874     |  ins_next
2875     |
2876     |4:  // Check for __newindex if previous value is nil.
2877     |  lwz TAB:TMP1, TAB:RB->metatable
2878     |  cmplwi TAB:TMP1, 0
2879     |  beq <2                           // No metatable: done.
2880     |  lbz TMP0, TAB:TMP1->nomm
2881     |  andi. TMP0, TMP0, 1<<MM_newindex
2882     |  bne <2                           // 'no __newindex' flag set: done.
2883     |  b ->vmeta_tsets
2884     |
2885     |5:  // Follow hash chain.
2886     |  lwz NODE:TMP2, NODE:TMP2->next
2887     |  cmplwi NODE:TMP2, 0
2888     |  bne <1
2889     |  // End of hash chain: key not found, add a new one.
2890     |
2891     |  // But check for __newindex first.
2892     |  lwz TAB:TMP1, TAB:RB->metatable
2893     |   la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
2894     |   stw PC, SAVE_PC
2895     |   mr CARG1, L
2896     |  cmplwi TAB:TMP1, 0
2897     |   stw BASE, L->base
2898     |  beq >6                           // No metatable: continue.
2899     |  lbz TMP0, TAB:TMP1->nomm
2900     |  andi. TMP0, TMP0, 1<<MM_newindex
2901     |  beq ->vmeta_tsets                // 'no __newindex' flag NOT set: check.
2902     |6:
2903     |  mr CARG2, TAB:RB
2904     |  evstdd STR:RC, 0(CARG3)
2905     |  bl extern lj_tab_newkey          // (lua_State *L, GCtab *t, TValue *k)
2906     |  // Returns TValue *.
2907     |  lwz BASE, L->base
2908     |  evstdd SAVE0, 0(CRET1)
2909     |  b <3                             // No 2nd write barrier needed.
2910     |
2911     |7:  // Possible table write barrier for the value. Skip valiswhite check.
2912     |  barrierback TAB:RB, TMP3, TMP0
2913     |  b <3
2914     break;
2915   case BC_TSETB:
2916     |  // RA = src*8, RB = table*8, RC = index*8
2917     |  evlddx TAB:RB, BASE, RB
2918     |   srwi TMP0, RC, 3
2919     |  checktab TAB:RB
2920     |  checkfail ->vmeta_tsetb
2921     |  lwz TMP1, TAB:RB->asize
2922     |   lwz TMP2, TAB:RB->array
2923     |    lbz TMP3, TAB:RB->marked
2924     |  cmplw TMP0, TMP1
2925     |   evlddx SAVE0, BASE, RA
2926     |  bge ->vmeta_tsetb
2927     |  evlddx TMP1, TMP2, RC
2928     |  checknil TMP1
2929     |  checkok >5
2930     |1:
2931     |  andi. TMP0, TMP3, LJ_GC_BLACK    // isblack(table)
2932     |   evstddx SAVE0, TMP2, RC
2933     |  bne >7
2934     |2:
2935     |  ins_next
2936     |
2937     |5:  // Check for __newindex if previous value is nil.
2938     |  lwz TAB:TMP1, TAB:RB->metatable
2939     |  cmplwi TAB:TMP1, 0
2940     |  beq <1                           // No metatable: done.
2941     |  lbz TMP1, TAB:TMP1->nomm
2942     |  andi. TMP1, TMP1, 1<<MM_newindex
2943     |  bne <1                           // 'no __newindex' flag set: done.
2944     |  b ->vmeta_tsetb                  // Caveat: preserve TMP0!
2945     |
2946     |7:  // Possible table write barrier for the value. Skip valiswhite check.
2947     |  barrierback TAB:RB, TMP3, TMP0
2948     |  b <2
2949     break;
2951   case BC_TSETM:
2952     |  // RA = base*8 (table at base-1), RD = num_const*8 (start index)
2953     |  add RA, BASE, RA
2954     |1:
2955     |   add TMP3, KBASE, RD
2956     |  lwz TAB:CARG2, -4(RA)            // Guaranteed to be a table.
2957     |    addic. TMP0, MULTRES, -8
2958     |   lwz TMP3, 4(TMP3)               // Integer constant is in lo-word.
2959     |    srwi CARG3, TMP0, 3
2960     |    beq >4                         // Nothing to copy?
2961     |  add CARG3, CARG3, TMP3
2962     |  lwz TMP2, TAB:CARG2->asize
2963     |   slwi TMP1, TMP3, 3
2964     |    lbz TMP3, TAB:CARG2->marked
2965     |  cmplw CARG3, TMP2
2966     |   add TMP2, RA, TMP0
2967     |   lwz TMP0, TAB:CARG2->array
2968     |  bgt >5
2969     |   add TMP1, TMP1, TMP0
2970     |    andi. TMP0, TMP3, LJ_GC_BLACK  // isblack(table)
2971     |3:  // Copy result slots to table.
2972     |   evldd TMP0, 0(RA)
2973     |  addi RA, RA, 8
2974     |  cmpw cr1, RA, TMP2
2975     |   evstdd TMP0, 0(TMP1)
2976     |    addi TMP1, TMP1, 8
2977     |  blt cr1, <3
2978     |  bne >7
2979     |4:
2980     |  ins_next
2981     |
2982     |5:  // Need to resize array part.
2983     |   stw BASE, L->base
2984     |  mr CARG1, L
2985     |   stw PC, SAVE_PC
2986     |  mr SAVE0, RD
2987     |  bl extern lj_tab_reasize         // (lua_State *L, GCtab *t, int nasize)
2988     |  // Must not reallocate the stack.
2989     |  mr RD, SAVE0
2990     |  b <1
2991     |
2992     |7:  // Possible table write barrier for any value. Skip valiswhite check.
2993     |  barrierback TAB:CARG2, TMP3, TMP0
2994     |  b <4
2995     break;
2997   /* -- Calls and vararg handling ----------------------------------------- */
2999   case BC_CALLM:
3000     |  // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8
3001     |  add NARGS8:RC, NARGS8:RC, MULTRES
3002     |  // Fall through. Assumes BC_CALL follows.
3003     break;
3004   case BC_CALL:
3005     |  // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8
3006     |  evlddx LFUNC:RB, BASE, RA
3007     |   mr TMP2, BASE
3008     |   add BASE, BASE, RA
3009     |    subi NARGS8:RC, NARGS8:RC, 8
3010     |  checkfunc LFUNC:RB
3011     |   addi BASE, BASE, 8
3012     |  checkfail ->vmeta_call
3013     |  ins_call
3014     break;
3016   case BC_CALLMT:
3017     |  // RA = base*8, (RB = 0,) RC = extra_nargs*8
3018     |  add NARGS8:RC, NARGS8:RC, MULTRES
3019     |  // Fall through. Assumes BC_CALLT follows.
3020     break;
3021   case BC_CALLT:
3022     |  // RA = base*8, (RB = 0,) RC = (nargs+1)*8
3023     |  evlddx LFUNC:RB, BASE, RA
3024     |   add RA, BASE, RA
3025     |    lwz TMP1, FRAME_PC(BASE)
3026     |    subi NARGS8:RC, NARGS8:RC, 8
3027     |  checkfunc LFUNC:RB
3028     |   addi RA, RA, 8
3029     |  checkfail ->vmeta_callt
3030     |->BC_CALLT_Z:
3031     |  andi. TMP0, TMP1, FRAME_TYPE     // Caveat: preserve cr0 until the crand.
3032     |   lbz TMP3, LFUNC:RB->ffid
3033     |    xori TMP2, TMP1, FRAME_VARG
3034     |    cmplwi cr1, NARGS8:RC, 0
3035     |  bne >7
3036     |1:
3037     |  stw LFUNC:RB, FRAME_FUNC(BASE)   // Copy function down, but keep PC.
3038     |  li TMP2, 0
3039     |   cmplwi cr7, TMP3, 1             // (> FF_C) Calling a fast function?
3040     |    beq cr1, >3
3041     |2:
3042     |  addi TMP3, TMP2, 8
3043     |   evlddx TMP0, RA, TMP2
3044     |  cmplw cr1, TMP3, NARGS8:RC
3045     |   evstddx TMP0, BASE, TMP2
3046     |  mr TMP2, TMP3
3047     |  bne cr1, <2
3048     |3:
3049     |  crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt
3050     |  beq >5
3051     |4:
3052     |  ins_callt
3053     |
3054     |5:  // Tailcall to a fast function with a Lua frame below.
3055     |  lwz INS, -4(TMP1)
3056     |  decode_RA8 RA, INS
3057     |  sub TMP1, BASE, RA
3058     |  lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1)
3059     |  lwz TMP1, LFUNC:TMP1->pc
3060     |  lwz KBASE, PC2PROTO(k)(TMP1)     // Need to prepare KBASE.
3061     |  b <4
3062     |
3063     |7:  // Tailcall from a vararg function.
3064     |  andi. TMP0, TMP2, FRAME_TYPEP
3065     |  bne <1                           // Vararg frame below?
3066     |  sub BASE, BASE, TMP2             // Relocate BASE down.
3067     |  lwz TMP1, FRAME_PC(BASE)
3068     |  andi. TMP0, TMP1, FRAME_TYPE
3069     |  b <1
3070     break;
3072   case BC_ITERC:
3073     |  // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8))
3074     |  subi RA, RA, 24                  // evldd doesn't support neg. offsets.
3075     |   mr TMP2, BASE
3076     |  evlddx LFUNC:RB, BASE, RA
3077     |   add BASE, BASE, RA
3078     |   evldd TMP0, 8(BASE)
3079     |    evldd TMP1, 16(BASE)
3080     |  evstdd LFUNC:RB, 24(BASE)        // Copy callable.
3081     |  checkfunc LFUNC:RB
3082     |   evstdd TMP0, 32(BASE)           // Copy state.
3083     |     li NARGS8:RC, 16              // Iterators get 2 arguments.
3084     |    evstdd TMP1, 40(BASE)          // Copy control var.
3085     |     addi BASE, BASE, 32
3086     |  checkfail ->vmeta_call
3087     |  ins_call
3088     break;
3090   case BC_ITERN:
3091     |  // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8)
3092     |.if JIT
3093     |  // NYI: add hotloop, record BC_ITERN.
3094     |.endif
3095     |  add RA, BASE, RA
3096     |  lwz TAB:RB, -12(RA)
3097     |  lwz RC, -4(RA)                   // Get index from control var.
3098     |  lwz TMP0, TAB:RB->asize
3099     |  lwz TMP1, TAB:RB->array
3100     |   addi PC, PC, 4
3101     |1:  // Traverse array part.
3102     |  cmplw RC, TMP0
3103     |   slwi TMP3, RC, 3
3104     |  bge >5                           // Index points after array part?
3105     |  evlddx TMP2, TMP1, TMP3
3106     |  checknil TMP2
3107     |     lwz INS, -4(PC)
3108     |  checkok >4
3109     |   efdcfsi TMP0, RC
3110     |    addi RC, RC, 1
3111     |     addis TMP3, PC, -(BCBIAS_J*4 >> 16)
3112     |  evstdd TMP2, 8(RA)
3113     |     decode_RD4 TMP1, INS
3114     |    stw RC, -4(RA)                 // Update control var.
3115     |     add PC, TMP1, TMP3
3116     |   evstdd TMP0, 0(RA)
3117     |3:
3118     |  ins_next
3119     |
3120     |4:  // Skip holes in array part.
3121     |  addi RC, RC, 1
3122     |  b <1
3123     |
3124     |5:  // Traverse hash part.
3125     |  lwz TMP1, TAB:RB->hmask
3126     |  sub RC, RC, TMP0
3127     |   lwz TMP2, TAB:RB->node
3128     |6:
3129     |  cmplw RC, TMP1                   // End of iteration? Branch to ITERL+1.
3130     |   slwi TMP3, RC, 5
3131     |  bgt <3
3132     |   slwi RB, RC, 3
3133     |   sub TMP3, TMP3, RB
3134     |  evlddx RB, TMP2, TMP3
3135     |   add NODE:TMP3, TMP2, TMP3
3136     |  checknil RB
3137     |     lwz INS, -4(PC)
3138     |  checkok >7
3139     |   evldd TMP3, NODE:TMP3->key
3140     |     addis TMP2, PC, -(BCBIAS_J*4 >> 16)
3141     |  evstdd RB, 8(RA)
3142     |    add RC, RC, TMP0
3143     |     decode_RD4 TMP1, INS
3144     |   evstdd TMP3, 0(RA)
3145     |    addi RC, RC, 1
3146     |     add PC, TMP1, TMP2
3147     |    stw RC, -4(RA)                 // Update control var.
3148     |  b <3
3149     |
3150     |7:  // Skip holes in hash part.
3151     |  addi RC, RC, 1
3152     |  b <6
3153     break;
3155   case BC_ISNEXT:
3156     |  // RA = base*8, RD = target (points to ITERN)
3157     |  add RA, BASE, RA
3158     |   li TMP2, -24
3159     |  evlddx CFUNC:TMP1, RA, TMP2
3160     |   lwz TMP2, -16(RA)
3161     |    lwz TMP3, -8(RA)
3162     |  evmergehi TMP0, CFUNC:TMP1, CFUNC:TMP1
3163     |   cmpwi cr0, TMP2, LJ_TTAB
3164     |  cmpwi cr1, TMP0, LJ_TFUNC
3165     |    cmpwi cr6, TMP3, LJ_TNIL
3166     |  bne cr1, >5
3167     |  lbz TMP1, CFUNC:TMP1->ffid
3168     |   crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq
3169     |  cmpwi cr7, TMP1, FF_next_N
3170     |    srwi TMP0, RD, 1
3171     |  crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq
3172     |    add TMP3, PC, TMP0
3173     |  bne cr0, >5
3174     |  lus TMP1, 0xfffe
3175     |  ori TMP1, TMP1, 0x7fff
3176     |  stw ZERO, -4(RA)                 // Initialize control var.
3177     |  stw TMP1, -8(RA)
3178     |    addis PC, TMP3, -(BCBIAS_J*4 >> 16)
3179     |1:
3180     |  ins_next
3181     |5:  // Despecialize bytecode if any of the checks fail.
3182     |  li TMP0, BC_JMP
3183     |   li TMP1, BC_ITERC
3184     |  stb TMP0, -1(PC)
3185     |    addis PC, TMP3, -(BCBIAS_J*4 >> 16)
3186     |   stb TMP1, 3(PC)
3187     |  b <1
3188     break;
3190   case BC_VARG:
3191     |  // RA = base*8, RB = (nresults+1)*8, RC = numparams*8
3192     |  lwz TMP0, FRAME_PC(BASE)
3193     |  add RC, BASE, RC
3194     |   add RA, BASE, RA
3195     |  addi RC, RC, FRAME_VARG
3196     |   add TMP2, RA, RB
3197     |  subi TMP3, BASE, 8               // TMP3 = vtop
3198     |  sub RC, RC, TMP0                 // RC = vbase
3199     |  // Note: RC may now be even _above_ BASE if nargs was < numparams.
3200     |  cmplwi cr1, RB, 0
3201     |   sub. TMP1, TMP3, RC
3202     |  beq cr1, >5                      // Copy all varargs?
3203     |   subi TMP2, TMP2, 16
3204     |   ble >2                          // No vararg slots?
3205     |1:  // Copy vararg slots to destination slots.
3206     |  evldd TMP0, 0(RC)
3207     |   addi RC, RC, 8
3208     |  evstdd TMP0, 0(RA)
3209     |  cmplw RA, TMP2
3210     |   cmplw cr1, RC, TMP3
3211     |  bge >3                           // All destination slots filled?
3212     |    addi RA, RA, 8
3213     |   blt cr1, <1                     // More vararg slots?
3214     |2:  // Fill up remainder with nil.
3215     |  evstdd TISNIL, 0(RA)
3216     |  cmplw RA, TMP2
3217     |   addi RA, RA, 8
3218     |  blt <2
3219     |3:
3220     |  ins_next
3221     |
3222     |5:  // Copy all varargs.
3223     |  lwz TMP0, L->maxstack
3224     |   li MULTRES, 8                   // MULTRES = (0+1)*8
3225     |  ble <3                           // No vararg slots?
3226     |  add TMP2, RA, TMP1
3227     |  cmplw TMP2, TMP0
3228     |   addi MULTRES, TMP1, 8
3229     |  bgt >7
3230     |6:
3231     |  evldd TMP0, 0(RC)
3232     |   addi RC, RC, 8
3233     |  evstdd TMP0, 0(RA)
3234     |  cmplw RC, TMP3
3235     |   addi RA, RA, 8
3236     |  blt <6                           // More vararg slots?
3237     |  b <3
3238     |
3239     |7:  // Grow stack for varargs.
3240     |  mr CARG1, L
3241     |   stw RA, L->top
3242     |  sub SAVE0, RC, BASE              // Need delta, because BASE may change.
3243     |   stw BASE, L->base
3244     |  sub RA, RA, BASE
3245     |   stw PC, SAVE_PC
3246     |  srwi CARG2, TMP1, 3
3247     |  bl extern lj_state_growstack     // (lua_State *L, int n)
3248     |  lwz BASE, L->base
3249     |  add RA, BASE, RA
3250     |  add RC, BASE, SAVE0
3251     |  subi TMP3, BASE, 8
3252     |  b <6
3253     break;
3255   /* -- Returns ----------------------------------------------------------- */
3257   case BC_RETM:
3258     |  // RA = results*8, RD = extra_nresults*8
3259     |  add RD, RD, MULTRES              // MULTRES >= 8, so RD >= 8.
3260     |  // Fall through. Assumes BC_RET follows.
3261     break;
3263   case BC_RET:
3264     |  // RA = results*8, RD = (nresults+1)*8
3265     |  lwz PC, FRAME_PC(BASE)
3266     |   add RA, BASE, RA
3267     |    mr MULTRES, RD
3268     |1:
3269     |  andi. TMP0, PC, FRAME_TYPE
3270     |   xori TMP1, PC, FRAME_VARG
3271     |  bne ->BC_RETV_Z
3272     |
3273     |->BC_RET_Z:
3274     |  // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return
3275     |   lwz INS, -4(PC)
3276     |  cmpwi RD, 8
3277     |   subi TMP2, BASE, 8
3278     |   subi RC, RD, 8
3279     |   decode_RB8 RB, INS
3280     |  beq >3
3281     |   li TMP1, 0
3282     |2:
3283     |  addi TMP3, TMP1, 8
3284     |   evlddx TMP0, RA, TMP1
3285     |  cmpw TMP3, RC
3286     |   evstddx TMP0, TMP2, TMP1
3287     |  beq >3
3288     |  addi TMP1, TMP3, 8
3289     |   evlddx TMP0, RA, TMP3
3290     |  cmpw TMP1, RC
3291     |   evstddx TMP0, TMP2, TMP3
3292     |  bne <2
3293     |3:
3294     |5:
3295     |  cmplw RB, RD
3296     |   decode_RA8 RA, INS
3297     |  bgt >6
3298     |   sub BASE, TMP2, RA
3299     |  lwz LFUNC:TMP1, FRAME_FUNC(BASE)
3300     |  ins_next1
3301     |  lwz TMP1, LFUNC:TMP1->pc
3302     |  lwz KBASE, PC2PROTO(k)(TMP1)
3303     |  ins_next2
3304     |
3305     |6:  // Fill up results with nil.
3306     |  subi TMP1, RD, 8
3307     |   addi RD, RD, 8
3308     |  evstddx TISNIL, TMP2, TMP1
3309     |  b <5
3310     |
3311     |->BC_RETV_Z:  // Non-standard return case.
3312     |  andi. TMP2, TMP1, FRAME_TYPEP
3313     |  bne ->vm_return
3314     |  // Return from vararg function: relocate BASE down.
3315     |  sub BASE, BASE, TMP1
3316     |  lwz PC, FRAME_PC(BASE)
3317     |  b <1
3318     break;
3320   case BC_RET0: case BC_RET1:
3321     |  // RA = results*8, RD = (nresults+1)*8
3322     |  lwz PC, FRAME_PC(BASE)
3323     |   add RA, BASE, RA
3324     |    mr MULTRES, RD
3325     |  andi. TMP0, PC, FRAME_TYPE
3326     |   xori TMP1, PC, FRAME_VARG
3327     |  bne ->BC_RETV_Z
3328     |
3329     |  lwz INS, -4(PC)
3330     |   subi TMP2, BASE, 8
3331     |  decode_RB8 RB, INS
3332     if (op == BC_RET1) {
3333       |  evldd TMP0, 0(RA)
3334       |  evstdd TMP0, 0(TMP2)
3335     }
3336     |5:
3337     |  cmplw RB, RD
3338     |   decode_RA8 RA, INS
3339     |  bgt >6
3340     |   sub BASE, TMP2, RA
3341     |  lwz LFUNC:TMP1, FRAME_FUNC(BASE)
3342     |  ins_next1
3343     |  lwz TMP1, LFUNC:TMP1->pc
3344     |  lwz KBASE, PC2PROTO(k)(TMP1)
3345     |  ins_next2
3346     |
3347     |6:  // Fill up results with nil.
3348     |  subi TMP1, RD, 8
3349     |   addi RD, RD, 8
3350     |  evstddx TISNIL, TMP2, TMP1
3351     |  b <5
3352     break;
3354   /* -- Loops and branches ------------------------------------------------ */
3356   case BC_FORL:
3357     |.if JIT
3358     |  hotloop
3359     |.endif
3360     |  // Fall through. Assumes BC_IFORL follows.
3361     break;
3363   case BC_JFORI:
3364   case BC_JFORL:
3365 #if !LJ_HASJIT
3366     break;
3367 #endif
3368   case BC_FORI:
3369   case BC_IFORL:
3370     |  // RA = base*8, RD = target (after end of loop or start of loop)
3371     vk = (op == BC_IFORL || op == BC_JFORL);
3372     |  add RA, BASE, RA
3373     |  evldd TMP1, FORL_IDX*8(RA)
3374     |  evldd TMP3, FORL_STEP*8(RA)
3375     |  evldd TMP2, FORL_STOP*8(RA)
3376     if (!vk) {
3377       |  evcmpgtu cr0, TMP1, TISNUM
3378       |  evcmpgtu cr7, TMP3, TISNUM
3379       |  evcmpgtu cr1, TMP2, TISNUM
3380       |  cror 4*cr0+lt, 4*cr0+lt, 4*cr7+lt
3381       |  cror 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3382       |  blt ->vmeta_for
3383     }
3384     if (vk) {
3385       |  efdadd TMP1, TMP1, TMP3
3386       |  evstdd TMP1, FORL_IDX*8(RA)
3387     }
3388     |   evcmpgts TMP3, TISNIL
3389     |  evstdd TMP1, FORL_EXT*8(RA)
3390     |   bge >2
3391     |  efdcmpgt TMP1, TMP2
3392     |1:
3393     if (op != BC_JFORL) {
3394       |  srwi RD, RD, 1
3395       |  add RD, PC, RD
3396       if (op == BC_JFORI) {
3397         |  addis PC, RD, -(BCBIAS_J*4 >> 16)
3398       } else {
3399         |  addis RD, RD, -(BCBIAS_J*4 >> 16)
3400       }
3401     }
3402     if (op == BC_FORI) {
3403       |  iselgt PC, RD, PC
3404     } else if (op == BC_IFORL) {
3405       |  iselgt PC, PC, RD
3406     } else {
3407       |  ble =>BC_JLOOP
3408     }
3409     |  ins_next
3410     |2:
3411     |  efdcmpgt TMP2, TMP1
3412     |  b <1
3413     break;
3415   case BC_ITERL:
3416     |.if JIT
3417     |  hotloop
3418     |.endif
3419     |  // Fall through. Assumes BC_IITERL follows.
3420     break;
3422   case BC_JITERL:
3423 #if !LJ_HASJIT
3424     break;
3425 #endif
3426   case BC_IITERL:
3427     |  // RA = base*8, RD = target
3428     |  evlddx TMP1, BASE, RA
3429     |   subi RA, RA, 8
3430     |  checknil TMP1
3431     |  checkok >1                       // Stop if iterator returned nil.
3432     if (op == BC_JITERL) {
3433       |  NYI
3434     } else {
3435       |  branch_RD                      // Otherwise save control var + branch.
3436       |  evstddx TMP1, BASE, RA
3437     }
3438     |1:
3439     |  ins_next
3440     break;
3442   case BC_LOOP:
3443     |  // RA = base*8, RD = target (loop extent)
3444     |  // Note: RA/RD is only used by trace recorder to determine scope/extent
3445     |  // This opcode does NOT jump, it's only purpose is to detect a hot loop.
3446     |.if JIT
3447     |  hotloop
3448     |.endif
3449     |  // Fall through. Assumes BC_ILOOP follows.
3450     break;
3452   case BC_ILOOP:
3453     |  // RA = base*8, RD = target (loop extent)
3454     |  ins_next
3455     break;
3457   case BC_JLOOP:
3458     |.if JIT
3459     |  NYI
3460     |.endif
3461     break;
3463   case BC_JMP:
3464     |  // RA = base*8 (only used by trace recorder), RD = target
3465     |  branch_RD
3466     |  ins_next
3467     break;
3469   /* -- Function headers -------------------------------------------------- */
3471   case BC_FUNCF:
3472     |.if JIT
3473     |  hotcall
3474     |.endif
3475   case BC_FUNCV:  /* NYI: compiled vararg functions. */
3476     |  // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow.
3477     break;
3479   case BC_JFUNCF:
3480 #if !LJ_HASJIT
3481     break;
3482 #endif
3483   case BC_IFUNCF:
3484     |  // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
3485     |  lwz TMP2, L->maxstack
3486     |   lbz TMP1, -4+PC2PROTO(numparams)(PC)
3487     |    lwz KBASE, -4+PC2PROTO(k)(PC)
3488     |  cmplw RA, TMP2
3489     |   slwi TMP1, TMP1, 3
3490     |  bgt ->vm_growstack_l
3491     |  ins_next1
3492     |2:
3493     |  cmplw NARGS8:RC, TMP1            // Check for missing parameters.
3494     |  ble >3
3495     if (op == BC_JFUNCF) {
3496       |  NYI
3497     } else {
3498       |  ins_next2
3499     }
3500     |
3501     |3:  // Clear missing parameters.
3502     |  evstddx TISNIL, BASE, NARGS8:RC
3503     |  addi NARGS8:RC, NARGS8:RC, 8
3504     |  b <2
3505     break;
3507   case BC_JFUNCV:
3508 #if !LJ_HASJIT
3509     break;
3510 #endif
3511     |  NYI  // NYI: compiled vararg functions
3512     break;  /* NYI: compiled vararg functions. */
3514   case BC_IFUNCV:
3515     |  // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
3516     |  lwz TMP2, L->maxstack
3517     |   add TMP1, BASE, RC
3518     |  add TMP0, RA, RC
3519     |   stw LFUNC:RB, 4(TMP1)           // Store copy of LFUNC.
3520     |   addi TMP3, RC, 8+FRAME_VARG
3521     |    lwz KBASE, -4+PC2PROTO(k)(PC)
3522     |  cmplw TMP0, TMP2
3523     |   stw TMP3, 0(TMP1)               // Store delta + FRAME_VARG.
3524     |  bge ->vm_growstack_l
3525     |  lbz TMP2, -4+PC2PROTO(numparams)(PC)
3526     |   mr RA, BASE
3527     |   mr RC, TMP1
3528     |  ins_next1
3529     |  cmpwi TMP2, 0
3530     |   addi BASE, TMP1, 8
3531     |  beq >3
3532     |1:
3533     |  cmplw RA, RC                     // Less args than parameters?
3534     |   evldd TMP0, 0(RA)
3535     |  bge >4
3536     |    evstdd TISNIL, 0(RA)           // Clear old fixarg slot (help the GC).
3537     |    addi RA, RA, 8
3538     |2:
3539     |  addic. TMP2, TMP2, -1
3540     |   evstdd TMP0, 8(TMP1)
3541     |    addi TMP1, TMP1, 8
3542     |  bne <1
3543     |3:
3544     |  ins_next2
3545     |
3546     |4:  // Clear missing parameters.
3547     |  evmr TMP0, TISNIL
3548     |  b <2
3549     break;
3551   case BC_FUNCC:
3552   case BC_FUNCCW:
3553     |  // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8
3554     if (op == BC_FUNCC) {
3555       |  lwz TMP3, CFUNC:RB->f
3556     } else {
3557       |  lwz TMP3, DISPATCH_GL(wrapf)(DISPATCH)
3558     }
3559     |   add TMP1, RA, NARGS8:RC
3560     |   lwz TMP2, L->maxstack
3561     |    add RC, BASE, NARGS8:RC
3562     |   stw BASE, L->base
3563     |   cmplw TMP1, TMP2
3564     |    stw RC, L->top
3565     |     li_vmstate C
3566     |  mtctr TMP3
3567     if (op == BC_FUNCCW) {
3568       |  lwz CARG2, CFUNC:RB->f
3569     }
3570     |  mr CARG1, L
3571     |   bgt ->vm_growstack_c            // Need to grow stack.
3572     |     st_vmstate
3573     |  bctrl                            // (lua_State *L [, lua_CFunction f])
3574     |  // Returns nresults.
3575     |  lwz TMP1, L->top
3576     |   slwi RD, CRET1, 3
3577     |  lwz BASE, L->base
3578     |    li_vmstate INTERP
3579     |  lwz PC, FRAME_PC(BASE)           // Fetch PC of caller.
3580     |   sub RA, TMP1, RD                // RA = L->top - nresults*8
3581     |    st_vmstate
3582     |  b ->vm_returnc
3583     break;
3585   /* ---------------------------------------------------------------------- */
3587   default:
3588     fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]);
3589     exit(2);
3590     break;
3591   }
3594 static int build_backend(BuildCtx *ctx)
3596   int op;
3598   dasm_growpc(Dst, BC__MAX);
3600   build_subroutines(ctx);
3602   |.code_op
3603   for (op = 0; op < BC__MAX; op++)
3604     build_ins(ctx, (BCOp)op, op);
3606   return BC__MAX;
3609 /* Emit pseudo frame-info for all assembler functions. */
3610 static void emit_asm_debug(BuildCtx *ctx)
3612   int i;
3613   switch (ctx->mode) {
3614   case BUILD_elfasm:
3615     fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n");
3616     fprintf(ctx->fp,
3617         ".Lframe0:\n"
3618         "\t.long .LECIE0-.LSCIE0\n"
3619         ".LSCIE0:\n"
3620         "\t.long 0xffffffff\n"
3621         "\t.byte 0x1\n"
3622         "\t.string \"\"\n"
3623         "\t.uleb128 0x1\n"
3624         "\t.sleb128 -4\n"
3625         "\t.byte 65\n"
3626         "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
3627         "\t.align 2\n"
3628         ".LECIE0:\n\n");
3629     fprintf(ctx->fp,
3630         ".LSFDE0:\n"
3631         "\t.long .LEFDE0-.LASFDE0\n"
3632         ".LASFDE0:\n"
3633         "\t.long .Lframe0\n"
3634         "\t.long .Lbegin\n"
3635         "\t.long %d\n"
3636         "\t.byte 0xe\n\t.uleb128 %d\n"
3637         "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
3638         "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n",
3639         (int)ctx->codesz, CFRAME_SIZE);
3640     for (i = 14; i <= 31; i++)
3641       fprintf(ctx->fp,
3642         "\t.byte %d\n\t.uleb128 %d\n"
3643         "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n",
3644         0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i));
3645     fprintf(ctx->fp,
3646         "\t.align 2\n"
3647         ".LEFDE0:\n\n");
3648     fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
3649     fprintf(ctx->fp,
3650         ".Lframe1:\n"
3651         "\t.long .LECIE1-.LSCIE1\n"
3652         ".LSCIE1:\n"
3653         "\t.long 0\n"
3654         "\t.byte 0x1\n"
3655         "\t.string \"zPR\"\n"
3656         "\t.uleb128 0x1\n"
3657         "\t.sleb128 -4\n"
3658         "\t.byte 65\n"
3659         "\t.uleb128 6\n"                        /* augmentation length */
3660         "\t.byte 0x1b\n"                        /* pcrel|sdata4 */
3661         "\t.long lj_err_unwind_dwarf-.\n"
3662         "\t.byte 0x1b\n"                        /* pcrel|sdata4 */
3663         "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
3664         "\t.align 2\n"
3665         ".LECIE1:\n\n");
3666     fprintf(ctx->fp,
3667         ".LSFDE1:\n"
3668         "\t.long .LEFDE1-.LASFDE1\n"
3669         ".LASFDE1:\n"
3670         "\t.long .LASFDE1-.Lframe1\n"
3671         "\t.long .Lbegin-.\n"
3672         "\t.long %d\n"
3673         "\t.uleb128 0\n"                        /* augmentation length */
3674         "\t.byte 0xe\n\t.uleb128 %d\n"
3675         "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
3676         "\t.byte 0x5\n\t.uleb128 70\n\t.sleb128 37\n",
3677         (int)ctx->codesz, CFRAME_SIZE);
3678     for (i = 14; i <= 31; i++)
3679       fprintf(ctx->fp,
3680         "\t.byte %d\n\t.uleb128 %d\n"
3681         "\t.byte 5\n\t.uleb128 %d\n\t.uleb128 %d\n",
3682         0x80+i, 1+2*(31-i), 1200+i, 2+2*(31-i));
3683     fprintf(ctx->fp,
3684         "\t.align 2\n"
3685         ".LEFDE1:\n\n");
3686     break;
3687   default:
3688     break;
3689   }