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