aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraph <none@none>2014-07-08 05:25:15 -0400
committeraph <none@none>2014-07-08 05:25:15 -0400
commite36c95fa95ece488b015314dc5618c512320bfb8 (patch)
tree0df142f44c7854ffbc5e10b97eeb7ead684d930c
parent25b7dc9658d9e21c7471d5b48826ae3b61039f6d (diff)
parentae2174287dc0eaa9e54382ec730d8bacaba7379d (diff)
Merge
-rw-r--r--src/cpu/aarch64/vm/aarch64.ad223
-rw-r--r--test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java4
-rw-r--r--test/testlibrary/com/oracle/java/testlibrary/Platform.java4
3 files changed, 229 insertions, 2 deletions
diff --git a/src/cpu/aarch64/vm/aarch64.ad b/src/cpu/aarch64/vm/aarch64.ad
index caf3bfb8c..2e3b568af 100644
--- a/src/cpu/aarch64/vm/aarch64.ad
+++ b/src/cpu/aarch64/vm/aarch64.ad
@@ -10470,6 +10470,229 @@ instruct clearArray_reg_reg(iRegL_R11 cnt, iRegP_R10 base, Universe dummy, rFlag
%}
// ============================================================================
+// Overflow Math Instructions
+
+instruct overflowAddI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2)
+%{
+ match(Set cr (OverflowAddI op1 op2));
+
+ format %{ "cmnw $op1, $op2\t# overflow check int" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmnw($op1$$Register, $op2$$Register);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowAddI_reg_imm(rFlagsReg cr, iRegI op1, immIAddSub op2)
+%{
+ match(Set cr (OverflowAddI op1 op2));
+
+ format %{ "cmnw $op1, $op2\t# overflow check int" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmnw($op1$$Register, $op2$$constant);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowAddL_reg_reg(rFlagsReg cr, iRegL op1, iRegL op2)
+%{
+ match(Set cr (OverflowAddL op1 op2));
+
+ format %{ "cmn $op1, $op2\t# overflow check long" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmn($op1$$Register, $op2$$Register);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowAddL_reg_imm(rFlagsReg cr, iRegL op1, immLAddSub op2)
+%{
+ match(Set cr (OverflowAddL op1 op2));
+
+ format %{ "cmn $op1, $op2\t# overflow check long" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmn($op1$$Register, $op2$$constant);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowSubI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2)
+%{
+ match(Set cr (OverflowSubI op1 op2));
+
+ format %{ "cmpw $op1, $op2\t# overflow check int" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmpw($op1$$Register, $op2$$Register);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowSubI_reg_imm(rFlagsReg cr, iRegI op1, immIAddSub op2)
+%{
+ match(Set cr (OverflowSubI op1 op2));
+
+ format %{ "cmpw $op1, $op2\t# overflow check int" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmpw($op1$$Register, $op2$$constant);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowSubL_reg_reg(rFlagsReg cr, iRegL op1, iRegL op2)
+%{
+ match(Set cr (OverflowSubL op1 op2));
+
+ format %{ "cmp $op1, $op2\t# overflow check long" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmp($op1$$Register, $op2$$Register);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowSubL_reg_imm(rFlagsReg cr, iRegL op1, immLAddSub op2)
+%{
+ match(Set cr (OverflowSubL op1 op2));
+
+ format %{ "cmp $op1, $op2\t# overflow check long" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmp($op1$$Register, $op2$$constant);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowNegI_reg(rFlagsReg cr, immI0 zero, iRegI op2)
+%{
+ match(Set cr (OverflowSubI zero op2));
+
+ format %{ "cmpw zr, $op2\t# overflow check int" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmpw(zr, $op2$$Register);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowNegL_reg(rFlagsReg cr, immI0 zero, iRegL op2)
+%{
+ match(Set cr (OverflowSubL zero op2));
+
+ format %{ "cmp zr, $op2\t# overflow check long" %}
+ ins_cost(INSN_COST);
+ ins_encode %{
+ __ cmp(zr, $op2$$Register);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowMulI_reg(rFlagsReg cr, iRegI op1, iRegI op2)
+%{
+ match(Set cr (OverflowMulI op1 op2));
+
+ format %{ "smull rscratch1, $op1, $op2\t# overflow check int\n\t"
+ "cmp rscratch1, rscratch1, sxtw\n\t"
+ "movw rscratch1, #0x80000000\n\t"
+ "cselw rscratch1, rscratch1, zr, NE\n\t"
+ "cmpw rscratch1, #1" %}
+ ins_cost(5 * INSN_COST);
+ ins_encode %{
+ __ smull(rscratch1, $op1$$Register, $op2$$Register);
+ __ subs(zr, rscratch1, rscratch1, ext::sxtw); // NE => overflow
+ __ movw(rscratch1, 0x80000000); // Develop 0 (EQ),
+ __ cselw(rscratch1, rscratch1, zr, Assembler::NE); // or 0x80000000 (NE)
+ __ cmpw(rscratch1, 1); // 0x80000000 - 1 => VS
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowMulI_reg_branch(cmpOp cmp, iRegI op1, iRegI op2, label labl, rFlagsReg cr)
+%{
+ match(If cmp (OverflowMulI op1 op2));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::overflow
+ || n->in(1)->as_Bool()->_test._test == BoolTest::no_overflow);
+ effect(USE labl, KILL cr);
+
+ format %{ "smull rscratch1, $op1, $op2\t# overflow check int\n\t"
+ "cmp rscratch1, rscratch1, sxtw\n\t"
+ "b$cmp $labl" %}
+ ins_cost(3 * INSN_COST); // Branch is rare so treat as INSN_COST
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ __ smull(rscratch1, $op1$$Register, $op2$$Register);
+ __ subs(zr, rscratch1, rscratch1, ext::sxtw); // NE => overflow
+ __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowMulL_reg(rFlagsReg cr, iRegL op1, iRegL op2)
+%{
+ match(Set cr (OverflowMulL op1 op2));
+
+ format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
+ "smulh rscratch2, $op1, $op2\n\t"
+ "cmp rscratch2, rscratch1, ASR #31\n\t"
+ "movw rscratch1, #0x80000000\n\t"
+ "cselw rscratch1, rscratch1, zr, NE\n\t"
+ "cmpw rscratch1, #1" %}
+ ins_cost(6 * INSN_COST);
+ ins_encode %{
+ __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
+ __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
+ __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext
+ __ movw(rscratch1, 0x80000000); // Develop 0 (EQ),
+ __ cselw(rscratch1, rscratch1, zr, Assembler::NE); // or 0x80000000 (NE)
+ __ cmpw(rscratch1, 1); // 0x80000000 - 1 => VS
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+instruct overflowMulL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, rFlagsReg cr)
+%{
+ match(If cmp (OverflowMulL op1 op2));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::overflow
+ || n->in(1)->as_Bool()->_test._test == BoolTest::no_overflow);
+ effect(USE labl, KILL cr);
+
+ format %{ "mul rscratch1, $op1, $op2\t#overflow check long\n\t"
+ "smulh rscratch2, $op1, $op2\n\t"
+ "cmp rscratch2, rscratch1, ASR #31\n\t"
+ "b$cmp $labl" %}
+ ins_cost(4 * INSN_COST); // Branch is rare so treat as INSN_COST
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ __ mul(rscratch1, $op1$$Register, $op2$$Register); // Result bits 0..63
+ __ smulh(rscratch2, $op1$$Register, $op2$$Register); // Result bits 64..127
+ __ cmp(rscratch2, rscratch1, Assembler::ASR, 31); // Top is pure sign ext
+ __ br(cond == Assembler::VS ? Assembler::NE : Assembler::EQ, *L);
+ %}
+
+ ins_pipe(pipe_class_default);
+%}
+
+// ============================================================================
// Compare Instructions
instruct compI_reg_reg(rFlagsReg cr, iRegI op1, iRegI op2)
diff --git a/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java b/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java
index cecd6ce2d..337007dd7 100644
--- a/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java
+++ b/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java
@@ -128,7 +128,7 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest {
@Override
protected boolean isIntrinsicSupported() {
- return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && (Platform.isX86() || Platform.isX64());
+ return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && (Platform.isX86() || Platform.isX64() || Platform.isAArch64());
}
@Override
@@ -144,7 +144,7 @@ public abstract class IntrinsicBase extends CompilerWhiteBoxTest {
@Override
protected boolean isIntrinsicSupported() {
- return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && Platform.isX64();
+ return isServerVM() && Boolean.valueOf(useMathExactIntrinsics) && (Platform.isX64() || Platform.isAArch64());
}
@Override
diff --git a/test/testlibrary/com/oracle/java/testlibrary/Platform.java b/test/testlibrary/com/oracle/java/testlibrary/Platform.java
index fa4b36361..9bce59585 100644
--- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java
+++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java
@@ -113,6 +113,10 @@ public class Platform {
return (isArch("amd64") || isArch("x86_64"));
}
+ public static boolean isAArch64() {
+ return isArch("aarch64");
+ }
+
private static boolean isArch(String archname) {
return osArch.toLowerCase().startsWith(archname.toLowerCase());
}