14069 "cmp rscratch1, rscratch1, sxtw\n\t"
14070 "b$cmp $labl" %}
14071 ins_cost(3 * INSN_COST); // Branch is rare so treat as INSN_COST
14072 ins_encode %{
14073 Label* L = $labl$$label;
14074 Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
14075 __ smull(rscratch1, $op1$$Register, $op2$$Register);
14076 __ subs(zr, rscratch1, rscratch1, ext::sxtw); // NE => overflow
14077 __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L);
14078 %}
14079
14080 ins_pipe(pipe_serial);
14081 %}
14082
14083 instruct overflowMulL_reg(rFlagsReg cr, iRegL op1, iRegL op2)
14084 %{
14085 match(Set cr (OverflowMulL op1 op2));
14086
14087 format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
14088 "smulh rscratch2, $op1, $op2\n\t"
14089 "cmp rscratch2, rscratch1, ASR #31\n\t"
14090 "movw rscratch1, #0x80000000\n\t"
14091 "cselw rscratch1, rscratch1, zr, NE\n\t"
14092 "cmpw rscratch1, #1" %}
14093 ins_cost(6 * INSN_COST);
14094 ins_encode %{
14095 __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
14096 __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
14097 __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext
14098 __ movw(rscratch1, 0x80000000); // Develop 0 (EQ),
14099 __ cselw(rscratch1, rscratch1, zr, Assembler::NE); // or 0x80000000 (NE)
14100 __ cmpw(rscratch1, 1); // 0x80000000 - 1 => VS
14101 %}
14102
14103 ins_pipe(pipe_slow);
14104 %}
14105
14106 instruct overflowMulL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, rFlagsReg cr)
14107 %{
14108 match(If cmp (OverflowMulL op1 op2));
14109 predicate(n->in(1)->as_Bool()->_test._test == BoolTest::overflow
14110 || n->in(1)->as_Bool()->_test._test == BoolTest::no_overflow);
14111 effect(USE labl, KILL cr);
14112
14113 format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
14114 "smulh rscratch2, $op1, $op2\n\t"
14115 "cmp rscratch2, rscratch1, ASR #31\n\t"
14116 "b$cmp $labl" %}
14117 ins_cost(4 * INSN_COST); // Branch is rare so treat as INSN_COST
14118 ins_encode %{
14119 Label* L = $labl$$label;
14120 Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
14121 __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
14122 __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
14123 __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext
14124 __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L);
14125 %}
14126
14127 ins_pipe(pipe_serial);
14128 %}
14129
14130 // ============================================================================
14131 // Compare Instructions
14132
14133 instruct compI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2)
14134 %{
14135 match(Set cr (CmpI op1 op2));
14136
14137 effect(DEF cr, USE op1, USE op2);
14138
14139 ins_cost(INSN_COST);
14140 format %{ "cmpw $op1, $op2" %}
14141
14142 ins_encode(aarch64_enc_cmpw(op1, op2));
14143
|
14069 "cmp rscratch1, rscratch1, sxtw\n\t"
14070 "b$cmp $labl" %}
14071 ins_cost(3 * INSN_COST); // Branch is rare so treat as INSN_COST
14072 ins_encode %{
14073 Label* L = $labl$$label;
14074 Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
14075 __ smull(rscratch1, $op1$$Register, $op2$$Register);
14076 __ subs(zr, rscratch1, rscratch1, ext::sxtw); // NE => overflow
14077 __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L);
14078 %}
14079
14080 ins_pipe(pipe_serial);
14081 %}
14082
14083 instruct overflowMulL_reg(rFlagsReg cr, iRegL op1, iRegL op2)
14084 %{
14085 match(Set cr (OverflowMulL op1 op2));
14086
14087 format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
14088 "smulh rscratch2, $op1, $op2\n\t"
14089 "cmp rscratch2, rscratch1, ASR #63\n\t"
14090 "movw rscratch1, #0x80000000\n\t"
14091 "cselw rscratch1, rscratch1, zr, NE\n\t"
14092 "cmpw rscratch1, #1" %}
14093 ins_cost(6 * INSN_COST);
14094 ins_encode %{
14095 __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
14096 __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
14097 __ cmp(rscratch2, rscratch1, Assembler::ASR, 63); // Top is pure sign ext
14098 __ movw(rscratch1, 0x80000000); // Develop 0 (EQ),
14099 __ cselw(rscratch1, rscratch1, zr, Assembler::NE); // or 0x80000000 (NE)
14100 __ cmpw(rscratch1, 1); // 0x80000000 - 1 => VS
14101 %}
14102
14103 ins_pipe(pipe_slow);
14104 %}
14105
14106 instruct overflowMulL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, rFlagsReg cr)
14107 %{
14108 match(If cmp (OverflowMulL op1 op2));
14109 predicate(n->in(1)->as_Bool()->_test._test == BoolTest::overflow
14110 || n->in(1)->as_Bool()->_test._test == BoolTest::no_overflow);
14111 effect(USE labl, KILL cr);
14112
14113 format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
14114 "smulh rscratch2, $op1, $op2\n\t"
14115 "cmp rscratch2, rscratch1, ASR #63\n\t"
14116 "b$cmp $labl" %}
14117 ins_cost(4 * INSN_COST); // Branch is rare so treat as INSN_COST
14118 ins_encode %{
14119 Label* L = $labl$$label;
14120 Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
14121 __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
14122 __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
14123 __ cmp(rscratch2, rscratch1, Assembler::ASR, 63); // Top is pure sign ext
14124 __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L);
14125 %}
14126
14127 ins_pipe(pipe_serial);
14128 %}
14129
14130 // ============================================================================
14131 // Compare Instructions
14132
14133 instruct compI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2)
14134 %{
14135 match(Set cr (CmpI op1 op2));
14136
14137 effect(DEF cr, USE op1, USE op2);
14138
14139 ins_cost(INSN_COST);
14140 format %{ "cmpw $op1, $op2" %}
14141
14142 ins_encode(aarch64_enc_cmpw(op1, op2));
14143
|