📄 jit-alpha.def
字号:
op_subs_su(r1, r2, t); op_trapb();#endif if (t == REG_ft) { op_fmov(t, w); }}define_insn(sub_double, subd_RRR){ int r2 = rreg_double(2); int r1 = rreg_double(1); int w = wreg_double(0); int t = ((r1 == w) || (r2 == w)) ? REG_ft : w; alpha_jit_info.ieee = 1;#ifndef AXP_FULL_IEEE_FP op_subt(r1, r2, t);#else op_subt_su(r1, r2, t); op_trapb();#endif if (t == REG_ft) { op_fmov(t, w); }}/* Implement these because the compiler don't know about $zero and will attempt to load a constant zero. */define_insn(neg_int, negi_RxR){ int r = rreg_int(2); int w = wreg_int(0); op_subl(REG_zero, r, w);}define_insn(neg_long, negl_RxR){ int r = rreg_long(2); int w = wreg_long(0); op_subq(REG_zero, r, w);}define_insn(neg_float, negf_RxR){ int r = rreg_float(2); int w = wreg_float(0); op_cpysn(r, r, w);}define_insn(neg_double, negd_RxR){ int r = rreg_double(2); int w = wreg_double(0); op_cpysn(r, r, w);}define_insn(mul_int_const, muli_RRC){ int o = const_int(2); int r = rreg_int(1); int w = wreg_int(0); assert(o >= 0 && o <= 0xFF); switch (o) { case 0: op_mov(REG_zero, w); break; case 1: op_mov(r, w); break; case 2: op_addl(r, r, w); break; case 3: op_s4subl(r, r, w); break; case 4: op_s4addl(r, REG_zero, w); break; case 5: op_s4addl(r, r, w); break; case 7: op_s8subl(r, r, w); break; case 8: op_s8addl(r, REG_zero, w); break; case 9: op_s8addl(r, r, w); break; default: op_mull_i(r, o, w); break; }}define_insn(mul_long_const, mull_RRC){ int o = const_int(2); int r = rreg_long(1); int w = wreg_long(0); assert(o >= 0 && o <= 0xFF); switch (o) { case 0: op_mov(REG_zero, w); break; case 1: op_mov(r, w); break; case 2: op_addq(r, r, w); break; case 3: op_s4subq(r, r, w); break; case 4: op_s4addq(r, REG_zero, w); break; case 5: op_s4addq(r, r, w); break; case 7: op_s8subq(r, r, w); break; case 8: op_s8addq(r, REG_zero, w); break; case 9: op_s8addq(r, r, w); break; default: op_mulq_i(r, o, w); break; }}define_insn(mul_int, muli_RRR){ int r2 = rreg_int(2); int r1 = rreg_int(1); int w = wreg_int(0); op_mull(r1, r2, w);}define_insn(mul_long, mull_RRR){ int r2 = rreg_long(2); int r1 = rreg_long(1); int w = wreg_long(0); op_mulq(r1, r2, w);}define_insn(mul_float, mulf_RRR){ int r2 = rreg_float(2); int r1 = rreg_float(1); int w = wreg_float(0); int t = ((r1 == w) || (r2 == w)) ? REG_ft : w; alpha_jit_info.ieee = 1;#ifndef AXP_FULL_IEEE_FP op_muls(r1, r2, t);#else op_muls_su(r1, r2, t); op_trapb();#endif if (t == REG_ft) { op_fmov(t, w); }}define_insn(mul_double, muld_RRR){ int r2 = rreg_double(2); int r1 = rreg_double(1); int w = wreg_double(0); int t = ((r1 == w) || (r2 == w)) ? REG_ft : w; alpha_jit_info.ieee = 1;#ifndef AXP_FULL_IEEE_FP op_mult(r1, r2, t);#else op_mult_su(r1, r2, t); op_trapb();#endif if (t == REG_ft) { op_fmov(t, w); }}/* While we don't have a native integer division instruction, we do have library functions with extra friendly calling conventions. */static voidalpha_division(sequence *s, int type, void *fn){ extern void alpha_do_call_div(void); int r1 = NOREG, r2 = NOREG; /* Move the arguments into place. */ if (slotInRegister(1, type)) { r1 = fastSlotRegister(seq_slot(s, 1), type, rread); } if (slotInRegister(2, type)) { r2 = fastSlotRegister(seq_slot(s, 2), type, rread); } if (r2 == REG_t10 && r1 == REG_t11) { /* Urg. They are just in the wrong place. Exchange them and diddle the compiler's structures. */ register_invalidate(REG_t10); register_invalidate(REG_t11); forceRegister(seq_slot(s, 1), REG_t10, type); forceRegister(seq_slot(s, 2), REG_t11, type); op_mov(REG_t10, REG_at); op_mov(REG_t11, REG_t10); op_mov(REG_at, REG_t11); } else { if (r2 == REG_t10) { forceRegister(seq_slot(s, 2), REG_t11, type); op_mov(REG_t10, REG_t11); } if (r1 == NOREG) { r1 = slowSlotOffset(seq_slot(s, 1), type, rread); assert(r1 >= -0x8000 && r1 < 0x8000); forceRegister(seq_slot(s, 1), REG_t10, type); if (type == Rint) op_ldl(REG_t10, REG_fp, r1); else op_ldq(REG_t10, REG_fp, r1); } else if (r1 != REG_t10) { forceRegister(seq_slot(s, 1), REG_t10, type); op_mov(r1, REG_t10); } if (r2 == NOREG) { r2 = slowSlotOffset(seq_slot(s, 2), type, rread); assert(r2 >= -0x8000 && r2 < 0x8000); forceRegister(seq_slot(s, 2), REG_t11, type); if (type == Rint) op_ldl(REG_t11, REG_fp, r2); else op_ldq(REG_t11, REG_fp, r2); } else if (r2 != REG_t10 && r2 != REG_t11) { forceRegister(seq_slot(s, 2), REG_t11, type); op_mov(r2, REG_t11); } } clobberRegister(REG_t9); clobberRegister(REG_pv); alpha_move_const_pool(REG_pv, NULL, CPref, fn, op_ldq); op_jsr(REG_t9, REG_pv, 0); alpha_ldgp(REG_t9); forceRegister(seq_dst(s), REG_pv, type);}define_insn(div_int, divi_RRR){ extern void __divl(void); alpha_division(s, Rint, &__divl);}define_insn(div_long, divl_RRR){ extern void __divq(void); alpha_division(s, Rlong, &__divq);}define_insn(div_float, divf_RRR){ int r2 = rreg_float(2); int r1 = rreg_float(1); int w = wreg_float(0); int t = ((r1 == w) || (r2 == w)) ? REG_ft : w; alpha_jit_info.ieee = 1;#ifndef AXP_FULL_IEEE_FP op_divs(r1, r2, t);#else op_divs_su(r1, r2, t); op_trapb();#endif if (t == REG_ft) { op_fmov(t, w); }}define_insn(div_double, divd_RRR){ int r2 = rreg_double(2); int r1 = rreg_double(1); int w = wreg_double(0); int t = ((r1 == w) || (r2 == w)) ? REG_ft : w; alpha_jit_info.ieee = 1;#ifndef AXP_FULL_IEEE_FP op_divt(r1, r2, t);#else op_divt_su(r1, r2, t); op_trapb();#endif if (t == REG_ft) { op_fmov(t, w); }}define_insn(rem_int, remi_RRR){ extern void __reml(void); alpha_division(s, Rint, &__reml);}define_insn(rem_long, reml_RRR){ extern void __remq(void); alpha_division(s, Rlong, &__remq);}/* --------------------------------------------------------------------- */static inline voidalpha_and_const(int r, long o, int w){ if (o >= 0 && o <= 0xFF) { op_and_i(r, o, w); } else if (~o >= 0 && ~o <= 0xFF) { op_andnot_i(r, ~o, w); } else { /* Our rangecheck asserts that this is the only other option here. */ o = alpha_zapnot_const(o); op_zapnot_i(r, o, w); }}define_insn(and_int_const, andi_RRC){ alpha_and_const(rreg_int(1), const_int(2), wreg_int(0));}define_insn(and_long_const, andl_RRC){ alpha_and_const(rreg_long(1), const_long(2), wreg_long(0));}define_insn(and_int, andi_RRR){ int r2 = rreg_int(2); int r1 = rreg_int(1); int w = wreg_int(0); op_and(r1, r2, w);}define_insn(and_long, andl_RRR){ int r2 = rreg_long(2); int r1 = rreg_long(1); int w = wreg_long(0); op_and(r1, r2, w);}define_insn(or_int, ori_RRR){ int r2 = rreg_int(2); int r1 = rreg_int(1); int w = wreg_int(0); op_or(r1, r2, w);}define_insn(or_long, orl_RRR){ int r2 = rreg_long(2); int r1 = rreg_long(1); int w = wreg_long(0); op_or(r1, r2, w);}define_insn(xor_int, xori_RRR){ int r2 = rreg_int(2); int r1 = rreg_int(1); int w = wreg_int(0); op_xor(r1, r2, w);}define_insn(xor_long, xorl_RRR){ int r2 = rreg_long(2); int r1 = rreg_long(1); int w = wreg_long(0); op_xor(r1, r2, w);}define_insn(ashr_int_const, ashri_RRC){ int o = const_int(2); int r = rreg_int(1); int w = wreg_int(0); op_sra_i(r, o, w);}define_insn(ashr_long_const, ashrl_RRC){ int o = const_int(2); int r = rreg_long(1); int w = wreg_long(0); op_sra_i(r, o, w);}define_insn(ashr_int, ashri_RRR){ int r2 = rreg_int(2); int r1 = rreg_int(1); int w = wreg_int(0); op_sra(r1, r2, w);}define_insn(ashr_long, ashrl_RRR){ int r2 = rreg_long(2); int r1 = rreg_long(1); int w = wreg_long(0); op_sra(r1, r2, w);}define_insn(lshr_int_const, lshri_RRC){ int o = const_int(2); int r = rreg_int(1); int w = wreg_int(0); op_zapnot_i(r, 15, w); op_srl_i(w, o, w);}define_insn(lshr_long_const, lshrl_RRC){ int o = const_int(2); int r = rreg_long(1); int w = wreg_long(0); op_srl_i(r, o, w);}define_insn(lshr_int, lshri_RRR){ int r2 = rreg_int(2); int r1 = rreg_int(1); int w = wreg_int(0); op_zapnot_i(r1, 15, w); op_srl(w, r2, w);}define_insn(lshr_long, lshrl_RRR){ int r2 = rreg_long(2); int r1 = rreg_long(1); int w = wreg_long(0); op_srl(r1, r2, w);}define_insn(lshl_int_const, lshli_RRC){ int o = const_int(2); int r = rreg_int(1); int w = wreg_int(0); /* Attempt to use an addition instruction because (1) they slot better on the EV5, and (2) they have better latency on the EV4. */ switch (o) { case 0: if (r != w) op_mov(r, w); break; case 1: op_addl(r, r, w); break; case 2: op_s4addl(r, REG_zero, w); break; case 3: op_s8addl(r, REG_zero, w); break; default: op_sll_i(r, o, w); op_addl(w, REG_zero, w); /* care for proper overflow. */ break; }}define_insn(lshl_long_const, lshll_RRC){ int o = const_int(2); int r = rreg_long(1); int w = wreg_long(0); /* Attempt to use an addition instruction because (1) they slot better on the EV5, and (2) they have better latency on the EV4. */ switch (o) { case 0: if (r != w) op_mov(r, w); break; case 1: op_addq(r, r, w); break; case 2: op_s4addq(r, REG_zero, w); break; case 3: op_s8addq(r, REG_zero, w); break; default: op_sll_i(r, o, w);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -