📄 jit-alpha.def
字号:
insn_mem(0x0C, (ra), (rb), (off))#define op_sextb(rb, rc) \ debug(("sextb\t%s,%s\n",regname(rb),regname(rc))), \ insn_opr(0x1C, 0x00, REG_zero, (rb), (rc))#define op_sextw(rb, rc) \ debug(("sextw\t%s,%s\n",regname(rb),regname(rc))), \ insn_opr(0x1C, 0x01, REG_zero, (rb), (rc))#define op_stb(ra, rb, off) \ debug(("stb\t%s,%hd(%s)\n",regname(ra),(off),regname(rb))), \ insn_mem(0x0E, (ra), (rb), (off))#define op_stw(ra, rb, off) \ debug(("stw\t%s,%hd(%s)\n",regname(ra),(off),regname(rb))), \ insn_mem(0x0D, (ra), (rb), (off))static inline longalpha_have_bwx(void){#ifdef HAVE_ALPHA_ASM_AMASK long r; __asm__("amask 1,%0" : "=r"(r));#else /* For those whose assemblers are so far behind not to have the amask instruction. */ register long r __asm__("$0"); __asm__(".long %1" : "=r"(r) : "i"((0x11 << 26) | (REG_zero << 21) | (1 << 13) | 0x1000 | (0x61 << 5) | REG_v0));#endif return !r;}static inline longalpha_have_precise_trap(void){#ifdef HAVE_ALPHA_ASM_AMASK long r; __asm__("amask %1,%0" : "=r"(r) : "r"(1<<9));#else /* For those whose assemblers are so far behind not to have the amask instruction. */ register long r __asm__("$0") = (1 << 9); __asm__(".long %1" : "=r"(r) : "i"((0x11 << 26) | (REG_zero << 21) | (REG_v0 << 16) | (0x61 << 5) | REG_v0));#endif return !r;}/* --------------------------------------------------------------------- *//* Recognize constants that go to either and or zapnot. */static inline longalpha_zapnot_const(long x){ /* Create a mask of bits in which bit n == 1 iff byte n == 0xFF. */ __asm__("cmpbge %1,%2,%0" : "=r"(x) : "r"(x), "r"(-1)); return x;}intalpha_andconst_rangecheck(long v){ if (v >= 0 && v <= 0xFF) { /* we can just use "and" */ return 1; } else if (~v >= 0 && ~v <= 0xFF) { /* we can use "andnot" */ return 1; } else if ((alpha_zapnot_const(v) ^ alpha_zapnot_const(~v)) == 0xFF) { /* we can use "zapnot" */ return 1; } return 0;}/* --------------------------------------------------------------------- */define_insn(unimplemented, unimplemented){ ABORT();}define_insn(nop, nop){ /* Presumably we're nop'ing for alignment not delay. */ op_unop();}static voidalpha_ldgp(int reg){ long hi, lo; hi = -CODEPC; lo = (short)hi; hi = (hi - lo) >> 16; if (hi) { op_ldah(REG_gp, reg, hi); op_lda(REG_gp, REG_gp, lo); } else { op_lda(REG_gp, reg, lo); }}/* --------------------------------------------------------------------- */define_insn(prologue, prologue_xxC){ int r, N; int l; int sl; int aspill; label* L; Method* meth; int rsa_size; L = const_label(1); meth = const_method(2);#ifdef KAFFE_VMDEBUG if (jit_debug) { dprintf("\n%s.%s %s\n", meth->class->name->data, meth->name->data, METHOD_SIGD(meth)); }#endif alpha_jit_info.ieee = 0; /* Initial stack frame looks like: * * | Argument above 6 | * SP-> |-------------------------------| * * Calling Standard for Alpha Systems * 3.1.2.1 Stack Frame Format * * Figure 3-1: Fixed Size Stack Frame Format * (PDSC_FLAGS_BASE_REG_IS_FP is 0) * octaword-aligned * | Argument above 6 | * |-------------------------------| <- PDSC_RPD_FRAME_SIZE from SP * | Argument home area | * |- - - - - - - - - - - - - - - -| * | Fixed temporary locations | * |-------------------------------| * | Register save area | * |-------------------------------| <- PDSC_RPD_RSA_OFFSET from SP * | Fixed temporary locations | * |-------------------------------| <- SP * * Figure 3-2: Variable Size Stack Frame Format * (PDSC_FLAGS_BASE_REG_IS_FP is 1) * octaword-aligned * | Argument above 6 | * |-------------------------------| <- PDSC_RPD_FRAME_SIZE from FP * | Argument home area | * |- - - - - - - - - - - - - - - -| * | Fixed temporary locations | * |-------------------------------| * | Register save area | * |-------------------------------| <- PDSC_RPD_RSA_OFFSET from FP * | Fixed temporary locations | * |-------------------------------| <- FP * | Stack temporary area | * |-------------------------------| <- SP * * * Fixed temporary locations are optional sections. These locations * might include, for exemple, register spill areas, ..., or fixed * temporary locations. * * * The argument home area is an optionl section, it is a region of * memory used by the called procedure for the purpose of assembling * in contignous memory the arguments passed in registers adjacent to * the arguments passed in memory, so that all argument can be * addressed as a contignous array. * * * The register save area is the set of consecutive quadwords where * the current procedure saves and restores registers. The registers * save area begins at the location pointed to by the frame base * register (as indicated by PDSC_FLAGS_BASE_REG_IS_FP) added to the * value of the content of PDSC_RPD_RSA_OFFSET. The result must be * a quadword-aligned address. * * All registers saved in the variable portion of the register save * area must have the corresponding bit set to 1 in the appropriate * procedure descriptor register save mask. The algorithm for * packing saved register in the quadword-aligned register save area * is as follows: * . The return address is save at the lowest address of the * register save area, offset 0. * . All saved integer registers, as indicated by the corresponding * bit in PDSC_RPD_IMASK being set to 1, are store, in register * order, in consecutive quadwords beginning at offset 8 of the * register save area. * . All saved floating-point registers, as indicated by the * corresponding bit in PDSC_RPD_FMASK being set to 1, are stored, * in register-number order, in consecutive quadwords following * the saved integer registers. * * A standard-conforming procedure that utilizes a register save area * must save the return address register at offset 0 in the register * save area. There is no corresponding bit in the register save * mask for this register slot. * * * Applied for JIT Stack Frame: * We use a fixed-stack frame (PDSC_FLAGS_BASE_REG_IS_FP is 0) with * FP used as a virtual frame pointer to improve FRAMEOBJECT() macro. * * | Argument above 6 | * FP ->|-------------------------------| <- PDSC_RPD_FRAME_SIZE from SP * | Spill for up to 6 args | * |-------------------------------| * | Locals, temps | * |-------------------------------| * | Register save area | * |-------------------------------| <- PDSC_RPD_RSA_OFFSET from SP * | outgoing parameters past 6 | * |-------------------------------| <- SP * * * Until we have some method of determining in the prologue which * Rnosaveoncall registers are used by a method, we will save registers * s0 to s5 and f2 to f9. As we change FP, we must save it also. * * imask = (1 << 9) + ... + (1 << 14) + (1 << 15) * fmask = (1 << 2) + ... + (1 << 9) * * with the return address register, we save 16 registers in RSA. * ra, s0 ... s5, fp, f2 ... f9 * */ /* Calling Standard for Alpha Systems * 3.2.6.1 Entry Code Sequence * Because the value of the PC defines the currently executing * procedure, all properties of the environment specified by a * procedure's descriptor must be valid before the first instruction * after the procedure prologue (as defined by PDSC_RPD_ENTRY_LENGTH) * is executed. In addition, none of the properties specified in the * calling procedure's descriptor may be invalidated before the called * procedure becomes current. Thus, until the procedure becomes current, * all entry code must adhere to the following rules: * . All registers specified by this standard as saved across a * standard-conforming call must contain their original (at entry) * contents. * . The register designated by PDSC_RPD_ENTRY_RA ($26 in a standard * call) must contain its original (at entry) contents. This * requirement also applies to nonstandard procedures to allow for * proper unwinding. * . No standard calls can be made. * * These actions involve the following steps, performed in the * specified order: * * 1. Compute and load the procedure's GP value using the * passed-in-procedure (code address) value in $27. * * 2. If stack space is allocated (PDSC_RPD_FRAME_SIZE is not 0), set * register SP to SP - PDSC_RPD_FRAME_SIZE. * After any necessary calculations and stack limit checks, this * step must be completed in exactly one instruction that modifies * SP. This instruction must be the one specified by * PDSC_RPD_SP_SET. * * 3. For a stack frame procedure (PDSC_FLAGS_REGISTER_FRAME is 0), do * both of these steps. (There is no requirement as to which step * occurs first.) * * Store the registers specified by PDSC_RPD_IMASK and * PDSC_RDP_FMASK in the register save area based on * PDSC_RPD_RSA_OFFSET. * * Store the return address in the register save area. * * 4. For a register frame procedure (PDSC_FLAGS_REGISTER_FRAME is 1), * copy the return address to the register specified by * PDSC_RPD_SAVE_RA if the value is not already there. * * 5. Execute trapb, if required. (See Section 5.1.12 for details.) * * 6. For a variable-size stack frame procedure * (PDSC_FLAGS_BASE_REG_IS_FP is 1), copy the SP value to register * FP. This step must be completed in exactly one instruction that * modifies the FP and that instruction must be the last instruction * in the prologue. */ /* Calling Standard for Alpha Systems * 3.2.6.1 Entry Code Sequence * 1. Compute and load the procedure's GP value using the * passed-in-procedure (code address) value in $27. */ op_lda(REG_gp, REG_pv, 0); // op_mov(REG_pv, REG_gp); /* Calling Standard for Alpha Systems * 3.2.6.1 Entry Code Sequence * 2. If stack space is allocated (PDSC_RPD_FRAME_SIZE is not 0), set * register SP to SP - PDSC_RPD_FRAME_SIZE. * After any necessary calculations and stack limit checks, this * step must be completed in exactly one instruction that modifies * SP. This instruction must be the one specified by * PDSC_RPD_SP_SET. */ alpha_jit_info.sp_set = CODEPC / 4; L->type = Lnegframe|Labsolute|Lgeneral; L->at = (uintp)CODEPC; op_lda(REG_sp, REG_sp, 0); /* Calling Standard for Alpha Systems * 3.2.6.1 Entry Code Sequence * 3. For a stack frame procedure (PDSC_FLAGS_REGISTER_FRAME is 0), do * both of these steps. (There is no requirement as to which step * occurs first.) * * Store the registers specified by PDSC_RPD_IMASK and * PDSC_RDP_FMASK in the register save area based on * PDSC_RPD_RSA_OFFSET. * * Store the return address in the register save area. */ /* Build Register Save mask (without ra) */ alpha_jit_info.imask = 0xFE00; /* s0 to s5 and fp */ alpha_jit_info.fmask = 0x3FC; /* f2 to f9 */ /* compute rsa_size for ra, s0-s5, fp, f2-f9 */ rsa_size = 1 + (5 - 0 + 1) + 1 + (9 - 2 + 1); alpha_jit_info.rsa_size = rsa_size; /* return address */ L = newLabel(); L->type = Lrsa|Labsolute|Lgeneral; L->at = (uintp)CODEPC; op_stq(REG_ra, REG_sp, 0); N = 1; /* registers s0 - s5 and fp (also know as s6) */ for (r = 0; r < 7; r++, N++) { L = newLabel(); L->type = Lrsa|Labsolute|Lgeneral; L->at = (uintp)CODEPC; op_stq(REG_s0+r, REG_sp, SLOTSIZE * N); } /* registers f2 - f9 */ for (r = 0; r < (9 - 2 + 1); r++, N++) { L = newLabel(); L->type = Lrsa|Labsolute|Lgeneral; L->at = (uintp)CODEPC; op_stt(REG_f2+r, REG_sp, SLOTSIZE * N); } /* this is the end of the prologue */ alpha_jit_info.entry_length = CODEPC / 4; /* setup our virtual frame pointer, it's not part of the prologue. */ L = newLabel(); L->type = Lframe|Labsolute|Lgeneral; L->at = (uintp)CODEPC; op_lda(REG_fp, REG_sp, 0); /* Work out which register is what and where. */ l = maxLocal + maxStack + maxTemp; if (alpha_nslot2argoffset < l) { alpha_nslot2argoffset = l; alpha_slot2argoffset = KREALLOC(alpha_slot2argoffset, l * sizeof(alpha_slot2argoffset[0])); } if (isStatic) { r = 0; } else { alpha_slot2argoffset[0] = -SLOTSIZE; r = 1; } sl = r; /* register passed arguments */ for (l = 0; l < METHOD_NARGS(meth) && r < 6; l++, r++) { char type = *METHOD_ARG_TYPE(meth, l); alpha_slot2argoffset[sl++] = -SLOTSIZE * (r+1); if (type == 'J' || type == 'D') { /* long and double use two slots */ alpha_slot2argoffset[sl++] = -SLOTSIZE * (r+1); } } aspill = r + 1; /* memory passed arguments */ for (; l < METHOD_NARGS(meth); l++, r++) { char type = *METHOD_ARG_TYPE(meth, l); alpha_slot2argoffset[sl++] = SLOTSIZE * (r-6); if (type == 'J' || type == 'D') { /* long and double use two slots */ alpha_slot2argoffset[sl++] = SLOTSIZE * (r-6); } }#ifdef KAFFE_VMDEBUG if (jit_debug) { dprintf ("nr arg slots = %d\n", sl); }#endif l = maxLocal + maxStack + maxTemp; /* locals and temps */ while (sl < l) { alpha_slot2argoffset[sl++] = -SLOTSIZE * (aspill++); }#ifdef KAFFE_VMDEBUG if (jit_debug) { for (sl = 0; sl < l; sl++) { dprintf ("slot(%d) = %d\n", sl, alpha_slot2argoffset[sl]); } }#endif /* Now assign the registers to slots */ if (isStatic) { r = 0; } else { forceRegister(&localinfo[0], REG_a0, Rref); r = 1; } sl = r; for (l = 0; l < METHOD_NARGS(meth) && r < 6; l++, r++, sl++) { switch (*METHOD_ARG_TYPE(meth, l)) { case 'L': case '[': forceRegister(&localinfo[sl], REG_a0+r, Rref); break; case 'B': case 'C': case 'I': case 'S': case 'Z': forceRegister(&localinfo[sl], REG_a0+r, Rint); break; case 'F': forceRegister(&localinfo[sl], REG_fa0+r, Rfloat); break; case 'J': forceRegister(&localinfo[sl], REG_a0+r, Rlong); sl++; break; case 'D': forceRegister(&localinfo[sl], REG_fa0+r, Rdouble); sl++; break; default: ABORT(); } }}define_insn(epilogue, epilogue_xxx){ label *l; int r, N; setEpilogueLabel ((uintp)CODEPC); /* Calling Standard for Alpha Systems * 3.2.6.2.2 Exit Code Sequence Steps * When a procedure returns, the exit code must restore the caller's * context, synchronize any pending hardware exceptions, and make the * calling procedure current by returning control to it. The following * list contains the exit code sequence steps. The program performs * step 1, followed by steps 2 through 5 in any order, followed by * steps 6 through 8 in exact order. * * 1. If the GP register has been modified or a call has been made, * restore the GP register to the GOT segment pointer of the current * procedure. * * 2. For a variable-size stack frame procedure that does not return a * value on the top of stack (PDSC_FLAGS_BASE_REG_IS_FP is 1), copy * FP to SP. * * 3. For a stack frame procedure (PDSC_FLAGS_REGISTER_FRAME is 0), * reload any saved registers from the register save area as * specified by PDSC_RPD_RSA_OFFSET. Note that, for a variable-size * stack frame procedure (PDSC_FLAGS_BASE_REG_IS_FP is 1), FP is not * reloaded in this step. For a fixed-size stack frame procedure * (PDSC_FLAGS_BASE_REG_IS_FP is 0), $15 is reloaded if it was saved * on entry. * * 4. Reload the register that held the return address on entry with * the saved return address, if necessary. * * For a stack frame procedure (PDSC_FLAGS_REGISTER_FRAME is 0), * load the register designated by PDSC_RPD_ENTRY_RA ($26 in a * standard call) with the return address from the register save * area as specified by PDSC_RPD_RSA_OFFSET. * * For a register frame procedure (PDSC_FLAGS_REGISTER_FRAME is 1), * copy the return address from the register specified by * PDSC_RPD_SAVE_RA to the register designated by PDSC_RPD_ENTRY_RA. * * 5. Execute trapb, if required. (See Section 5.1.12 for details.) * * 6. For a variable-size stack frame procedure * (PDSC_FLAGS_REGISTER_FRAME is 0 and PDSC_FLAGS_BASE_REG_IS_FP is * 1), reload $15 (FP) as would be done for any other saved register. * * After any necessary calculations, this step must be completed by * exactly one instruction, as described in Section 3.2.6.1. * * 7. If a function value is not being returned on the stack, restore * SP to the value it had at procedure entry by adding the value in * PDSC_RDP_FRAME_SIZE to SP. In some cases, the returning procedure * leaves SP pointing to a lower stack address than it had on entry * to the procedure, as specified in Section 4.1.7. * * After any necessary calculations, this step must be completed by * exactly one instruction, as described in Section 3.2.6.1. * * 8. Execute the ret $31,($n),0001 instruction, as described in * Section 3.2.6.2.1, to return control to the calling procedure. * In almost all cases the $n used will be $26 (the return address * register) because its value must be restored before the call * returns. * * Note that the called routine does not adjust the stack to remove * any arguments passed in memory. This responsibility falls to the * calling routine, which can choose to defer removal of arguments
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -