|// Low-level VM code for PowerPC CPUs. |// Bytecode interpreter, fast functions and helper functions. |// Copyright (C) 2005-2010 Mike Pall. See Copyright Notice in luajit.h | |.arch ppc |.section code_op, code_sub | |.actionlist build_actionlist |.globals GLOB_ |.globalnames globnames |.externnames extnames | |.if not SPE |.error "No support for plain PowerPC CPUs (yet)" |.endif | |// Note: The ragged indentation of the instructions is intentional. |// The starting columns indicate data dependencies. | |//----------------------------------------------------------------------- | |// Fixed register assignments for the interpreter. |// Don't use: r1 = sp, r2 and r13 = reserved and/or small data area ptr | |// The following must be C callee-save (but BASE is often refetched). |.define BASE, r14 // Base of current Lua stack frame. |.define KBASE, r15 // Constants of current Lua function. |.define PC, r16 // Next PC. |.define DISPATCH, r17 // Opcode dispatch table. |.define LREG, r18 // Register holding lua_State (also in SAVE_L). | |// Constants for vectorized type-comparisons (hi+low GPR). C callee-save. |.define TISNUM, r21 |.if SPE |.define TISSTR, r22 |.define TISTAB, r23 |.define TISFUNC, r24 |.define TISNIL, r25 |.endif | |// The following temporaries are not saved across C calls, except for RA. |.define RA, r19 // Callee-save. |.define RB, r10 |.define RC, r11 |.define RD, r12 |.define INS, r7 // Overlaps CARG5. | |.define TMP0, r0 |.define TMP1, r8 |.define TMP2, r9 |.define TMP3, r6 // Overlaps CARG4. | |// Saved temporaries. |.define SAVE0, r20 | |// Calling conventions. |.define CARG1, r3 |.define CARG2, r4 |.define CARG3, r5 |.define CARG4, r6 // Overlaps TMP3. |.define CARG5, r7 // Overlaps INS. | |.define CRET1, r3 |.define CRET2, r4 | |// Stack layout while in interpreter. Must match with lj_frame.h. |.if SPE |.define SAVE_LR, 180(sp) |.define CFRAME_SPACE, 176 // Delta for sp. |// Back chain for sp: 176(sp) <-- sp entering interpreter |.define SAVE_r31, 168(sp) // 64 bit register saves. |.define SAVE_r30, 160(sp) |.define SAVE_r29, 152(sp) |.define SAVE_r28, 144(sp) |.define SAVE_r27, 136(sp) |.define SAVE_r26, 128(sp) |.define SAVE_r25, 120(sp) |.define SAVE_r24, 112(sp) |.define SAVE_r23, 104(sp) |.define SAVE_r22, 96(sp) |.define SAVE_r21, 88(sp) |.define SAVE_r20, 80(sp) |.define SAVE_r19, 72(sp) |.define SAVE_r18, 64(sp) |.define SAVE_r17, 56(sp) |.define SAVE_r16, 48(sp) |.define SAVE_r15, 40(sp) |.define SAVE_r14, 32(sp) |.define SAVE_ERRF, 28(sp) // 32 bit C frame info. |.define SAVE_NRES, 24(sp) |.define SAVE_CFRAME, 20(sp) |.define SAVE_L, 16(sp) |.define SAVE_PC, 12(sp) |.define SAVE_MULTRES, 8(sp) |// Next frame lr: 4(sp) |// Back chain for sp: 0(sp) <-- sp while in interpreter | |.macro save_, reg; evstdd reg, SAVE_..reg; .endmacro |.macro rest_, reg; evldd reg, SAVE_..reg; .endmacro |.endif | |.macro saveregs | stwu sp, -CFRAME_SPACE(sp) | save_ r14; save_ r15; save_ r16; save_ r17; save_ r18; save_ r19 | mflr r0 | save_ r20; save_ r21; save_ r22; save_ r23; save_ r24; save_ r25 | stw r0, SAVE_LR | save_ r26; save_ r27; save_ r28; save_ r29; save_ r30; save_ r31 |.endmacro | |.macro restoreregs | lwz r0, SAVE_LR | rest_ r14; rest_ r15; rest_ r16; rest_ r17; rest_ r18; rest_ r19 | mtlr r0 | rest_ r20; rest_ r21; rest_ r22; rest_ r23; rest_ r24; rest_ r25 | rest_ r26; rest_ r27; rest_ r28; rest_ r29; rest_ r30; rest_ r31 | addi sp, sp, CFRAME_SPACE |.endmacro | |// Type definitions. Some of these are only used for documentation. |.type L, lua_State, LREG |.type GL, global_State |.type TVALUE, TValue |.type GCOBJ, GCobj |.type STR, GCstr |.type TAB, GCtab |.type LFUNC, GCfuncL |.type CFUNC, GCfuncC |.type PROTO, GCproto |.type UPVAL, GCupval |.type NODE, Node |.type NARGS8, int |.type TRACE, GCtrace | |//----------------------------------------------------------------------- | |// Trap for not-yet-implemented parts. |.macro NYI; tw 4, sp, sp; .endmacro | |//----------------------------------------------------------------------- | |// Assumes DISPATCH is relative to GL. #define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field)) #define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field)) | #define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto)) | |.macro hotloop | NYI |.endmacro | |.macro hotcall | NYI |.endmacro | |//----------------------------------------------------------------------- /* Generate subroutines used by opcodes and other parts of the VM. */ /* The .code_sub section should be last to help static branch prediction. */ static void build_subroutines(BuildCtx *ctx) { |.code_sub | |//----------------------------------------------------------------------- |//-- Return handling ---------------------------------------------------- |//----------------------------------------------------------------------- | |->vm_returnp: | NYI | |->vm_returnc: | NYI | |->vm_return: | NYI | |->vm_leave_cp: | NYI | |->vm_leave_unw: | NYI | |->vm_unwind_c: // Unwind C stack, return from vm_pcall. | NYI |->vm_unwind_c_eh: // Landing pad for external unwinder. | NYI | |->vm_unwind_ff: // Unwind C stack, return from ff pcall. | NYI |->vm_unwind_ff_eh: // Landing pad for external unwinder. | NYI | |//----------------------------------------------------------------------- |//-- Grow stack for calls ----------------------------------------------- |//----------------------------------------------------------------------- | |->vm_growstack_c: // Grow stack for C function. | NYI | |->vm_growstack_l: // Grow stack for Lua function. | NYI | |//----------------------------------------------------------------------- |//-- Entry points into the assembler VM --------------------------------- |//----------------------------------------------------------------------- | |->vm_resume: // Setup C frame and resume thread. | NYI | |->vm_pcall: // Setup protected C frame and enter VM. | NYI | |->vm_call: // Setup C frame and enter VM. | NYI | |->vm_call_dispatch: | NYI | |->vm_call_dispatch_f: | NYI | |->vm_cpcall: // Setup protected C frame, call C. | NYI | |//----------------------------------------------------------------------- |//-- Metamethod handling ------------------------------------------------ |//----------------------------------------------------------------------- | |//-- Continuation dispatch ---------------------------------------------- | |->cont_dispatch: | NYI | |->cont_cat: | NYI | |//-- Table indexing metamethods ----------------------------------------- | |->vmeta_tgets: | NYI | |->vmeta_tgetb: | NYI | |->vmeta_tgetv: | NYI | |//----------------------------------------------------------------------- | |->vmeta_tsets: | NYI | |->vmeta_tsetb: | NYI | |->vmeta_tsetv: | NYI | |//-- Comparison metamethods --------------------------------------------- | |->vmeta_comp: | NYI |->cont_nop: | NYI | |->cont_ra: | NYI | |->cont_condt: | NYI | |->cont_condf: | NYI | |->vmeta_equal: | NYI | |//-- Arithmetic metamethods --------------------------------------------- | |->vmeta_arith_vn: | NYI | |->vmeta_arith_nv: | NYI | |->vmeta_unm: | NYI | |->vmeta_arith_vv: | NYI | |->vmeta_binop: | NYI | |->vmeta_len: | NYI | |//-- Call metamethod ---------------------------------------------------- | |->vmeta_call_ra: | NYI | |->vmeta_call: // Resolve and call __call metamethod. | NYI | |//-- Argument coercion for 'for' statement ------------------------------ | |->vmeta_for: | NYI | |//----------------------------------------------------------------------- |//-- Fast functions ----------------------------------------------------- |//----------------------------------------------------------------------- | |.macro .ffunc, name |->ff_ .. name: |.endmacro | |.macro .ffunc_1, name |->ff_ .. name: | NYI |.endmacro | |.macro .ffunc_2, name |->ff_ .. name: | NYI |.endmacro | |.macro .ffunc_n, name | .ffunc_1 name | NYI |.endmacro | |.macro .ffunc_nn, name | .ffunc_2 name | NYI |.endmacro | |.macro ffgccheck | NYI |.endmacro | |//-- Base library: checks ----------------------------------------------- | |.ffunc assert | NYI | |.ffunc type | NYI | |//-- Base library: getters and setters --------------------------------- | |.ffunc_1 getmetatable | NYI | |.ffunc_2 setmetatable | NYI | |.ffunc_2 rawget | NYI | |//-- Base library: conversions ------------------------------------------ | |.ffunc tonumber | NYI | |.ffunc_1 tostring | NYI | |//-- Base library: iterators ------------------------------------------- | |.ffunc_1 next | NYI | |->fff_res2: | NYI | |.ffunc_1 pairs | NYI | |.ffunc_1 ipairs_aux | NYI | |->fff_res0: | NYI | |.ffunc_1 ipairs | NYI | |//-- Base library: catch errors ---------------------------------------- | |.ffunc_1 pcall | NYI | |.ffunc_2 xpcall | NYI | |//-- Coroutine library -------------------------------------------------- | |.macro coroutine_resume_wrap, resume |.if resume |.ffunc_1 coroutine_resume |.else |.ffunc coroutine_wrap_aux |.endif | NYI |.endmacro | | coroutine_resume_wrap 1 // coroutine.resume | coroutine_resume_wrap 0 // coroutine.wrap | |.ffunc coroutine_yield | NYI | |//-- Math library ------------------------------------------------------- | |.ffunc_n math_abs | NYI | // Fallthrough. | |->fff_res1: | NYI |->fff_res: | NYI | |.macro math_extern, func | .ffunc math_ .. func | NYI |.endmacro | |.macro math_extern2, func | .ffunc math_ .. func | NYI |.endmacro | | math_extern floor | math_extern ceil | | math_extern sqrt | math_extern log | math_extern log10 | math_extern exp | math_extern sin | math_extern cos | math_extern tan | math_extern asin | math_extern acos | math_extern atan | math_extern sinh | math_extern cosh | math_extern tanh | math_extern2 atan2 | math_extern2 fmod | |->ff_math_deg: |.ffunc_1 math_rad | NYI | |.ffunc_nn math_ldexp; NYI |.ffunc_n math_frexp; NYI |.ffunc_n math_modf; NYI | |.ffunc_nn math_pow; NYI | |.macro math_minmax, name, cmpop | .ffunc_1 name | NYI |.endmacro | | math_minmax math_min, efdtstlt | math_minmax math_max, efdtstgt | |//-- String library ----------------------------------------------------- | |.ffunc_1 string_len | NYI | |.ffunc string_byte // Only handle the 1-arg case here. | NYI | |.ffunc string_char // Only handle the 1-arg case here. | NYI | |->fff_newstr: | NYI | |.ffunc string_sub | NYI | |->fff_emptystr: // Range underflow. | NYI | |.ffunc_2 string_rep // Only handle the 1-char case inline. | NYI | |.ffunc_1 string_reverse | NYI | |.macro ffstring_case, name, lo, hi | .ffunc_1 name | NYI |.endmacro | |ffstring_case string_lower, 0x41, 0x5a |ffstring_case string_upper, 0x61, 0x7a | |//-- Table library ------------------------------------------------------ | |.ffunc_1 table_getn | NYI | |//-- Bit library -------------------------------------------------------- | |.ffunc_n bit_tobit | NYI | |.macro .ffunc_bit, name | .ffunc_n name | NYI |.endmacro | |.macro .ffunc_bit_op, name, ins | .ffunc_bit name | NYI |.endmacro | |.ffunc_bit_op bit_band, and |.ffunc_bit_op bit_bor, or |.ffunc_bit_op bit_bxor, xor | |.ffunc_bit bit_bswap | NYI | |.ffunc_bit bit_bnot | NYI | |->fff_resbit: | NYI | |->fff_fallback_bit_op: | NYI | |.macro .ffunc_bit_sh, name, ins | .ffunc_nn name | NYI |.endmacro | |.ffunc_bit_sh bit_lshift, shl |.ffunc_bit_sh bit_rshift, shr |.ffunc_bit_sh bit_arshift, sar |.ffunc_bit_sh bit_rol, rol |.ffunc_bit_sh bit_ror, ror | |//----------------------------------------------------------------------- | |->fff_fallback: // Call fast function fallback handler. | NYI | |->fff_gcstep: // Call GC step function. | NYI | |//----------------------------------------------------------------------- |//-- Special dispatch targets ------------------------------------------- |//----------------------------------------------------------------------- | |->vm_record: // Dispatch target for recording phase. #if LJ_HASJIT | NYI #endif | |->vm_rethook: // Dispatch target for return hooks. | NYI | |->vm_inshook: // Dispatch target for instr/line hooks. | NYI | |->cont_hook: // Continue from hook yield. | NYI | |->vm_hotloop: // Hot loop counter underflow. #if LJ_HASJIT | NYI #endif | |->vm_callhook: // Dispatch target for call hooks. | NYI | |->vm_hotcall: // Hot call counter underflow. #if LJ_HASJIT | NYI #endif | |//----------------------------------------------------------------------- |//-- Trace exit handler ------------------------------------------------- |//----------------------------------------------------------------------- | |->vm_exit_handler: #if LJ_HASJIT | NYI #endif |->vm_exit_interp: #if LJ_HASJIT | NYI #endif | |//----------------------------------------------------------------------- |//-- Math helper functions ---------------------------------------------- |//----------------------------------------------------------------------- | |// FP value rounding. Called by math.floor/math.ceil fast functions |// and from JIT code. | |.macro vm_round, name, mode |->name: | NYI |.endmacro | | vm_round vm_floor, 0 | vm_round vm_ceil, 1 | vm_round vm_trunc, 2 | |->vm_mod: | NYI | |->vm_exp: | NYI |->vm_exp2: | NYI | |->vm_pow: | NYI | |->vm_powi_sse: | NYI | |->vm_foldfpm: | NYI | |// Callable from C: double lj_vm_foldarith(double x, double y, int op) |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) |// and basic math functions. ORDER ARITH |->vm_foldarith: | NYI | |//----------------------------------------------------------------------- |//-- Miscellaneous functions -------------------------------------------- |//----------------------------------------------------------------------- | |//----------------------------------------------------------------------- } /* Generate the code for a single instruction. */ static void build_ins(BuildCtx *ctx, BCOp op, int defop) { |=>defop: switch (op) { /* -- Comparison ops ---------------------------------------------------- */ /* Remember: all ops branch for a true comparison, fall through otherwise. */ case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: | NYI break; case BC_ISEQV: case BC_ISNEV: | NYI break; case BC_ISEQS: case BC_ISNES: | NYI break; case BC_ISEQN: case BC_ISNEN: | NYI break; case BC_ISEQP: case BC_ISNEP: | NYI break; /* -- Unary test and copy ops ------------------------------------------- */ case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF: | NYI break; /* -- Unary ops --------------------------------------------------------- */ case BC_MOV: | NYI break; case BC_NOT: | NYI break; case BC_UNM: | NYI break; case BC_LEN: | NYI break; /* -- Binary ops -------------------------------------------------------- */ case BC_ADDVN: case BC_ADDNV: case BC_ADDVV: | NYI break; case BC_SUBVN: case BC_SUBNV: case BC_SUBVV: | NYI break; case BC_MULVN: case BC_MULNV: case BC_MULVV: | NYI break; case BC_DIVVN: case BC_DIVNV: case BC_DIVVV: | NYI break; case BC_MODVN: | NYI break; case BC_MODNV: case BC_MODVV: | NYI break; case BC_POW: | NYI break; case BC_CAT: | NYI break; /* -- Constant ops ------------------------------------------------------ */ case BC_KSTR: | NYI break; case BC_KSHORT: | NYI break; case BC_KNUM: | NYI break; case BC_KPRI: | NYI break; case BC_KNIL: | NYI break; /* -- Upvalue and function ops ------------------------------------------ */ case BC_UGET: | NYI break; case BC_USETV: | NYI break; case BC_USETS: | NYI break; case BC_USETN: | NYI break; case BC_USETP: | NYI break; case BC_UCLO: | NYI break; case BC_FNEW: | NYI break; /* -- Table ops --------------------------------------------------------- */ case BC_TNEW: | NYI break; case BC_TDUP: | NYI break; case BC_GGET: case BC_GSET: | NYI break; case BC_TGETV: | NYI break; case BC_TGETS: | NYI break; case BC_TGETB: | NYI break; case BC_TSETV: | NYI break; case BC_TSETS: | NYI break; case BC_TSETB: | NYI break; case BC_TSETM: | NYI break; /* -- Calls and vararg handling ----------------------------------------- */ case BC_CALLM: | NYI break; case BC_CALL: | NYI break; case BC_CALLMT: | NYI break; case BC_CALLT: | NYI break; case BC_ITERC: | NYI break; case BC_VARG: | NYI break; /* -- Returns ----------------------------------------------------------- */ case BC_RETM: | NYI break; case BC_RET: | NYI break; case BC_RET0: case BC_RET1: | NYI break; /* -- Loops and branches ------------------------------------------------ */ case BC_FORL: #if LJ_HASJIT | hotloop #endif | // Fall through. Assumes BC_IFORL follows. break; case BC_JFORI: case BC_JFORL: #if !LJ_HASJIT break; #endif case BC_FORI: case BC_IFORL: | NYI break; case BC_ITERL: #if LJ_HASJIT | hotloop #endif | // Fall through. Assumes BC_IITERL follows. break; case BC_JITERL: #if !LJ_HASJIT break; #endif case BC_IITERL: | NYI break; case BC_LOOP: | NYI #if LJ_HASJIT | // Fall through. Assumes BC_ILOOP follows. #endif break; case BC_ILOOP: | NYI break; case BC_JLOOP: | NYI break; case BC_JMP: | hotcall break; /* -- Function headers -------------------------------------------------- */ case BC_FUNCF: #if LJ_HASJIT | hotcall #endif case BC_FUNCV: /* NYI: compiled vararg functions. */ | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow. break; case BC_JFUNCF: #if !LJ_HASJIT break; #endif case BC_IFUNCF: | NYI break; case BC_JFUNCV: #if !LJ_HASJIT break; #endif | NYI // NYI: compiled vararg functions break; /* NYI: compiled vararg functions. */ case BC_IFUNCV: | NYI break; case BC_FUNCC: case BC_FUNCCW: | NYI break; /* ---------------------------------------------------------------------- */ default: fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]); exit(2); break; } } static int build_backend(BuildCtx *ctx) { int op; dasm_growpc(Dst, BC__MAX); build_subroutines(ctx); |.code_op for (op = 0; op < BC__MAX; op++) build_ins(ctx, (BCOp)op, op); return BC__MAX; } /* Emit pseudo frame-info for all assembler functions. */ static void emit_asm_debug(BuildCtx *ctx) { /* NYI */ UNUSED(ctx); }