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