/** * Provides fine-tuned implementation for IDIV/IREM operations on IA32-compatible platforms, * in replacement of common arithmetic helper (see arith_rt.h). */ bool CodeGen::gen_a_platf(JavaByteCodes op, jtype jt) { if (jt != i32) return false; if (op != OPCODE_IDIV && op != OPCODE_IREM) { return false; } // // The method is supposed to be platform-depended, and may not have // Encoder support - leaving as-is, without implementing general // support in Encoder // vpark(eax.reg()); vpark(edx.reg()); rlock(eax); rlock(edx); Val& v1 = vstack(1, vis_imm(1)); Val& v2 = vstack(0, true); alu(alu_cmp, v2.as_opnd(), Opnd(-1)); unsigned br_normal = br(ne, 0, 0); alu(alu_cmp, v1.as_opnd(), Opnd(INT_MIN)); unsigned br_exit = NOTHING; if (op == OPCODE_IREM) { do_mov(edx, Opnd(0)); // prepare exit value for the corner case br_exit = br(eq, 0, 0); } else { do_mov(eax, v1); br_exit = br(eq, 0, 0); } patch(br_normal, ip()); do_mov(eax, v1); // // The method is supposed to be platform-depended, and may not have // Encoder support - leaving as-is, without implementing general // support in Encoder // //CDQ EncoderBase::Operands args0(RegName_EDX, RegName_EAX); ip(EncoderBase::encode(ip(), Mnemonic_CDQ, args0)); //IDIV EncoderBase::Operands args(RegName_EDX, RegName_EAX, devirt(v2.reg(), i32)); ip(EncoderBase::encode(ip(), Mnemonic_IDIV, args)); patch(br_exit, ip()); vpop(); vpop(); vpush(op == OPCODE_IREM ? edx : eax); runlock(eax); runlock(edx); return true; }
void Compiler::gen_if(JavaByteCodes opcod, unsigned target) { if (target <= m_pc) { // have back branch here gen_prof_be(); gen_gc_safe_point(); } jtype jt = i32; if (opcod == OPCODE_IFNULL) { opcod = OPCODE_IFEQ; jt = jobj; } else if (opcod == OPCODE_IFNONNULL) { opcod = OPCODE_IFNE; jt = jobj; } OpndKind kind = m_jframe->dip(0).kind(); bool forceReg = (kind == opnd_imm) || (jt == jobj && g_refs_squeeze); Opnd op1 = vstack(0, forceReg).as_opnd(); vpop(); rlock(op1); COND cond = to_cond(opcod); static const Opnd zero((int)0); if (jt == jobj && g_refs_squeeze) { AR ar = valloc(jobj); movp(ar, NULL_REF); alu(alu_cmp, Opnd(jobj, ar), op1); } else if (opcod == OPCODE_IFEQ || opcod == OPCODE_IFNE) { if (op1.is_reg()) { alu(alu_test, op1, op1); } else { alu(alu_cmp, op1, zero); } } else { alu(alu_cmp, op1, zero); } runlock(op1); gen_bb_leave(target); br(cond, target, m_bbinfo->start); }
Opnd opnd_null() { return Opnd(); }
void Compiler::gen_switch(const JInst & jinst) { assert(jinst.opcode == OPCODE_LOOKUPSWITCH || jinst.opcode == OPCODE_TABLESWITCH); Opnd val = vstack(0, true).as_opnd(); vpop(); rlock(val); gen_bb_leave(NOTHING); if (jinst.opcode == OPCODE_LOOKUPSWITCH) { unsigned n = jinst.get_num_targets(); for (unsigned i = 0; i < n; i++) { Opnd key(jinst.key(i)); unsigned pc = jinst.get_target(i); alu(alu_cmp, val, key); br(eq, pc, m_bbinfo->start); } runlock(val); br(cond_none, jinst.get_def_target(), m_bbinfo->start); return; } // // TABLESWITCH // alu(alu_cmp, val, jinst.high()); br(gt, jinst.get_def_target(), m_bbinfo->start); alu(alu_cmp, val, jinst.low()); br(lt, jinst.get_def_target(), m_bbinfo->start); AR gr_tabl = valloc(jobj); movp(gr_tabl, DATA_SWITCH_TABLE | m_curr_inst->pc, m_bbinfo->start); #ifdef _EM64T_ // On EM64T, we operate with I_32 value in a register, but the // register will be used as 64 bit in address form - have to extend sx(Opnd(i64, val.reg()), Opnd(i32, val.reg())); #endif // Here, we need to extract 'index-=low()' - can pack this into // complex address form: // [table + index*sizeof(void*) - low()*sizeof(void*)], // but only if low()*sizeof(void*) does fit into displacement ... int tmp = -jinst.low(); const int LO_BOUND = INT_MIN/(int)sizeof(void*); const int UP_BOUND = INT_MAX/(int)sizeof(void*); if (LO_BOUND<=tmp && tmp<=UP_BOUND) { ld(jobj, gr_tabl, gr_tabl, -jinst.low()*sizeof(void*), val.reg(), sizeof(void*)); } else { // ... otherwise subtract explicitly, but only if the register // is not used anywhere else if (rrefs(val.reg()) !=0) { Opnd vtmp(i32, valloc(i32)); mov(vtmp, val); // make a copy of val runlock(val); val = vtmp; rlock(val); } alu(alu_sub, val, jinst.low()); ld(jobj, gr_tabl, gr_tabl, 0, val.reg(), sizeof(void*)); } runlock(val); br(gr_tabl); }