aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/luajit-2.0/src/buildvm_ppc.dasc
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/luajit-2.0/src/buildvm_ppc.dasc')
-rw-r--r--libraries/luajit-2.0/src/buildvm_ppc.dasc4873
1 files changed, 4873 insertions, 0 deletions
diff --git a/libraries/luajit-2.0/src/buildvm_ppc.dasc b/libraries/luajit-2.0/src/buildvm_ppc.dasc
new file mode 100644
index 0000000..c26f392
--- /dev/null
+++ b/libraries/luajit-2.0/src/buildvm_ppc.dasc
@@ -0,0 +1,4873 @@
1|// Low-level VM code for PowerPC CPUs.
2|// Bytecode interpreter, fast functions and helper functions.
3|// Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
4|
5|.arch ppc
6|.section code_op, code_sub
7|
8|.actionlist build_actionlist
9|.globals GLOB_
10|.globalnames globnames
11|.externnames extnames
12|
13|// Note: The ragged indentation of the instructions is intentional.
14|// The starting columns indicate data dependencies.
15|
16|//-----------------------------------------------------------------------
17|
18|// Fixed register assignments for the interpreter.
19|// Don't use: r1 = sp, r2 and r13 = reserved (TOC, TLS or SDATA)
20|
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.
28|.define JGL, r31 // On-trace: global_State + 32768.
29|
30|// Constants for type-comparisons, stores and conversions. C callee-save.
31|.define TISNUM, r22
32|.define TISNIL, r23
33|.define ZERO, r24
34|.define TOBIT, f30 // 2^52 + 2^51.
35|.define TONUM, f31 // 2^52 + 2^51 + 2^31.
36|
37|// The following temporaries are not saved across C calls, except for RA.
38|.define RA, r20 // Callee-save.
39|.define RB, r10
40|.define RC, r11
41|.define RD, r12
42|.define INS, r7 // Overlaps CARG5.
43|
44|.define TMP0, r0
45|.define TMP1, r8
46|.define TMP2, r9
47|.define TMP3, r6 // Overlaps CARG4.
48|
49|// Saved temporaries.
50|.define SAVE0, r21
51|
52|// Calling conventions.
53|.define CARG1, r3
54|.define CARG2, r4
55|.define CARG3, r5
56|.define CARG4, r6 // Overlaps TMP3.
57|.define CARG5, r7 // Overlaps INS.
58|
59|.define FARG1, f1
60|.define FARG2, f2
61|
62|.define CRET1, r3
63|.define CRET2, r4
64|
65|// Stack layout while in interpreter. Must match with lj_frame.h.
66|.define SAVE_LR, 276(sp)
67|.define CFRAME_SPACE, 272 // Delta for sp.
68|// Back chain for sp: 272(sp) <-- sp entering interpreter
69|.define SAVE_FPR_, 128 // .. 128+18*8: 64 bit FPR saves.
70|.define SAVE_GPR_, 56 // .. 56+18*4: 32 bit GPR saves.
71|.define SAVE_CR, 52(sp) // 32 bit CR save.
72|.define SAVE_ERRF, 48(sp) // 32 bit C frame info.
73|.define SAVE_NRES, 44(sp)
74|.define SAVE_CFRAME, 40(sp)
75|.define SAVE_L, 36(sp)
76|.define SAVE_PC, 32(sp)
77|.define SAVE_MULTRES, 28(sp)
78|.define UNUSED1, 24(sp)
79|.define TMPD_LO, 20(sp)
80|.define TMPD_HI, 16(sp)
81|.define TONUM_LO, 12(sp)
82|.define TONUM_HI, 8(sp)
83|// Next frame lr: 4(sp)
84|// Back chain for sp: 0(sp) <-- sp while in interpreter
85|
86|.define TMPD_BLO, 23(sp)
87|.define TMPD, TMPD_HI
88|.define TONUM_D, TONUM_HI
89|
90|.macro save_, reg
91| stw r..reg, SAVE_GPR_+(reg-14)*4(sp)
92| stfd f..reg, SAVE_FPR_+(reg-14)*8(sp)
93|.endmacro
94|.macro rest_, reg
95| lwz r..reg, SAVE_GPR_+(reg-14)*4(sp)
96| lfd f..reg, SAVE_FPR_+(reg-14)*8(sp)
97|.endmacro
98|
99|.macro saveregs
100| stwu sp, -CFRAME_SPACE(sp)
101| save_ 14; save_ 15; save_ 16
102| mflr r0
103| save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22
104| stw r0, SAVE_LR
105| save_ 23; save_ 24; save_ 25
106| mfcr r0
107| save_ 26; save_ 27; save_ 28; save_ 29; save_ 30; save_ 31
108| stw r0, SAVE_CR
109|.endmacro
110|
111|.macro restoreregs
112| lwz r0, SAVE_LR; lwz r12, SAVE_CR
113| rest_ 14; rest_ 15; rest_ 16; rest_ 17; rest_ 18; rest_ 19
114| mtlr r0; mtcrf 0x38, r12
115| rest_ 20; rest_ 21; rest_ 22; rest_ 23; rest_ 24; rest_ 25
116| rest_ 26; rest_ 27; rest_ 28; rest_ 29; rest_ 30; rest_ 31
117| addi sp, sp, CFRAME_SPACE
118|.endmacro
119|
120|// Type definitions. Some of these are only used for documentation.
121|.type L, lua_State, LREG
122|.type GL, global_State
123|.type TVALUE, TValue
124|.type GCOBJ, GCobj
125|.type STR, GCstr
126|.type TAB, GCtab
127|.type LFUNC, GCfuncL
128|.type CFUNC, GCfuncC
129|.type PROTO, GCproto
130|.type UPVAL, GCupval
131|.type NODE, Node
132|.type NARGS8, int
133|.type TRACE, GCtrace
134|
135|//-----------------------------------------------------------------------
136|
137|// These basic macros should really be part of DynASM.
138|.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro
139|.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro
140|.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro
141|.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro
142|.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro
143|
144|// Trap for not-yet-implemented parts.
145|.macro NYI; tw 4, sp, sp; .endmacro
146|
147|// int/FP conversions.
148|.macro tonum_i, freg, reg
149| xoris reg, reg, 0x8000
150| stw reg, TONUM_LO
151| lfd freg, TONUM_D
152| fsub freg, freg, TONUM
153|.endmacro
154|
155|.macro tonum_u, freg, reg
156| stw reg, TONUM_LO
157| lfd freg, TONUM_D
158| fsub freg, freg, TOBIT
159|.endmacro
160|
161|.macro toint, reg, freg, tmpfreg
162| fctiwz tmpfreg, freg
163| stfd tmpfreg, TMPD
164| lwz reg, TMPD_LO
165|.endmacro
166|
167|.macro toint, reg, freg
168| toint reg, freg, freg
169|.endmacro
170|
171|//-----------------------------------------------------------------------
172|
173|// Access to frame relative to BASE.
174|.define FRAME_PC, -8
175|.define FRAME_FUNC, -4
176|
177|// Instruction decode.
178|.macro decode_OP4, dst, ins; rlwinm dst, ins, 2, 22, 29; .endmacro
179|.macro decode_RA8, dst, ins; rlwinm dst, ins, 27, 21, 28; .endmacro
180|.macro decode_RB8, dst, ins; rlwinm dst, ins, 11, 21, 28; .endmacro
181|.macro decode_RC8, dst, ins; rlwinm dst, ins, 19, 21, 28; .endmacro
182|.macro decode_RD8, dst, ins; rlwinm dst, ins, 19, 13, 28; .endmacro
183|
184|.macro decode_OP1, dst, ins; rlwinm dst, ins, 0, 24, 31; .endmacro
185|.macro decode_RD4, dst, ins; rlwinm dst, ins, 18, 14, 29; .endmacro
186|
187|// Instruction fetch.
188|.macro ins_NEXT1
189| lwz INS, 0(PC)
190| addi PC, PC, 4
191|.endmacro
192|// Instruction decode+dispatch. Note: optimized for e300!
193|.macro ins_NEXT2
194| decode_OP4 TMP1, INS
195| lwzx TMP0, DISPATCH, TMP1
196| mtctr TMP0
197| decode_RB8 RB, INS
198| decode_RD8 RD, INS
199| decode_RA8 RA, INS
200| decode_RC8 RC, INS
201| bctr
202|.endmacro
203|.macro ins_NEXT
204| ins_NEXT1
205| ins_NEXT2
206|.endmacro
207|
208|// Instruction footer.
209|.if 1
210| // Replicated dispatch. Less unpredictable branches, but higher I-Cache use.
211| .define ins_next, ins_NEXT
212| .define ins_next_, ins_NEXT
213| .define ins_next1, ins_NEXT1
214| .define ins_next2, ins_NEXT2
215|.else
216| // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch.
217| // Affects only certain kinds of benchmarks (and only with -j off).
218| .macro ins_next
219| b ->ins_next
220| .endmacro
221| .macro ins_next1
222| .endmacro
223| .macro ins_next2
224| b ->ins_next
225| .endmacro
226| .macro ins_next_
227| ->ins_next:
228| ins_NEXT
229| .endmacro
230|.endif
231|
232|// Call decode and dispatch.
233|.macro ins_callt
234| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
235| lwz PC, LFUNC:RB->pc
236| lwz INS, 0(PC)
237| addi PC, PC, 4
238| decode_OP4 TMP1, INS
239| decode_RA8 RA, INS
240| lwzx TMP0, DISPATCH, TMP1
241| add RA, RA, BASE
242| mtctr TMP0
243| bctr
244|.endmacro
245|
246|.macro ins_call
247| // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC
248| stw PC, FRAME_PC(BASE)
249| ins_callt
250|.endmacro
251|
252|//-----------------------------------------------------------------------
253|
254|// Macros to test operand types.
255|.macro checknum, reg; cmplw reg, TISNUM; .endmacro
256|.macro checknum, cr, reg; cmplw cr, reg, TISNUM; .endmacro
257|.macro checkstr, reg; cmpwi reg, LJ_TSTR; .endmacro
258|.macro checktab, reg; cmpwi reg, LJ_TTAB; .endmacro
259|.macro checkfunc, reg; cmpwi reg, LJ_TFUNC; .endmacro
260|.macro checknil, reg; cmpwi reg, LJ_TNIL; .endmacro
261|
262|.macro branch_RD
263| srwi TMP0, RD, 1
264| addis PC, PC, -(BCBIAS_J*4 >> 16)
265| add PC, PC, TMP0
266|.endmacro
267|
268|// Assumes DISPATCH is relative to GL.
269#define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
270#define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
271|
272#define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto))
273|
274|.macro hotcheck, delta, target
275| rlwinm TMP1, PC, 31, 25, 30
276| addi TMP1, TMP1, GG_DISP2HOT
277| lhzx TMP2, DISPATCH, TMP1
278| addic. TMP2, TMP2, -delta
279| sthx TMP2, DISPATCH, TMP1
280| blt target
281|.endmacro
282|
283|.macro hotloop
284| hotcheck HOTCOUNT_LOOP, ->vm_hotloop
285|.endmacro
286|
287|.macro hotcall
288| hotcheck HOTCOUNT_CALL, ->vm_hotcall
289|.endmacro
290|
291|// Set current VM state. Uses TMP0.
292|.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro
293|.macro st_vmstate; stw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro
294|
295|// Move table write barrier back. Overwrites mark and tmp.
296|.macro barrierback, tab, mark, tmp
297| lwz tmp, DISPATCH_GL(gc.grayagain)(DISPATCH)
298| // Assumes LJ_GC_BLACK is 0x04.
299| rlwinm mark, mark, 0, 30, 28 // black2gray(tab)
300| stw tab, DISPATCH_GL(gc.grayagain)(DISPATCH)
301| stb mark, tab->marked
302| stw tmp, tab->gclist
303|.endmacro
304|
305|//-----------------------------------------------------------------------
306
307/* Generate subroutines used by opcodes and other parts of the VM. */
308/* The .code_sub section should be last to help static branch prediction. */
309static void build_subroutines(BuildCtx *ctx)
310{
311 |.code_sub
312 |
313 |//-----------------------------------------------------------------------
314 |//-- Return handling ----------------------------------------------------
315 |//-----------------------------------------------------------------------
316 |
317 |->vm_returnp:
318 | // See vm_return. Also: TMP2 = previous base.
319 | andi. TMP0, PC, FRAME_P
320 | li TMP1, LJ_TTRUE
321 | beq ->cont_dispatch
322 |
323 | // Return from pcall or xpcall fast func.
324 | lwz PC, FRAME_PC(TMP2) // Fetch PC of previous frame.
325 | mr BASE, TMP2 // Restore caller base.
326 | // Prepending may overwrite the pcall frame, so do it at the end.
327 | stwu TMP1, FRAME_PC(RA) // Prepend true to results.
328 |
329 |->vm_returnc:
330 | andi. TMP0, PC, FRAME_TYPE
331 | addi RD, RD, 8 // RD = (nresults+1)*8.
332 | mr MULTRES, RD
333 | beq ->BC_RET_Z // Handle regular return to Lua.
334 |
335 |->vm_return:
336 | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return
337 | // TMP0 = PC & FRAME_TYPE
338 | cmpwi TMP0, FRAME_C
339 | rlwinm TMP2, PC, 0, 0, 28
340 | li_vmstate C
341 | sub TMP2, BASE, TMP2 // TMP2 = previous base.
342 | bney ->vm_returnp
343 |
344 | addic. TMP1, RD, -8
345 | stw TMP2, L->base
346 | lwz TMP2, SAVE_NRES
347 | subi BASE, BASE, 8
348 | st_vmstate
349 | slwi TMP2, TMP2, 3
350 | beq >2
351 |1:
352 | addic. TMP1, TMP1, -8
353 | lfd f0, 0(RA)
354 | addi RA, RA, 8
355 | stfd f0, 0(BASE)
356 | addi BASE, BASE, 8
357 | bney <1
358 |
359 |2:
360 | cmpw TMP2, RD // More/less results wanted?
361 | bne >6
362 |3:
363 | stw BASE, L->top // Store new top.
364 |
365 |->vm_leave_cp:
366 | lwz TMP0, SAVE_CFRAME // Restore previous C frame.
367 | li CRET1, 0 // Ok return status for vm_pcall.
368 | stw TMP0, L->cframe
369 |
370 |->vm_leave_unw:
371 | restoreregs
372 | blr
373 |
374 |6:
375 | ble >7 // Less results wanted?
376 | // More results wanted. Check stack size and fill up results with nil.
377 | lwz TMP1, L->maxstack
378 | cmplw BASE, TMP1
379 | bge >8
380 | stw TISNIL, 0(BASE)
381 | addi RD, RD, 8
382 | addi BASE, BASE, 8
383 | b <2
384 |
385 |7: // Less results wanted.
386 | subfic TMP3, TMP2, 0 // LUA_MULTRET+1 case?
387 | sub TMP0, RD, TMP2
388 | subfe TMP1, TMP1, TMP1 // TMP1 = TMP2 == 0 ? 0 : -1
389 | and TMP0, TMP0, TMP1
390 | sub BASE, BASE, TMP0 // Either keep top or shrink it.
391 | b <3
392 |
393 |8: // Corner case: need to grow stack for filling up results.
394 | // This can happen if:
395 | // - A C function grows the stack (a lot).
396 | // - The GC shrinks the stack in between.
397 | // - A return back from a lua_call() with (high) nresults adjustment.
398 | stw BASE, L->top // Save current top held in BASE (yes).
399 | mr SAVE0, RD
400 | mr CARG2, TMP2
401 | mr CARG1, L
402 | bl extern lj_state_growstack // (lua_State *L, int n)
403 | lwz TMP2, SAVE_NRES
404 | mr RD, SAVE0
405 | slwi TMP2, TMP2, 3
406 | lwz BASE, L->top // Need the (realloced) L->top in BASE.
407 | b <2
408 |
409 |->vm_unwind_c: // Unwind C stack, return from vm_pcall.
410 | // (void *cframe, int errcode)
411 | mr sp, CARG1
412 | mr CRET1, CARG2
413 |->vm_unwind_c_eh: // Landing pad for external unwinder.
414 | lwz L, SAVE_L
415 | li TMP0, ~LJ_VMST_C
416 | lwz GL:TMP1, L->glref
417 | stw TMP0, GL:TMP1->vmstate
418 | b ->vm_leave_unw
419 |
420 |->vm_unwind_ff: // Unwind C stack, return from ff pcall.
421 | // (void *cframe)
422 | rlwinm sp, CARG1, 0, 0, 29
423 |->vm_unwind_ff_eh: // Landing pad for external unwinder.
424 | lwz L, SAVE_L
425 | li TISNUM, LJ_TISNUM // Setup type comparison constants.
426 | lwz BASE, L->base
427 | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
428 | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
429 | li ZERO, 0
430 | stw TMP3, TMPD
431 | li TMP1, LJ_TFALSE
432 | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
433 | li TISNIL, LJ_TNIL
434 | li_vmstate INTERP
435 | lfs TOBIT, TMPD
436 | lwz PC, FRAME_PC(BASE) // Fetch PC of previous frame.
437 | la RA, -8(BASE) // Results start at BASE-8.
438 | stw TMP3, TMPD
439 | addi DISPATCH, DISPATCH, GG_G2DISP
440 | stw TMP1, 0(RA) // Prepend false to error message.
441 | li RD, 16 // 2 results: false + error message.
442 | st_vmstate
443 | lfs TONUM, TMPD
444 | b ->vm_returnc
445 |
446 |//-----------------------------------------------------------------------
447 |//-- Grow stack for calls -----------------------------------------------
448 |//-----------------------------------------------------------------------
449 |
450 |->vm_growstack_c: // Grow stack for C function.
451 | li CARG2, LUA_MINSTACK
452 | b >2
453 |
454 |->vm_growstack_l: // Grow stack for Lua function.
455 | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC
456 | add RC, BASE, RC
457 | sub RA, RA, BASE
458 | stw BASE, L->base
459 | addi PC, PC, 4 // Must point after first instruction.
460 | stw RC, L->top
461 | srwi CARG2, RA, 3
462 |2:
463 | // L->base = new base, L->top = top
464 | stw PC, SAVE_PC
465 | mr CARG1, L
466 | bl extern lj_state_growstack // (lua_State *L, int n)
467 | lwz BASE, L->base
468 | lwz RC, L->top
469 | lwz LFUNC:RB, FRAME_FUNC(BASE)
470 | sub RC, RC, BASE
471 | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
472 | ins_callt // Just retry the call.
473 |
474 |//-----------------------------------------------------------------------
475 |//-- Entry points into the assembler VM ---------------------------------
476 |//-----------------------------------------------------------------------
477 |
478 |->vm_resume: // Setup C frame and resume thread.
479 | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0)
480 | saveregs
481 | mr L, CARG1
482 | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
483 | mr BASE, CARG2
484 | lbz TMP1, L->status
485 | stw L, SAVE_L
486 | li PC, FRAME_CP
487 | addi TMP0, sp, CFRAME_RESUME
488 | addi DISPATCH, DISPATCH, GG_G2DISP
489 | stw CARG3, SAVE_NRES
490 | cmplwi TMP1, 0
491 | stw CARG3, SAVE_ERRF
492 | stw TMP0, L->cframe
493 | stw CARG3, SAVE_CFRAME
494 | stw CARG1, SAVE_PC // Any value outside of bytecode is ok.
495 | beq >3
496 |
497 | // Resume after yield (like a return).
498 | mr RA, BASE
499 | lwz BASE, L->base
500 | li TISNUM, LJ_TISNUM // Setup type comparison constants.
501 | lwz TMP1, L->top
502 | lwz PC, FRAME_PC(BASE)
503 | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
504 | sub RD, TMP1, BASE
505 | stb CARG3, L->status
506 | stw TMP3, TMPD
507 | andi. TMP0, PC, FRAME_TYPE
508 | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
509 | lfs TOBIT, TMPD
510 | li ZERO, 0
511 | stw TMP3, TMPD
512 | addi RD, RD, 8
513 | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double)
514 | mr MULTRES, RD
515 | stw TMP0, TONUM_HI
516 | li_vmstate INTERP
517 | lfs TONUM, TMPD
518 | li TISNIL, LJ_TNIL
519 | st_vmstate
520 | beq ->BC_RET_Z
521 | b ->vm_return
522 |
523 |->vm_pcall: // Setup protected C frame and enter VM.
524 | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef)
525 | saveregs
526 | li PC, FRAME_CP
527 | stw CARG4, SAVE_ERRF
528 | b >1
529 |
530 |->vm_call: // Setup C frame and enter VM.
531 | // (lua_State *L, TValue *base, int nres1)
532 | saveregs
533 | li PC, FRAME_C
534 |
535 |1: // Entry point for vm_pcall above (PC = ftype).
536 | lwz TMP1, L:CARG1->cframe
537 | stw CARG3, SAVE_NRES
538 | mr L, CARG1
539 | stw CARG1, SAVE_L
540 | mr BASE, CARG2
541 | stw sp, L->cframe // Add our C frame to cframe chain.
542 | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
543 | stw CARG1, SAVE_PC // Any value outside of bytecode is ok.
544 | stw TMP1, SAVE_CFRAME
545 | addi DISPATCH, DISPATCH, GG_G2DISP
546 |
547 |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
548 | lwz TMP2, L->base // TMP2 = old base (used in vmeta_call).
549 | li TISNUM, LJ_TISNUM // Setup type comparison constants.
550 | lwz TMP1, L->top
551 | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
552 | add PC, PC, BASE
553 | stw TMP3, TMPD
554 | li ZERO, 0
555 | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
556 | lfs TOBIT, TMPD
557 | sub PC, PC, TMP2 // PC = frame delta + frame type
558 | stw TMP3, TMPD
559 | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double)
560 | sub NARGS8:RC, TMP1, BASE
561 | stw TMP0, TONUM_HI
562 | li_vmstate INTERP
563 | lfs TONUM, TMPD
564 | li TISNIL, LJ_TNIL
565 | st_vmstate
566 |
567 |->vm_call_dispatch:
568 | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC
569 | lwz TMP0, FRAME_PC(BASE)
570 | lwz LFUNC:RB, FRAME_FUNC(BASE)
571 | checkfunc TMP0; bne ->vmeta_call
572 |
573 |->vm_call_dispatch_f:
574 | ins_call
575 | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC
576 |
577 |->vm_cpcall: // Setup protected C frame, call C.
578 | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp)
579 | saveregs
580 | mr L, CARG1
581 | lwz TMP0, L:CARG1->stack
582 | stw CARG1, SAVE_L
583 | lwz TMP1, L->top
584 | stw CARG1, SAVE_PC // Any value outside of bytecode is ok.
585 | sub TMP0, TMP0, TMP1 // Compute -savestack(L, L->top).
586 | lwz TMP1, L->cframe
587 | stw sp, L->cframe // Add our C frame to cframe chain.
588 | li TMP2, 0
589 | stw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame.
590 | stw TMP2, SAVE_ERRF // No error function.
591 | stw TMP1, SAVE_CFRAME
592 | mtctr CARG4
593 | bctrl // (lua_State *L, lua_CFunction func, void *ud)
594 | mr. BASE, CRET1
595 | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
596 | li PC, FRAME_CP
597 | addi DISPATCH, DISPATCH, GG_G2DISP
598 | bne <3 // Else continue with the call.
599 | b ->vm_leave_cp // No base? Just remove C frame.
600 |
601 |//-----------------------------------------------------------------------
602 |//-- Metamethod handling ------------------------------------------------
603 |//-----------------------------------------------------------------------
604 |
605 |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the
606 |// stack, so BASE doesn't need to be reloaded across these calls.
607 |
608 |//-- Continuation dispatch ----------------------------------------------
609 |
610 |->cont_dispatch:
611 | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8
612 | lwz TMP0, -12(BASE) // Continuation.
613 | mr RB, BASE
614 | mr BASE, TMP2 // Restore caller BASE.
615 | lwz LFUNC:TMP1, FRAME_FUNC(TMP2)
616#if LJ_HASFFI
617 | cmplwi TMP0, 1
618#endif
619 | lwz PC, -16(RB) // Restore PC from [cont|PC].
620 | subi TMP2, RD, 8
621 | lwz TMP1, LFUNC:TMP1->pc
622 | stwx TISNIL, RA, TMP2 // Ensure one valid arg.
623#if LJ_HASFFI
624 | ble >1
625#endif
626 | lwz KBASE, PC2PROTO(k)(TMP1)
627 | // BASE = base, RA = resultptr, RB = meta base
628 | mtctr TMP0
629 | bctr // Jump to continuation.
630 |
631#if LJ_HASFFI
632 |1:
633 | beq ->cont_ffi_callback // cont = 1: return from FFI callback.
634 | // cont = 0: tailcall from C function.
635 | subi TMP1, RB, 16
636 | sub RC, TMP1, BASE
637 | b ->vm_call_tail
638#endif
639 |
640 |->cont_cat: // RA = resultptr, RB = meta base
641 | lwz INS, -4(PC)
642 | subi CARG2, RB, 16
643 | decode_RB8 SAVE0, INS
644 | lfd f0, 0(RA)
645 | add TMP1, BASE, SAVE0
646 | stw BASE, L->base
647 | cmplw TMP1, CARG2
648 | sub CARG3, CARG2, TMP1
649 | decode_RA8 RA, INS
650 | stfd f0, 0(CARG2)
651 | bney ->BC_CAT_Z
652 | stfdx f0, BASE, RA
653 | b ->cont_nop
654 |
655 |//-- Table indexing metamethods -----------------------------------------
656 |
657 |->vmeta_tgets1:
658 | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
659 | li TMP0, LJ_TSTR
660 | decode_RB8 RB, INS
661 | stw STR:RC, 4(CARG3)
662 | add CARG2, BASE, RB
663 | stw TMP0, 0(CARG3)
664 | b >1
665 |
666 |->vmeta_tgets:
667 | la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
668 | li TMP0, LJ_TTAB
669 | stw TAB:RB, 4(CARG2)
670 | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH)
671 | stw TMP0, 0(CARG2)
672 | li TMP1, LJ_TSTR
673 | stw STR:RC, 4(CARG3)
674 | stw TMP1, 0(CARG3)
675 | b >1
676 |
677 |->vmeta_tgetb: // TMP0 = index
678 if (!LJ_DUALNUM) {
679 | tonum_u f0, TMP0
680 }
681 | decode_RB8 RB, INS
682 | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
683 | add CARG2, BASE, RB
684 if (LJ_DUALNUM) {
685 | stw TISNUM, 0(CARG3)
686 | stw TMP0, 4(CARG3)
687 } else {
688 | stfd f0, 0(CARG3)
689 }
690 | b >1
691 |
692 |->vmeta_tgetv:
693 | decode_RB8 RB, INS
694 | decode_RC8 RC, INS
695 | add CARG2, BASE, RB
696 | add CARG3, BASE, RC
697 |1:
698 | stw BASE, L->base
699 | mr CARG1, L
700 | stw PC, SAVE_PC
701 | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k)
702 | // Returns TValue * (finished) or NULL (metamethod).
703 | cmplwi CRET1, 0
704 | beq >3
705 | lfd f0, 0(CRET1)
706 | ins_next1
707 | stfdx f0, BASE, RA
708 | ins_next2
709 |
710 |3: // Call __index metamethod.
711 | // BASE = base, L->top = new base, stack = cont/func/t/k
712 | subfic TMP1, BASE, FRAME_CONT
713 | lwz BASE, L->top
714 | stw PC, -16(BASE) // [cont|PC]
715 | add PC, TMP1, BASE
716 | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
717 | li NARGS8:RC, 16 // 2 args for func(t, k).
718 | b ->vm_call_dispatch_f
719 |
720 |//-----------------------------------------------------------------------
721 |
722 |->vmeta_tsets1:
723 | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
724 | li TMP0, LJ_TSTR
725 | decode_RB8 RB, INS
726 | stw STR:RC, 4(CARG3)
727 | add CARG2, BASE, RB
728 | stw TMP0, 0(CARG3)
729 | b >1
730 |
731 |->vmeta_tsets:
732 | la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
733 | li TMP0, LJ_TTAB
734 | stw TAB:RB, 4(CARG2)
735 | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH)
736 | stw TMP0, 0(CARG2)
737 | li TMP1, LJ_TSTR
738 | stw STR:RC, 4(CARG3)
739 | stw TMP1, 0(CARG3)
740 | b >1
741 |
742 |->vmeta_tsetb: // TMP0 = index
743 if (!LJ_DUALNUM) {
744 | tonum_u f0, TMP0
745 }
746 | decode_RB8 RB, INS
747 | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
748 | add CARG2, BASE, RB
749 if (LJ_DUALNUM) {
750 | stw TISNUM, 0(CARG3)
751 | stw TMP0, 4(CARG3)
752 } else {
753 | stfd f0, 0(CARG3)
754 }
755 | b >1
756 |
757 |->vmeta_tsetv:
758 | decode_RB8 RB, INS
759 | decode_RC8 RC, INS
760 | add CARG2, BASE, RB
761 | add CARG3, BASE, RC
762 |1:
763 | stw BASE, L->base
764 | mr CARG1, L
765 | stw PC, SAVE_PC
766 | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k)
767 | // Returns TValue * (finished) or NULL (metamethod).
768 | cmplwi CRET1, 0
769 | lfdx f0, BASE, RA
770 | beq >3
771 | // NOBARRIER: lj_meta_tset ensures the table is not black.
772 | ins_next1
773 | stfd f0, 0(CRET1)
774 | ins_next2
775 |
776 |3: // Call __newindex metamethod.
777 | // BASE = base, L->top = new base, stack = cont/func/t/k/(v)
778 | subfic TMP1, BASE, FRAME_CONT
779 | lwz BASE, L->top
780 | stw PC, -16(BASE) // [cont|PC]
781 | add PC, TMP1, BASE
782 | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
783 | li NARGS8:RC, 24 // 3 args for func(t, k, v)
784 | stfd f0, 16(BASE) // Copy value to third argument.
785 | b ->vm_call_dispatch_f
786 |
787 |//-- Comparison metamethods ---------------------------------------------
788 |
789 |->vmeta_comp:
790 | mr CARG1, L
791 | subi PC, PC, 4
792 if (LJ_DUALNUM) {
793 | mr CARG2, RA
794 } else {
795 | add CARG2, BASE, RA
796 }
797 | stw PC, SAVE_PC
798 if (LJ_DUALNUM) {
799 | mr CARG3, RD
800 } else {
801 | add CARG3, BASE, RD
802 }
803 | stw BASE, L->base
804 | decode_OP1 CARG4, INS
805 | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op)
806 | // Returns 0/1 or TValue * (metamethod).
807 |3:
808 | cmplwi CRET1, 1
809 | bgt ->vmeta_binop
810 | subfic CRET1, CRET1, 0
811 |4:
812 | lwz INS, 0(PC)
813 | addi PC, PC, 4
814 | decode_RD4 TMP2, INS
815 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
816 | and TMP2, TMP2, CRET1
817 | add PC, PC, TMP2
818 |->cont_nop:
819 | ins_next
820 |
821 |->cont_ra: // RA = resultptr
822 | lwz INS, -4(PC)
823 | lfd f0, 0(RA)
824 | decode_RA8 TMP1, INS
825 | stfdx f0, BASE, TMP1
826 | b ->cont_nop
827 |
828 |->cont_condt: // RA = resultptr
829 | lwz TMP0, 0(RA)
830 | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is true.
831 | subfe CRET1, CRET1, CRET1
832 | not CRET1, CRET1
833 | b <4
834 |
835 |->cont_condf: // RA = resultptr
836 | lwz TMP0, 0(RA)
837 | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is false.
838 | subfe CRET1, CRET1, CRET1
839 | b <4
840 |
841 |->vmeta_equal:
842 | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV.
843 | subi PC, PC, 4
844 | stw BASE, L->base
845 | mr CARG1, L
846 | stw PC, SAVE_PC
847 | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne)
848 | // Returns 0/1 or TValue * (metamethod).
849 | b <3
850 |
851 |->vmeta_equal_cd:
852#if LJ_HASFFI
853 | mr CARG2, INS
854 | subi PC, PC, 4
855 | stw BASE, L->base
856 | mr CARG1, L
857 | stw PC, SAVE_PC
858 | bl extern lj_meta_equal_cd // (lua_State *L, BCIns op)
859 | // Returns 0/1 or TValue * (metamethod).
860 | b <3
861#endif
862 |
863 |//-- Arithmetic metamethods ---------------------------------------------
864 |
865 |->vmeta_arith_nv:
866 | add CARG3, KBASE, RC
867 | add CARG4, BASE, RB
868 | b >1
869 |->vmeta_arith_nv2:
870 if (LJ_DUALNUM) {
871 | mr CARG3, RC
872 | mr CARG4, RB
873 | b >1
874 }
875 |
876 |->vmeta_unm:
877 | mr CARG3, RD
878 | mr CARG4, RD
879 | b >1
880 |
881 |->vmeta_arith_vn:
882 | add CARG3, BASE, RB
883 | add CARG4, KBASE, RC
884 | b >1
885 |
886 |->vmeta_arith_vv:
887 | add CARG3, BASE, RB
888 | add CARG4, BASE, RC
889 if (LJ_DUALNUM) {
890 | b >1
891 }
892 |->vmeta_arith_vn2:
893 |->vmeta_arith_vv2:
894 if (LJ_DUALNUM) {
895 | mr CARG3, RB
896 | mr CARG4, RC
897 }
898 |1:
899 | add CARG2, BASE, RA
900 | stw BASE, L->base
901 | mr CARG1, L
902 | stw PC, SAVE_PC
903 | decode_OP1 CARG5, INS // Caveat: CARG5 overlaps INS.
904 | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
905 | // Returns NULL (finished) or TValue * (metamethod).
906 | cmplwi CRET1, 0
907 | beq ->cont_nop
908 |
909 | // Call metamethod for binary op.
910 |->vmeta_binop:
911 | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2
912 | sub TMP1, CRET1, BASE
913 | stw PC, -16(CRET1) // [cont|PC]
914 | mr TMP2, BASE
915 | addi PC, TMP1, FRAME_CONT
916 | mr BASE, CRET1
917 | li NARGS8:RC, 16 // 2 args for func(o1, o2).
918 | b ->vm_call_dispatch
919 |
920 |->vmeta_len:
921#ifdef LUAJIT_ENABLE_LUA52COMPAT
922 | mr SAVE0, CARG1
923#endif
924 | mr CARG2, RD
925 | stw BASE, L->base
926 | mr CARG1, L
927 | stw PC, SAVE_PC
928 | bl extern lj_meta_len // (lua_State *L, TValue *o)
929 | // Returns NULL (retry) or TValue * (metamethod base).
930#ifdef LUAJIT_ENABLE_LUA52COMPAT
931 | cmplwi CRET1, 0
932 | bne ->vmeta_binop // Binop call for compatibility.
933 | mr CARG1, SAVE0
934 | b ->BC_LEN_Z
935#else
936 | b ->vmeta_binop // Binop call for compatibility.
937#endif
938 |
939 |//-- Call metamethod ----------------------------------------------------
940 |
941 |->vmeta_call: // Resolve and call __call metamethod.
942 | // TMP2 = old base, BASE = new base, RC = nargs*8
943 | mr CARG1, L
944 | stw TMP2, L->base // This is the callers base!
945 | subi CARG2, BASE, 8
946 | stw PC, SAVE_PC
947 | add CARG3, BASE, RC
948 | mr SAVE0, NARGS8:RC
949 | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
950 | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
951 | addi NARGS8:RC, SAVE0, 8 // Got one more argument now.
952 | ins_call
953 |
954 |->vmeta_callt: // Resolve __call for BC_CALLT.
955 | // BASE = old base, RA = new base, RC = nargs*8
956 | mr CARG1, L
957 | stw BASE, L->base
958 | subi CARG2, RA, 8
959 | stw PC, SAVE_PC
960 | add CARG3, RA, RC
961 | mr SAVE0, NARGS8:RC
962 | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
963 | lwz TMP1, FRAME_PC(BASE)
964 | addi NARGS8:RC, SAVE0, 8 // Got one more argument now.
965 | lwz LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here.
966 | b ->BC_CALLT_Z
967 |
968 |//-- Argument coercion for 'for' statement ------------------------------
969 |
970 |->vmeta_for:
971 | mr CARG1, L
972 | stw BASE, L->base
973 | mr CARG2, RA
974 | stw PC, SAVE_PC
975 | mr SAVE0, INS
976 | bl extern lj_meta_for // (lua_State *L, TValue *base)
977#if LJ_HASJIT
978 | decode_OP1 TMP0, SAVE0
979#endif
980 | decode_RA8 RA, SAVE0
981#if LJ_HASJIT
982 | cmpwi TMP0, BC_JFORI
983#endif
984 | decode_RD8 RD, SAVE0
985#if LJ_HASJIT
986 | beqy =>BC_JFORI
987#endif
988 | b =>BC_FORI
989 |
990 |//-----------------------------------------------------------------------
991 |//-- Fast functions -----------------------------------------------------
992 |//-----------------------------------------------------------------------
993 |
994 |.macro .ffunc, name
995 |->ff_ .. name:
996 |.endmacro
997 |
998 |.macro .ffunc_1, name
999 |->ff_ .. name:
1000 | cmplwi NARGS8:RC, 8
1001 | lwz CARG3, 0(BASE)
1002 | lwz CARG1, 4(BASE)
1003 | blt ->fff_fallback
1004 |.endmacro
1005 |
1006 |.macro .ffunc_2, name
1007 |->ff_ .. name:
1008 | cmplwi NARGS8:RC, 16
1009 | lwz CARG3, 0(BASE)
1010 | lwz CARG4, 8(BASE)
1011 | lwz CARG1, 4(BASE)
1012 | lwz CARG2, 12(BASE)
1013 | blt ->fff_fallback
1014 |.endmacro
1015 |
1016 |.macro .ffunc_n, name
1017 |->ff_ .. name:
1018 | cmplwi NARGS8:RC, 8
1019 | lwz CARG3, 0(BASE)
1020 | lfd FARG1, 0(BASE)
1021 | blt ->fff_fallback
1022 | checknum CARG3; bge ->fff_fallback
1023 |.endmacro
1024 |
1025 |.macro .ffunc_nn, name
1026 |->ff_ .. name:
1027 | cmplwi NARGS8:RC, 16
1028 | lwz CARG3, 0(BASE)
1029 | lfd FARG1, 0(BASE)
1030 | lwz CARG4, 8(BASE)
1031 | lfd FARG2, 8(BASE)
1032 | blt ->fff_fallback
1033 | checknum CARG3; bge ->fff_fallback
1034 | checknum CARG4; bge ->fff_fallback
1035 |.endmacro
1036 |
1037 |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1.
1038 |.macro ffgccheck
1039 | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH)
1040 | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
1041 | cmplw TMP0, TMP1
1042 | bgel ->fff_gcstep
1043 |.endmacro
1044 |
1045 |//-- Base library: checks -----------------------------------------------
1046 |
1047 |.ffunc_1 assert
1048 | li TMP1, LJ_TFALSE
1049 | la RA, -8(BASE)
1050 | cmplw cr1, CARG3, TMP1
1051 | lwz PC, FRAME_PC(BASE)
1052 | bge cr1, ->fff_fallback
1053 | stw CARG3, 0(RA)
1054 | addi RD, NARGS8:RC, 8 // Compute (nresults+1)*8.
1055 | stw CARG1, 4(RA)
1056 | beq ->fff_res // Done if exactly 1 argument.
1057 | li TMP1, 8
1058 | subi RC, RC, 8
1059 |1:
1060 | cmplw TMP1, RC
1061 | lfdx f0, BASE, TMP1
1062 | stfdx f0, RA, TMP1
1063 | addi TMP1, TMP1, 8
1064 | bney <1
1065 | b ->fff_res
1066 |
1067 |.ffunc type
1068 | cmplwi NARGS8:RC, 8
1069 | lwz CARG1, 0(BASE)
1070 | blt ->fff_fallback
1071 | subfc TMP0, TISNUM, CARG1
1072 | subfe TMP2, CARG1, CARG1
1073 | orc TMP1, TMP2, TMP0
1074 | addi TMP1, TMP1, ~LJ_TISNUM+1
1075 | slwi TMP1, TMP1, 3
1076 | la TMP2, CFUNC:RB->upvalue
1077 | lfdx FARG1, TMP2, TMP1
1078 | b ->fff_resn
1079 |
1080 |//-- Base library: getters and setters ---------------------------------
1081 |
1082 |.ffunc_1 getmetatable
1083 | checktab CARG3; bne >6
1084 |1: // Field metatable must be at same offset for GCtab and GCudata!
1085 | lwz TAB:CARG1, TAB:CARG1->metatable
1086 |2:
1087 | li CARG3, LJ_TNIL
1088 | cmplwi TAB:CARG1, 0
1089 | lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH)
1090 | beq ->fff_restv
1091 | lwz TMP0, TAB:CARG1->hmask
1092 | li CARG3, LJ_TTAB // Use metatable as default result.
1093 | lwz TMP1, STR:RC->hash
1094 | lwz NODE:TMP2, TAB:CARG1->node
1095 | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
1096 | slwi TMP0, TMP1, 5
1097 | slwi TMP1, TMP1, 3
1098 | sub TMP1, TMP0, TMP1
1099 | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
1100 |3: // Rearranged logic, because we expect _not_ to find the key.
1101 | lwz CARG4, NODE:TMP2->key
1102 | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2)
1103 | lwz CARG2, NODE:TMP2->val
1104 | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2)
1105 | checkstr CARG4; bne >4
1106 | cmpw TMP0, STR:RC; beq >5
1107 |4:
1108 | lwz NODE:TMP2, NODE:TMP2->next
1109 | cmplwi NODE:TMP2, 0
1110 | beq ->fff_restv // Not found, keep default result.
1111 | b <3
1112 |5:
1113 | checknil CARG2
1114 | beq ->fff_restv // Ditto for nil value.
1115 | mr CARG3, CARG2 // Return value of mt.__metatable.
1116 | mr CARG1, TMP1
1117 | b ->fff_restv
1118 |
1119 |6:
1120 | cmpwi CARG3, LJ_TUDATA; beq <1
1121 | subfc TMP0, TISNUM, CARG3
1122 | subfe TMP2, CARG3, CARG3
1123 | orc TMP1, TMP2, TMP0
1124 | addi TMP1, TMP1, ~LJ_TISNUM+1
1125 | slwi TMP1, TMP1, 2
1126 | la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH)
1127 | lwzx TAB:CARG1, TMP2, TMP1
1128 | b <2
1129 |
1130 |.ffunc_2 setmetatable
1131 | // Fast path: no mt for table yet and not clearing the mt.
1132 | checktab CARG3; bne ->fff_fallback
1133 | lwz TAB:TMP1, TAB:CARG1->metatable
1134 | checktab CARG4; bne ->fff_fallback
1135 | cmplwi TAB:TMP1, 0
1136 | lbz TMP3, TAB:CARG1->marked
1137 | bne ->fff_fallback
1138 | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
1139 | stw TAB:CARG2, TAB:CARG1->metatable
1140 | beq ->fff_restv
1141 | barrierback TAB:CARG1, TMP3, TMP0
1142 | b ->fff_restv
1143 |
1144 |.ffunc rawget
1145 | cmplwi NARGS8:RC, 8
1146 | lwz CARG4, 0(BASE)
1147 | lwz TAB:CARG2, 4(BASE)
1148 | blt ->fff_fallback
1149 | checktab CARG4; bne ->fff_fallback
1150 | la CARG3, 8(BASE)
1151 | mr CARG1, L
1152 | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key)
1153 | // Returns cTValue *.
1154 | lfd FARG1, 0(CRET1)
1155 | b ->fff_resn
1156 |
1157 |//-- Base library: conversions ------------------------------------------
1158 |
1159 |.ffunc tonumber
1160 | // Only handles the number case inline (without a base argument).
1161 | cmplwi NARGS8:RC, 8
1162 | lwz CARG1, 0(BASE)
1163 | lfd FARG1, 0(BASE)
1164 | bne ->fff_fallback // Exactly one argument.
1165 | checknum CARG1; bgt ->fff_fallback
1166 | b ->fff_resn
1167 |
1168 |.ffunc_1 tostring
1169 | // Only handles the string or number case inline.
1170 | checkstr CARG3
1171 | // A __tostring method in the string base metatable is ignored.
1172 | beq ->fff_restv // String key?
1173 | // Handle numbers inline, unless a number base metatable is present.
1174 | lwz TMP0, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH)
1175 | checknum CARG3
1176 | cmplwi cr1, TMP0, 0
1177 | stw BASE, L->base // Add frame since C call can throw.
1178 | crorc 4*cr0+eq, 4*cr0+gt, 4*cr1+eq
1179 | stw PC, SAVE_PC // Redundant (but a defined value).
1180 | beq ->fff_fallback
1181 | ffgccheck
1182 | mr CARG1, L
1183 | mr CARG2, BASE
1184 if (LJ_DUALNUM) {
1185 | bl extern lj_str_fromnumber // (lua_State *L, cTValue *o)
1186 } else {
1187 | bl extern lj_str_fromnum // (lua_State *L, lua_Number *np)
1188 }
1189 | // Returns GCstr *.
1190 | li CARG3, LJ_TSTR
1191 | b ->fff_restv
1192 |
1193 |//-- Base library: iterators -------------------------------------------
1194 |
1195 |.ffunc next
1196 | cmplwi NARGS8:RC, 8
1197 | lwz CARG1, 0(BASE)
1198 | lwz TAB:CARG2, 4(BASE)
1199 | blt ->fff_fallback
1200 | stwx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil.
1201 | checktab CARG1
1202 | lwz PC, FRAME_PC(BASE)
1203 | bne ->fff_fallback
1204 | stw BASE, L->base // Add frame since C call can throw.
1205 | mr CARG1, L
1206 | stw BASE, L->top // Dummy frame length is ok.
1207 | la CARG3, 8(BASE)
1208 | stw PC, SAVE_PC
1209 | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key)
1210 | // Returns 0 at end of traversal.
1211 | cmplwi CRET1, 0
1212 | li CARG3, LJ_TNIL
1213 | beq ->fff_restv // End of traversal: return nil.
1214 | lfd f0, 8(BASE) // Copy key and value to results.
1215 | la RA, -8(BASE)
1216 | lfd f1, 16(BASE)
1217 | stfd f0, 0(RA)
1218 | li RD, (2+1)*8
1219 | stfd f1, 8(RA)
1220 | b ->fff_res
1221 |
1222 |.ffunc_1 pairs
1223 | checktab CARG3
1224 | lwz PC, FRAME_PC(BASE)
1225 | bne ->fff_fallback
1226#ifdef LUAJIT_ENABLE_LUA52COMPAT
1227 | lwz TAB:TMP2, TAB:CARG1->metatable
1228 | lfd f0, CFUNC:RB->upvalue[0]
1229 | cmplwi TAB:TMP2, 0
1230 | la RA, -8(BASE)
1231 | bne ->fff_fallback
1232#else
1233 | lfd f0, CFUNC:RB->upvalue[0]
1234 | la RA, -8(BASE)
1235#endif
1236 | stw TISNIL, 8(BASE)
1237 | li RD, (3+1)*8
1238 | stfd f0, 0(RA)
1239 | b ->fff_res
1240 |
1241 |.ffunc ipairs_aux
1242 | cmplwi NARGS8:RC, 16
1243 | lwz CARG3, 0(BASE)
1244 | lwz TAB:CARG1, 4(BASE)
1245 | lwz CARG4, 8(BASE)
1246 if (LJ_DUALNUM) {
1247 | lwz TMP2, 12(BASE)
1248 } else {
1249 | lfd FARG2, 8(BASE)
1250 }
1251 | blt ->fff_fallback
1252 | checktab CARG3
1253 | checknum cr1, CARG4
1254 | lwz PC, FRAME_PC(BASE)
1255 if (LJ_DUALNUM) {
1256 | bne ->fff_fallback
1257 | bne cr1, ->fff_fallback
1258 } else {
1259 | lus TMP0, 0x3ff0
1260 | stw ZERO, TMPD_LO
1261 | bne ->fff_fallback
1262 | stw TMP0, TMPD_HI
1263 | bge cr1, ->fff_fallback
1264 | lfd FARG1, TMPD
1265 | toint TMP2, FARG2, f0
1266 }
1267 | lwz TMP0, TAB:CARG1->asize
1268 | lwz TMP1, TAB:CARG1->array
1269 if (!LJ_DUALNUM) {
1270 | fadd FARG2, FARG2, FARG1
1271 }
1272 | addi TMP2, TMP2, 1
1273 | la RA, -8(BASE)
1274 | cmplw TMP0, TMP2
1275 if (LJ_DUALNUM) {
1276 | stw TISNUM, 0(RA)
1277 | slwi TMP3, TMP2, 3
1278 | stw TMP2, 4(RA)
1279 } else {
1280 | slwi TMP3, TMP2, 3
1281 | stfd FARG2, 0(RA)
1282 }
1283 | ble >2 // Not in array part?
1284 | lwzx TMP2, TMP1, TMP3
1285 | lfdx f0, TMP1, TMP3
1286 |1:
1287 | checknil TMP2
1288 | li RD, (0+1)*8
1289 | beq ->fff_res // End of iteration, return 0 results.
1290 | li RD, (2+1)*8
1291 | stfd f0, 8(RA)
1292 | b ->fff_res
1293 |2: // Check for empty hash part first. Otherwise call C function.
1294 | lwz TMP0, TAB:CARG1->hmask
1295 | cmplwi TMP0, 0
1296 | li RD, (0+1)*8
1297 | beq ->fff_res
1298 | mr CARG2, TMP2
1299 | bl extern lj_tab_getinth // (GCtab *t, int32_t key)
1300 | // Returns cTValue * or NULL.
1301 | cmplwi CRET1, 0
1302 | li RD, (0+1)*8
1303 | beq ->fff_res
1304 | lwz TMP2, 0(CRET1)
1305 | lfd f0, 0(CRET1)
1306 | b <1
1307 |
1308 |.ffunc_1 ipairs
1309 | checktab CARG3
1310 | lwz PC, FRAME_PC(BASE)
1311 | bne ->fff_fallback
1312#ifdef LUAJIT_ENABLE_LUA52COMPAT
1313 | lwz TAB:TMP2, TAB:CARG1->metatable
1314 | lfd f0, CFUNC:RB->upvalue[0]
1315 | cmplwi TAB:TMP2, 0
1316 | la RA, -8(BASE)
1317 | bne ->fff_fallback
1318#else
1319 | lfd f0, CFUNC:RB->upvalue[0]
1320 | la RA, -8(BASE)
1321#endif
1322 if (LJ_DUALNUM) {
1323 | stw TISNUM, 8(BASE)
1324 } else {
1325 | stw ZERO, 8(BASE)
1326 }
1327 | stw ZERO, 12(BASE)
1328 | li RD, (3+1)*8
1329 | stfd f0, 0(RA)
1330 | b ->fff_res
1331 |
1332 |//-- Base library: catch errors ----------------------------------------
1333 |
1334 |.ffunc pcall
1335 | cmplwi NARGS8:RC, 8
1336 | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
1337 | blt ->fff_fallback
1338 | mr TMP2, BASE
1339 | la BASE, 8(BASE)
1340 | // Remember active hook before pcall.
1341 | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31
1342 | subi NARGS8:RC, NARGS8:RC, 8
1343 | addi PC, TMP3, 8+FRAME_PCALL
1344 | b ->vm_call_dispatch
1345 |
1346 |.ffunc xpcall
1347 | cmplwi NARGS8:RC, 16
1348 | lwz CARG4, 8(BASE)
1349 | lfd FARG2, 8(BASE)
1350 | lwz CARG3, 0(BASE)
1351 | lfd FARG1, 0(BASE)
1352 | blt ->fff_fallback
1353 | lbz TMP1, DISPATCH_GL(hookmask)(DISPATCH)
1354 | mr TMP2, BASE
1355 | checkfunc CARG4; bne ->fff_fallback // Traceback must be a function.
1356 | la BASE, 16(BASE)
1357 | // Remember active hook before pcall.
1358 | rlwinm TMP1, TMP1, 32-HOOK_ACTIVE_SHIFT, 31, 31
1359 | stfd FARG2, 0(TMP2) // Swap function and traceback.
1360 | subi NARGS8:RC, NARGS8:RC, 16
1361 | stfd FARG1, 8(TMP2)
1362 | addi PC, TMP1, 16+FRAME_PCALL
1363 | b ->vm_call_dispatch
1364 |
1365 |//-- Coroutine library --------------------------------------------------
1366 |
1367 |.macro coroutine_resume_wrap, resume
1368 |.if resume
1369 |.ffunc_1 coroutine_resume
1370 | cmpwi CARG3, LJ_TTHREAD; bne ->fff_fallback
1371 |.else
1372 |.ffunc coroutine_wrap_aux
1373 | lwz L:CARG1, CFUNC:RB->upvalue[0].gcr
1374 |.endif
1375 | lbz TMP0, L:CARG1->status
1376 | lwz TMP1, L:CARG1->cframe
1377 | lwz CARG2, L:CARG1->top
1378 | cmplwi cr0, TMP0, LUA_YIELD
1379 | lwz TMP2, L:CARG1->base
1380 | cmplwi cr1, TMP1, 0
1381 | lwz TMP0, L:CARG1->maxstack
1382 | cmplw cr7, CARG2, TMP2
1383 | lwz PC, FRAME_PC(BASE)
1384 | crorc 4*cr6+lt, 4*cr0+gt, 4*cr1+eq // st>LUA_YIELD || cframe!=0
1385 | add TMP2, CARG2, NARGS8:RC
1386 | crandc 4*cr6+gt, 4*cr7+eq, 4*cr0+eq // base==top && st!=LUA_YIELD
1387 | cmplw cr1, TMP2, TMP0
1388 | cror 4*cr6+lt, 4*cr6+lt, 4*cr6+gt
1389 | stw PC, SAVE_PC
1390 | cror 4*cr6+lt, 4*cr6+lt, 4*cr1+gt // cond1 || cond2 || stackov
1391 | stw BASE, L->base
1392 | blt cr6, ->fff_fallback
1393 |1:
1394 |.if resume
1395 | addi BASE, BASE, 8 // Keep resumed thread in stack for GC.
1396 | subi NARGS8:RC, NARGS8:RC, 8
1397 | subi TMP2, TMP2, 8
1398 |.endif
1399 | stw TMP2, L:CARG1->top
1400 | li TMP1, 0
1401 | stw BASE, L->top
1402 |2: // Move args to coroutine.
1403 | cmpw TMP1, NARGS8:RC
1404 | lfdx f0, BASE, TMP1
1405 | beq >3
1406 | stfdx f0, CARG2, TMP1
1407 | addi TMP1, TMP1, 8
1408 | b <2
1409 |3:
1410 | li CARG3, 0
1411 | mr L:SAVE0, L:CARG1
1412 | li CARG4, 0
1413 | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0)
1414 | // Returns thread status.
1415 |4:
1416 | lwz TMP2, L:SAVE0->base
1417 | cmplwi CRET1, LUA_YIELD
1418 | lwz TMP3, L:SAVE0->top
1419 | li_vmstate INTERP
1420 | lwz BASE, L->base
1421 | st_vmstate
1422 | bgt >8
1423 | sub RD, TMP3, TMP2
1424 | lwz TMP0, L->maxstack
1425 | cmplwi RD, 0
1426 | add TMP1, BASE, RD
1427 | beq >6 // No results?
1428 | cmplw TMP1, TMP0
1429 | li TMP1, 0
1430 | bgt >9 // Need to grow stack?
1431 |
1432 | subi TMP3, RD, 8
1433 | stw TMP2, L:SAVE0->top // Clear coroutine stack.
1434 |5: // Move results from coroutine.
1435 | cmplw TMP1, TMP3
1436 | lfdx f0, TMP2, TMP1
1437 | stfdx f0, BASE, TMP1
1438 | addi TMP1, TMP1, 8
1439 | bne <5
1440 |6:
1441 | andi. TMP0, PC, FRAME_TYPE
1442 |.if resume
1443 | li TMP1, LJ_TTRUE
1444 | la RA, -8(BASE)
1445 | stw TMP1, -8(BASE) // Prepend true to results.
1446 | addi RD, RD, 16
1447 |.else
1448 | mr RA, BASE
1449 | addi RD, RD, 8
1450 |.endif
1451 |7:
1452 | stw PC, SAVE_PC
1453 | mr MULTRES, RD
1454 | beq ->BC_RET_Z
1455 | b ->vm_return
1456 |
1457 |8: // Coroutine returned with error (at co->top-1).
1458 |.if resume
1459 | andi. TMP0, PC, FRAME_TYPE
1460 | la TMP3, -8(TMP3)
1461 | li TMP1, LJ_TFALSE
1462 | lfd f0, 0(TMP3)
1463 | stw TMP3, L:SAVE0->top // Remove error from coroutine stack.
1464 | li RD, (2+1)*8
1465 | stw TMP1, -8(BASE) // Prepend false to results.
1466 | la RA, -8(BASE)
1467 | stfd f0, 0(BASE) // Copy error message.
1468 | b <7
1469 |.else
1470 | mr CARG1, L
1471 | mr CARG2, L:SAVE0
1472 | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co)
1473 |.endif
1474 |
1475 |9: // Handle stack expansion on return from yield.
1476 | mr CARG1, L
1477 | srwi CARG2, RD, 3
1478 | bl extern lj_state_growstack // (lua_State *L, int n)
1479 | li CRET1, 0
1480 | b <4
1481 |.endmacro
1482 |
1483 | coroutine_resume_wrap 1 // coroutine.resume
1484 | coroutine_resume_wrap 0 // coroutine.wrap
1485 |
1486 |.ffunc coroutine_yield
1487 | lwz TMP0, L->cframe
1488 | add TMP1, BASE, NARGS8:RC
1489 | stw BASE, L->base
1490 | andi. TMP0, TMP0, CFRAME_RESUME
1491 | stw TMP1, L->top
1492 | li CRET1, LUA_YIELD
1493 | beq ->fff_fallback
1494 | stw ZERO, L->cframe
1495 | stb CRET1, L->status
1496 | b ->vm_leave_unw
1497 |
1498 |//-- Math library -------------------------------------------------------
1499 |
1500 |.ffunc_1 math_abs
1501 | checknum CARG3
1502 if (LJ_DUALNUM) {
1503 | bne >2
1504 | srawi TMP1, CARG1, 31
1505 | xor TMP2, TMP1, CARG1
1506 | sub. CARG1, TMP2, TMP1
1507 | blt >1
1508 |->fff_resi:
1509 | lwz PC, FRAME_PC(BASE)
1510 | la RA, -8(BASE)
1511 | stw TISNUM, -8(BASE)
1512 | stw CRET1, -4(BASE)
1513 | b ->fff_res1
1514 |1:
1515 | lus CARG3, 0x41e0 // 2^31.
1516 | li CARG1, 0
1517 | b ->fff_restv
1518 |2:
1519 }
1520 | bge ->fff_fallback
1521 | rlwinm CARG3, CARG3, 0, 1, 31
1522 | // Fallthrough.
1523 |
1524 |->fff_restv:
1525 | // CARG3/CARG1 = TValue result.
1526 | lwz PC, FRAME_PC(BASE)
1527 | stw CARG3, -8(BASE)
1528 | la RA, -8(BASE)
1529 | stw CARG1, -4(BASE)
1530 |->fff_res1:
1531 | // RA = results, PC = return.
1532 | li RD, (1+1)*8
1533 |->fff_res:
1534 | // RA = results, RD = (nresults+1)*8, PC = return.
1535 | andi. TMP0, PC, FRAME_TYPE
1536 | mr MULTRES, RD
1537 | bney ->vm_return
1538 | lwz INS, -4(PC)
1539 | decode_RB8 RB, INS
1540 |5:
1541 | cmplw RB, RD // More results expected?
1542 | decode_RA8 TMP0, INS
1543 | bgt >6
1544 | ins_next1
1545 | // Adjust BASE. KBASE is assumed to be set for the calling frame.
1546 | sub BASE, RA, TMP0
1547 | ins_next2
1548 |
1549 |6: // Fill up results with nil.
1550 | subi TMP1, RD, 8
1551 | addi RD, RD, 8
1552 | stwx TISNIL, RA, TMP1
1553 | b <5
1554 |
1555 |.macro math_extern, func
1556 | .ffunc_n math_ .. func
1557 | bl extern func
1558 | b ->fff_resn
1559 |.endmacro
1560 |
1561 |.macro math_extern2, func
1562 | .ffunc_nn math_ .. func
1563 | bl extern func
1564 | b ->fff_resn
1565 |.endmacro
1566 |
1567 |.macro math_round, func
1568 | .ffunc_1 math_ .. func
1569 | checknum CARG3; beqy ->fff_restv
1570 | rlwinm TMP2, CARG3, 12, 21, 31
1571 | bge ->fff_fallback
1572 | addic. TMP2, TMP2, -1023 // exp = exponent(x) - 1023
1573 | cmplwi cr1, TMP2, 31 // 0 <= exp < 31?
1574 | subfic TMP0, TMP2, 31
1575 | blt >3
1576 | slwi TMP1, CARG3, 11
1577 | srwi TMP3, CARG1, 21
1578 | oris TMP1, TMP1, 0x8000
1579 | addi TMP2, TMP2, 1
1580 | or TMP1, TMP1, TMP3
1581 | slwi CARG2, CARG1, 11
1582 | bge cr1, >4
1583 | slw TMP3, TMP1, TMP2
1584 | srw CARG1, TMP1, TMP0
1585 | or TMP3, TMP3, CARG2
1586 | srawi TMP2, CARG3, 31
1587 |.if "func" == "floor"
1588 | and TMP1, TMP3, TMP2
1589 | addic TMP0, TMP1, -1
1590 | subfe TMP1, TMP0, TMP1
1591 | add CARG1, CARG1, TMP1
1592 | xor CARG1, CARG1, TMP2
1593 | sub CARG1, CARG1, TMP2
1594 | b ->fff_resi
1595 |.else
1596 | andc TMP1, TMP3, TMP2
1597 | addic TMP0, TMP1, -1
1598 | subfe TMP1, TMP0, TMP1
1599 | addo. CARG1, CARG1, TMP1
1600 | xor CARG1, CARG1, TMP2
1601 | sub CARG1, CARG1, TMP2
1602 | bns ->fff_resi
1603 | // Potential overflow.
1604 | mcrxr cr0; bley ->fff_resi // Ignore unrelated overflow.
1605 | lus CARG3, 0x41e0 // 2^31.
1606 | li CARG1, 0
1607 | b ->fff_restv
1608 |.endif
1609 |3: // |x| < 1
1610 | add TMP2, CARG3, CARG3
1611 | srawi TMP1, CARG3, 31
1612 | or TMP2, CARG1, TMP2 // ztest = (hi+hi) | lo
1613 |.if "func" == "floor"
1614 | and TMP1, TMP2, TMP1 // (ztest & sign) == 0 ? 0 : -1
1615 | subfic TMP2, TMP1, 0
1616 | subfe CARG1, CARG1, CARG1
1617 |.else
1618 | andc TMP1, TMP2, TMP1 // (ztest & ~sign) == 0 ? 0 : 1
1619 | addic TMP2, TMP1, -1
1620 | subfe CARG1, TMP2, TMP1
1621 |.endif
1622 | b ->fff_resi
1623 |4: // exp >= 31. Check for -(2^31).
1624 | xoris TMP1, TMP1, 0x8000
1625 | srawi TMP2, CARG3, 31
1626 |.if "func" == "floor"
1627 | or TMP1, TMP1, CARG2
1628 |.endif
1629 | orc. TMP1, TMP1, TMP2
1630 | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
1631 | lus CARG1, 0x8000 // -(2^31).
1632 | beqy ->fff_resi
1633 |5:
1634 | lfd FARG1, 0(BASE)
1635 | bl extern func
1636 | b ->fff_resn
1637 |.endmacro
1638 |
1639 if (LJ_DUALNUM) {
1640 | math_round floor
1641 | math_round ceil
1642 } else {
1643 | // NYI: use internal implementation.
1644 | math_extern floor
1645 | math_extern ceil
1646 }
1647 |
1648 | math_extern sqrt
1649 | math_extern log
1650 | math_extern log10
1651 | math_extern exp
1652 | math_extern sin
1653 | math_extern cos
1654 | math_extern tan
1655 | math_extern asin
1656 | math_extern acos
1657 | math_extern atan
1658 | math_extern sinh
1659 | math_extern cosh
1660 | math_extern tanh
1661 | math_extern2 pow
1662 | math_extern2 atan2
1663 | math_extern2 fmod
1664 |
1665 |->ff_math_deg:
1666 |.ffunc_n math_rad
1667 | lfd FARG2, CFUNC:RB->upvalue[0]
1668 | fmul FARG1, FARG1, FARG2
1669 | b ->fff_resn
1670 |
1671 if (LJ_DUALNUM) {
1672 |.ffunc math_ldexp
1673 | cmplwi NARGS8:RC, 16
1674 | lwz CARG3, 0(BASE)
1675 | lfd FARG1, 0(BASE)
1676 | lwz CARG4, 8(BASE)
1677 | lwz CARG1, 12(BASE)
1678 | blt ->fff_fallback
1679 | checknum CARG3; bge ->fff_fallback
1680 | checknum CARG4; bne ->fff_fallback
1681 } else {
1682 |.ffunc_nn math_ldexp
1683 | toint CARG1, FARG2
1684 }
1685 | bl extern ldexp
1686 | b ->fff_resn
1687 |
1688 |.ffunc_n math_frexp
1689 | la CARG1, DISPATCH_GL(tmptv)(DISPATCH)
1690 | lwz PC, FRAME_PC(BASE)
1691 | bl extern frexp
1692 | lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH)
1693 | la RA, -8(BASE)
1694 if (!LJ_DUALNUM) {
1695 | tonum_i FARG2, TMP1
1696 }
1697 | stfd FARG1, 0(RA)
1698 | li RD, (2+1)*8
1699 if (LJ_DUALNUM) {
1700 | stw TISNUM, 8(RA)
1701 | stw TMP1, 12(RA)
1702 } else {
1703 | stfd FARG2, 8(RA)
1704 }
1705 | b ->fff_res
1706 |
1707 |.ffunc_n math_modf
1708 | la CARG1, -8(BASE)
1709 | lwz PC, FRAME_PC(BASE)
1710 | bl extern modf
1711 | la RA, -8(BASE)
1712 | stfd FARG1, 0(BASE)
1713 | li RD, (2+1)*8
1714 | b ->fff_res
1715 |
1716 |.macro math_minmax, name, ismax
1717 ||if (LJ_DUALNUM) {
1718 | .ffunc_1 name
1719 | checknum CARG3
1720 | addi TMP1, BASE, 8
1721 | add TMP2, BASE, NARGS8:RC
1722 | bne >4
1723 |1: // Handle integers.
1724 | lwz CARG4, 0(TMP1)
1725 | cmplw cr1, TMP1, TMP2
1726 | lwz CARG2, 4(TMP1)
1727 | bge cr1, ->fff_resi
1728 | checknum CARG4
1729 | xoris TMP0, CARG1, 0x8000
1730 | xoris TMP3, CARG2, 0x8000
1731 | bne >3
1732 | subfc TMP3, TMP3, TMP0
1733 | subfe TMP0, TMP0, TMP0
1734 |.if ismax
1735 | andc TMP3, TMP3, TMP0
1736 |.else
1737 | and TMP3, TMP3, TMP0
1738 |.endif
1739 | add CARG1, TMP3, CARG2
1740 | addi TMP1, TMP1, 8
1741 | b <1
1742 |3:
1743 | bge ->fff_fallback
1744 | // Convert intermediate result to number and continue below.
1745 | tonum_i FARG1, CARG1
1746 | lfd FARG2, 0(TMP1)
1747 | b >6
1748 |4:
1749 | lfd FARG1, 0(BASE)
1750 | bge ->fff_fallback
1751 |5: // Handle numbers.
1752 | lwz CARG4, 0(TMP1)
1753 | cmplw cr1, TMP1, TMP2
1754 | lfd FARG2, 0(TMP1)
1755 | bge cr1, ->fff_resn
1756 | checknum CARG4; bge >7
1757 |6:
1758 | fsub f0, FARG1, FARG2
1759 | addi TMP1, TMP1, 8
1760 |.if ismax
1761 | fsel FARG1, f0, FARG1, FARG2
1762 |.else
1763 | fsel FARG1, f0, FARG2, FARG1
1764 |.endif
1765 | b <5
1766 |7: // Convert integer to number and continue above.
1767 | lwz CARG2, 4(TMP1)
1768 | bne ->fff_fallback
1769 | tonum_i FARG2, CARG2
1770 | b <6
1771 ||} else {
1772 | .ffunc_n name
1773 | li TMP1, 8
1774 |1:
1775 | lwzx CARG2, BASE, TMP1
1776 | lfdx FARG2, BASE, TMP1
1777 | cmplw cr1, TMP1, NARGS8:RC
1778 | checknum CARG2
1779 | bge cr1, ->fff_resn
1780 | bge ->fff_fallback
1781 | fsub f0, FARG1, FARG2
1782 | addi TMP1, TMP1, 8
1783 |.if ismax
1784 | fsel FARG1, f0, FARG1, FARG2
1785 |.else
1786 | fsel FARG1, f0, FARG2, FARG1
1787 |.endif
1788 | b <1
1789 ||}
1790 |.endmacro
1791 |
1792 | math_minmax math_min, 0
1793 | math_minmax math_max, 1
1794 |
1795 |//-- String library -----------------------------------------------------
1796 |
1797 |.ffunc_1 string_len
1798 | checkstr CARG3; bne ->fff_fallback
1799 | lwz CRET1, STR:CARG1->len
1800 | b ->fff_resi
1801 |
1802 |.ffunc string_byte // Only handle the 1-arg case here.
1803 | cmplwi NARGS8:RC, 8
1804 | lwz CARG3, 0(BASE)
1805 | lwz STR:CARG1, 4(BASE)
1806 | bne ->fff_fallback // Need exactly 1 argument.
1807 | checkstr CARG3
1808 | bne ->fff_fallback
1809 | lwz TMP0, STR:CARG1->len
1810 if (LJ_DUALNUM) {
1811 | lbz CARG1, STR:CARG1[1] // Access is always ok (NUL at end).
1812 | li RD, (0+1)*8
1813 | lwz PC, FRAME_PC(BASE)
1814 | cmplwi TMP0, 0
1815 | la RA, -8(BASE)
1816 | beqy ->fff_res
1817 | b ->fff_resi
1818 } else {
1819 | lbz TMP1, STR:CARG1[1] // Access is always ok (NUL at end).
1820 | addic TMP3, TMP0, -1 // RD = ((str->len != 0)+1)*8
1821 | subfe RD, TMP3, TMP0
1822 | stw TMP1, TONUM_LO // Inlined tonum_u f0, TMP1.
1823 | addi RD, RD, 1
1824 | lfd f0, TONUM_D
1825 | la RA, -8(BASE)
1826 | lwz PC, FRAME_PC(BASE)
1827 | fsub f0, f0, TOBIT
1828 | slwi RD, RD, 3
1829 | stfd f0, 0(RA)
1830 | b ->fff_res
1831 }
1832 |
1833 |.ffunc string_char // Only handle the 1-arg case here.
1834 | ffgccheck
1835 | cmplwi NARGS8:RC, 8
1836 | lwz CARG3, 0(BASE)
1837 if (LJ_DUALNUM) {
1838 | lwz TMP0, 4(BASE)
1839 | bne ->fff_fallback // Exactly 1 argument.
1840 | checknum CARG3; bne ->fff_fallback
1841 | la CARG2, 7(BASE)
1842 } else {
1843 | lfd FARG1, 0(BASE)
1844 | bne ->fff_fallback // Exactly 1 argument.
1845 | checknum CARG3; bge ->fff_fallback
1846 | toint TMP0, FARG1
1847 | la CARG2, TMPD_BLO
1848 }
1849 | li CARG3, 1
1850 | cmplwi TMP0, 255; bgt ->fff_fallback
1851 |->fff_newstr:
1852 | mr CARG1, L
1853 | stw BASE, L->base
1854 | stw PC, SAVE_PC
1855 | bl extern lj_str_new // (lua_State *L, char *str, size_t l)
1856 | // Returns GCstr *.
1857 | lwz BASE, L->base
1858 | li CARG3, LJ_TSTR
1859 | b ->fff_restv
1860 |
1861 |.ffunc string_sub
1862 | ffgccheck
1863 | cmplwi NARGS8:RC, 16
1864 | lwz CARG3, 16(BASE)
1865 if (!LJ_DUALNUM) {
1866 | lfd f0, 16(BASE)
1867 }
1868 | lwz TMP0, 0(BASE)
1869 | lwz STR:CARG1, 4(BASE)
1870 | blt ->fff_fallback
1871 | lwz CARG2, 8(BASE)
1872 if (LJ_DUALNUM) {
1873 | lwz TMP1, 12(BASE)
1874 } else {
1875 | lfd f1, 8(BASE)
1876 }
1877 | li TMP2, -1
1878 | beq >1
1879 if (LJ_DUALNUM) {
1880 | checknum CARG3
1881 | lwz TMP2, 20(BASE)
1882 | bne ->fff_fallback
1883 |1:
1884 | checknum CARG2; bne ->fff_fallback
1885 } else {
1886 | checknum CARG3; bge ->fff_fallback
1887 | toint TMP2, f0
1888 |1:
1889 | checknum CARG2; bge ->fff_fallback
1890 }
1891 | checkstr TMP0; bne ->fff_fallback
1892 if (!LJ_DUALNUM) {
1893 | toint TMP1, f1
1894 }
1895 | lwz TMP0, STR:CARG1->len
1896 | cmplw TMP0, TMP2 // len < end? (unsigned compare)
1897 | addi TMP3, TMP2, 1
1898 | blt >5
1899 |2:
1900 | cmpwi TMP1, 0 // start <= 0?
1901 | add TMP3, TMP1, TMP0
1902 | ble >7
1903 |3:
1904 | sub CARG3, TMP2, TMP1
1905 | addi CARG2, STR:CARG1, #STR-1
1906 | srawi TMP0, CARG3, 31
1907 | addi CARG3, CARG3, 1
1908 | add CARG2, CARG2, TMP1
1909 | andc CARG3, CARG3, TMP0
1910 | b ->fff_newstr
1911 |
1912 |5: // Negative end or overflow.
1913 | sub CARG2, TMP0, TMP2
1914 | srawi CARG2, CARG2, 31
1915 | andc TMP3, TMP3, CARG2 // end = end > len ? len : end+len+1
1916 | add TMP2, TMP0, TMP3
1917 | b <2
1918 |
1919 |7: // Negative start or underflow.
1920 | addic CARG3, TMP1, -1
1921 | subfe CARG3, CARG3, CARG3
1922 | srawi CARG2, TMP3, 31 // Note: modifies carry.
1923 | andc TMP3, TMP3, CARG3
1924 | andc TMP1, TMP3, CARG2
1925 | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0)
1926 | b <3
1927 |
1928 |.ffunc string_rep // Only handle the 1-char case inline.
1929 | ffgccheck
1930 | cmplwi NARGS8:RC, 16
1931 | lwz TMP0, 0(BASE)
1932 | lwz STR:CARG1, 4(BASE)
1933 | lwz CARG4, 8(BASE)
1934 if (LJ_DUALNUM) {
1935 | lwz CARG3, 12(BASE)
1936 } else {
1937 | lfd FARG2, 8(BASE)
1938 }
1939 | blt ->fff_fallback
1940 | checkstr TMP0; bne ->fff_fallback
1941 if (LJ_DUALNUM) {
1942 | checknum CARG4; bne ->fff_fallback
1943 } else {
1944 | checknum CARG4; bge ->fff_fallback
1945 | toint CARG3, FARG2
1946 }
1947 | lwz TMP0, STR:CARG1->len
1948 | cmpwi CARG3, 0
1949 | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
1950 | ble >2 // Count <= 0? (or non-int)
1951 | cmplwi TMP0, 1
1952 | subi TMP2, CARG3, 1
1953 | blt >2 // Zero length string?
1954 | cmplw cr1, TMP1, CARG3
1955 | bne ->fff_fallback // Fallback for > 1-char strings.
1956 | lbz TMP0, STR:CARG1[1]
1957 | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
1958 | blt cr1, ->fff_fallback
1959 |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?).
1960 | cmplwi TMP2, 0
1961 | stbx TMP0, CARG2, TMP2
1962 | subi TMP2, TMP2, 1
1963 | bne <1
1964 | b ->fff_newstr
1965 |2: // Return empty string.
1966 | la STR:CARG1, DISPATCH_GL(strempty)(DISPATCH)
1967 | li CARG3, LJ_TSTR
1968 | b ->fff_restv
1969 |
1970 |.ffunc string_reverse
1971 | ffgccheck
1972 | cmplwi NARGS8:RC, 8
1973 | lwz CARG3, 0(BASE)
1974 | lwz STR:CARG1, 4(BASE)
1975 | blt ->fff_fallback
1976 | checkstr CARG3
1977 | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
1978 | bne ->fff_fallback
1979 | lwz CARG3, STR:CARG1->len
1980 | la CARG1, #STR(STR:CARG1)
1981 | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
1982 | li TMP2, 0
1983 | cmplw TMP1, CARG3
1984 | subi TMP3, CARG3, 1
1985 | blt ->fff_fallback
1986 |1: // Reverse string copy.
1987 | cmpwi TMP3, 0
1988 | lbzx TMP1, CARG1, TMP2
1989 | blty ->fff_newstr
1990 | stbx TMP1, CARG2, TMP3
1991 | subi TMP3, TMP3, 1
1992 | addi TMP2, TMP2, 1
1993 | b <1
1994 |
1995 |.macro ffstring_case, name, lo
1996 | .ffunc name
1997 | ffgccheck
1998 | cmplwi NARGS8:RC, 8
1999 | lwz CARG3, 0(BASE)
2000 | lwz STR:CARG1, 4(BASE)
2001 | blt ->fff_fallback
2002 | checkstr CARG3
2003 | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
2004 | bne ->fff_fallback
2005 | lwz CARG3, STR:CARG1->len
2006 | la CARG1, #STR(STR:CARG1)
2007 | lwz CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
2008 | cmplw TMP1, CARG3
2009 | li TMP2, 0
2010 | blt ->fff_fallback
2011 |1: // ASCII case conversion.
2012 | cmplw TMP2, CARG3
2013 | lbzx TMP1, CARG1, TMP2
2014 | bgey ->fff_newstr
2015 | subi TMP0, TMP1, lo
2016 | xori TMP3, TMP1, 0x20
2017 | addic TMP0, TMP0, -26
2018 | subfe TMP3, TMP3, TMP3
2019 | andi. TMP3, TMP3, 0x20
2020 | xor TMP1, TMP1, TMP3
2021 | stbx TMP1, CARG2, TMP2
2022 | addi TMP2, TMP2, 1
2023 | b <1
2024 |.endmacro
2025 |
2026 |ffstring_case string_lower, 65
2027 |ffstring_case string_upper, 97
2028 |
2029 |//-- Table library ------------------------------------------------------
2030 |
2031 |.ffunc_1 table_getn
2032 | checktab CARG3; bne ->fff_fallback
2033 | bl extern lj_tab_len // (GCtab *t)
2034 | // Returns uint32_t (but less than 2^31).
2035 | b ->fff_resi
2036 |
2037 |//-- Bit library --------------------------------------------------------
2038 |
2039 |.macro .ffunc_bit, name
2040 ||if (LJ_DUALNUM) {
2041 | .ffunc_1 bit_..name
2042 | checknum CARG3; bnel ->fff_tobit_fb
2043 ||} else {
2044 | .ffunc_n bit_..name
2045 | fadd FARG1, FARG1, TOBIT
2046 | stfd FARG1, TMPD
2047 | lwz CARG1, TMPD_LO
2048 ||}
2049 |.endmacro
2050 |
2051 |.macro .ffunc_bit_op, name, ins
2052 | .ffunc_bit name
2053 | addi TMP1, BASE, 8
2054 | add TMP2, BASE, NARGS8:RC
2055 |1:
2056 | lwz CARG4, 0(TMP1)
2057 | cmplw cr1, TMP1, TMP2
2058 ||if (LJ_DUALNUM) {
2059 | lwz CARG2, 4(TMP1)
2060 ||} else {
2061 | lfd FARG1, 0(TMP1)
2062 ||}
2063 | bgey cr1, ->fff_resi
2064 | checknum CARG4
2065 ||if (LJ_DUALNUM) {
2066 | bnel ->fff_bitop_fb
2067 ||} else {
2068 | fadd FARG1, FARG1, TOBIT
2069 | bge ->fff_fallback
2070 | stfd FARG1, TMPD
2071 | lwz CARG2, TMPD_LO
2072 ||}
2073 | ins CARG1, CARG1, CARG2
2074 | addi TMP1, TMP1, 8
2075 | b <1
2076 |.endmacro
2077 |
2078 |.ffunc_bit_op band, and
2079 |.ffunc_bit_op bor, or
2080 |.ffunc_bit_op bxor, xor
2081 |
2082 |.ffunc_bit bswap
2083 | rotlwi TMP0, CARG1, 8
2084 | rlwimi TMP0, CARG1, 24, 0, 7
2085 | rlwimi TMP0, CARG1, 24, 16, 23
2086 | mr CRET1, TMP0
2087 | b ->fff_resi
2088 |
2089 |.ffunc_bit bnot
2090 | not CRET1, CARG1
2091 | b ->fff_resi
2092 |
2093 |.macro .ffunc_bit_sh, name, ins, shmod
2094 ||if (LJ_DUALNUM) {
2095 | .ffunc_2 bit_..name
2096 | checknum CARG3; bnel ->fff_tobit_fb
2097 | // Note: no inline conversion from number for 2nd argument!
2098 | checknum CARG4; bne ->fff_fallback
2099 ||} else {
2100 | .ffunc_nn bit_..name
2101 | fadd FARG1, FARG1, TOBIT
2102 | fadd FARG2, FARG2, TOBIT
2103 | stfd FARG1, TMPD
2104 | lwz CARG1, TMPD_LO
2105 | stfd FARG2, TMPD
2106 | lwz CARG2, TMPD_LO
2107 ||}
2108 |.if shmod == 1
2109 | rlwinm CARG2, CARG2, 0, 27, 31
2110 |.elif shmod == 2
2111 | neg CARG2, CARG2
2112 |.endif
2113 | ins CRET1, CARG1, CARG2
2114 | b ->fff_resi
2115 |.endmacro
2116 |
2117 |.ffunc_bit_sh lshift, slw, 1
2118 |.ffunc_bit_sh rshift, srw, 1
2119 |.ffunc_bit_sh arshift, sraw, 1
2120 |.ffunc_bit_sh rol, rotlw, 0
2121 |.ffunc_bit_sh ror, rotlw, 2
2122 |
2123 |.ffunc_bit tobit
2124 if (LJ_DUALNUM) {
2125 | b ->fff_resi
2126 } else {
2127 |->fff_resi:
2128 | tonum_i FARG1, CRET1
2129 }
2130 |->fff_resn:
2131 | lwz PC, FRAME_PC(BASE)
2132 | la RA, -8(BASE)
2133 | stfd FARG1, -8(BASE)
2134 | b ->fff_res1
2135 |
2136 |// Fallback FP number to bit conversion.
2137 |->fff_tobit_fb:
2138 if (LJ_DUALNUM) {
2139 | lfd FARG1, 0(BASE)
2140 | bgt ->fff_fallback
2141 | fadd FARG1, FARG1, TOBIT
2142 | stfd FARG1, TMPD
2143 | lwz CARG1, TMPD_LO
2144 | blr
2145 }
2146 |->fff_bitop_fb:
2147 if (LJ_DUALNUM) {
2148 | lfd FARG1, 0(TMP1)
2149 | bgt ->fff_fallback
2150 | fadd FARG1, FARG1, TOBIT
2151 | stfd FARG1, TMPD
2152 | lwz CARG2, TMPD_LO
2153 | blr
2154 }
2155 |
2156 |//-----------------------------------------------------------------------
2157 |
2158 |->fff_fallback: // Call fast function fallback handler.
2159 | // BASE = new base, RB = CFUNC, RC = nargs*8
2160 | lwz TMP3, CFUNC:RB->f
2161 | add TMP1, BASE, NARGS8:RC
2162 | lwz PC, FRAME_PC(BASE) // Fallback may overwrite PC.
2163 | addi TMP0, TMP1, 8*LUA_MINSTACK
2164 | lwz TMP2, L->maxstack
2165 | stw PC, SAVE_PC // Redundant (but a defined value).
2166 | cmplw TMP0, TMP2
2167 | stw BASE, L->base
2168 | stw TMP1, L->top
2169 | mr CARG1, L
2170 | bgt >5 // Need to grow stack.
2171 | mtctr TMP3
2172 | bctrl // (lua_State *L)
2173 | // Either throws an error, or recovers and returns -1, 0 or nresults+1.
2174 | lwz BASE, L->base
2175 | cmpwi CRET1, 0
2176 | slwi RD, CRET1, 3
2177 | la RA, -8(BASE)
2178 | bgt ->fff_res // Returned nresults+1?
2179 |1: // Returned 0 or -1: retry fast path.
2180 | lwz TMP0, L->top
2181 | lwz LFUNC:RB, FRAME_FUNC(BASE)
2182 | sub NARGS8:RC, TMP0, BASE
2183 | bne ->vm_call_tail // Returned -1?
2184 | ins_callt // Returned 0: retry fast path.
2185 |
2186 |// Reconstruct previous base for vmeta_call during tailcall.
2187 |->vm_call_tail:
2188 | andi. TMP0, PC, FRAME_TYPE
2189 | rlwinm TMP1, PC, 0, 0, 28
2190 | bne >3
2191 | lwz INS, -4(PC)
2192 | decode_RA8 TMP1, INS
2193 |3:
2194 | sub TMP2, BASE, TMP1
2195 | b ->vm_call_dispatch // Resolve again for tailcall.
2196 |
2197 |5: // Grow stack for fallback handler.
2198 | li CARG2, LUA_MINSTACK
2199 | bl extern lj_state_growstack // (lua_State *L, int n)
2200 | lwz BASE, L->base
2201 | cmpw TMP0, TMP0 // Set 4*cr0+eq to force retry.
2202 | b <1
2203 |
2204 |->fff_gcstep: // Call GC step function.
2205 | // BASE = new base, RC = nargs*8
2206 | mflr SAVE0
2207 | stw BASE, L->base
2208 | add TMP0, BASE, NARGS8:RC
2209 | stw PC, SAVE_PC // Redundant (but a defined value).
2210 | stw TMP0, L->top
2211 | mr CARG1, L
2212 | bl extern lj_gc_step // (lua_State *L)
2213 | lwz BASE, L->base
2214 | mtlr SAVE0
2215 | lwz TMP0, L->top
2216 | sub NARGS8:RC, TMP0, BASE
2217 | lwz CFUNC:RB, FRAME_FUNC(BASE)
2218 | blr
2219 |
2220 |//-----------------------------------------------------------------------
2221 |//-- Special dispatch targets -------------------------------------------
2222 |//-----------------------------------------------------------------------
2223 |
2224 |->vm_record: // Dispatch target for recording phase.
2225#if LJ_HASJIT
2226 | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
2227 | andi. TMP0, TMP3, HOOK_VMEVENT // No recording while in vmevent.
2228 | bne >5
2229 | // Decrement the hookcount for consistency, but always do the call.
2230 | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH)
2231 | andi. TMP0, TMP3, HOOK_ACTIVE
2232 | bne >1
2233 | subi TMP2, TMP2, 1
2234 | andi. TMP0, TMP3, LUA_MASKLINE|LUA_MASKCOUNT
2235 | beqy >1
2236 | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
2237 | b >1
2238#endif
2239 |
2240 |->vm_rethook: // Dispatch target for return hooks.
2241 | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
2242 | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active?
2243 | beq >1
2244 |5: // Re-dispatch to static ins.
2245 | addi TMP1, TMP1, GG_DISP2STATIC // Assumes decode_OP4 TMP1, INS.
2246 | lwzx TMP0, DISPATCH, TMP1
2247 | mtctr TMP0
2248 | bctr
2249 |
2250 |->vm_inshook: // Dispatch target for instr/line hooks.
2251 | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
2252 | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH)
2253 | andi. TMP0, TMP3, HOOK_ACTIVE // Hook already active?
2254 | rlwinm TMP0, TMP3, 31-LUA_HOOKLINE, 31, 0
2255 | bne <5
2256 |
2257 | cmpwi cr1, TMP0, 0
2258 | addic. TMP2, TMP2, -1
2259 | beq cr1, <5
2260 | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
2261 | beq >1
2262 | bge cr1, <5
2263 |1:
2264 | mr CARG1, L
2265 | stw MULTRES, SAVE_MULTRES
2266 | mr CARG2, PC
2267 | stw BASE, L->base
2268 | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC.
2269 | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc)
2270 |3:
2271 | lwz BASE, L->base
2272 |4: // Re-dispatch to static ins.
2273 | lwz INS, -4(PC)
2274 | decode_OP4 TMP1, INS
2275 | decode_RB8 RB, INS
2276 | addi TMP1, TMP1, GG_DISP2STATIC
2277 | decode_RD8 RD, INS
2278 | lwzx TMP0, DISPATCH, TMP1
2279 | decode_RA8 RA, INS
2280 | decode_RC8 RC, INS
2281 | mtctr TMP0
2282 | bctr
2283 |
2284 |->cont_hook: // Continue from hook yield.
2285 | addi PC, PC, 4
2286 | lwz MULTRES, -20(RB) // Restore MULTRES for *M ins.
2287 | b <4
2288 |
2289 |->vm_hotloop: // Hot loop counter underflow.
2290#if LJ_HASJIT
2291 | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
2292 | addi CARG1, DISPATCH, GG_DISP2J
2293 | stw PC, SAVE_PC
2294 | lwz TMP1, LFUNC:TMP1->pc
2295 | mr CARG2, PC
2296 | stw L, DISPATCH_J(L)(DISPATCH)
2297 | lbz TMP1, PC2PROTO(framesize)(TMP1)
2298 | stw BASE, L->base
2299 | slwi TMP1, TMP1, 3
2300 | add TMP1, BASE, TMP1
2301 | stw TMP1, L->top
2302 | bl extern lj_trace_hot // (jit_State *J, const BCIns *pc)
2303 | b <3
2304#endif
2305 |
2306 |->vm_callhook: // Dispatch target for call hooks.
2307 | mr CARG2, PC
2308#if LJ_HASJIT
2309 | b >1
2310#endif
2311 |
2312 |->vm_hotcall: // Hot call counter underflow.
2313#if LJ_HASJIT
2314 | ori CARG2, PC, 1
2315 |1:
2316#endif
2317 | add TMP0, BASE, RC
2318 | stw PC, SAVE_PC
2319 | mr CARG1, L
2320 | stw BASE, L->base
2321 | sub RA, RA, BASE
2322 | stw TMP0, L->top
2323 | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc)
2324 | // Returns ASMFunction.
2325 | lwz BASE, L->base
2326 | lwz TMP0, L->top
2327 | stw ZERO, SAVE_PC // Invalidate for subsequent line hook.
2328 | sub NARGS8:RC, TMP0, BASE
2329 | add RA, BASE, RA
2330 | lwz LFUNC:RB, FRAME_FUNC(BASE)
2331 | lwz INS, -4(PC)
2332 | mtctr CRET1
2333 | bctr
2334 |
2335 |//-----------------------------------------------------------------------
2336 |//-- Trace exit handler -------------------------------------------------
2337 |//-----------------------------------------------------------------------
2338 |
2339 |.macro savex_, a, b, c, d
2340 | stfd f..a, 16+a*8(sp)
2341 | stfd f..b, 16+b*8(sp)
2342 | stfd f..c, 16+c*8(sp)
2343 | stfd f..d, 16+d*8(sp)
2344 |.endmacro
2345 |
2346 |->vm_exit_handler:
2347#if LJ_HASJIT
2348 | addi sp, sp, -(16+32*8+32*4)
2349 | stmw r2, 16+32*8+2*4(sp)
2350 | addi DISPATCH, JGL, -GG_DISP2G-32768
2351 | li CARG2, ~LJ_VMST_EXIT
2352 | lwz CARG1, 16+32*8+32*4(sp) // Get stack chain.
2353 | stw CARG2, DISPATCH_GL(vmstate)(DISPATCH)
2354 | savex_ 0,1,2,3
2355 | stw CARG1, 0(sp) // Store extended stack chain.
2356 | mcrxr cr0 // Clear SO flag.
2357 | savex_ 4,5,6,7
2358 | addi CARG2, sp, 16+32*8+32*4 // Recompute original value of sp.
2359 | savex_ 8,9,10,11
2360 | stw CARG2, 16+32*8+1*4(sp) // Store sp in RID_SP.
2361 | savex_ 12,13,14,15
2362 | mflr CARG3
2363 | li TMP1, 0
2364 | savex_ 16,17,18,19
2365 | stw TMP1, 16+32*8+0*4(sp) // Clear RID_TMP.
2366 | savex_ 20,21,22,23
2367 | lhz CARG4, 2(CARG3) // Load trace number.
2368 | savex_ 24,25,26,27
2369 | lwz L, DISPATCH_GL(jit_L)(DISPATCH)
2370 | savex_ 28,29,30,31
2371 | sub CARG3, TMP0, CARG3 // Compute exit number.
2372 | lwz BASE, DISPATCH_GL(jit_base)(DISPATCH)
2373 | srwi CARG3, CARG3, 2
2374 | stw L, DISPATCH_J(L)(DISPATCH)
2375 | subi CARG3, CARG3, 2
2376 | stw TMP1, DISPATCH_GL(jit_L)(DISPATCH)
2377 | stw CARG4, DISPATCH_J(parent)(DISPATCH)
2378 | stw BASE, L->base
2379 | addi CARG1, DISPATCH, GG_DISP2J
2380 | stw CARG3, DISPATCH_J(exitno)(DISPATCH)
2381 | addi CARG2, sp, 16
2382 | bl extern lj_trace_exit // (jit_State *J, ExitState *ex)
2383 | // Returns MULTRES (unscaled) or negated error code.
2384 | lwz TMP1, L->cframe
2385 | lwz TMP2, 0(sp)
2386 | lwz BASE, L->base
2387 | rlwinm sp, TMP1, 0, 0, 29
2388 | lwz PC, SAVE_PC // Get SAVE_PC.
2389 | stw TMP2, 0(sp)
2390 | stw L, SAVE_L // Set SAVE_L (on-trace resume/yield).
2391 | b >1
2392#endif
2393 |->vm_exit_interp:
2394#if LJ_HASJIT
2395 | // CARG1 = MULTRES or negated error code, BASE, PC and JGL set.
2396 | lwz L, SAVE_L
2397 | addi DISPATCH, JGL, -GG_DISP2G-32768
2398 |1:
2399 | cmpwi CARG1, 0
2400 | blt >3 // Check for error from exit.
2401 | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
2402 | slwi MULTRES, CARG1, 3
2403 | li TMP2, 0
2404 | stw MULTRES, SAVE_MULTRES
2405 | lwz TMP1, LFUNC:TMP1->pc
2406 | stw TMP2, DISPATCH_GL(jit_L)(DISPATCH)
2407 | lwz KBASE, PC2PROTO(k)(TMP1)
2408 | // Setup type comparison constants.
2409 | li TISNUM, LJ_TISNUM
2410 | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
2411 | stw TMP3, TMPD
2412 | li ZERO, 0
2413 | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
2414 | lfs TOBIT, TMPD
2415 | stw TMP3, TMPD
2416 | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double)
2417 | li TISNIL, LJ_TNIL
2418 | stw TMP0, TONUM_HI
2419 | lfs TONUM, TMPD
2420 | // Modified copy of ins_next which handles function header dispatch, too.
2421 | lwz INS, 0(PC)
2422 | addi PC, PC, 4
2423 | // Assumes TISNIL == ~LJ_VMST_INTERP == -1.
2424 | stw TISNIL, DISPATCH_GL(vmstate)(DISPATCH)
2425 | decode_OP4 TMP1, INS
2426 | decode_RA8 RA, INS
2427 | lwzx TMP0, DISPATCH, TMP1
2428 | mtctr TMP0
2429 | cmplwi TMP1, BC_FUNCF*4 // Function header?
2430 | bge >2
2431 | decode_RB8 RB, INS
2432 | decode_RD8 RD, INS
2433 | decode_RC8 RC, INS
2434 | bctr
2435 |2:
2436 | subi RC, MULTRES, 8
2437 | add RA, RA, BASE
2438 | bctr
2439 |
2440 |3: // Rethrow error from the right C frame.
2441 | neg CARG2, CARG1
2442 | mr CARG1, L
2443 | bl extern lj_err_throw // (lua_State *L, int errcode)
2444#endif
2445 |
2446 |//-----------------------------------------------------------------------
2447 |//-- Math helper functions ----------------------------------------------
2448 |//-----------------------------------------------------------------------
2449 |
2450 | // NYI: Use internal implementation.
2451 |->vm_floor:
2452 | b extern floor
2453 |->vm_ceil:
2454 | b extern ceil
2455 |->vm_trunc:
2456#if LJ_HASJIT
2457 | b extern trunc
2458#endif
2459 |
2460 |->vm_modi:
2461 | divwo. TMP0, CARG1, CARG2
2462 | bso >1
2463 | xor. CARG3, CARG1, CARG2
2464 | mullw TMP0, TMP0, CARG2
2465 | sub CARG1, CARG1, TMP0
2466 | bgelr
2467 | cmpwi CARG1, 0; beqlr
2468 | add CARG1, CARG1, CARG2
2469 | blr
2470 |1:
2471 | cmpwi CARG2, 0
2472 | li CARG1, 0
2473 | beqlr
2474 | mcrxr cr0 // Clear SO for -2147483648 % -1 and return 0.
2475 | blr
2476 |
2477 |// Callable from C: double lj_vm_foldarith(double x, double y, int op)
2478 |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -)
2479 |// and basic math functions. ORDER ARITH
2480 |->vm_foldarith:
2481 | cmplwi CARG1, 1
2482 | beq >1; bgt >2
2483 | fadd FARG1, FARG1, FARG2; blr
2484 |1:
2485 | fsub FARG1, FARG1, FARG2; blr
2486 |2:
2487 | cmplwi CARG1, 3; beq >1; bgt >2
2488 | fmul FARG1, FARG1, FARG2; blr
2489 |1:
2490 | fdiv FARG1, FARG1, FARG2; blr
2491 |2:
2492 | cmplwi CARG1, 5; beq >1; bgt >2
2493 | // NYI: Use internal implementation of floor and avoid spills.
2494 | stwu sp, -32(sp); stfd f14, 16(sp); stfd f15, 24(sp)
2495 | mflr r0
2496 | fmr f14, FARG1
2497 | fdiv FARG1, FARG1, FARG2
2498 | stw r0, 36(sp)
2499 | fmr f15, FARG2
2500 | bl extern floor
2501 | lwz r0, 36(sp)
2502 | fmul FARG1, FARG1, f15
2503 | mtlr r0
2504 | fsub FARG1, f14, FARG1
2505 | lfd f14, 16(sp); lfd f15, 24(sp); addi sp, sp, 32; blr
2506 |1:
2507 | b extern pow
2508 |2:
2509 | cmplwi CARG1, 7; beq >1; bgt >2
2510 | fneg FARG1, FARG1; blr
2511 |1:
2512 | fabs FARG1, FARG1; blr
2513 |2:
2514#if LJ_HASJIT
2515 | cmplwi CARG1, 9; beq >9; bgt >2
2516 | b extern atan2
2517 | // No support needed for IR_LDEXP.
2518 |2:
2519 | cmplwi CARG1, 11; bgt >9
2520 | fsub f0, FARG1, FARG2
2521 | beq >1
2522 | fsel FARG1, f0, FARG2, FARG1 // IR_MAX
2523 | blr
2524 |1:
2525 | fsel FARG1, f0, FARG1, FARG2 // IR_MIN
2526 | blr
2527 |9:
2528 | NYI // Bad op.
2529#else
2530 | NYI // Other operations only needed by JIT compiler.
2531#endif
2532 |
2533 |//-----------------------------------------------------------------------
2534 |//-- Miscellaneous functions --------------------------------------------
2535 |//-----------------------------------------------------------------------
2536 |
2537 |//-----------------------------------------------------------------------
2538 |//-- FFI helper functions -----------------------------------------------
2539 |//-----------------------------------------------------------------------
2540 |
2541 |// Handler for callback functions. Callback slot number in r11, g in r12.
2542 |->vm_ffi_callback:
2543#if LJ_HASFFI
2544 |.type CTSTATE, CTState, PC
2545 | saveregs
2546 | lwz CTSTATE, GL:r12->ctype_state
2547 | addi DISPATCH, r12, GG_G2DISP
2548 | stw r11, CTSTATE->cb.slot
2549 | stw r3, CTSTATE->cb.gpr[0]
2550 | stfd f1, CTSTATE->cb.fpr[0]
2551 | stw r4, CTSTATE->cb.gpr[1]
2552 | stfd f2, CTSTATE->cb.fpr[1]
2553 | stw r5, CTSTATE->cb.gpr[2]
2554 | stfd f3, CTSTATE->cb.fpr[2]
2555 | stw r6, CTSTATE->cb.gpr[3]
2556 | stfd f4, CTSTATE->cb.fpr[3]
2557 | stw r7, CTSTATE->cb.gpr[4]
2558 | stfd f5, CTSTATE->cb.fpr[4]
2559 | stw r8, CTSTATE->cb.gpr[5]
2560 | stfd f6, CTSTATE->cb.fpr[5]
2561 | stw r9, CTSTATE->cb.gpr[6]
2562 | stfd f7, CTSTATE->cb.fpr[6]
2563 | stw r10, CTSTATE->cb.gpr[7]
2564 | stfd f8, CTSTATE->cb.fpr[7]
2565 | addi TMP0, sp, CFRAME_SPACE+8
2566 | stw TMP0, CTSTATE->cb.stack
2567 | mr CARG1, CTSTATE
2568 | stw CTSTATE, SAVE_PC // Any value outside of bytecode is ok.
2569 | mr CARG2, sp
2570 | bl extern lj_ccallback_enter // (CTState *cts, void *cf)
2571 | // Returns lua_State *.
2572 | lwz BASE, L:CRET1->base
2573 | li TISNUM, LJ_TISNUM // Setup type comparison constants.
2574 | lwz RC, L:CRET1->top
2575 | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
2576 | li ZERO, 0
2577 | mr L, CRET1
2578 | stw TMP3, TMPD
2579 | lwz LFUNC:RB, FRAME_FUNC(BASE)
2580 | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
2581 | li TISNIL, LJ_TNIL
2582 | li_vmstate INTERP
2583 | lfs TOBIT, TMPD
2584 | stw TMP3, TMPD
2585 | sub RC, RC, BASE
2586 | st_vmstate
2587 | lfs TONUM, TMPD
2588 | ins_callt
2589#endif
2590 |
2591 |->cont_ffi_callback: // Return from FFI callback.
2592#if LJ_HASFFI
2593 | lwz CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH)
2594 | stw BASE, L->base
2595 | stw RB, L->top
2596 | stw L, CTSTATE->L
2597 | mr CARG1, CTSTATE
2598 | mr CARG2, RA
2599 | bl extern lj_ccallback_leave // (CTState *cts, TValue *o)
2600 | lwz CRET1, CTSTATE->cb.gpr[0]
2601 | lfd FARG1, CTSTATE->cb.fpr[0]
2602 | lwz CRET2, CTSTATE->cb.gpr[1]
2603 | b ->vm_leave_unw
2604#endif
2605 |
2606 |->vm_ffi_call: // Call C function via FFI.
2607 | // Caveat: needs special frame unwinding, see below.
2608#if LJ_HASFFI
2609 | .type CCSTATE, CCallState, CARG1
2610 | lwz TMP1, CCSTATE->spadj
2611 | mflr TMP0
2612 | lbz CARG2, CCSTATE->nsp
2613 | lbz CARG3, CCSTATE->nfpr
2614 | neg TMP1, TMP1
2615 | stw TMP0, 4(sp)
2616 | cmpwi cr1, CARG3, 0
2617 | mr TMP2, sp
2618 | addic. CARG2, CARG2, -1
2619 | stwux sp, sp, TMP1
2620 | crnot 4*cr1+eq, 4*cr1+eq // For vararg calls.
2621 | stw r14, -4(TMP2)
2622 | li TMP3, 0
2623 | stw CCSTATE, -8(TMP2)
2624 | mr r14, TMP2
2625 | la TMP1, CCSTATE->stack
2626 | slwi CARG2, CARG2, 2
2627 | blty >2
2628 | la TMP2, 8(sp)
2629 |1:
2630 | lwzx TMP0, TMP1, CARG2
2631 | stwx TMP0, TMP2, CARG2
2632 | addic. CARG2, CARG2, -4
2633 | bge <1
2634 |2:
2635 | bney cr1, >3
2636 | lfd f1, CCSTATE->fpr[0]
2637 | lfd f2, CCSTATE->fpr[1]
2638 | lfd f3, CCSTATE->fpr[2]
2639 | lfd f4, CCSTATE->fpr[3]
2640 | lfd f5, CCSTATE->fpr[4]
2641 | lfd f6, CCSTATE->fpr[5]
2642 | lfd f7, CCSTATE->fpr[6]
2643 | lfd f8, CCSTATE->fpr[7]
2644 |3:
2645 | lwz TMP0, CCSTATE->func
2646 | lwz CARG2, CCSTATE->gpr[1]
2647 | lwz CARG3, CCSTATE->gpr[2]
2648 | lwz CARG4, CCSTATE->gpr[3]
2649 | lwz CARG5, CCSTATE->gpr[4]
2650 | mtctr TMP0
2651 | lwz r8, CCSTATE->gpr[5]
2652 | lwz r9, CCSTATE->gpr[6]
2653 | lwz r10, CCSTATE->gpr[7]
2654 | lwz CARG1, CCSTATE->gpr[0] // Do this last, since CCSTATE is CARG1.
2655 | bctrl
2656 | lwz CCSTATE:TMP1, -8(r14)
2657 | lwz TMP2, -4(r14)
2658 | lwz TMP0, 4(r14)
2659 | stw CARG1, CCSTATE:TMP1->gpr[0]
2660 | stfd FARG1, CCSTATE:TMP1->fpr[0]
2661 | stw CARG2, CCSTATE:TMP1->gpr[1]
2662 | mtlr TMP0
2663 | stw CARG3, CCSTATE:TMP1->gpr[2]
2664 | mr sp, r14
2665 | stw CARG4, CCSTATE:TMP1->gpr[3]
2666 | mr r14, TMP2
2667 | blr
2668#endif
2669 |// Note: vm_ffi_call must be the last function in this object file!
2670 |
2671 |//-----------------------------------------------------------------------
2672}
2673
2674/* Generate the code for a single instruction. */
2675static void build_ins(BuildCtx *ctx, BCOp op, int defop)
2676{
2677 int vk = 0;
2678 |=>defop:
2679
2680 switch (op) {
2681
2682 /* -- Comparison ops ---------------------------------------------------- */
2683
2684 /* Remember: all ops branch for a true comparison, fall through otherwise. */
2685
2686 case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
2687 | // RA = src1*8, RD = src2*8, JMP with RD = target
2688 if (LJ_DUALNUM) {
2689 | lwzux TMP0, RA, BASE
2690 | addi PC, PC, 4
2691 | lwz CARG2, 4(RA)
2692 | lwzux TMP1, RD, BASE
2693 | lwz TMP2, -4(PC)
2694 | checknum cr0, TMP0
2695 | lwz CARG3, 4(RD)
2696 | decode_RD4 TMP2, TMP2
2697 | checknum cr1, TMP1
2698 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
2699 | bne cr0, >7
2700 | bne cr1, >8
2701 | cmpw CARG2, CARG3
2702 if (op == BC_ISLT) {
2703 | bge >2
2704 } else if (op == BC_ISGE) {
2705 | blt >2
2706 } else if (op == BC_ISLE) {
2707 | bgt >2
2708 } else {
2709 | ble >2
2710 }
2711 |1:
2712 | add PC, PC, TMP2
2713 |2:
2714 | ins_next
2715 |
2716 |7: // RA is not an integer.
2717 | bgt cr0, ->vmeta_comp
2718 | // RA is a number.
2719 | lfd f0, 0(RA)
2720 | bgt cr1, ->vmeta_comp
2721 | blt cr1, >4
2722 | // RA is a number, RD is an integer.
2723 | tonum_i f1, CARG3
2724 | b >5
2725 |
2726 |8: // RA is an integer, RD is not an integer.
2727 | bgt cr1, ->vmeta_comp
2728 | // RA is an integer, RD is a number.
2729 | tonum_i f0, CARG2
2730 |4:
2731 | lfd f1, 0(RD)
2732 |5:
2733 | fcmpu cr0, f0, f1
2734 if (op == BC_ISLT) {
2735 | bge <2
2736 } else if (op == BC_ISGE) {
2737 | blt <2
2738 } else if (op == BC_ISLE) {
2739 | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
2740 | bge <2
2741 } else {
2742 | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
2743 | blt <2
2744 }
2745 | b <1
2746 } else {
2747 | lwzx TMP0, BASE, RA
2748 | addi PC, PC, 4
2749 | lfdx f0, BASE, RA
2750 | lwzx TMP1, BASE, RD
2751 | checknum cr0, TMP0
2752 | lwz TMP2, -4(PC)
2753 | lfdx f1, BASE, RD
2754 | checknum cr1, TMP1
2755 | decode_RD4 TMP2, TMP2
2756 | bge cr0, ->vmeta_comp
2757 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
2758 | bge cr1, ->vmeta_comp
2759 | fcmpu cr0, f0, f1
2760 if (op == BC_ISLT) {
2761 | bge >1
2762 } else if (op == BC_ISGE) {
2763 | blt >1
2764 } else if (op == BC_ISLE) {
2765 | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
2766 | bge >1
2767 } else {
2768 | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
2769 | blt >1
2770 }
2771 | add PC, PC, TMP2
2772 |1:
2773 | ins_next
2774 }
2775 break;
2776
2777 case BC_ISEQV: case BC_ISNEV:
2778 vk = op == BC_ISEQV;
2779 | // RA = src1*8, RD = src2*8, JMP with RD = target
2780 if (LJ_DUALNUM) {
2781 | lwzux TMP0, RA, BASE
2782 | addi PC, PC, 4
2783 | lwz CARG2, 4(RA)
2784 | lwzux TMP1, RD, BASE
2785 | checknum cr0, TMP0
2786 | lwz TMP2, -4(PC)
2787 | checknum cr1, TMP1
2788 | decode_RD4 TMP2, TMP2
2789 | lwz CARG3, 4(RD)
2790 | cror 4*cr7+gt, 4*cr0+gt, 4*cr1+gt
2791 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
2792 if (vk) {
2793 | ble cr7, ->BC_ISEQN_Z
2794 } else {
2795 | ble cr7, ->BC_ISNEN_Z
2796 }
2797 } else {
2798 | lwzux TMP0, RA, BASE
2799 | lwz TMP2, 0(PC)
2800 | lfd f0, 0(RA)
2801 | addi PC, PC, 4
2802 | lwzux TMP1, RD, BASE
2803 | checknum cr0, TMP0
2804 | decode_RD4 TMP2, TMP2
2805 | lfd f1, 0(RD)
2806 | checknum cr1, TMP1
2807 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
2808 | bge cr0, >5
2809 | bge cr1, >5
2810 | fcmpu cr0, f0, f1
2811 if (vk) {
2812 | bne >1
2813 | add PC, PC, TMP2
2814 } else {
2815 | beq >1
2816 | add PC, PC, TMP2
2817 }
2818 |1:
2819 | ins_next
2820 }
2821 |5: // Either or both types are not numbers.
2822 if (!LJ_DUALNUM) {
2823 | lwz CARG2, 4(RA)
2824 | lwz CARG3, 4(RD)
2825 }
2826 if (LJ_HASFFI) {
2827 | cmpwi cr7, TMP0, LJ_TCDATA
2828 | cmpwi cr5, TMP1, LJ_TCDATA
2829 }
2830 | not TMP3, TMP0
2831 | cmplw TMP0, TMP1
2832 | cmplwi cr1, TMP3, ~LJ_TISPRI // Primitive?
2833 if (LJ_HASFFI) {
2834 | cror 4*cr7+eq, 4*cr7+eq, 4*cr5+eq
2835 }
2836 | cmplwi cr6, TMP3, ~LJ_TISTABUD // Table or userdata?
2837 if (LJ_HASFFI) {
2838 | beq cr7, ->vmeta_equal_cd
2839 }
2840 | cmplw cr5, CARG2, CARG3
2841 | crandc 4*cr0+gt, 4*cr0+eq, 4*cr1+gt // 2: Same type and primitive.
2842 | crorc 4*cr0+lt, 4*cr5+eq, 4*cr0+eq // 1: Same tv or different type.
2843 | crand 4*cr0+eq, 4*cr0+eq, 4*cr5+eq // 0: Same type and same tv.
2844 | mr SAVE0, PC
2845 | cror 4*cr0+eq, 4*cr0+eq, 4*cr0+gt // 0 or 2.
2846 | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+gt // 1 or 2.
2847 if (vk) {
2848 | bne cr0, >6
2849 | add PC, PC, TMP2
2850 |6:
2851 } else {
2852 | beq cr0, >6
2853 | add PC, PC, TMP2
2854 |6:
2855 }
2856 if (LJ_DUALNUM) {
2857 | bge cr0, >2 // Done if 1 or 2.
2858 |1:
2859 | ins_next
2860 |2:
2861 } else {
2862 | blt cr0, <1 // Done if 1 or 2.
2863 }
2864 | blt cr6, <1 // Done if not tab/ud.
2865 |
2866 | // Different tables or userdatas. Need to check __eq metamethod.
2867 | // Field metatable must be at same offset for GCtab and GCudata!
2868 | lwz TAB:TMP2, TAB:CARG2->metatable
2869 | li CARG4, 1-vk // ne = 0 or 1.
2870 | cmplwi TAB:TMP2, 0
2871 | beq <1 // No metatable?
2872 | lbz TMP2, TAB:TMP2->nomm
2873 | andi. TMP2, TMP2, 1<<MM_eq
2874 | bne <1 // Or 'no __eq' flag set?
2875 | mr PC, SAVE0 // Restore old PC.
2876 | b ->vmeta_equal // Handle __eq metamethod.
2877 break;
2878
2879 case BC_ISEQS: case BC_ISNES:
2880 vk = op == BC_ISEQS;
2881 | // RA = src*8, RD = str_const*8 (~), JMP with RD = target
2882 | lwzux TMP0, RA, BASE
2883 | srwi RD, RD, 1
2884 | lwz STR:TMP3, 4(RA)
2885 | lwz TMP2, 0(PC)
2886 | subfic RD, RD, -4
2887 | addi PC, PC, 4
2888 if (LJ_HASFFI) {
2889 | cmpwi TMP0, LJ_TCDATA
2890 }
2891 | lwzx STR:TMP1, KBASE, RD // KBASE-4-str_const*4
2892 | subfic TMP0, TMP0, LJ_TSTR
2893 if (LJ_HASFFI) {
2894 | beq ->vmeta_equal_cd
2895 }
2896 | sub TMP1, STR:TMP1, STR:TMP3
2897 | or TMP0, TMP0, TMP1
2898 | decode_RD4 TMP2, TMP2
2899 | subfic TMP0, TMP0, 0
2900 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
2901 | subfe TMP1, TMP1, TMP1
2902 if (vk) {
2903 | andc TMP2, TMP2, TMP1
2904 } else {
2905 | and TMP2, TMP2, TMP1
2906 }
2907 | add PC, PC, TMP2
2908 | ins_next
2909 break;
2910
2911 case BC_ISEQN: case BC_ISNEN:
2912 vk = op == BC_ISEQN;
2913 | // RA = src*8, RD = num_const*8, JMP with RD = target
2914 if (LJ_DUALNUM) {
2915 | lwzux TMP0, RA, BASE
2916 | addi PC, PC, 4
2917 | lwz CARG2, 4(RA)
2918 | lwzux TMP1, RD, KBASE
2919 | checknum cr0, TMP0
2920 | lwz TMP2, -4(PC)
2921 | checknum cr1, TMP1
2922 | decode_RD4 TMP2, TMP2
2923 | lwz CARG3, 4(RD)
2924 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
2925 if (vk) {
2926 |->BC_ISEQN_Z:
2927 } else {
2928 |->BC_ISNEN_Z:
2929 }
2930 | bne cr0, >7
2931 | bne cr1, >8
2932 | cmpw CARG2, CARG3
2933 |4:
2934 } else {
2935 if (vk) {
2936 |->BC_ISEQN_Z: // Dummy label.
2937 } else {
2938 |->BC_ISNEN_Z: // Dummy label.
2939 }
2940 | lwzx TMP0, BASE, RA
2941 | addi PC, PC, 4
2942 | lfdx f0, BASE, RA
2943 | lwz TMP2, -4(PC)
2944 | lfdx f1, KBASE, RD
2945 | decode_RD4 TMP2, TMP2
2946 | checknum TMP0
2947 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
2948 | bge >3
2949 | fcmpu cr0, f0, f1
2950 }
2951 if (vk) {
2952 | bne >1
2953 | add PC, PC, TMP2
2954 |1:
2955 if (!LJ_HASFFI) {
2956 |3:
2957 }
2958 } else {
2959 | beq >2
2960 |1:
2961 if (!LJ_HASFFI) {
2962 |3:
2963 }
2964 | add PC, PC, TMP2
2965 |2:
2966 }
2967 | ins_next
2968 if (LJ_HASFFI) {
2969 |3:
2970 | cmpwi TMP0, LJ_TCDATA
2971 | beq ->vmeta_equal_cd
2972 | b <1
2973 }
2974 if (LJ_DUALNUM) {
2975 |7: // RA is not an integer.
2976 | bge cr0, <3
2977 | // RA is a number.
2978 | lfd f0, 0(RA)
2979 | blt cr1, >1
2980 | // RA is a number, RD is an integer.
2981 | tonum_i f1, CARG3
2982 | b >2
2983 |
2984 |8: // RA is an integer, RD is a number.
2985 | tonum_i f0, CARG2
2986 |1:
2987 | lfd f1, 0(RD)
2988 |2:
2989 | fcmpu cr0, f0, f1
2990 | b <4
2991 }
2992 break;
2993
2994 case BC_ISEQP: case BC_ISNEP:
2995 vk = op == BC_ISEQP;
2996 | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target
2997 | lwzx TMP0, BASE, RA
2998 | srwi TMP1, RD, 3
2999 | lwz TMP2, 0(PC)
3000 | not TMP1, TMP1
3001 | addi PC, PC, 4
3002 if (LJ_HASFFI) {
3003 | cmpwi TMP0, LJ_TCDATA
3004 }
3005 | sub TMP0, TMP0, TMP1
3006 if (LJ_HASFFI) {
3007 | beq ->vmeta_equal_cd
3008 }
3009 | decode_RD4 TMP2, TMP2
3010 | addic TMP0, TMP0, -1
3011 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
3012 | subfe TMP1, TMP1, TMP1
3013 if (vk) {
3014 | and TMP2, TMP2, TMP1
3015 } else {
3016 | andc TMP2, TMP2, TMP1
3017 }
3018 | add PC, PC, TMP2
3019 | ins_next
3020 break;
3021
3022 /* -- Unary test and copy ops ------------------------------------------- */
3023
3024 case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF:
3025 | // RA = dst*8 or unused, RD = src*8, JMP with RD = target
3026 | lwzx TMP0, BASE, RD
3027 | lwz INS, 0(PC)
3028 | addi PC, PC, 4
3029 if (op == BC_IST || op == BC_ISF) {
3030 | subfic TMP0, TMP0, LJ_TTRUE
3031 | decode_RD4 TMP2, INS
3032 | subfe TMP1, TMP1, TMP1
3033 | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
3034 if (op == BC_IST) {
3035 | andc TMP2, TMP2, TMP1
3036 } else {
3037 | and TMP2, TMP2, TMP1
3038 }
3039 | add PC, PC, TMP2
3040 } else {
3041 | li TMP1, LJ_TFALSE
3042 | lfdx f0, BASE, RD
3043 | cmplw TMP0, TMP1
3044 if (op == BC_ISTC) {
3045 | bge >1
3046 } else {
3047 | blt >1
3048 }
3049 | addis PC, PC, -(BCBIAS_J*4 >> 16)
3050 | decode_RD4 TMP2, INS
3051 | stfdx f0, BASE, RA
3052 | add PC, PC, TMP2
3053 |1:
3054 }
3055 | ins_next
3056 break;
3057
3058 /* -- Unary ops --------------------------------------------------------- */
3059
3060 case BC_MOV:
3061 | // RA = dst*8, RD = src*8
3062 | ins_next1
3063 | lfdx f0, BASE, RD
3064 | stfdx f0, BASE, RA
3065 | ins_next2
3066 break;
3067 case BC_NOT:
3068 | // RA = dst*8, RD = src*8
3069 | ins_next1
3070 | lwzx TMP0, BASE, RD
3071 | subfic TMP1, TMP0, LJ_TTRUE
3072 | adde TMP0, TMP0, TMP1
3073 | stwx TMP0, BASE, RA
3074 | ins_next2
3075 break;
3076 case BC_UNM:
3077 | // RA = dst*8, RD = src*8
3078 | lwzux TMP1, RD, BASE
3079 | lwz TMP0, 4(RD)
3080 | checknum TMP1
3081 if (LJ_DUALNUM) {
3082 | bne >5
3083 | nego. TMP0, TMP0
3084 | bso >4
3085 |1:
3086 | ins_next1
3087 | stwux TISNUM, RA, BASE
3088 | stw TMP0, 4(RA)
3089 |3:
3090 | ins_next2
3091 |4: // Potential overflow.
3092 | mcrxr cr0; bley <1 // Ignore unrelated overflow.
3093 | lus TMP1, 0x41e0 // 2^31.
3094 | li TMP0, 0
3095 | b >7
3096 }
3097 |5:
3098 | bge ->vmeta_unm
3099 | xoris TMP1, TMP1, 0x8000
3100 |7:
3101 | ins_next1
3102 | stwux TMP1, RA, BASE
3103 | stw TMP0, 4(RA)
3104 if (LJ_DUALNUM) {
3105 | b <3
3106 } else {
3107 | ins_next2
3108 }
3109 break;
3110 case BC_LEN:
3111 | // RA = dst*8, RD = src*8
3112 | lwzux TMP0, RD, BASE
3113 | lwz CARG1, 4(RD)
3114 | checkstr TMP0; bne >2
3115 | lwz CRET1, STR:CARG1->len
3116 |1:
3117 if (LJ_DUALNUM) {
3118 | ins_next1
3119 | stwux TISNUM, RA, BASE
3120 | stw CRET1, 4(RA)
3121 } else {
3122 | tonum_u f0, CRET1 // Result is a non-negative integer.
3123 | ins_next1
3124 | stfdx f0, BASE, RA
3125 }
3126 | ins_next2
3127 |2:
3128 | checktab TMP0; bne ->vmeta_len
3129#ifdef LUAJIT_ENABLE_LUA52COMPAT
3130 | lwz TAB:TMP2, TAB:CARG1->metatable
3131 | cmplwi TAB:TMP2, 0
3132 | bne >9
3133 |3:
3134#endif
3135 |->BC_LEN_Z:
3136 | bl extern lj_tab_len // (GCtab *t)
3137 | // Returns uint32_t (but less than 2^31).
3138 | b <1
3139#ifdef LUAJIT_ENABLE_LUA52COMPAT
3140 |9:
3141 | lbz TMP0, TAB:TMP2->nomm
3142 | andi. TMP0, TMP0, 1<<MM_len
3143 | bne <3 // 'no __len' flag set: done.
3144 | b ->vmeta_len
3145#endif
3146 break;
3147
3148 /* -- Binary ops -------------------------------------------------------- */
3149
3150 |.macro ins_arithpre
3151 | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
3152 ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
3153 ||switch (vk) {
3154 ||case 0:
3155 | lwzx TMP1, BASE, RB
3156 ||if (LJ_DUALNUM) {
3157 | lwzx TMP2, KBASE, RC
3158 ||}
3159 | lfdx f14, BASE, RB
3160 | lfdx f15, KBASE, RC
3161 ||if (LJ_DUALNUM) {
3162 | checknum cr0, TMP1
3163 | checknum cr1, TMP2
3164 | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3165 | bge ->vmeta_arith_vn
3166 ||} else {
3167 | checknum TMP1; bge ->vmeta_arith_vn
3168 ||}
3169 || break;
3170 ||case 1:
3171 | lwzx TMP1, BASE, RB
3172 ||if (LJ_DUALNUM) {
3173 | lwzx TMP2, KBASE, RC
3174 ||}
3175 | lfdx f15, BASE, RB
3176 | lfdx f14, KBASE, RC
3177 ||if (LJ_DUALNUM) {
3178 | checknum cr0, TMP1
3179 | checknum cr1, TMP2
3180 | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3181 | bge ->vmeta_arith_nv
3182 ||} else {
3183 | checknum TMP1; bge ->vmeta_arith_nv
3184 ||}
3185 || break;
3186 ||default:
3187 | lwzx TMP1, BASE, RB
3188 | lwzx TMP2, BASE, RC
3189 | lfdx f14, BASE, RB
3190 | lfdx f15, BASE, RC
3191 | checknum cr0, TMP1
3192 | checknum cr1, TMP2
3193 | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3194 | bge ->vmeta_arith_vv
3195 || break;
3196 ||}
3197 |.endmacro
3198 |
3199 |.macro ins_arithfallback, ins
3200 ||switch (vk) {
3201 ||case 0:
3202 | ins ->vmeta_arith_vn2
3203 || break;
3204 ||case 1:
3205 | ins ->vmeta_arith_nv2
3206 || break;
3207 ||default:
3208 | ins ->vmeta_arith_vv2
3209 || break;
3210 ||}
3211 |.endmacro
3212 |
3213 |.macro intmod, a, b, c
3214 | bl ->vm_modi
3215 |.endmacro
3216 |
3217 |.macro fpmod, a, b, c
3218 |->BC_MODVN_Z:
3219 | fdiv FARG1, b, c
3220 | // NYI: Use internal implementation of floor.
3221 | bl extern floor // floor(b/c)
3222 | fmul a, FARG1, c
3223 | fsub a, b, a // b - floor(b/c)*c
3224 |.endmacro
3225 |
3226 |.macro ins_arithfp, fpins
3227 | ins_arithpre
3228 |.if "fpins" == "fpmod_"
3229 | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway.
3230 |.else
3231 | fpins f0, f14, f15
3232 | ins_next1
3233 | stfdx f0, BASE, RA
3234 | ins_next2
3235 |.endif
3236 |.endmacro
3237 |
3238 |.macro ins_arithdn, intins, fpins
3239 | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
3240 ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
3241 ||switch (vk) {
3242 ||case 0:
3243 | lwzux TMP1, RB, BASE
3244 | lwzux TMP2, RC, KBASE
3245 | lwz CARG1, 4(RB)
3246 | checknum cr0, TMP1
3247 | lwz CARG2, 4(RC)
3248 || break;
3249 ||case 1:
3250 | lwzux TMP1, RB, BASE
3251 | lwzux TMP2, RC, KBASE
3252 | lwz CARG2, 4(RB)
3253 | checknum cr0, TMP1
3254 | lwz CARG1, 4(RC)
3255 || break;
3256 ||default:
3257 | lwzux TMP1, RB, BASE
3258 | lwzux TMP2, RC, BASE
3259 | lwz CARG1, 4(RB)
3260 | checknum cr0, TMP1
3261 | lwz CARG2, 4(RC)
3262 || break;
3263 ||}
3264 | checknum cr1, TMP2
3265 | bne >5
3266 | bne cr1, >5
3267 | intins CARG1, CARG1, CARG2
3268 | bso >4
3269 |1:
3270 | ins_next1
3271 | stwux TISNUM, RA, BASE
3272 | stw CARG1, 4(RA)
3273 |2:
3274 | ins_next2
3275 |4: // Overflow.
3276 | mcrxr cr0; bley <1 // Ignore unrelated overflow.
3277 | ins_arithfallback b
3278 |5: // FP variant.
3279 ||if (vk == 1) {
3280 | lfd f15, 0(RB)
3281 | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3282 | lfd f14, 0(RC)
3283 ||} else {
3284 | lfd f14, 0(RB)
3285 | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3286 | lfd f15, 0(RC)
3287 ||}
3288 | ins_arithfallback bge
3289 |.if "fpins" == "fpmod_"
3290 | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway.
3291 |.else
3292 | fpins f0, f14, f15
3293 | ins_next1
3294 | stfdx f0, BASE, RA
3295 | b <2
3296 |.endif
3297 |.endmacro
3298 |
3299 |.macro ins_arith, intins, fpins
3300 ||if (LJ_DUALNUM) {
3301 | ins_arithdn intins, fpins
3302 ||} else {
3303 | ins_arithfp fpins
3304 ||}
3305 |.endmacro
3306
3307 case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
3308 | ins_arith addo., fadd
3309 break;
3310 case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
3311 | ins_arith subo., fsub
3312 break;
3313 case BC_MULVN: case BC_MULNV: case BC_MULVV:
3314 | ins_arith mullwo., fmul
3315 break;
3316 case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
3317 | ins_arithfp fdiv
3318 break;
3319 case BC_MODVN:
3320 | ins_arith intmod, fpmod
3321 break;
3322 case BC_MODNV: case BC_MODVV:
3323 | ins_arith intmod, fpmod_
3324 break;
3325 case BC_POW:
3326 | // NYI: (partial) integer arithmetic.
3327 | lwzx TMP1, BASE, RB
3328 | lfdx FARG1, BASE, RB
3329 | lwzx TMP2, BASE, RC
3330 | lfdx FARG2, BASE, RC
3331 | checknum cr0, TMP1
3332 | checknum cr1, TMP2
3333 | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
3334 | bge ->vmeta_arith_vv
3335 | bl extern pow
3336 | ins_next1
3337 | stfdx FARG1, BASE, RA
3338 | ins_next2
3339 break;
3340
3341 case BC_CAT:
3342 | // RA = dst*8, RB = src_start*8, RC = src_end*8
3343 | sub CARG3, RC, RB
3344 | stw BASE, L->base
3345 | add CARG2, BASE, RC
3346 | mr SAVE0, RB
3347 |->BC_CAT_Z:
3348 | stw PC, SAVE_PC
3349 | mr CARG1, L
3350 | srwi CARG3, CARG3, 3
3351 | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left)
3352 | // Returns NULL (finished) or TValue * (metamethod).
3353 | cmplwi CRET1, 0
3354 | lwz BASE, L->base
3355 | bne ->vmeta_binop
3356 | ins_next1
3357 | lfdx f0, BASE, SAVE0 // Copy result from RB to RA.
3358 | stfdx f0, BASE, RA
3359 | ins_next2
3360 break;
3361
3362 /* -- Constant ops ------------------------------------------------------ */
3363
3364 case BC_KSTR:
3365 | // RA = dst*8, RD = str_const*8 (~)
3366 | srwi TMP1, RD, 1
3367 | subfic TMP1, TMP1, -4
3368 | ins_next1
3369 | lwzx TMP0, KBASE, TMP1 // KBASE-4-str_const*4
3370 | li TMP2, LJ_TSTR
3371 | stwux TMP2, RA, BASE
3372 | stw TMP0, 4(RA)
3373 | ins_next2
3374 break;
3375 case BC_KCDATA:
3376#if LJ_HASFFI
3377 | // RA = dst*8, RD = cdata_const*8 (~)
3378 | srwi TMP1, RD, 1
3379 | subfic TMP1, TMP1, -4
3380 | ins_next1
3381 | lwzx TMP0, KBASE, TMP1 // KBASE-4-cdata_const*4
3382 | li TMP2, LJ_TCDATA
3383 | stwux TMP2, RA, BASE
3384 | stw TMP0, 4(RA)
3385 | ins_next2
3386#endif
3387 break;
3388 case BC_KSHORT:
3389 | // RA = dst*8, RD = int16_literal*8
3390 if (LJ_DUALNUM) {
3391 | slwi RD, RD, 13
3392 | srawi RD, RD, 16
3393 | ins_next1
3394 | stwux TISNUM, RA, BASE
3395 | stw RD, 4(RA)
3396 | ins_next2
3397 } else {
3398 | // The soft-float approach is faster.
3399 | slwi RD, RD, 13
3400 | srawi TMP1, RD, 31
3401 | xor TMP2, TMP1, RD
3402 | sub TMP2, TMP2, TMP1 // TMP2 = abs(x)
3403 | cntlzw TMP3, TMP2
3404 | subfic TMP1, TMP3, 0x40d // TMP1 = exponent-1
3405 | slw TMP2, TMP2, TMP3 // TMP2 = left aligned mantissa
3406 | subfic TMP3, RD, 0
3407 | slwi TMP1, TMP1, 20
3408 | rlwimi RD, TMP2, 21, 1, 31 // hi = sign(x) | (mantissa>>11)
3409 | subfe TMP0, TMP0, TMP0
3410 | add RD, RD, TMP1 // hi = hi + exponent-1
3411 | and RD, RD, TMP0 // hi = x == 0 ? 0 : hi
3412 | ins_next1
3413 | stwux RD, RA, BASE
3414 | stw ZERO, 4(RA)
3415 | ins_next2
3416 }
3417 break;
3418 case BC_KNUM:
3419 | // RA = dst*8, RD = num_const*8
3420 | ins_next1
3421 | lfdx f0, KBASE, RD
3422 | stfdx f0, BASE, RA
3423 | ins_next2
3424 break;
3425 case BC_KPRI:
3426 | // RA = dst*8, RD = primitive_type*8 (~)
3427 | srwi TMP1, RD, 3
3428 | not TMP0, TMP1
3429 | ins_next1
3430 | stwx TMP0, BASE, RA
3431 | ins_next2
3432 break;
3433 case BC_KNIL:
3434 | // RA = base*8, RD = end*8
3435 | stwx TISNIL, BASE, RA
3436 | addi RA, RA, 8
3437 |1:
3438 | stwx TISNIL, BASE, RA
3439 | cmpw RA, RD
3440 | addi RA, RA, 8
3441 | blt <1
3442 | ins_next_
3443 break;
3444
3445 /* -- Upvalue and function ops ------------------------------------------ */
3446
3447 case BC_UGET:
3448 | // RA = dst*8, RD = uvnum*8
3449 | lwz LFUNC:RB, FRAME_FUNC(BASE)
3450 | srwi RD, RD, 1
3451 | addi RD, RD, offsetof(GCfuncL, uvptr)
3452 | lwzx UPVAL:RB, LFUNC:RB, RD
3453 | ins_next1
3454 | lwz TMP1, UPVAL:RB->v
3455 | lfd f0, 0(TMP1)
3456 | stfdx f0, BASE, RA
3457 | ins_next2
3458 break;
3459 case BC_USETV:
3460 | // RA = uvnum*8, RD = src*8
3461 | lwz LFUNC:RB, FRAME_FUNC(BASE)
3462 | srwi RA, RA, 1
3463 | addi RA, RA, offsetof(GCfuncL, uvptr)
3464 | lfdux f0, RD, BASE
3465 | lwzx UPVAL:RB, LFUNC:RB, RA
3466 | lbz TMP3, UPVAL:RB->marked
3467 | lwz CARG2, UPVAL:RB->v
3468 | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv)
3469 | lbz TMP0, UPVAL:RB->closed
3470 | lwz TMP2, 0(RD)
3471 | stfd f0, 0(CARG2)
3472 | cmplwi cr1, TMP0, 0
3473 | lwz TMP1, 4(RD)
3474 | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
3475 | subi TMP2, TMP2, (LJ_TISNUM+1)
3476 | bne >2 // Upvalue is closed and black?
3477 |1:
3478 | ins_next
3479 |
3480 |2: // Check if new value is collectable.
3481 | cmplwi TMP2, LJ_TISGCV - (LJ_TISNUM+1)
3482 | bge <1 // tvisgcv(v)
3483 | lbz TMP3, GCOBJ:TMP1->gch.marked
3484 | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(v)
3485 | la CARG1, GG_DISP2G(DISPATCH)
3486 | // Crossed a write barrier. Move the barrier forward.
3487 | beq <1
3488 | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv)
3489 | b <1
3490 break;
3491 case BC_USETS:
3492 | // RA = uvnum*8, RD = str_const*8 (~)
3493 | lwz LFUNC:RB, FRAME_FUNC(BASE)
3494 | srwi TMP1, RD, 1
3495 | srwi RA, RA, 1
3496 | subfic TMP1, TMP1, -4
3497 | addi RA, RA, offsetof(GCfuncL, uvptr)
3498 | lwzx STR:TMP1, KBASE, TMP1 // KBASE-4-str_const*4
3499 | lwzx UPVAL:RB, LFUNC:RB, RA
3500 | lbz TMP3, UPVAL:RB->marked
3501 | lwz CARG2, UPVAL:RB->v
3502 | andi. TMP3, TMP3, LJ_GC_BLACK // isblack(uv)
3503 | lbz TMP3, STR:TMP1->marked
3504 | lbz TMP2, UPVAL:RB->closed
3505 | li TMP0, LJ_TSTR
3506 | stw STR:TMP1, 4(CARG2)
3507 | stw TMP0, 0(CARG2)
3508 | bne >2
3509 |1:
3510 | ins_next
3511 |
3512 |2: // Check if string is white and ensure upvalue is closed.
3513 | andi. TMP3, TMP3, LJ_GC_WHITES // iswhite(str)
3514 | cmplwi cr1, TMP2, 0
3515 | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
3516 | la CARG1, GG_DISP2G(DISPATCH)
3517 | // Crossed a write barrier. Move the barrier forward.
3518 | beq <1
3519 | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv)
3520 | b <1
3521 break;
3522 case BC_USETN:
3523 | // RA = uvnum*8, RD = num_const*8
3524 | lwz LFUNC:RB, FRAME_FUNC(BASE)
3525 | srwi RA, RA, 1
3526 | addi RA, RA, offsetof(GCfuncL, uvptr)
3527 | lfdx f0, KBASE, RD
3528 | lwzx UPVAL:RB, LFUNC:RB, RA
3529 | ins_next1
3530 | lwz TMP1, UPVAL:RB->v
3531 | stfd f0, 0(TMP1)
3532 | ins_next2
3533 break;
3534 case BC_USETP:
3535 | // RA = uvnum*8, RD = primitive_type*8 (~)
3536 | lwz LFUNC:RB, FRAME_FUNC(BASE)
3537 | srwi RA, RA, 1
3538 | srwi TMP0, RD, 3
3539 | addi RA, RA, offsetof(GCfuncL, uvptr)
3540 | not TMP0, TMP0
3541 | lwzx UPVAL:RB, LFUNC:RB, RA
3542 | ins_next1
3543 | lwz TMP1, UPVAL:RB->v
3544 | stw TMP0, 0(TMP1)
3545 | ins_next2
3546 break;
3547
3548 case BC_UCLO:
3549 | // RA = level*8, RD = target
3550 | lwz TMP1, L->openupval
3551 | branch_RD // Do this first since RD is not saved.
3552 | stw BASE, L->base
3553 | cmplwi TMP1, 0
3554 | mr CARG1, L
3555 | beq >1
3556 | add CARG2, BASE, RA
3557 | bl extern lj_func_closeuv // (lua_State *L, TValue *level)
3558 | lwz BASE, L->base
3559 |1:
3560 | ins_next
3561 break;
3562
3563 case BC_FNEW:
3564 | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype)
3565 | srwi TMP1, RD, 1
3566 | stw BASE, L->base
3567 | subfic TMP1, TMP1, -4
3568 | stw PC, SAVE_PC
3569 | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4
3570 | mr CARG1, L
3571 | lwz CARG3, FRAME_FUNC(BASE)
3572 | // (lua_State *L, GCproto *pt, GCfuncL *parent)
3573 | bl extern lj_func_newL_gc
3574 | // Returns GCfuncL *.
3575 | lwz BASE, L->base
3576 | li TMP0, LJ_TFUNC
3577 | stwux TMP0, RA, BASE
3578 | stw LFUNC:CRET1, 4(RA)
3579 | ins_next
3580 break;
3581
3582 /* -- Table ops --------------------------------------------------------- */
3583
3584 case BC_TNEW:
3585 case BC_TDUP:
3586 | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~)
3587 | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH)
3588 | mr CARG1, L
3589 | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
3590 | stw BASE, L->base
3591 | cmplw TMP0, TMP1
3592 | stw PC, SAVE_PC
3593 | bge >5
3594 |1:
3595 if (op == BC_TNEW) {
3596 | rlwinm CARG2, RD, 29, 21, 31
3597 | rlwinm CARG3, RD, 18, 27, 31
3598 | cmpwi CARG2, 0x7ff; beq >3
3599 |2:
3600 | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits)
3601 | // Returns Table *.
3602 } else {
3603 | srwi TMP1, RD, 1
3604 | subfic TMP1, TMP1, -4
3605 | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4
3606 | bl extern lj_tab_dup // (lua_State *L, Table *kt)
3607 | // Returns Table *.
3608 }
3609 | lwz BASE, L->base
3610 | li TMP0, LJ_TTAB
3611 | stwux TMP0, RA, BASE
3612 | stw TAB:CRET1, 4(RA)
3613 | ins_next
3614 if (op == BC_TNEW) {
3615 |3:
3616 | li CARG2, 0x801
3617 | b <2
3618 }
3619 |5:
3620 | mr SAVE0, RD
3621 | bl extern lj_gc_step_fixtop // (lua_State *L)
3622 | mr RD, SAVE0
3623 | mr CARG1, L
3624 | b <1
3625 break;
3626
3627 case BC_GGET:
3628 | // RA = dst*8, RD = str_const*8 (~)
3629 case BC_GSET:
3630 | // RA = src*8, RD = str_const*8 (~)
3631 | lwz LFUNC:TMP2, FRAME_FUNC(BASE)
3632 | srwi TMP1, RD, 1
3633 | lwz TAB:RB, LFUNC:TMP2->env
3634 | subfic TMP1, TMP1, -4
3635 | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4
3636 if (op == BC_GGET) {
3637 | b ->BC_TGETS_Z
3638 } else {
3639 | b ->BC_TSETS_Z
3640 }
3641 break;
3642
3643 case BC_TGETV:
3644 | // RA = dst*8, RB = table*8, RC = key*8
3645 | lwzux CARG1, RB, BASE
3646 | lwzux CARG2, RC, BASE
3647 | lwz TAB:RB, 4(RB)
3648 if (LJ_DUALNUM) {
3649 | lwz RC, 4(RC)
3650 } else {
3651 | lfd f0, 0(RC)
3652 }
3653 | checktab CARG1
3654 | checknum cr1, CARG2
3655 | bne ->vmeta_tgetv
3656 if (LJ_DUALNUM) {
3657 | lwz TMP0, TAB:RB->asize
3658 | bne cr1, >5
3659 | lwz TMP1, TAB:RB->array
3660 | cmplw TMP0, RC
3661 | slwi TMP2, RC, 3
3662 } else {
3663 | bge cr1, >5
3664 | // Convert number key to integer, check for integerness and range.
3665 | fctiwz f1, f0
3666 | fadd f2, f0, TOBIT
3667 | stfd f1, TMPD
3668 | lwz TMP0, TAB:RB->asize
3669 | fsub f2, f2, TOBIT
3670 | lwz TMP2, TMPD_LO
3671 | lwz TMP1, TAB:RB->array
3672 | fcmpu cr1, f0, f2
3673 | cmplw cr0, TMP0, TMP2
3674 | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq
3675 | slwi TMP2, TMP2, 3
3676 }
3677 | ble ->vmeta_tgetv // Integer key and in array part?
3678 | lwzx TMP0, TMP1, TMP2
3679 | lfdx f14, TMP1, TMP2
3680 | checknil TMP0; beq >2
3681 |1:
3682 | ins_next1
3683 | stfdx f14, BASE, RA
3684 | ins_next2
3685 |
3686 |2: // Check for __index if table value is nil.
3687 | lwz TAB:TMP2, TAB:RB->metatable
3688 | cmplwi TAB:TMP2, 0
3689 | beq <1 // No metatable: done.
3690 | lbz TMP0, TAB:TMP2->nomm
3691 | andi. TMP0, TMP0, 1<<MM_index
3692 | bne <1 // 'no __index' flag set: done.
3693 | b ->vmeta_tgetv
3694 |
3695 |5:
3696 | checkstr CARG2; bne ->vmeta_tgetv
3697 if (!LJ_DUALNUM) {
3698 | lwz STR:RC, 4(RC)
3699 }
3700 | b ->BC_TGETS_Z // String key?
3701 break;
3702 case BC_TGETS:
3703 | // RA = dst*8, RB = table*8, RC = str_const*8 (~)
3704 | lwzux CARG1, RB, BASE
3705 | srwi TMP1, RC, 1
3706 | lwz TAB:RB, 4(RB)
3707 | subfic TMP1, TMP1, -4
3708 | checktab CARG1
3709 | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4
3710 | bne ->vmeta_tgets1
3711 |->BC_TGETS_Z:
3712 | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8
3713 | lwz TMP0, TAB:RB->hmask
3714 | lwz TMP1, STR:RC->hash
3715 | lwz NODE:TMP2, TAB:RB->node
3716 | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
3717 | slwi TMP0, TMP1, 5
3718 | slwi TMP1, TMP1, 3
3719 | sub TMP1, TMP0, TMP1
3720 | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
3721 |1:
3722 | lwz CARG1, NODE:TMP2->key
3723 | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2)
3724 | lwz CARG2, NODE:TMP2->val
3725 | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2)
3726 | checkstr CARG1; bne >4
3727 | cmpw TMP0, STR:RC; bne >4
3728 | checknil CARG2; beq >5 // Key found, but nil value?
3729 |3:
3730 | stwux CARG2, RA, BASE
3731 | stw TMP1, 4(RA)
3732 | ins_next
3733 |
3734 |4: // Follow hash chain.
3735 | lwz NODE:TMP2, NODE:TMP2->next
3736 | cmplwi NODE:TMP2, 0
3737 | bne <1
3738 | // End of hash chain: key not found, nil result.
3739 | li CARG2, LJ_TNIL
3740 |
3741 |5: // Check for __index if table value is nil.
3742 | lwz TAB:TMP2, TAB:RB->metatable
3743 | cmplwi TAB:TMP2, 0
3744 | beq <3 // No metatable: done.
3745 | lbz TMP0, TAB:TMP2->nomm
3746 | andi. TMP0, TMP0, 1<<MM_index
3747 | bne <3 // 'no __index' flag set: done.
3748 | b ->vmeta_tgets
3749 break;
3750 case BC_TGETB:
3751 | // RA = dst*8, RB = table*8, RC = index*8
3752 | lwzux CARG1, RB, BASE
3753 | srwi TMP0, RC, 3
3754 | lwz TAB:RB, 4(RB)
3755 | checktab CARG1; bne ->vmeta_tgetb
3756 | lwz TMP1, TAB:RB->asize
3757 | lwz TMP2, TAB:RB->array
3758 | cmplw TMP0, TMP1; bge ->vmeta_tgetb
3759 | lwzx TMP1, TMP2, RC
3760 | lfdx f0, TMP2, RC
3761 | checknil TMP1; beq >5
3762 |1:
3763 | ins_next1
3764 | stfdx f0, BASE, RA
3765 | ins_next2
3766 |
3767 |5: // Check for __index if table value is nil.
3768 | lwz TAB:TMP2, TAB:RB->metatable
3769 | cmplwi TAB:TMP2, 0
3770 | beq <1 // No metatable: done.
3771 | lbz TMP2, TAB:TMP2->nomm
3772 | andi. TMP2, TMP2, 1<<MM_index
3773 | bne <1 // 'no __index' flag set: done.
3774 | b ->vmeta_tgetb // Caveat: preserve TMP0!
3775 break;
3776
3777 case BC_TSETV:
3778 | // RA = src*8, RB = table*8, RC = key*8
3779 | lwzux CARG1, RB, BASE
3780 | lwzux CARG2, RC, BASE
3781 | lwz TAB:RB, 4(RB)
3782 if (LJ_DUALNUM) {
3783 | lwz RC, 4(RC)
3784 } else {
3785 | lfd f0, 0(RC)
3786 }
3787 | checktab CARG1
3788 | checknum cr1, CARG2
3789 | bne ->vmeta_tsetv
3790 if (LJ_DUALNUM) {
3791 | lwz TMP0, TAB:RB->asize
3792 | bne cr1, >5
3793 | lwz TMP1, TAB:RB->array
3794 | cmplw TMP0, RC
3795 | slwi TMP0, RC, 3
3796 } else {
3797 | bge cr1, >5
3798 | // Convert number key to integer, check for integerness and range.
3799 | fctiwz f1, f0
3800 | fadd f2, f0, TOBIT
3801 | stfd f1, TMPD
3802 | lwz TMP0, TAB:RB->asize
3803 | fsub f2, f2, TOBIT
3804 | lwz TMP2, TMPD_LO
3805 | lwz TMP1, TAB:RB->array
3806 | fcmpu cr1, f0, f2
3807 | cmplw cr0, TMP0, TMP2
3808 | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq
3809 | slwi TMP0, TMP2, 3
3810 }
3811 | ble ->vmeta_tsetv // Integer key and in array part?
3812 | lwzx TMP2, TMP1, TMP0
3813 | lbz TMP3, TAB:RB->marked
3814 | lfdx f14, BASE, RA
3815 | checknil TMP2; beq >3
3816 |1:
3817 | andi. TMP2, TMP3, LJ_GC_BLACK // isblack(table)
3818 | stfdx f14, TMP1, TMP0
3819 | bne >7
3820 |2:
3821 | ins_next
3822 |
3823 |3: // Check for __newindex if previous value is nil.
3824 | lwz TAB:TMP2, TAB:RB->metatable
3825 | cmplwi TAB:TMP2, 0
3826 | beq <1 // No metatable: done.
3827 | lbz TMP2, TAB:TMP2->nomm
3828 | andi. TMP2, TMP2, 1<<MM_newindex
3829 | bne <1 // 'no __newindex' flag set: done.
3830 | b ->vmeta_tsetv
3831 |
3832 |5:
3833 | checkstr CARG2; bne ->vmeta_tsetv
3834 if (!LJ_DUALNUM) {
3835 | lwz STR:RC, 4(RC)
3836 }
3837 | b ->BC_TSETS_Z // String key?
3838 |
3839 |7: // Possible table write barrier for the value. Skip valiswhite check.
3840 | barrierback TAB:RB, TMP3, TMP0
3841 | b <2
3842 break;
3843 |1:
3844 | checkstr CARG1; bne >4
3845 | cmpw TMP0, STR:RC; bne >4
3846 | checknil CARG2; beq >5 // Key found, but nil value?
3847 |3:
3848 | stwux CARG2, RA, BASE
3849 | stw TMP1, 4(RA)
3850 | ins_next
3851 case BC_TSETS:
3852 | // RA = src*8, RB = table*8, RC = str_const*8 (~)
3853 | lwzux CARG1, RB, BASE
3854 | srwi TMP1, RC, 1
3855 | lwz TAB:RB, 4(RB)
3856 | subfic TMP1, TMP1, -4
3857 | checktab CARG1
3858 | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4
3859 | bne ->vmeta_tsets1
3860 |->BC_TSETS_Z:
3861 | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8
3862 | lwz TMP0, TAB:RB->hmask
3863 | lwz TMP1, STR:RC->hash
3864 | lwz NODE:TMP2, TAB:RB->node
3865 | stb ZERO, TAB:RB->nomm // Clear metamethod cache.
3866 | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
3867 | lfdx f14, BASE, RA
3868 | slwi TMP0, TMP1, 5
3869 | slwi TMP1, TMP1, 3
3870 | sub TMP1, TMP0, TMP1
3871 | lbz TMP3, TAB:RB->marked
3872 | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
3873 |1:
3874 | lwz CARG1, NODE:TMP2->key
3875 | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2)
3876 | lwz CARG2, NODE:TMP2->val
3877 | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2)
3878 | checkstr CARG1; bne >5
3879 | cmpw TMP0, STR:RC; bne >5
3880 | checknil CARG2; beq >4 // Key found, but nil value?
3881 |2:
3882 | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
3883 | stfd f14, NODE:TMP2->val
3884 | bne >7
3885 |3:
3886 | ins_next
3887 |
3888 |4: // Check for __newindex if previous value is nil.
3889 | lwz TAB:TMP1, TAB:RB->metatable
3890 | cmplwi TAB:TMP1, 0
3891 | beq <2 // No metatable: done.
3892 | lbz TMP0, TAB:TMP1->nomm
3893 | andi. TMP0, TMP0, 1<<MM_newindex
3894 | bne <2 // 'no __newindex' flag set: done.
3895 | b ->vmeta_tsets
3896 |
3897 |5: // Follow hash chain.
3898 | lwz NODE:TMP2, NODE:TMP2->next
3899 | cmplwi NODE:TMP2, 0
3900 | bne <1
3901 | // End of hash chain: key not found, add a new one.
3902 |
3903 | // But check for __newindex first.
3904 | lwz TAB:TMP1, TAB:RB->metatable
3905 | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
3906 | stw PC, SAVE_PC
3907 | mr CARG1, L
3908 | cmplwi TAB:TMP1, 0
3909 | stw BASE, L->base
3910 | beq >6 // No metatable: continue.
3911 | lbz TMP0, TAB:TMP1->nomm
3912 | andi. TMP0, TMP0, 1<<MM_newindex
3913 | beq ->vmeta_tsets // 'no __newindex' flag NOT set: check.
3914 |6:
3915 | li TMP0, LJ_TSTR
3916 | stw STR:RC, 4(CARG3)
3917 | mr CARG2, TAB:RB
3918 | stw TMP0, 0(CARG3)
3919 | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k)
3920 | // Returns TValue *.
3921 | lwz BASE, L->base
3922 | stfd f14, 0(CRET1)
3923 | b <3 // No 2nd write barrier needed.
3924 |
3925 |7: // Possible table write barrier for the value. Skip valiswhite check.
3926 | barrierback TAB:RB, TMP3, TMP0
3927 | b <3
3928 break;
3929 case BC_TSETB:
3930 | // RA = src*8, RB = table*8, RC = index*8
3931 | lwzux CARG1, RB, BASE
3932 | srwi TMP0, RC, 3
3933 | lwz TAB:RB, 4(RB)
3934 | checktab CARG1; bne ->vmeta_tsetb
3935 | lwz TMP1, TAB:RB->asize
3936 | lwz TMP2, TAB:RB->array
3937 | lbz TMP3, TAB:RB->marked
3938 | cmplw TMP0, TMP1
3939 | lfdx f14, BASE, RA
3940 | bge ->vmeta_tsetb
3941 | lwzx TMP1, TMP2, RC
3942 | checknil TMP1; beq >5
3943 |1:
3944 | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
3945 | stfdx f14, TMP2, RC
3946 | bne >7
3947 |2:
3948 | ins_next
3949 |
3950 |5: // Check for __newindex if previous value is nil.
3951 | lwz TAB:TMP1, TAB:RB->metatable
3952 | cmplwi TAB:TMP1, 0
3953 | beq <1 // No metatable: done.
3954 | lbz TMP1, TAB:TMP1->nomm
3955 | andi. TMP1, TMP1, 1<<MM_newindex
3956 | bne <1 // 'no __newindex' flag set: done.
3957 | b ->vmeta_tsetb // Caveat: preserve TMP0!
3958 |
3959 |7: // Possible table write barrier for the value. Skip valiswhite check.
3960 | barrierback TAB:RB, TMP3, TMP0
3961 | b <2
3962 break;
3963
3964 case BC_TSETM:
3965 | // RA = base*8 (table at base-1), RD = num_const*8 (start index)
3966 | add RA, BASE, RA
3967 |1:
3968 | add TMP3, KBASE, RD
3969 | lwz TAB:CARG2, -4(RA) // Guaranteed to be a table.
3970 | addic. TMP0, MULTRES, -8
3971 | lwz TMP3, 4(TMP3) // Integer constant is in lo-word.
3972 | srwi CARG3, TMP0, 3
3973 | beq >4 // Nothing to copy?
3974 | add CARG3, CARG3, TMP3
3975 | lwz TMP2, TAB:CARG2->asize
3976 | slwi TMP1, TMP3, 3
3977 | lbz TMP3, TAB:CARG2->marked
3978 | cmplw CARG3, TMP2
3979 | add TMP2, RA, TMP0
3980 | lwz TMP0, TAB:CARG2->array
3981 | bgt >5
3982 | add TMP1, TMP1, TMP0
3983 | andi. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
3984 |3: // Copy result slots to table.
3985 | lfd f0, 0(RA)
3986 | addi RA, RA, 8
3987 | cmpw cr1, RA, TMP2
3988 | stfd f0, 0(TMP1)
3989 | addi TMP1, TMP1, 8
3990 | blt cr1, <3
3991 | bne >7
3992 |4:
3993 | ins_next
3994 |
3995 |5: // Need to resize array part.
3996 | stw BASE, L->base
3997 | mr CARG1, L
3998 | stw PC, SAVE_PC
3999 | mr SAVE0, RD
4000 | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize)
4001 | // Must not reallocate the stack.
4002 | mr RD, SAVE0
4003 | b <1
4004 |
4005 |7: // Possible table write barrier for any value. Skip valiswhite check.
4006 | barrierback TAB:CARG2, TMP3, TMP0
4007 | b <4
4008 break;
4009
4010 /* -- Calls and vararg handling ----------------------------------------- */
4011
4012 case BC_CALLM:
4013 | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8
4014 | add NARGS8:RC, NARGS8:RC, MULTRES
4015 | // Fall through. Assumes BC_CALL follows.
4016 break;
4017 case BC_CALL:
4018 | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8
4019 | mr TMP2, BASE
4020 | lwzux TMP0, BASE, RA
4021 | lwz LFUNC:RB, 4(BASE)
4022 | subi NARGS8:RC, NARGS8:RC, 8
4023 | addi BASE, BASE, 8
4024 | checkfunc TMP0; bne ->vmeta_call
4025 | ins_call
4026 break;
4027
4028 case BC_CALLMT:
4029 | // RA = base*8, (RB = 0,) RC = extra_nargs*8
4030 | add NARGS8:RC, NARGS8:RC, MULTRES
4031 | // Fall through. Assumes BC_CALLT follows.
4032 break;
4033 case BC_CALLT:
4034 | // RA = base*8, (RB = 0,) RC = (nargs+1)*8
4035 | lwzux TMP0, RA, BASE
4036 | lwz LFUNC:RB, 4(RA)
4037 | subi NARGS8:RC, NARGS8:RC, 8
4038 | lwz TMP1, FRAME_PC(BASE)
4039 | checkfunc TMP0
4040 | addi RA, RA, 8
4041 | bne ->vmeta_callt
4042 |->BC_CALLT_Z:
4043 | andi. TMP0, TMP1, FRAME_TYPE // Caveat: preserve cr0 until the crand.
4044 | lbz TMP3, LFUNC:RB->ffid
4045 | xori TMP2, TMP1, FRAME_VARG
4046 | cmplwi cr1, NARGS8:RC, 0
4047 | bne >7
4048 |1:
4049 | stw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC.
4050 | li TMP2, 0
4051 | cmplwi cr7, TMP3, 1 // (> FF_C) Calling a fast function?
4052 | beq cr1, >3
4053 |2:
4054 | addi TMP3, TMP2, 8
4055 | lfdx f0, RA, TMP2
4056 | cmplw cr1, TMP3, NARGS8:RC
4057 | stfdx f0, BASE, TMP2
4058 | mr TMP2, TMP3
4059 | bne cr1, <2
4060 |3:
4061 | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt
4062 | beq >5
4063 |4:
4064 | ins_callt
4065 |
4066 |5: // Tailcall to a fast function with a Lua frame below.
4067 | lwz INS, -4(TMP1)
4068 | decode_RA8 RA, INS
4069 | sub TMP1, BASE, RA
4070 | lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1)
4071 | lwz TMP1, LFUNC:TMP1->pc
4072 | lwz KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE.
4073 | b <4
4074 |
4075 |7: // Tailcall from a vararg function.
4076 | andi. TMP0, TMP2, FRAME_TYPEP
4077 | bne <1 // Vararg frame below?
4078 | sub BASE, BASE, TMP2 // Relocate BASE down.
4079 | lwz TMP1, FRAME_PC(BASE)
4080 | andi. TMP0, TMP1, FRAME_TYPE
4081 | b <1
4082 break;
4083
4084 case BC_ITERC:
4085 | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8))
4086 | mr TMP2, BASE
4087 | add BASE, BASE, RA
4088 | lwz TMP1, -24(BASE)
4089 | lwz LFUNC:RB, -20(BASE)
4090 | lfd f1, -8(BASE)
4091 | lfd f0, -16(BASE)
4092 | stw TMP1, 0(BASE) // Copy callable.
4093 | stw LFUNC:RB, 4(BASE)
4094 | checkfunc TMP1
4095 | stfd f1, 16(BASE) // Copy control var.
4096 | li NARGS8:RC, 16 // Iterators get 2 arguments.
4097 | stfdu f0, 8(BASE) // Copy state.
4098 | bne ->vmeta_call
4099 | ins_call
4100 break;
4101
4102 case BC_ITERN:
4103 | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8)
4104#if LJ_HASJIT
4105 | // NYI: add hotloop, record BC_ITERN.
4106#endif
4107 | add RA, BASE, RA
4108 | lwz TAB:RB, -12(RA)
4109 | lwz RC, -4(RA) // Get index from control var.
4110 | lwz TMP0, TAB:RB->asize
4111 | lwz TMP1, TAB:RB->array
4112 | addi PC, PC, 4
4113 |1: // Traverse array part.
4114 | cmplw RC, TMP0
4115 | slwi TMP3, RC, 3
4116 | bge >5 // Index points after array part?
4117 | lwzx TMP2, TMP1, TMP3
4118 | lfdx f0, TMP1, TMP3
4119 | checknil TMP2
4120 | lwz INS, -4(PC)
4121 | beq >4
4122 if (LJ_DUALNUM) {
4123 | stw RC, 4(RA)
4124 | stw TISNUM, 0(RA)
4125 } else {
4126 | tonum_u f1, RC
4127 }
4128 | addi RC, RC, 1
4129 | addis TMP3, PC, -(BCBIAS_J*4 >> 16)
4130 | stfd f0, 8(RA)
4131 | decode_RD4 TMP1, INS
4132 | stw RC, -4(RA) // Update control var.
4133 | add PC, TMP1, TMP3
4134 if (!LJ_DUALNUM) {
4135 | stfd f1, 0(RA)
4136 }
4137 |3:
4138 | ins_next
4139 |
4140 |4: // Skip holes in array part.
4141 | addi RC, RC, 1
4142 | b <1
4143 |
4144 |5: // Traverse hash part.
4145 | lwz TMP1, TAB:RB->hmask
4146 | sub RC, RC, TMP0
4147 | lwz TMP2, TAB:RB->node
4148 |6:
4149 | cmplw RC, TMP1 // End of iteration? Branch to ITERL+1.
4150 | slwi TMP3, RC, 5
4151 | bgty <3
4152 | slwi RB, RC, 3
4153 | sub TMP3, TMP3, RB
4154 | lwzx RB, TMP2, TMP3
4155 | lfdx f0, TMP2, TMP3
4156 | add NODE:TMP3, TMP2, TMP3
4157 | checknil RB
4158 | lwz INS, -4(PC)
4159 | beq >7
4160 | lfd f1, NODE:TMP3->key
4161 | addis TMP2, PC, -(BCBIAS_J*4 >> 16)
4162 | stfd f0, 8(RA)
4163 | add RC, RC, TMP0
4164 | decode_RD4 TMP1, INS
4165 | stfd f1, 0(RA)
4166 | addi RC, RC, 1
4167 | add PC, TMP1, TMP2
4168 | stw RC, -4(RA) // Update control var.
4169 | b <3
4170 |
4171 |7: // Skip holes in hash part.
4172 | addi RC, RC, 1
4173 | b <6
4174 break;
4175
4176 case BC_ISNEXT:
4177 | // RA = base*8, RD = target (points to ITERN)
4178 | add RA, BASE, RA
4179 | lwz TMP0, -24(RA)
4180 | lwz CFUNC:TMP1, -20(RA)
4181 | lwz TMP2, -16(RA)
4182 | lwz TMP3, -8(RA)
4183 | cmpwi cr0, TMP2, LJ_TTAB
4184 | cmpwi cr1, TMP0, LJ_TFUNC
4185 | cmpwi cr6, TMP3, LJ_TNIL
4186 | bne cr1, >5
4187 | lbz TMP1, CFUNC:TMP1->ffid
4188 | crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq
4189 | cmpwi cr7, TMP1, FF_next_N
4190 | srwi TMP0, RD, 1
4191 | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq
4192 | add TMP3, PC, TMP0
4193 | bne cr0, >5
4194 | stw ZERO, -4(RA) // Initialize control var.
4195 | addis PC, TMP3, -(BCBIAS_J*4 >> 16)
4196 |1:
4197 | ins_next
4198 |5: // Despecialize bytecode if any of the checks fail.
4199 | li TMP0, BC_JMP
4200 | li TMP1, BC_ITERC
4201 | stb TMP0, -1(PC)
4202 | addis PC, TMP3, -(BCBIAS_J*4 >> 16)
4203 | stb TMP1, 3(PC)
4204 | b <1
4205 break;
4206
4207 case BC_VARG:
4208 | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8
4209 | lwz TMP0, FRAME_PC(BASE)
4210 | add RC, BASE, RC
4211 | add RA, BASE, RA
4212 | addi RC, RC, FRAME_VARG
4213 | add TMP2, RA, RB
4214 | subi TMP3, BASE, 8 // TMP3 = vtop
4215 | sub RC, RC, TMP0 // RC = vbase
4216 | // Note: RC may now be even _above_ BASE if nargs was < numparams.
4217 | cmplwi cr1, RB, 0
4218 | sub. TMP1, TMP3, RC
4219 | beq cr1, >5 // Copy all varargs?
4220 | subi TMP2, TMP2, 16
4221 | ble >2 // No vararg slots?
4222 |1: // Copy vararg slots to destination slots.
4223 | lfd f0, 0(RC)
4224 | addi RC, RC, 8
4225 | stfd f0, 0(RA)
4226 | cmplw RA, TMP2
4227 | cmplw cr1, RC, TMP3
4228 | bge >3 // All destination slots filled?
4229 | addi RA, RA, 8
4230 | blt cr1, <1 // More vararg slots?
4231 |2: // Fill up remainder with nil.
4232 | stw TISNIL, 0(RA)
4233 | cmplw RA, TMP2
4234 | addi RA, RA, 8
4235 | blt <2
4236 |3:
4237 | ins_next
4238 |
4239 |5: // Copy all varargs.
4240 | lwz TMP0, L->maxstack
4241 | li MULTRES, 8 // MULTRES = (0+1)*8
4242 | bley <3 // No vararg slots?
4243 | add TMP2, RA, TMP1
4244 | cmplw TMP2, TMP0
4245 | addi MULTRES, TMP1, 8
4246 | bgt >7
4247 |6:
4248 | lfd f0, 0(RC)
4249 | addi RC, RC, 8
4250 | stfd f0, 0(RA)
4251 | cmplw RC, TMP3
4252 | addi RA, RA, 8
4253 | blt <6 // More vararg slots?
4254 | b <3
4255 |
4256 |7: // Grow stack for varargs.
4257 | mr CARG1, L
4258 | stw RA, L->top
4259 | sub SAVE0, RC, BASE // Need delta, because BASE may change.
4260 | stw BASE, L->base
4261 | sub RA, RA, BASE
4262 | stw PC, SAVE_PC
4263 | srwi CARG2, TMP1, 3
4264 | bl extern lj_state_growstack // (lua_State *L, int n)
4265 | lwz BASE, L->base
4266 | add RA, BASE, RA
4267 | add RC, BASE, SAVE0
4268 | subi TMP3, BASE, 8
4269 | b <6
4270 break;
4271
4272 /* -- Returns ----------------------------------------------------------- */
4273
4274 case BC_RETM:
4275 | // RA = results*8, RD = extra_nresults*8
4276 | add RD, RD, MULTRES // MULTRES >= 8, so RD >= 8.
4277 | // Fall through. Assumes BC_RET follows.
4278 break;
4279
4280 case BC_RET:
4281 | // RA = results*8, RD = (nresults+1)*8
4282 | lwz PC, FRAME_PC(BASE)
4283 | add RA, BASE, RA
4284 | mr MULTRES, RD
4285 |1:
4286 | andi. TMP0, PC, FRAME_TYPE
4287 | xori TMP1, PC, FRAME_VARG
4288 | bne ->BC_RETV_Z
4289 |
4290 |->BC_RET_Z:
4291 | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return
4292 | lwz INS, -4(PC)
4293 | cmpwi RD, 8
4294 | subi TMP2, BASE, 8
4295 | subi RC, RD, 8
4296 | decode_RB8 RB, INS
4297 | beq >3
4298 | li TMP1, 0
4299 |2:
4300 | addi TMP3, TMP1, 8
4301 | lfdx f0, RA, TMP1
4302 | cmpw TMP3, RC
4303 | stfdx f0, TMP2, TMP1
4304 | beq >3
4305 | addi TMP1, TMP3, 8
4306 | lfdx f1, RA, TMP3
4307 | cmpw TMP1, RC
4308 | stfdx f1, TMP2, TMP3
4309 | bne <2
4310 |3:
4311 |5:
4312 | cmplw RB, RD
4313 | decode_RA8 RA, INS
4314 | bgt >6
4315 | sub BASE, TMP2, RA
4316 | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
4317 | ins_next1
4318 | lwz TMP1, LFUNC:TMP1->pc
4319 | lwz KBASE, PC2PROTO(k)(TMP1)
4320 | ins_next2
4321 |
4322 |6: // Fill up results with nil.
4323 | subi TMP1, RD, 8
4324 | addi RD, RD, 8
4325 | stwx TISNIL, TMP2, TMP1
4326 | b <5
4327 |
4328 |->BC_RETV_Z: // Non-standard return case.
4329 | andi. TMP2, TMP1, FRAME_TYPEP
4330 | bne ->vm_return
4331 | // Return from vararg function: relocate BASE down.
4332 | sub BASE, BASE, TMP1
4333 | lwz PC, FRAME_PC(BASE)
4334 | b <1
4335 break;
4336
4337 case BC_RET0: case BC_RET1:
4338 | // RA = results*8, RD = (nresults+1)*8
4339 | lwz PC, FRAME_PC(BASE)
4340 | add RA, BASE, RA
4341 | mr MULTRES, RD
4342 | andi. TMP0, PC, FRAME_TYPE
4343 | xori TMP1, PC, FRAME_VARG
4344 | bney ->BC_RETV_Z
4345 |
4346 | lwz INS, -4(PC)
4347 | subi TMP2, BASE, 8
4348 | decode_RB8 RB, INS
4349 if (op == BC_RET1) {
4350 | lfd f0, 0(RA)
4351 | stfd f0, 0(TMP2)
4352 }
4353 |5:
4354 | cmplw RB, RD
4355 | decode_RA8 RA, INS
4356 | bgt >6
4357 | sub BASE, TMP2, RA
4358 | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
4359 | ins_next1
4360 | lwz TMP1, LFUNC:TMP1->pc
4361 | lwz KBASE, PC2PROTO(k)(TMP1)
4362 | ins_next2
4363 |
4364 |6: // Fill up results with nil.
4365 | subi TMP1, RD, 8
4366 | addi RD, RD, 8
4367 | stwx TISNIL, TMP2, TMP1
4368 | b <5
4369 break;
4370
4371 /* -- Loops and branches ------------------------------------------------ */
4372
4373 case BC_FORL:
4374#if LJ_HASJIT
4375 | hotloop
4376#endif
4377 | // Fall through. Assumes BC_IFORL follows.
4378 break;
4379
4380 case BC_JFORI:
4381 case BC_JFORL:
4382#if !LJ_HASJIT
4383 break;
4384#endif
4385 case BC_FORI:
4386 case BC_IFORL:
4387 | // RA = base*8, RD = target (after end of loop or start of loop)
4388 vk = (op == BC_IFORL || op == BC_JFORL);
4389 if (LJ_DUALNUM) {
4390 | // Integer loop.
4391 | lwzux TMP1, RA, BASE
4392 | lwz CARG1, FORL_IDX*8+4(RA)
4393 | cmplw cr0, TMP1, TISNUM
4394 if (vk) {
4395 | lwz CARG3, FORL_STEP*8+4(RA)
4396 | bne >9
4397 | addo. CARG1, CARG1, CARG3
4398 | cmpwi cr6, CARG3, 0
4399 | lwz CARG2, FORL_STOP*8+4(RA)
4400 | bso >6
4401 |4:
4402 | stw CARG1, FORL_IDX*8+4(RA)
4403 } else {
4404 | lwz TMP3, FORL_STEP*8(RA)
4405 | lwz CARG3, FORL_STEP*8+4(RA)
4406 | lwz TMP2, FORL_STOP*8(RA)
4407 | lwz CARG2, FORL_STOP*8+4(RA)
4408 | cmplw cr7, TMP3, TISNUM
4409 | cmplw cr1, TMP2, TISNUM
4410 | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq
4411 | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
4412 | cmpwi cr6, CARG3, 0
4413 | bne >9
4414 }
4415 | blt cr6, >5
4416 | cmpw CARG1, CARG2
4417 |1:
4418 | stw TISNUM, FORL_EXT*8(RA)
4419 if (op != BC_JFORL) {
4420 | srwi RD, RD, 1
4421 }
4422 | stw CARG1, FORL_EXT*8+4(RA)
4423 if (op != BC_JFORL) {
4424 | add RD, PC, RD
4425 }
4426 if (op == BC_FORI) {
4427 | bgt >3 // See FP loop below.
4428 } else if (op == BC_JFORI) {
4429 | addis PC, RD, -(BCBIAS_J*4 >> 16)
4430 | bley >7
4431 } else if (op == BC_IFORL) {
4432 | bgt >2
4433 | addis PC, RD, -(BCBIAS_J*4 >> 16)
4434 } else {
4435 | bley =>BC_JLOOP
4436 }
4437 |2:
4438 | ins_next
4439 |5: // Invert check for negative step.
4440 | cmpw CARG2, CARG1
4441 | b <1
4442 if (vk) {
4443 |6: // Potential overflow.
4444 | mcrxr cr0; bley <4 // Ignore unrelated overflow.
4445 | b <2
4446 }
4447 }
4448 if (vk) {
4449 if (LJ_DUALNUM) {
4450 |9: // FP loop.
4451 | lfd f1, FORL_IDX*8(RA)
4452 } else {
4453 | lfdux f1, RA, BASE
4454 }
4455 | lfd f3, FORL_STEP*8(RA)
4456 | lfd f2, FORL_STOP*8(RA)
4457 | lwz TMP3, FORL_STEP*8(RA)
4458 | fadd f1, f1, f3
4459 | stfd f1, FORL_IDX*8(RA)
4460 } else {
4461 if (LJ_DUALNUM) {
4462 |9: // FP loop.
4463 } else {
4464 | lwzux TMP1, RA, BASE
4465 | lwz TMP3, FORL_STEP*8(RA)
4466 | lwz TMP2, FORL_STOP*8(RA)
4467 | cmplw cr0, TMP1, TISNUM
4468 | cmplw cr7, TMP3, TISNUM
4469 | cmplw cr1, TMP2, TISNUM
4470 }
4471 | lfd f1, FORL_IDX*8(RA)
4472 | crand 4*cr0+lt, 4*cr0+lt, 4*cr7+lt
4473 | lfd f3, FORL_STEP*8(RA)
4474 | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
4475 | lfd f2, FORL_STOP*8(RA)
4476 | bge ->vmeta_for
4477 }
4478 | cmpwi cr6, TMP3, 0
4479 if (op != BC_JFORL) {
4480 | srwi RD, RD, 1
4481 }
4482 | stfd f1, FORL_EXT*8(RA)
4483 if (op != BC_JFORL) {
4484 | add RD, PC, RD
4485 }
4486 | fcmpu cr0, f1, f2
4487 if (op == BC_JFORI) {
4488 | addis PC, RD, -(BCBIAS_J*4 >> 16)
4489 }
4490 | blt cr6, >5
4491 if (op == BC_FORI) {
4492 | bgt >3
4493 } else if (op == BC_IFORL) {
4494 if (LJ_DUALNUM) {
4495 | bgty <2
4496 } else {
4497 | bgt >2
4498 }
4499 |1:
4500 | addis PC, RD, -(BCBIAS_J*4 >> 16)
4501 } else if (op == BC_JFORI) {
4502 | bley >7
4503 } else {
4504 | bley =>BC_JLOOP
4505 }
4506 if (LJ_DUALNUM) {
4507 | b <2
4508 } else {
4509 |2:
4510 | ins_next
4511 }
4512 |5: // Negative step.
4513 if (op == BC_FORI) {
4514 | bge <2
4515 |3: // Used by integer loop, too.
4516 | addis PC, RD, -(BCBIAS_J*4 >> 16)
4517 } else if (op == BC_IFORL) {
4518 | bgey <1
4519 } else if (op == BC_JFORI) {
4520 | bgey >7
4521 } else {
4522 | bgey =>BC_JLOOP
4523 }
4524 | b <2
4525 if (op == BC_JFORI) {
4526 |7:
4527 | lwz INS, -4(PC)
4528 | decode_RD8 RD, INS
4529 | b =>BC_JLOOP
4530 }
4531 break;
4532
4533 case BC_ITERL:
4534#if LJ_HASJIT
4535 | hotloop
4536#endif
4537 | // Fall through. Assumes BC_IITERL follows.
4538 break;
4539
4540 case BC_JITERL:
4541#if !LJ_HASJIT
4542 break;
4543#endif
4544 case BC_IITERL:
4545 | // RA = base*8, RD = target
4546 | lwzux TMP1, RA, BASE
4547 | lwz TMP2, 4(RA)
4548 | checknil TMP1; beq >1 // Stop if iterator returned nil.
4549 if (op == BC_JITERL) {
4550 | stw TMP1, -8(RA)
4551 | stw TMP2, -4(RA)
4552 | b =>BC_JLOOP
4553 } else {
4554 | branch_RD // Otherwise save control var + branch.
4555 | stw TMP1, -8(RA)
4556 | stw TMP2, -4(RA)
4557 }
4558 |1:
4559 | ins_next
4560 break;
4561
4562 case BC_LOOP:
4563 | // RA = base*8, RD = target (loop extent)
4564 | // Note: RA/RD is only used by trace recorder to determine scope/extent
4565 | // This opcode does NOT jump, it's only purpose is to detect a hot loop.
4566#if LJ_HASJIT
4567 | hotloop
4568#endif
4569 | // Fall through. Assumes BC_ILOOP follows.
4570 break;
4571
4572 case BC_ILOOP:
4573 | // RA = base*8, RD = target (loop extent)
4574 | ins_next
4575 break;
4576
4577 case BC_JLOOP:
4578#if LJ_HASJIT
4579 | // RA = base*8 (ignored), RD = traceno*8
4580 | lwz TMP1, DISPATCH_J(trace)(DISPATCH)
4581 | srwi RD, RD, 1
4582 | // Traces on PPC don't store the trace number, so use 0.
4583 | stw ZERO, DISPATCH_GL(vmstate)(DISPATCH)
4584 | lwzx TRACE:TMP2, TMP1, RD
4585 | mcrxr cr0 // Clear SO flag.
4586 | lwz TMP2, TRACE:TMP2->mcode
4587 | stw BASE, DISPATCH_GL(jit_base)(DISPATCH)
4588 | mtctr TMP2
4589 | stw L, DISPATCH_GL(jit_L)(DISPATCH)
4590 | addi JGL, DISPATCH, GG_DISP2G+32768
4591 | bctr
4592#endif
4593 break;
4594
4595 case BC_JMP:
4596 | // RA = base*8 (only used by trace recorder), RD = target
4597 | branch_RD
4598 | ins_next
4599 break;
4600
4601 /* -- Function headers -------------------------------------------------- */
4602
4603 case BC_FUNCF:
4604#if LJ_HASJIT
4605 | hotcall
4606#endif
4607 case BC_FUNCV: /* NYI: compiled vararg functions. */
4608 | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow.
4609 break;
4610
4611 case BC_JFUNCF:
4612#if !LJ_HASJIT
4613 break;
4614#endif
4615 case BC_IFUNCF:
4616 | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
4617 | lwz TMP2, L->maxstack
4618 | lbz TMP1, -4+PC2PROTO(numparams)(PC)
4619 | lwz KBASE, -4+PC2PROTO(k)(PC)
4620 | cmplw RA, TMP2
4621 | slwi TMP1, TMP1, 3
4622 | bgt ->vm_growstack_l
4623 if (op != BC_JFUNCF) {
4624 | ins_next1
4625 }
4626 |2:
4627 | cmplw NARGS8:RC, TMP1 // Check for missing parameters.
4628 | ble >3
4629 if (op == BC_JFUNCF) {
4630 | decode_RD8 RD, INS
4631 | b =>BC_JLOOP
4632 } else {
4633 | ins_next2
4634 }
4635 |
4636 |3: // Clear missing parameters.
4637 | stwx TISNIL, BASE, NARGS8:RC
4638 | addi NARGS8:RC, NARGS8:RC, 8
4639 | b <2
4640 break;
4641
4642 case BC_JFUNCV:
4643#if !LJ_HASJIT
4644 break;
4645#endif
4646 | NYI // NYI: compiled vararg functions
4647 break; /* NYI: compiled vararg functions. */
4648
4649 case BC_IFUNCV:
4650 | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
4651 | lwz TMP2, L->maxstack
4652 | add TMP1, BASE, RC
4653 | add TMP0, RA, RC
4654 | stw LFUNC:RB, 4(TMP1) // Store copy of LFUNC.
4655 | addi TMP3, RC, 8+FRAME_VARG
4656 | lwz KBASE, -4+PC2PROTO(k)(PC)
4657 | cmplw TMP0, TMP2
4658 | stw TMP3, 0(TMP1) // Store delta + FRAME_VARG.
4659 | bge ->vm_growstack_l
4660 | lbz TMP2, -4+PC2PROTO(numparams)(PC)
4661 | mr RA, BASE
4662 | mr RC, TMP1
4663 | ins_next1
4664 | cmpwi TMP2, 0
4665 | addi BASE, TMP1, 8
4666 | beq >3
4667 |1:
4668 | cmplw RA, RC // Less args than parameters?
4669 | lwz TMP0, 0(RA)
4670 | lwz TMP3, 4(RA)
4671 | bge >4
4672 | stw TISNIL, 0(RA) // Clear old fixarg slot (help the GC).
4673 | addi RA, RA, 8
4674 |2:
4675 | addic. TMP2, TMP2, -1
4676 | stw TMP0, 8(TMP1)
4677 | stw TMP3, 12(TMP1)
4678 | addi TMP1, TMP1, 8
4679 | bne <1
4680 |3:
4681 | ins_next2
4682 |
4683 |4: // Clear missing parameters.
4684 | li TMP0, LJ_TNIL
4685 | b <2
4686 break;
4687
4688 case BC_FUNCC:
4689 case BC_FUNCCW:
4690 | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8
4691 if (op == BC_FUNCC) {
4692 | lwz TMP3, CFUNC:RB->f
4693 } else {
4694 | lwz TMP3, DISPATCH_GL(wrapf)(DISPATCH)
4695 }
4696 | add TMP1, RA, NARGS8:RC
4697 | lwz TMP2, L->maxstack
4698 | add RC, BASE, NARGS8:RC
4699 | stw BASE, L->base
4700 | cmplw TMP1, TMP2
4701 | stw RC, L->top
4702 | li_vmstate C
4703 | mtctr TMP3
4704 if (op == BC_FUNCCW) {
4705 | lwz CARG2, CFUNC:RB->f
4706 }
4707 | mr CARG1, L
4708 | bgt ->vm_growstack_c // Need to grow stack.
4709 | st_vmstate
4710 | bctrl // (lua_State *L [, lua_CFunction f])
4711 | // Returns nresults.
4712 | lwz BASE, L->base
4713 | slwi RD, CRET1, 3
4714 | lwz TMP1, L->top
4715 | li_vmstate INTERP
4716 | lwz PC, FRAME_PC(BASE) // Fetch PC of caller.
4717 | sub RA, TMP1, RD // RA = L->top - nresults*8
4718 | st_vmstate
4719 | b ->vm_returnc
4720 break;
4721
4722 /* ---------------------------------------------------------------------- */
4723
4724 default:
4725 fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]);
4726 exit(2);
4727 break;
4728 }
4729}
4730
4731static int build_backend(BuildCtx *ctx)
4732{
4733 int op;
4734
4735 dasm_growpc(Dst, BC__MAX);
4736
4737 build_subroutines(ctx);
4738
4739 |.code_op
4740 for (op = 0; op < BC__MAX; op++)
4741 build_ins(ctx, (BCOp)op, op);
4742
4743 return BC__MAX;
4744}
4745
4746/* Emit pseudo frame-info for all assembler functions. */
4747static void emit_asm_debug(BuildCtx *ctx)
4748{
4749 int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code);
4750 int i;
4751 switch (ctx->mode) {
4752 case BUILD_elfasm:
4753 fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n");
4754 fprintf(ctx->fp,
4755 ".Lframe0:\n"
4756 "\t.long .LECIE0-.LSCIE0\n"
4757 ".LSCIE0:\n"
4758 "\t.long 0xffffffff\n"
4759 "\t.byte 0x1\n"
4760 "\t.string \"\"\n"
4761 "\t.uleb128 0x1\n"
4762 "\t.sleb128 -4\n"
4763 "\t.byte 65\n"
4764 "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
4765 "\t.align 2\n"
4766 ".LECIE0:\n\n");
4767 fprintf(ctx->fp,
4768 ".LSFDE0:\n"
4769 "\t.long .LEFDE0-.LASFDE0\n"
4770 ".LASFDE0:\n"
4771 "\t.long .Lframe0\n"
4772 "\t.long .Lbegin\n"
4773 "\t.long %d\n"
4774 "\t.byte 0xe\n\t.uleb128 %d\n"
4775 "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
4776 "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n",
4777 fcofs, CFRAME_SIZE);
4778 for (i = 14; i <= 31; i++)
4779 fprintf(ctx->fp,
4780 "\t.byte %d\n\t.uleb128 %d\n"
4781 "\t.byte %d\n\t.uleb128 %d\n",
4782 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i));
4783 fprintf(ctx->fp,
4784 "\t.align 2\n"
4785 ".LEFDE0:\n\n");
4786#if LJ_HASFFI
4787 fprintf(ctx->fp,
4788 ".LSFDE1:\n"
4789 "\t.long .LEFDE1-.LASFDE1\n"
4790 ".LASFDE1:\n"
4791 "\t.long .Lframe0\n"
4792 "\t.long lj_vm_ffi_call\n"
4793 "\t.long %d\n"
4794 "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
4795 "\t.byte 0x8e\n\t.uleb128 2\n"
4796 "\t.byte 0xd\n\t.uleb128 0xe\n"
4797 "\t.align 2\n"
4798 ".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
4799#endif
4800 fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
4801 fprintf(ctx->fp,
4802 ".Lframe1:\n"
4803 "\t.long .LECIE1-.LSCIE1\n"
4804 ".LSCIE1:\n"
4805 "\t.long 0\n"
4806 "\t.byte 0x1\n"
4807 "\t.string \"zPR\"\n"
4808 "\t.uleb128 0x1\n"
4809 "\t.sleb128 -4\n"
4810 "\t.byte 65\n"
4811 "\t.uleb128 6\n" /* augmentation length */
4812 "\t.byte 0x1b\n" /* pcrel|sdata4 */
4813 "\t.long lj_err_unwind_dwarf-.\n"
4814 "\t.byte 0x1b\n" /* pcrel|sdata4 */
4815 "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
4816 "\t.align 2\n"
4817 ".LECIE1:\n\n");
4818 fprintf(ctx->fp,
4819 ".LSFDE2:\n"
4820 "\t.long .LEFDE2-.LASFDE2\n"
4821 ".LASFDE2:\n"
4822 "\t.long .LASFDE2-.Lframe1\n"
4823 "\t.long .Lbegin-.\n"
4824 "\t.long %d\n"
4825 "\t.uleb128 0\n" /* augmentation length */
4826 "\t.byte 0xe\n\t.uleb128 %d\n"
4827 "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
4828 "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n",
4829 fcofs, CFRAME_SIZE);
4830 for (i = 14; i <= 31; i++)
4831 fprintf(ctx->fp,
4832 "\t.byte %d\n\t.uleb128 %d\n"
4833 "\t.byte %d\n\t.uleb128 %d\n",
4834 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i));
4835 fprintf(ctx->fp,
4836 "\t.align 2\n"
4837 ".LEFDE2:\n\n");
4838#if LJ_HASFFI
4839 fprintf(ctx->fp,
4840 ".Lframe2:\n"
4841 "\t.long .LECIE2-.LSCIE2\n"
4842 ".LSCIE2:\n"
4843 "\t.long 0\n"
4844 "\t.byte 0x1\n"
4845 "\t.string \"zR\"\n"
4846 "\t.uleb128 0x1\n"
4847 "\t.sleb128 -4\n"
4848 "\t.byte 65\n"
4849 "\t.uleb128 1\n" /* augmentation length */
4850 "\t.byte 0x1b\n" /* pcrel|sdata4 */
4851 "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
4852 "\t.align 2\n"
4853 ".LECIE2:\n\n");
4854 fprintf(ctx->fp,
4855 ".LSFDE3:\n"
4856 "\t.long .LEFDE3-.LASFDE3\n"
4857 ".LASFDE3:\n"
4858 "\t.long .LASFDE3-.Lframe2\n"
4859 "\t.long lj_vm_ffi_call-.\n"
4860 "\t.long %d\n"
4861 "\t.uleb128 0\n" /* augmentation length */
4862 "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
4863 "\t.byte 0x8e\n\t.uleb128 2\n"
4864 "\t.byte 0xd\n\t.uleb128 0xe\n"
4865 "\t.align 2\n"
4866 ".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
4867#endif
4868 break;
4869 default:
4870 break;
4871 }
4872}
4873