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