[aarch64-port-dev ] A rather large patch to aarch64.ad

Andrew Haley aph at redhat.com
Fri Oct 25 09:37:21 PDT 2013


This is a substantial rewrite of the AArch64 patterns for arithmetic
and memory access.  The idea is to make use of the more complex
AArch64 instructions wherever possible, so that e.g. we use UBFX
rather than a series of shifts and masks, and LDR Xd, [Xn, Wn, sxtw #3]
for array loads.

The patch itself is hard to follow because of the reorganization I had
to do.  I apologize for that.  However, the resulting aarch64.ad isn't
so bad.

I have checked many of these patterns and HotSpot really does generate
the fast AArch64 instructions.

Comments?

Andrew.


diff -ur hs-tmp/src/cpu/aarch64/vm/aarch64.ad /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/aarch64.ad
--- hs-tmp/src/cpu/aarch64/vm/aarch64.ad	2013-10-25 16:34:20.464632075 +0100
+++ /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/aarch64.ad	2013-10-25 16:27:40.436100824 +0100
@@ -1772,8 +1772,63 @@
     }									\
     __ INSN(REG, SCRATCH);						\
   }
+
+typedef void (MacroAssembler::* mem_insn)(Register Rt, const Address &adr);
+typedef void (MacroAssembler::* mem_float_insn)(FloatRegister Rt, const Address &adr);
+
+  // Used for all non-volatile memory accesses.  The use of
+  // $mem->opcode() to discover whether this pattern uses sign-extended
+  // offsets is something of a kludge.
+  static void loadStore(MacroAssembler masm, mem_insn insn,
+			 Register reg, int opcode,
+			 Register base, int index, int size, int disp)
+  {
+    Address::extend scale;
+    if (opcode == INDINDEXSCALEDOFFSETI2L
+	|| opcode == INDINDEXSCALEDI2L)
+      scale = Address::sxtw(size);
+    else
+      scale = Address::lsl(size);
+
+    if (index == -1) {
+      (masm.*insn)(reg, Address(base, disp));
+    } else {
+      if (disp == 0) {
+	(masm.*insn)(reg, Address(base, as_Register(index), scale));
+      } else {
+	masm.lea(rscratch1, Address(base, disp));
+	(masm.*insn)(reg, Address(rscratch1, as_Register(index), scale));
+      }
+    }
+  }
+
+  static void loadStore(MacroAssembler masm, mem_float_insn insn,
+			 FloatRegister reg, int opcode,
+			 Register base, int index, int size, int disp)
+  {
+    Address::extend scale;
+    if (opcode == INDINDEXSCALEDOFFSETI2L
+	|| opcode == INDINDEXSCALEDI2L)
+      scale = Address::sxtw(size);
+    else
+      scale = Address::lsl(size);
+
+    if (index == -1) {
+      (masm.*insn)(reg, Address(base, disp));
+    } else {
+      if (disp == 0) {
+	(masm.*insn)(reg, Address(base, as_Register(index), scale));
+      } else {
+	masm.lea(rscratch1, Address(base, disp));
+	(masm.*insn)(reg, Address(rscratch1, as_Register(index), scale));
+      }
+    }
+  }
+
 %}

+
+
 //----------ENCODING BLOCK-----------------------------------------------------
 // This block specifies the encoding classes used by the compiler to
 // output byte streams.  Encoding classes are parameterized macros
@@ -1815,452 +1870,184 @@
     __ unimplemented("C2 catch all");
   %}

+  // BEGIN Non-volatile memory access
+
   enc_class aarch64_enc_ldrsbw(iRegI dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrsbw(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrsbw(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrsbw(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrsbw, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

-  enc_class aarch64_enc_ldrsb(iRegL dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
+  enc_class aarch64_enc_ldrsb(iRegI dst, memory mem) %{
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrsb(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrsb(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrsb(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrsb, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

-  enc_class aarch64_enc_ldrbw(iRegI dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
+  enc_class aarch64_enc_ldrb(iRegI dst, memory mem) %{
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrb(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrb(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrb(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrb, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrb(iRegL dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrb(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrb(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrb(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrb, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrshw(iRegI dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrshw(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrshw(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrshw(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrshw, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

-  enc_class aarch64_enc_ldrsh(iRegL dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
+  enc_class aarch64_enc_ldrsh(iRegI dst, memory mem) %{
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrsh(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrsh(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrsh(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrsh, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

-  enc_class aarch64_enc_ldrhw(iRegI dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
+  enc_class aarch64_enc_ldrh(iRegI dst, memory mem) %{
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrh(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrh(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrh(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrh, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrh(iRegL dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrh(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrh(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrh(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrh, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrw(iRegI dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrw(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrw(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrw(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrw, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrw(iRegL dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrw(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrw(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrw(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrw, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrsw(iRegL dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrsw(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrsw(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrsw(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrsw, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldr(iRegL dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register dst_reg = as_Register($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldr(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldr(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldr(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldr, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrs(vRegF dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     FloatRegister dst_reg = as_FloatRegister($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrs(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrs(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrs(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrs, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_ldrd(vRegD dst, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     FloatRegister dst_reg = as_FloatRegister($dst$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ ldrd(dst_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ ldrd(dst_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ ldrd(dst_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrd, dst_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_strb(iRegI src, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register src_reg = as_Register($src$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strb(src_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strb(src_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strb(src_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::strb, src_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_strb0(memory mem) %{
     MacroAssembler _masm(&cbuf);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strb(zr, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strb(zr, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strb(zr, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(_masm, &MacroAssembler::strb, zr, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_strh(iRegI src, memory mem) %{
-    MacroAssembler _masm(&cbuf);
     Register src_reg = as_Register($src$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strh(src_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strh(src_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strh(src_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::strh, src_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_strh0(memory mem) %{
     MacroAssembler _masm(&cbuf);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strh(zr, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strh(zr, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strh(zr, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(_masm, &MacroAssembler::strh, zr, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_strw(iRegI src, memory mem) %{
+    Register src_reg = as_Register($src$$reg);
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::strw, src_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+  %}
+
+  enc_class aarch64_enc_strw0(memory mem) %{
     MacroAssembler _masm(&cbuf);
+    loadStore(_masm, &MacroAssembler::strw, zr, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+  %}
+
+  enc_class aarch64_enc_str(iRegL src, memory mem) %{
     Register src_reg = as_Register($src$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strw(src_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strw(src_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strw(src_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
-  %}
-
-  enc_class aarch64_enc_strw0(memory mem) %{
-    MacroAssembler _masm(&cbuf);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strw(zr, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strw(zr, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strw(zr, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
-  %}
-
-  enc_class aarch64_enc_str(iRegL src, memory mem) %{
-    MacroAssembler _masm(&cbuf);
-    Register src_reg = as_Register($src$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-
     // we sometimes get asked to store the stack pointer into the
     // current thread -- we cannot do that directly on AArch64
-
     if (src_reg == r31_sp) {
-      assert(base == rthread, "unexpected store for sp");
+      MacroAssembler _masm(&cbuf);
+      assert(as_Register($mem$$base) == rthread, "unexpected store for sp");
       __ mov(rscratch2, sp);
       src_reg = rscratch2;
     }
-    if (index == -1) {
-      __ str(src_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ str(src_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ str(src_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::str, src_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

   enc_class aarch64_enc_str0(memory mem) %{
     MacroAssembler _masm(&cbuf);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
+    loadStore(_masm, &MacroAssembler::str, zr, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+  %}

-    if (index == -1) {
-      __ str(zr, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ str(zr, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ str(zr, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
+  enc_class aarch64_enc_strs(vRegF src, memory mem) %{
+    FloatRegister src_reg = as_FloatRegister($src$$reg);
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::strs, src_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+  %}
+
+  enc_class aarch64_enc_strd(vRegD src, memory mem) %{
+    FloatRegister src_reg = as_FloatRegister($src$$reg);
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::strd, src_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}

+  enc_class aarch64_enc_strw_immn(immN src, memory mem) %{
+    MacroAssembler _masm(&cbuf);
+    address con = (address)$src$$constant;
+    // need to do this the hard way until we can manage relocs
+    // for 32 bit constants
+    __ movoop(rscratch2, (jobject)con);
+    if (con) __ encode_heap_oop_not_null(rscratch2);
+    loadStore(_masm, &MacroAssembler::strw, rscratch2, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+  %}
+
+  enc_class aarch64_enc_strw_immnk(immN src, memory mem) %{
+    MacroAssembler _masm(&cbuf);
+    address con = (address)$src$$constant;
+    // need to do this the hard way until we can manage relocs
+    // for 32 bit constants
+    __ movoop(rscratch2, (jobject)con);
+    __ encode_klass_not_null(rscratch2);
+    loadStore(_masm, &MacroAssembler::strw, rscratch2, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+  %}
+
+  // END Non-volatile memory access
+
   // this encoding writes the address of the first instruction in the
   // call sequence for the runtime call into the anchor pc slot. this
   // address allows the runtime to i) locate the code buffer for the
@@ -2325,94 +2112,6 @@
     __ str(rscratch1, Address(rthread, field_offset));
   %}

-  enc_class aarch64_enc_strs(vRegF src, memory mem) %{
-    MacroAssembler _masm(&cbuf);
-    FloatRegister src_reg = as_FloatRegister($src$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strs(src_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strs(src_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strs(src_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
-  %}
-
-  enc_class aarch64_enc_strd(vRegD src, memory mem) %{
-    MacroAssembler _masm(&cbuf);
-    FloatRegister src_reg = as_FloatRegister($src$$reg);
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    if (index == -1) {
-      __ strd(src_reg, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strd(src_reg, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strd(src_reg, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
-  %}
-
-  enc_class aarch64_enc_strw_immn(immN src, memory mem) %{
-    MacroAssembler _masm(&cbuf);
-    address con = (address)$src$$constant;
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    // need to do this the hard way until we can manage relocs
-    // for 32 bit constants
-    __ movoop(rscratch2, (jobject)con);
-    if (con) __ encode_heap_oop_not_null(rscratch2);
-    if (index == -1) {
-      __ strw(rscratch2, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strw(rscratch2, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strw(rscratch2, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
-  %}
-
-  enc_class aarch64_enc_strw_immnk(immN src, memory mem) %{
-    MacroAssembler _masm(&cbuf);
-    address con = (address)$src$$constant;
-    Register base = as_Register($mem$$base);
-    int index = $mem$$index;
-    int scale = $mem$$scale;
-    int disp = $mem$$disp;
-    // need to do this the hard way until we can manage relocs
-    // for 32 bit constants
-    __ movoop(rscratch2, (jobject)con);
-    __ encode_klass_not_null(rscratch2);
-    if (index == -1) {
-      __ strw(rscratch2, Address(base, disp));
-    } else {
-      Register index_reg = as_Register(index);
-      if (disp == 0) {
-        __ strw(rscratch2, Address(base, index_reg, Address::lsl(scale)));
-      } else {
-        __ lea(rscratch1, Address(base, disp));
-	__ strw(rscratch2, Address(rscratch1, index_reg, Address::lsl(scale)));
-      }
-    }
-  %}
-
   // volatile loads and stores

   enc_class aarch64_enc_ldarsbw(iRegI dst, memory mem) %{
@@ -3719,103 +3418,99 @@
   interface(CONST_INTER);
 %}

-// Scale values for scaled offset addressing modes (up to long but not quad)
-operand immIScale()
+operand immI_8()
 %{
-  predicate(0 <= n->get_int() && (n->get_int() <= 3));
+  predicate(n->get_int() == 8);
   match(ConI);

+  op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 26 bit signed offset -- for pc-relative branches
-operand immI26()
+operand immI_16()
 %{
-  predicate(((-(1 << 25)) <= n->get_int()) && (n->get_int() < (1 << 25)));
+  predicate(n->get_int() == 16);
   match(ConI);

+  op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 19 bit signed offset -- for pc-relative loads
-operand immI19()
+operand immI_24()
 %{
-  predicate(((-(1 << 18)) <= n->get_int()) && (n->get_int() < (1 << 18)));
+  predicate(n->get_int() == 24);
   match(ConI);

+  op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 12 bit unsigned offset -- for base plus immediate loads
-operand immIU12()
+operand immI_32()
 %{
-  predicate((0 <= n->get_int()) && (n->get_int() < (1 << 12)));
+  predicate(n->get_int() == 32);
   match(ConI);

+  op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// Valid 9 bit unsigned offset
-operand immI9()
+operand immI_48()
 %{
-  predicate(((-(1 << 8)) <= n->get_int()) && (n->get_int() < (1 << 8)));
+  predicate(n->get_int() == 48);
   match(ConI);

+  op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 32 bit integer valid for add sub immediate
-operand immIAddSub()
+operand immI_56()
 %{
-  predicate(Assembler::operand_valid_for_add_sub_immediate((long)n->get_int()));
+  predicate(n->get_int() == 56);
   match(ConI);
+
   op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 32 bit unsigned integer valid for logical immediate
-// TODO -- check this is right when e.g the mask is 0x80000000
-operand immILog()
+operand immI_255()
 %{
-  predicate(Assembler::operand_valid_for_logical_immediate(true, (unsigned long)n->get_int()));
+  predicate(n->get_int() == 255);
   match(ConI);
+
   op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// Integer operands 64 bit
-// 64 bit immediate
-operand immL()
+operand immI_65535()
 %{
-  match(ConL);
+  predicate(n->get_int() == 65535);
+  match(ConI);

-  op_cost(20);
+  op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 64 bit zero
-operand immL0()
+operand immL_255()
 %{
-  predicate(n->get_long() == 0);
-  match(ConL);
+  predicate(n->get_int() == 255);
+  match(ConI);

   op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 64 bit unit increment
-operand immL_1()
+operand immL_65535()
 %{
-  predicate(n->get_long() == 1);
+  predicate(n->get_long() == 65535L);
   match(ConL);

   op_cost(0);
@@ -3823,10 +3518,9 @@
   interface(CONST_INTER);
 %}

-// 64 bit unit decrement
-operand immL_M1()
+operand immL_4294967295()
 %{
-  predicate(n->get_long() == 1);
+  predicate(n->get_long() == 4294967295L);
   match(ConL);

   op_cost(0);
@@ -3834,12 +3528,10 @@
   interface(CONST_INTER);
 %}

-// 32 bit offset of pc in thread anchor
-
-operand immL_pc_off()
+operand immL_bitmask()
 %{
-  predicate(n->get_long() == in_bytes(JavaThread::frame_anchor_offset()) +
-                             in_bytes(JavaFrameAnchor::last_Java_pc_offset()));
+  predicate(((n->get_long() & 0xc000000000000000l) == 0)
+	    && is_power_of_2(n->get_long() + 1));
   match(ConL);

   op_cost(0);
@@ -3847,61 +3539,200 @@
   interface(CONST_INTER);
 %}

-// 64 bit integer valid for add sub immediate
-operand immLAddSub()
+operand immI_bitmask()
 %{
-  predicate(Assembler::operand_valid_for_add_sub_immediate(n->get_long()));
-  match(ConL);
+  predicate(((n->get_int() & 0xc0000000) == 0)
+	    && is_power_of_2(n->get_int() + 1));
+  match(ConI);
+
   op_cost(0);
   format %{ %}
   interface(CONST_INTER);
 %}

-// 64 bit integer valid for logical immediate
-operand immLLog()
+// Scale values for scaled offset addressing modes (up to long but not quad)
+operand immIScale()
 %{
-  predicate(Assembler::operand_valid_for_logical_immediate(true, (unsigned long)n->get_long()));
-  match(ConL);
-  op_cost(0);
+  predicate(0 <= n->get_int() && (n->get_int() <= 3));
+  match(ConI);
+
   format %{ %}
   interface(CONST_INTER);
 %}

-// Long Immediate: low 32-bit mask
-operand immL_32bits()
+// 26 bit signed offset -- for pc-relative branches
+operand immI26()
 %{
-  predicate(n->get_long() == 0xFFFFFFFFL);
-  match(ConL);
-  op_cost(0);
+  predicate(((-(1 << 25)) <= n->get_int()) && (n->get_int() < (1 << 25)));
+  match(ConI);
+
   format %{ %}
   interface(CONST_INTER);
 %}

-// Pointer operands
-// Pointer Immediate
-operand immP()
+// 19 bit signed offset -- for pc-relative loads
+operand immI19()
 %{
-  match(ConP);
+  predicate(((-(1 << 18)) <= n->get_int()) && (n->get_int() < (1 << 18)));
+  match(ConI);

-  op_cost(10);
   format %{ %}
   interface(CONST_INTER);
 %}

-// NULL Pointer Immediate
-operand immP0()
+// 12 bit unsigned offset -- for base plus immediate loads
+operand immIU12()
 %{
-  predicate(n->get_ptr() == 0);
-  match(ConP);
+  predicate((0 <= n->get_int()) && (n->get_int() < (1 << 12)));
+  match(ConI);

-  op_cost(5);
   format %{ %}
   interface(CONST_INTER);
 %}

-// Pointer Immediate One
-// this is used in object initialization (initial object header)
-operand immP_1()
+// Valid 9 bit unsigned offset
+operand immI9()
+%{
+  predicate(((-(1 << 8)) <= n->get_int()) && (n->get_int() < (1 << 8)));
+  match(ConI);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 32 bit integer valid for add sub immediate
+operand immIAddSub()
+%{
+  predicate(Assembler::operand_valid_for_add_sub_immediate((long)n->get_int()));
+  match(ConI);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 32 bit unsigned integer valid for logical immediate
+// TODO -- check this is right when e.g the mask is 0x80000000
+operand immILog()
+%{
+  predicate(Assembler::operand_valid_for_logical_immediate(true, (unsigned long)n->get_int()));
+  match(ConI);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Integer operands 64 bit
+// 64 bit immediate
+operand immL()
+%{
+  match(ConL);
+
+  op_cost(20);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 64 bit zero
+operand immL0()
+%{
+  predicate(n->get_long() == 0);
+  match(ConL);
+
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 64 bit unit increment
+operand immL_1()
+%{
+  predicate(n->get_long() == 1);
+  match(ConL);
+
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 64 bit unit decrement
+operand immL_M1()
+%{
+  predicate(n->get_long() == -1);
+  match(ConL);
+
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 32 bit offset of pc in thread anchor
+
+operand immL_pc_off()
+%{
+  predicate(n->get_long() == in_bytes(JavaThread::frame_anchor_offset()) +
+                             in_bytes(JavaFrameAnchor::last_Java_pc_offset()));
+  match(ConL);
+
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 64 bit integer valid for add sub immediate
+operand immLAddSub()
+%{
+  predicate(Assembler::operand_valid_for_add_sub_immediate(n->get_long()));
+  match(ConL);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// 64 bit integer valid for logical immediate
+operand immLLog()
+%{
+  predicate(Assembler::operand_valid_for_logical_immediate(true, (unsigned long)n->get_long()));
+  match(ConL);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Long Immediate: low 32-bit mask
+operand immL_32bits()
+%{
+  predicate(n->get_long() == 0xFFFFFFFFL);
+  match(ConL);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Pointer operands
+// Pointer Immediate
+operand immP()
+%{
+  match(ConP);
+
+  op_cost(10);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// NULL Pointer Immediate
+operand immP0()
+%{
+  predicate(n->get_ptr() == 0);
+  match(ConP);
+
+  op_cost(5);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Pointer Immediate One
+// this is used in object initialization (initial object header)
+operand immP_1()
 %{
   predicate(n->get_ptr() == 1);
   match(ConP);
@@ -4279,15 +4110,11 @@
   %}
 %}

-// TODO this is the pattern used by x86/ppc but for aarch64 extended
-// reg we probably want to match (LShiftI ireg scale) need to see if
-// the ideal code will ever generate an LShiftI
-
 operand indIndexScaledOffsetI(iRegP reg, iRegL lreg, immIScale scale, immIAddSub off)
 %{
   constraint(ALLOC_IN_RC(ptr_reg));
   match(AddP (AddP reg (LShiftL lreg scale)) off);
-  op_cost(DEFAULT_COST_LOW);
+  op_cost(DEFAULT_COST);
   format %{ "$reg, $lreg lsl($scale), $off" %}
   interface(MEMORY_INTER) %{
     base($reg);
@@ -4301,7 +4128,7 @@
 %{
   constraint(ALLOC_IN_RC(ptr_reg));
   match(AddP (AddP reg (LShiftL lreg scale)) off);
-  op_cost(DEFAULT_COST_LOW);
+  op_cost(DEFAULT_COST);
   format %{ "$reg, $lreg lsl($scale), $off" %}
   interface(MEMORY_INTER) %{
     base($reg);
@@ -4311,6 +4138,34 @@
   %}
 %}

+operand indIndexScaledOffsetI2L(iRegP reg, iRegI ireg, immIScale scale, immLAddSub off)
+%{
+  constraint(ALLOC_IN_RC(ptr_reg));
+  match(AddP (AddP reg (LShiftL (ConvI2L ireg) scale)) off);
+  op_cost(DEFAULT_COST);
+  format %{ "$reg, $ireg sxtw($scale), $off I2L" %}
+  interface(MEMORY_INTER) %{
+    base($reg);
+    index($ireg);
+    scale($scale);
+    disp($off);
+  %}
+%}
+
+operand indIndexScaledI2L(iRegP reg, iRegI ireg, immIScale scale)
+%{
+  constraint(ALLOC_IN_RC(ptr_reg));
+  match(AddP reg (LShiftL (ConvI2L ireg) scale));
+  op_cost(0);
+  format %{ "$reg, $ireg sxtw($scale), 0, I2L" %}
+  interface(MEMORY_INTER) %{
+    base($reg);
+    index($ireg);
+    scale($scale);
+    disp(0x0);
+  %}
+%}
+
 operand indIndexScaled(iRegP reg, iRegL lreg, immIScale scale)
 %{
   constraint(ALLOC_IN_RC(ptr_reg));
@@ -4329,7 +4184,7 @@
 %{
   constraint(ALLOC_IN_RC(ptr_reg));
   match(AddP reg lreg);
-  op_cost(40);
+  op_cost(0);
   format %{ "$reg, $lreg" %}
   interface(MEMORY_INTER) %{
     base($reg);
@@ -4530,7 +4385,7 @@
 // memory is used to define read/write location for load/store
 // instruction defs. we can turn a memory op into an Address

-opclass memory(indirect, indIndexScaledOffsetI,  indIndexScaledOffsetL, indIndexScaled, indIndex, indOffI, indOffL);
+opclass memory(indirect, indIndexScaledOffsetI,  indIndexScaledOffsetL, indIndexScaledOffsetI2L, indIndexScaled, indIndexScaledI2L, indIndex, indOffI, indOffL);

 // iRegIorL2I is used for src inputs in rules for 32 bit int (I)
 // operations. it allows the src to be either an iRegI or a (ConvL2I
@@ -4702,7 +4557,7 @@
   ins_cost(MEMORY_REF_COST);
   format %{ "ldrbw  $dst, $mem\t# byte" %}

-  ins_encode(aarch64_enc_ldrbw(dst, mem));
+  ins_encode(aarch64_enc_ldrb(dst, mem));

   ins_pipe(pipe_class_memory);
 %}
@@ -4756,9 +4611,9 @@
   predicate(!((MemNode*)n)->is_volatile());

   ins_cost(MEMORY_REF_COST);
-  format %{ "ldrhw  $dst, $mem\t# short" %}
+  format %{ "ldrh  $dst, $mem\t# short" %}

-  ins_encode(aarch64_enc_ldrhw(dst, mem));
+  ins_encode(aarch64_enc_ldrh(dst, mem));

   ins_pipe(pipe_class_memory);
 %}
@@ -5916,6 +5771,7 @@
 instruct castX2P(iRegPNoSp dst, iRegL src) %{
   match(Set dst (CastX2P src));

+  ins_cost(DEFAULT_COST);
   format %{ "mov $dst, $src\t# long -> ptr" %}

   ins_encode %{
@@ -5930,6 +5786,7 @@
 instruct castP2X(iRegLNoSp dst, iRegP src) %{
   match(Set dst (CastP2X src));

+  ins_cost(DEFAULT_COST);
   format %{ "mov $dst, $src\t# ptr -> long" %}

   ins_encode %{
@@ -5945,6 +5802,7 @@
 instruct convP2I(iRegINoSp dst, iRegP src) %{
   match(Set dst (ConvL2I (CastP2X src)));

+  ins_cost(DEFAULT_COST);
   format %{ "movw $dst, $src\t# ptr -> int" %}
   ins_encode %{
     __ movw($dst$$Register, $src$$Register);
@@ -5960,6 +5818,7 @@
   predicate(Universe::narrow_oop_shift() == 0);
   match(Set dst (ConvL2I (CastP2X (DecodeN src))));

+  ins_cost(DEFAULT_COST);
   format %{ "mov dst, $src\t# compressed ptr -> int" %}
   ins_encode %{
     __ movw($dst$$Register, $src$$Register);
@@ -5973,6 +5832,7 @@
 instruct encodeHeapOop(iRegNNoSp dst, iRegP src, rFlagsReg cr) %{
   predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
   match(Set dst (EncodeP src));
+  ins_cost(DEFAULT_COST * 3);
   effect(KILL cr);
   format %{ "encode_heap_oop $dst, $src" %}
   ins_encode %{
@@ -5990,6 +5850,7 @@
   predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull);
   match(Set dst (EncodeP src));
   effect(KILL cr);
+  ins_cost(DEFAULT_COST * 3);
   format %{ "encode_heap_oop_not_null $dst, $src" %}
   ins_encode %{
     __ encode_heap_oop_not_null($dst$$Register, $src$$Register);
@@ -6002,6 +5863,7 @@
             n->bottom_type()->is_ptr()->ptr() != TypePtr::Constant);
   match(Set dst (DecodeN src));
   effect(KILL cr);
+  ins_cost(DEFAULT_COST * 3);
   format %{ "decode_heap_oop $dst, $src" %}
   ins_encode %{
     Register s = $src$$Register;
@@ -6021,6 +5883,7 @@
             n->bottom_type()->is_ptr()->ptr() == TypePtr::Constant);
   match(Set dst (DecodeN src));
   effect(KILL cr);
+  ins_cost(DEFAULT_COST * 3);
   format %{ "decode_heap_oop_not_null $dst, $src" %}
   ins_encode %{
     Register s = $src$$Register;
@@ -6041,6 +5904,7 @@
 instruct encodeKlass_not_null(iRegNNoSp dst, iRegP src) %{
   match(Set dst (EncodePKlass src));

+  ins_cost(DEFAULT_COST * 3);
   format %{ "encode_klass_not_null $dst,$src" %}

   ins_encode %{
@@ -6055,6 +5919,7 @@
 instruct decodeKlass_not_null(iRegPNoSp dst, iRegN src) %{
   match(Set dst (DecodeNKlass src));

+  ins_cost(DEFAULT_COST * 3);
   format %{ "decode_klass_not_null $dst,$src" %}

   ins_encode %{
@@ -6298,1110 +6163,2650 @@
 // which throws a ShouldNotHappen. So, we have to provide two flavours
 // of each rule, one for a cmpOp and a second for a cmpOpU (sigh).

-instruct cmovI_reg_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegI src1, iRegI src2) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 src2)));
+instruct cmovI_reg_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegI src1, iRegI src2) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, $src1 $cmp\t# signed, int"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUI_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegI src1, iRegI src2) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, $src1 $cmp\t# unsigned, int"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// special cases where one arg is zero
+
+// n.b. this is selected in preference to the rule above because it
+// avoids loading constant 0 into a source register
+
+// TODO
+// we ought only to be able to cull one of these variants as the ideal
+// transforms ought always to order the zero consistently (to left/right?)
+
+instruct cmovI_zero_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, immI0 zero, iRegI src2) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, zr $cmp\t# signed, int"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             zr,
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUI_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, immI0 zero, iRegI src2) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, zr $cmp\t# unsigned, int"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             zr,
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovI_reg_zero(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegI src1, immI0 zero) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, zr, $src1 $cmp\t# signed, int"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             zr,
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUI_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegI src1, immI0 zero) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, zr, $src1 $cmp\t# unsigned, int"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             zr,
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// special case for creating a boolean 0 or 1
+
+// n.b. this is selected in preference to the rule above because it
+// avoids loading constants 0 and 1 into a source register
+
+instruct cmovI_reg_zero_one(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, immI0 zero, immI_1 one) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary one zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csincw $dst, zr, zr $cmp\t# signed, int"  %}
+
+  ins_encode %{
+    // equivalently
+    // cset(as_Register($dst$$reg),
+    //      negate_condition((Assembler::Condition)$cmp$$cmpcode));
+    __ csincw(as_Register($dst$$reg),
+	     zr,
+	     zr,
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUI_reg_zero_one(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, immI0 zero, immI_1 one) %{
+  match(Set dst (CMoveI (Binary cmp cr) (Binary one zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csincw $dst, zr, zr $cmp\t# unsigned, int"  %}
+
+  ins_encode %{
+    // equivalently
+    // cset(as_Register($dst$$reg),
+    //      negate_condition((Assembler::Condition)$cmp$$cmpcode));
+    __ csincw(as_Register($dst$$reg),
+	     zr,
+	     zr,
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovL_reg_reg(cmpOp cmp, rFlagsReg cr, iRegLNoSp dst, iRegL src1, iRegL src2) %{
+  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, $src1 $cmp\t# signed, long"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUL_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegLNoSp dst, iRegL src1, iRegL src2) %{
+  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, $src1 $cmp\t# unsigned, long"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// special cases where one arg is zero
+
+instruct cmovL_reg_zero(cmpOp cmp, rFlagsReg cr, iRegLNoSp dst, iRegL src1, immL0 zero) %{
+  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, zr, $src1 $cmp\t# signed, long"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            zr,
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUL_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegLNoSp dst, iRegL src1, immL0 zero) %{
+  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, zr, $src1 $cmp\t# unsigned, long"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            zr,
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovL_zero_reg(cmpOp cmp, rFlagsReg cr, iRegLNoSp dst, immL0 zero, iRegL src2) %{
+  match(Set dst (CMoveL (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, zr $cmp\t# signed, long"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            zr,
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUL_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegLNoSp dst, immL0 zero, iRegL src2) %{
+  match(Set dst (CMoveL (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, zr $cmp\t# unsigned, long"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            zr,
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovP_reg_reg(cmpOp cmp, rFlagsReg cr, iRegPNoSp dst, iRegP src1, iRegP src2) %{
+  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, $src1 $cmp\t# signed, ptr"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUP_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegPNoSp dst, iRegP src1, iRegP src2) %{
+  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, $src1 $cmp\t# unsigned, ptr"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// special cases where one arg is zero
+
+instruct cmovP_reg_zero(cmpOp cmp, rFlagsReg cr, iRegPNoSp dst, iRegP src1, immP0 zero) %{
+  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, zr, $src1 $cmp\t# signed, ptr"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            zr,
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUP_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegPNoSp dst, iRegP src1, immP0 zero) %{
+  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, zr, $src1 $cmp\t# unsigned, ptr"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            zr,
+            as_Register($src1$$reg),
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovP_zero_reg(cmpOp cmp, rFlagsReg cr, iRegPNoSp dst, immP0 zero, iRegP src2) %{
+  match(Set dst (CMoveP (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, zr $cmp\t# signed, ptr"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            zr,
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUP_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegPNoSp dst, immP0 zero, iRegP src2) %{
+  match(Set dst (CMoveP (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "csel $dst, $src2, zr $cmp\t# unsigned, ptr"  %}
+
+  ins_encode %{
+    __ csel(as_Register($dst$$reg),
+            as_Register($src2$$reg),
+            zr,
+            (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovN_reg_reg(cmpOp cmp, rFlagsReg cr, iRegN dst, iRegN src1, iRegN src2) %{
+  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, $src1 $cmp\t# signed, compressed ptr"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUN_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegN dst, iRegN src1, iRegN src2) %{
+  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, $src1 $cmp\t# signed, compressed ptr"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// special cases where one arg is zero
+
+instruct cmovN_reg_zero(cmpOp cmp, rFlagsReg cr, iRegN dst, iRegN src1, immN0 zero) %{
+  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, zr, $src1 $cmp\t# signed, compressed ptr"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             zr,
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUN_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegN dst, iRegN src1, immN0 zero) %{
+  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 zero)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, zr, $src1 $cmp\t# unsigned, compressed ptr"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             zr,
+             as_Register($src1$$reg),
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovN_zero_reg(cmpOp cmp, rFlagsReg cr, iRegN dst, immN0 zero, iRegN src2) %{
+  match(Set dst (CMoveN (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, zr $cmp\t# signed, compressed ptr"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             zr,
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovUN_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegN dst, immN0 zero, iRegN src2) %{
+  match(Set dst (CMoveN (Binary cmp cr) (Binary zero src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "cselw $dst, $src2, zr $cmp\t# unsigned, compressed ptr"  %}
+
+  ins_encode %{
+    __ cselw(as_Register($dst$$reg),
+             as_Register($src2$$reg),
+             zr,
+             (Assembler::Condition)$cmp$$cmpcode);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovF_reg(cmpOp cmp, rFlagsReg cr, vRegF dst, vRegF src1,  vRegF src2)
+%{
+  match(Set dst (CMoveF (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+
+  format %{ "fcsels $dst, $src1, $src2, $cmp\t# signed cmove float\n\t" %}
+  ins_encode %{
+    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+    __ fcsels(as_FloatRegister($dst$$reg),
+              as_FloatRegister($src2$$reg),
+              as_FloatRegister($src1$$reg),
+              cond);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovF_regU(cmpOpU cmp, rFlagsRegU cr, vRegF dst, vRegF src1,  vRegF src2)
+%{
+  match(Set dst (CMoveF (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+
+  format %{ "fcsels $dst, $src1, $src2, $cmp\t# unsigned cmove float\n\t" %}
+  ins_encode %{
+    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+    __ fcsels(as_FloatRegister($dst$$reg),
+              as_FloatRegister($src2$$reg),
+              as_FloatRegister($src1$$reg),
+              cond);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovD_reg(cmpOp cmp, rFlagsReg cr, vRegD dst, vRegD src1,  vRegD src2)
+%{
+  match(Set dst (CMoveD (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+
+  format %{ "fcseld $dst, $src1, $src2, $cmp\t# signed cmove float\n\t" %}
+  ins_encode %{
+    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+    __ fcseld(as_FloatRegister($dst$$reg),
+              as_FloatRegister($src2$$reg),
+              as_FloatRegister($src1$$reg),
+              cond);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmovD_regU(cmpOpU cmp, rFlagsRegU cr, vRegD dst, vRegD src1,  vRegD src2)
+%{
+  match(Set dst (CMoveD (Binary cmp cr) (Binary src1 src2)));
+
+  ins_cost(DEFAULT_COST);
+
+  format %{ "fcseld $dst, $src1, $src2, $cmp\t# unsigned cmove float\n\t" %}
+  ins_encode %{
+    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+    __ fcseld(as_FloatRegister($dst$$reg),
+              as_FloatRegister($src2$$reg),
+              as_FloatRegister($src1$$reg),
+              cond);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// ============================================================================
+// Arithmetic Instructions
+//
+// TODO
+// these currently employ operations which do not set CR and hence are
+// not flagged as killing CR but we would like to isolate the cases
+// where we want to set flags from those where we don't. need to work
+// out how to do that.
+
+// Integer Addition
+
+instruct addI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (AddI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "addw  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ addw(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct addI_reg_imm(iRegINoSp dst, iRegI src1, immIAddSub src2) %{
+  match(Set dst (AddI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "addw $dst, $src1, $src2" %}
+
+  // use opcode to indicate that this is an add not a sub
+  opcode(0x0);
+
+  ins_encode(aarch64_enc_addsubw_imm(dst, src1, src2));
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct addI_reg_imm_i2l(iRegINoSp dst, iRegL src1, immIAddSub src2) %{
+  match(Set dst (AddI (ConvL2I src1) src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "addw $dst, $src1, $src2" %}
+
+  // use opcode to indicate that this is an add not a sub
+  opcode(0x0);
+
+  ins_encode(aarch64_enc_addsubw_imm(dst, src1, src2));
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Pointer Addition
+instruct addP_reg_reg(iRegPNoSp dst, iRegP src1, iRegL src2) %{
+  match(Set dst (AddP src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "add $dst, $src1, $src2\t# ptr" %}
+
+  ins_encode %{
+    __ add(as_Register($dst$$reg),
+           as_Register($src1$$reg),
+           as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct addP_reg_reg_ext(iRegPNoSp dst, iRegP src1, iRegI src2) %{
+  match(Set dst (AddP src1 (ConvI2L src2)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "add $dst, $src1, $src2\t# ptr" %}
+
+  ins_encode %{
+    __ add(as_Register($dst$$reg),
+           as_Register($src1$$reg),
+           as_Register($src2$$reg), ext::sxtw);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct addP_reg_reg_lsl(iRegPNoSp dst, iRegP src1, iRegL src2, immIScale scale) %{
+  match(Set dst (AddP src1 (LShiftL src2 scale)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "add $dst, $src1, $src2, LShiftL $scale\t# ptr" %}
+
+  ins_encode %{
+    __ lea(as_Register($dst$$reg),
+	   Address(as_Register($src1$$reg), as_Register($src2$$reg),
+		   Address::lsl($scale$$constant)));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct addP_reg_reg_ext_shift(iRegPNoSp dst, iRegP src1, iRegI src2, immIScale scale) %{
+  match(Set dst (AddP src1 (LShiftL (ConvI2L src2) scale)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "add $dst, $src1, $src2, I2L $scale\t# ptr" %}
+
+  ins_encode %{
+    __ lea(as_Register($dst$$reg),
+	   Address(as_Register($src1$$reg), as_Register($src2$$reg),
+		   Address::sxtw($scale$$constant)));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Pointer Immediate Addition
+// n.b. this needs to be more expensive than using an indirect memory
+// operand
+instruct addP_reg_imm(iRegPNoSp dst, iRegP src1, immLAddSub src2) %{
+  match(Set dst (AddP src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "add $dst, $src1, $src2\t# ptr" %}
+
+  // use opcode to indicate that this is an add not a sub
+  opcode(0x0);
+
+  ins_encode( aarch64_enc_addsub_imm(dst, src1, src2) );
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Long Addition
+instruct addL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
+
+  match(Set dst (AddL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ add(as_Register($dst$$reg),
+           as_Register($src1$$reg),
+           as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// No constant pool entries requiredLong Immediate Addition.
+instruct addL_reg_imm(iRegLNoSp dst, iRegL src1, immLAddSub src2) %{
+  match(Set dst (AddL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "add $dst, $src1, $src2" %}
+
+  // use opcode to indicate that this is an add not a sub
+  opcode(0x0);
+
+  ins_encode( aarch64_enc_addsub_imm(dst, src1, src2) );
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Integer Subtraction
+instruct subI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (SubI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "subw  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ subw(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Immediate Subtraction
+instruct subI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immIAddSub src2) %{
+  match(Set dst (SubI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "subw $dst, $src1, $src2" %}
+
+  // use opcode to indicate that this is a sub not an add
+  opcode(0x1);
+
+  ins_encode(aarch64_enc_addsubw_imm(dst, src1, src2));
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Long Subtraction
+instruct subL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
+
+  match(Set dst (SubL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "sub  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ sub(as_Register($dst$$reg),
+           as_Register($src1$$reg),
+           as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// No constant pool entries requiredLong Immediate Subtraction.
+instruct subL_reg_imm(iRegLNoSp dst, iRegL src1, immLAddSub src2) %{
+  match(Set dst (SubL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "sub$dst, $src1, $src2" %}
+
+  // use opcode to indicate that this is a sub not an add
+  opcode(0x1);
+
+  ins_encode( aarch64_enc_addsub_imm(dst, src1, src2) );
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Integer Negation (special case for sub)
+
+instruct negI_reg(iRegINoSp dst, iRegIorL2I src, immI0 zero, rFlagsReg cr) %{
+  match(Set dst (SubI zero src));
+
+  effect(KILL cr);
+
+  ins_cost(DEFAULT_COST);
+  format %{ "negsw $dst, $src\t# int" %}
+
+  ins_encode %{
+    __ negsw(as_Register($dst$$reg),
+             as_Register($src$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Long Negation
+
+instruct negL_reg(iRegLNoSp dst, iRegIorL2I src, immL0 zero, rFlagsReg cr) %{
+  match(Set dst (SubL zero src));
+
+  effect(KILL cr);
+
+  ins_cost(DEFAULT_COST);
+  format %{ "negs $dst, $src\t# long" %}
+
+  ins_encode %{
+    __ negs(as_Register($dst$$reg),
+            as_Register($src$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Integer Multiply
+
+instruct mulI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (MulI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "mulw  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ mulw(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Long Multiply
+
+instruct mulL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
+  match(Set dst (MulL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "mul  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ mul(as_Register($dst$$reg),
+           as_Register($src1$$reg),
+           as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Combined Integer Multiply & Add/Sub
+
+instruct maddI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, iRegIorL2I src3) %{
+  match(Set dst (AddI (MulI src1 src2) src3));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "madd  $dst, $src1, $src2, $src3" %}
+
+  ins_encode %{
+    __ maddw(as_Register($dst$$reg),
+             as_Register($src1$$reg),
+             as_Register($src2$$reg),
+             as_Register($src3$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct msubI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, iRegIorL2I src3) %{
+  match(Set dst (SubI (MulI src1 src2) src3));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "msub  $dst, $src1, $src2, $src3" %}
+
+  ins_encode %{
+    __ msubw(as_Register($dst$$reg),
+             as_Register($src1$$reg),
+             as_Register($src2$$reg),
+             as_Register($src3$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Combined Long Multiply & Add/Sub
+
+instruct maddL(iRegLNoSp dst, iRegL src1, iRegL src2, iRegL src3) %{
+  match(Set dst (AddL (MulL src1 src2) src3));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "madd  $dst, $src1, $src2, $src3" %}
+
+  ins_encode %{
+    __ madd(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg),
+            as_Register($src3$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct msubL(iRegLNoSp dst, iRegL src1, iRegL src2, iRegL src3) %{
+  match(Set dst (SubL (MulL src1 src2) src3));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "msub  $dst, $src1, $src2, $src3" %}
+
+  ins_encode %{
+    __ msub(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg),
+            as_Register($src3$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Integer Divide
+
+instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (DivI src1 src2));
+
+  ins_cost(10*DEFAULT_COST);
+  format %{ "cmpw   $src1, #0x80000000\t# idiv\n\t"
+            "bne    normal\n\t"
+            "cmnw   $src2, #1\n\t"
+            "beq    normal\n\t"
+            "movw   $dst, $src1\n\t"
+            "b      done\n"
+    "normal: sdivw  $dst, $src1, $src2\n"
+    "done:" %}
+
+  ins_encode(aarch64_enc_divw(dst, src1, src2));
+  ins_pipe(pipe_class_default);
+%}
+
+// Long Divide
+
+instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
+  match(Set dst (DivL src1 src2));
+
+  ins_cost(10*DEFAULT_COST);
+  format %{ "cmp    $src1, #0x8000000000000000\t# ldiv\n\t"
+            "bne    normal\n\t"
+            "cmn    $src2, #1\n\t"
+            "beq    normal\n\t"
+            "mov    $dst, $src1\n\t"
+            "b      done\n"
+    "normal: sdiv   $dst, $src1, $src2\n"
+    "done:" %}
+
+  ins_encode(aarch64_enc_div(dst, src1, src2));
+  ins_pipe(pipe_class_default);
+%}
+
+// Integer Remainder
+
+instruct modI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (ModI src1 src2));
+
+  format %{ "cmpw   $src1, #0x80000000\t# imod\n\t"
+            "bne    normal\n\t"
+            "cmnw   $src2, #1\n\t"
+            "beq    normal\n\t"
+            "movw   $dst, zr\n\t"
+            "b      done\n"
+    "normal: sdivw  rscratch1, $src1, $src2\n\t"
+            "msubw($dst, rscratch1, $src2, $src1"
+    "done:" %}
+
+  ins_encode(aarch64_enc_modw(dst, src1, src2));
+  ins_pipe(pipe_class_default);
+%}
+
+// Long Remainder
+
+instruct modL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
+  match(Set dst (ModL src1 src2));
+
+  ins_cost(10*DEFAULT_COST);
+  format %{ "cmp    $src1, #0x8000000000000000\t# lmod\n\t"
+            "bne    normal\n\t"
+            "cmn    $src2, #1\n\t"
+            "beq    normal\n\t"
+            "mov    $dst, zr\n\t"
+            "b      done\n"
+    "normal: sdiv   rscratch1, $src1, $src2\n"
+            "msub($dst, rscratch1, $src2, $src1"
+    "done:" %}
+
+  ins_encode(aarch64_enc_mod(dst, src1, src2));
+  ins_pipe(pipe_class_default);
+%}
+
+// Integer Shifts
+
+// Shift Left Register
+instruct lShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (LShiftI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "lslvw  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ lslvw(as_Register($dst$$reg),
+             as_Register($src1$$reg),
+             as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Left Immediate
+instruct lShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
+  match(Set dst (LShiftI src1 src2));
+
+  format %{ "lslw $dst, $src1, ($src2 & 0x1f)" %}
+
+  ins_encode %{
+    __ lslw(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            $src2$$constant & 0x1f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Logical Register
+instruct urShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (URShiftI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "lsrvw  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ lsrvw(as_Register($dst$$reg),
+             as_Register($src1$$reg),
+             as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Logical Immediate
+instruct urShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
+  match(Set dst (URShiftI src1 src2));
+
+  format %{ "lsrw $dst, $src1, ($src2 & 0x1f)" %}
+
+  ins_encode %{
+    __ lsrw(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            $src2$$constant & 0x1f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Arithmetic Register
+instruct rShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
+  match(Set dst (RShiftI src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "asrvw  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ asrvw(as_Register($dst$$reg),
+             as_Register($src1$$reg),
+             as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Arithmetic Immediate
+instruct rShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
+  match(Set dst (RShiftI src1 src2));
+
+  format %{ "asrw $dst, $src1, ($src2 & 0x1f)" %}
+
+  ins_encode %{
+    __ asrw(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            $src2$$constant & 0x1f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Combined Int Mask and Right Shift (using UBFM)
+// TODO
+
+// Long Shifts
+
+// Shift Left Register
+instruct lShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
+  match(Set dst (LShiftL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "lslv  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ lslv(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Left Immediate
+instruct lShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
+  match(Set dst (LShiftL src1 src2));
+
+  format %{ "lsl $dst, $src1, ($src2 & 0x3f)" %}
+
+  ins_encode %{
+    __ lsl(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            $src2$$constant & 0x3f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Logical Register
+instruct urShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
+  match(Set dst (URShiftL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "lsrv  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ lsrv(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Logical Immediate
+instruct urShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
+  match(Set dst (URShiftL src1 src2));
+
+  format %{ "lsr $dst, $src1, ($src2 & 0x3f)" %}
+
+  ins_encode %{
+    __ lsr(as_Register($dst$$reg),
+           as_Register($src1$$reg),
+           $src2$$constant & 0x3f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Arithmetic Register
+instruct rShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
+  match(Set dst (RShiftL src1 src2));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "asrv  $dst, $src1, $src2" %}
+
+  ins_encode %{
+    __ asrv(as_Register($dst$$reg),
+            as_Register($src1$$reg),
+            as_Register($src2$$reg));
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Right Arithmetic Immediate
+instruct rShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
+  match(Set dst (RShiftL src1 src2));
+
+  format %{ "asr $dst, $src1, ($src2 & 0x3f)" %}
+
+  ins_encode %{
+    __ asr(as_Register($dst$$reg),
+           as_Register($src1$$reg),
+           $src2$$constant & 0x3f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+// BEGIN This section of the file is automatically generated. Do not edit --------------
+
+
+
+
+
+
+

+
+instruct regL_not_reg(iRegLNoSp dst,
+                         iRegL src1, immL_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (XorL src1 m1));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, $src1 $cmp\t# signed, int"  %}
+  format %{ "eon  $dst, $src1, zr" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ eon(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              zr,
+              Assembler::LSL, 0);
   %}

   ins_pipe(pipe_class_default);
 %}
-
-instruct cmovUI_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegI src1, iRegI src2) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 src2)));
-
+instruct regI_not_reg(iRegINoSp dst,
+                         iRegI src1, immI_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (XorI src1 m1));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, $src1 $cmp\t# unsigned, int"  %}
+  format %{ "eonw  $dst, $src1, zr" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ eonw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              zr,
+              Assembler::LSL, 0);
   %}

   ins_pipe(pipe_class_default);
 %}

-// special cases where one arg is zero
-
-// n.b. this is selected in preference to the rule above because it
-// avoids loading constant 0 into a source register
+instruct AndI_reg_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2, immI_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (AndI src1 (XorI src2 m1)));
+  ins_cost(DEFAULT_COST);
+  format %{ "bic  $dst, $src1, $src2" %}

-// TODO
-// we ought only to be able to cull one of these variants as the ideal
-// transforms ought always to order the zero consistently (to left/right?)
+  ins_encode %{
+    __ bic(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL, 0);
+  %}

-instruct cmovI_zero_reg(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, immI0 zero, iRegI src2) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary zero src2)));
+  ins_pipe(pipe_class_default);
+%}

+instruct AndL_reg_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2, immL_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (AndL src1 (XorL src2 m1)));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, zr $cmp\t# signed, int"  %}
+  format %{ "bic  $dst, $src1, $src2" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             zr,
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ bic(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL, 0);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUI_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, immI0 zero, iRegI src2) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary zero src2)));
-
+instruct OrI_reg_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2, immI_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (OrI src1 (XorI src2 m1)));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, zr $cmp\t# unsigned, int"  %}
+  format %{ "orn  $dst, $src1, $src2" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             zr,
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ orn(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL, 0);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovI_reg_zero(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, iRegI src1, immI0 zero) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 zero)));
-
+instruct OrL_reg_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2, immL_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (OrL src1 (XorL src2 m1)));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, zr, $src1 $cmp\t# signed, int"  %}
+  format %{ "orn  $dst, $src1, $src2" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             zr,
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ orn(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL, 0);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUI_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, iRegI src1, immI0 zero) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary src1 zero)));
-
+instruct XorI_reg_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2, immI_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (XorI m1 (XorI src2 src1)));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, zr, $src1 $cmp\t# unsigned, int"  %}
+  format %{ "eon  $dst, $src1, $src2" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             zr,
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ eon(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL, 0);
   %}

   ins_pipe(pipe_class_default);
 %}

-// special case for creating a boolean 0 or 1
+instruct XorL_reg_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2, immL_M1 m1,
+                         rFlagsReg cr) %{
+  match(Set dst (XorL m1 (XorL src2 src1)));
+  ins_cost(DEFAULT_COST);
+  format %{ "eon  $dst, $src1, $src2" %}

-// n.b. this is selected in preference to the rule above because it
-// avoids loading constants 0 and 1 into a source register
+  ins_encode %{
+    __ eon(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL, 0);
+  %}

-instruct cmovI_reg_zero_one(cmpOp cmp, rFlagsReg cr, iRegINoSp dst, immI0 zero, immI_1 one) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary one zero)));
+  ins_pipe(pipe_class_default);
+%}

+instruct AndI_reg_URShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (AndI src1 (XorI(URShiftI src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csincw $dst, zr, zr $cmp\t# signed, int"  %}
+  format %{ "bicw  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    // equivalently
-    // cset(as_Register($dst$$reg),
-    //      negate_condition((Assembler::Condition)$cmp$$cmpcode));
-    __ csincw(as_Register($dst$$reg),
-	     zr,
-	     zr,
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ bicw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUI_reg_zero_one(cmpOpU cmp, rFlagsRegU cr, iRegINoSp dst, immI0 zero, immI_1 one) %{
-  match(Set dst (CMoveI (Binary cmp cr) (Binary one zero)));
-
+instruct AndL_reg_URShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (AndL src1 (XorL(URShiftL src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csincw $dst, zr, zr $cmp\t# unsigned, int"  %}
+  format %{ "bic  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    // equivalently
-    // cset(as_Register($dst$$reg),
-    //      negate_condition((Assembler::Condition)$cmp$$cmpcode));
-    __ csincw(as_Register($dst$$reg),
-	     zr,
-	     zr,
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ bic(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovL_reg_reg(cmpOp cmp, rFlagsReg cr, iRegLNoSp dst, iRegL src1, iRegL src2) %{
-  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 src2)));
-
+instruct AndI_reg_RShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (AndI src1 (XorI(RShiftI src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, $src1 $cmp\t# signed, long"  %}
+  format %{ "bicw  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ bicw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUL_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegLNoSp dst, iRegL src1, iRegL src2) %{
-  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 src2)));
-
+instruct AndL_reg_RShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (AndL src1 (XorL(RShiftL src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, $src1 $cmp\t# unsigned, long"  %}
+  format %{ "bic  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ bic(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// special cases where one arg is zero
-
-instruct cmovL_reg_zero(cmpOp cmp, rFlagsReg cr, iRegLNoSp dst, iRegL src1, immL0 zero) %{
-  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 zero)));
-
+instruct AndI_reg_LShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (AndI src1 (XorI(LShiftI src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, zr, $src1 $cmp\t# signed, long"  %}
+  format %{ "bicw  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            zr,
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ bicw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUL_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegLNoSp dst, iRegL src1, immL0 zero) %{
-  match(Set dst (CMoveL (Binary cmp cr) (Binary src1 zero)));
-
+instruct AndL_reg_LShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (AndL src1 (XorL(LShiftL src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, zr, $src1 $cmp\t# unsigned, long"  %}
+  format %{ "bic  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            zr,
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ bic(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovL_zero_reg(cmpOp cmp, rFlagsReg cr, iRegLNoSp dst, immL0 zero, iRegL src2) %{
-  match(Set dst (CMoveL (Binary cmp cr) (Binary zero src2)));
-
+instruct XorI_reg_URShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (XorI src4 (XorI(URShiftI src2 src3) src1)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, zr $cmp\t# signed, long"  %}
+  format %{ "eonw  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            zr,
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ eonw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUL_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegLNoSp dst, immL0 zero, iRegL src2) %{
-  match(Set dst (CMoveL (Binary cmp cr) (Binary zero src2)));
-
+instruct XorL_reg_URShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (XorL src4 (XorL(URShiftL src2 src3) src1)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, zr $cmp\t# unsigned, long"  %}
+  format %{ "eon  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            zr,
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ eon(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovP_reg_reg(cmpOp cmp, rFlagsReg cr, iRegPNoSp dst, iRegP src1, iRegP src2) %{
-  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 src2)));
-
+instruct XorI_reg_RShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (XorI src4 (XorI(RShiftI src2 src3) src1)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, $src1 $cmp\t# signed, ptr"  %}
+  format %{ "eonw  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ eonw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUP_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegPNoSp dst, iRegP src1, iRegP src2) %{
-  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 src2)));
-
+instruct XorL_reg_RShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (XorL src4 (XorL(RShiftL src2 src3) src1)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, $src1 $cmp\t# unsigned, ptr"  %}
+  format %{ "eon  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ eon(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// special cases where one arg is zero
-
-instruct cmovP_reg_zero(cmpOp cmp, rFlagsReg cr, iRegPNoSp dst, iRegP src1, immP0 zero) %{
-  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 zero)));
-
+instruct XorI_reg_LShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (XorI src4 (XorI(LShiftI src2 src3) src1)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, zr, $src1 $cmp\t# signed, ptr"  %}
+  format %{ "eonw  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            zr,
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ eonw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUP_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegPNoSp dst, iRegP src1, immP0 zero) %{
-  match(Set dst (CMoveP (Binary cmp cr) (Binary src1 zero)));
-
+instruct XorL_reg_LShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (XorL src4 (XorL(LShiftL src2 src3) src1)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, zr, $src1 $cmp\t# unsigned, ptr"  %}
+  format %{ "eon  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            zr,
-            as_Register($src1$$reg),
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ eon(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovP_zero_reg(cmpOp cmp, rFlagsReg cr, iRegPNoSp dst, immP0 zero, iRegP src2) %{
-  match(Set dst (CMoveP (Binary cmp cr) (Binary zero src2)));
-
+instruct OrI_reg_URShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (OrI src1 (XorI(URShiftI src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, zr $cmp\t# signed, ptr"  %}
+  format %{ "ornw  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            zr,
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ ornw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUP_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegPNoSp dst, immP0 zero, iRegP src2) %{
-  match(Set dst (CMoveP (Binary cmp cr) (Binary zero src2)));
-
+instruct OrL_reg_URShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (OrL src1 (XorL(URShiftL src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "csel $dst, $src2, zr $cmp\t# unsigned, ptr"  %}
+  format %{ "orn  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ csel(as_Register($dst$$reg),
-            as_Register($src2$$reg),
-            zr,
-            (Assembler::Condition)$cmp$$cmpcode);
+    __ orn(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovN_reg_reg(cmpOp cmp, rFlagsReg cr, iRegN dst, iRegN src1, iRegN src2) %{
-  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 src2)));
-
+instruct OrI_reg_RShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (OrI src1 (XorI(RShiftI src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, $src1 $cmp\t# signed, compressed ptr"  %}
+  format %{ "ornw  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ ornw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUN_reg_reg(cmpOpU cmp, rFlagsRegU cr, iRegN dst, iRegN src1, iRegN src2) %{
-  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 src2)));
-
+instruct OrL_reg_RShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (OrL src1 (XorL(RShiftL src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, $src1 $cmp\t# signed, compressed ptr"  %}
+  format %{ "orn  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ orn(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// special cases where one arg is zero
+instruct OrI_reg_LShift_not_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, immI_M1 src4, rFlagsReg cr) %{
+  match(Set dst (OrI src1 (XorI(LShiftI src2 src3) src4)));
+  ins_cost(DEFAULT_COST);
+  format %{ "ornw  $dst, $src1, $src2, LSL $src3" %}

-instruct cmovN_reg_zero(cmpOp cmp, rFlagsReg cr, iRegN dst, iRegN src1, immN0 zero) %{
-  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 zero)));
+  ins_encode %{
+    __ ornw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}

+instruct OrL_reg_LShift_not_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, immL_M1 src4, rFlagsReg cr) %{
+  match(Set dst (OrL src1 (XorL(LShiftL src2 src3) src4)));
   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, zr, $src1 $cmp\t# signed, compressed ptr"  %}
+  format %{ "orn  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             zr,
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ orn(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUN_reg_zero(cmpOpU cmp, rFlagsRegU cr, iRegN dst, iRegN src1, immN0 zero) %{
-  match(Set dst (CMoveN (Binary cmp cr) (Binary src1 zero)));
+instruct AndI_reg_URShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AndI src1 (URShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, zr, $src1 $cmp\t# unsigned, compressed ptr"  %}
+  format %{ "andw  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             zr,
-             as_Register($src1$$reg),
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ andw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovN_zero_reg(cmpOp cmp, rFlagsReg cr, iRegN dst, immN0 zero, iRegN src2) %{
-  match(Set dst (CMoveN (Binary cmp cr) (Binary zero src2)));
+instruct AndL_reg_URShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AndL src1 (URShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, zr $cmp\t# signed, compressed ptr"  %}
+  format %{ "andr  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             zr,
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ andr(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovUN_zero_reg(cmpOpU cmp, rFlagsRegU cr, iRegN dst, immN0 zero, iRegN src2) %{
-  match(Set dst (CMoveN (Binary cmp cr) (Binary zero src2)));
+instruct AndI_reg_RShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AndI src1 (RShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "cselw $dst, $src2, zr $cmp\t# unsigned, compressed ptr"  %}
+  format %{ "andw  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ cselw(as_Register($dst$$reg),
-             as_Register($src2$$reg),
-             zr,
-             (Assembler::Condition)$cmp$$cmpcode);
+    __ andw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovF_reg(cmpOp cmp, rFlagsReg cr, vRegF dst, vRegF src1,  vRegF src2)
-%{
-  match(Set dst (CMoveF (Binary cmp cr) (Binary src1 src2)));
+instruct AndL_reg_RShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AndL src1 (RShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
+  format %{ "andr  $dst, $src1, $src2, ASR $src3" %}

-  format %{ "fcsels $dst, $src1, $src2, $cmp\t# signed cmove float\n\t" %}
   ins_encode %{
-    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
-    __ fcsels(as_FloatRegister($dst$$reg),
-              as_FloatRegister($src2$$reg),
-              as_FloatRegister($src1$$reg),
-              cond);
+    __ andr(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct AndI_reg_LShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AndI src1 (LShiftI src2 src3)));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "andw  $dst, $src1, $src2, LSL $src3" %}
+
+  ins_encode %{
+    __ andw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovF_regU(cmpOpU cmp, rFlagsRegU cr, vRegF dst, vRegF src1,  vRegF src2)
-%{
-  match(Set dst (CMoveF (Binary cmp cr) (Binary src1 src2)));
+instruct AndL_reg_LShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AndL src1 (LShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
+  format %{ "andr  $dst, $src1, $src2, LSL $src3" %}

-  format %{ "fcsels $dst, $src1, $src2, $cmp\t# unsigned cmove float\n\t" %}
   ins_encode %{
-    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
-    __ fcsels(as_FloatRegister($dst$$reg),
-              as_FloatRegister($src2$$reg),
-              as_FloatRegister($src1$$reg),
-              cond);
+    __ andr(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovD_reg(cmpOp cmp, rFlagsReg cr, vRegD dst, vRegD src1,  vRegD src2)
-%{
-  match(Set dst (CMoveD (Binary cmp cr) (Binary src1 src2)));
+instruct XorI_reg_URShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (XorI src1 (URShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
+  format %{ "eorw  $dst, $src1, $src2, LSR $src3" %}

-  format %{ "fcseld $dst, $src1, $src2, $cmp\t# signed cmove float\n\t" %}
   ins_encode %{
-    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
-    __ fcseld(as_FloatRegister($dst$$reg),
-              as_FloatRegister($src2$$reg),
-              as_FloatRegister($src1$$reg),
-              cond);
+    __ eorw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct cmovD_regU(cmpOpU cmp, rFlagsRegU cr, vRegD dst, vRegD src1,  vRegD src2)
-%{
-  match(Set dst (CMoveD (Binary cmp cr) (Binary src1 src2)));
+instruct XorL_reg_URShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (XorL src1 (URShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
+  format %{ "eor  $dst, $src1, $src2, LSR $src3" %}

-  format %{ "fcseld $dst, $src1, $src2, $cmp\t# unsigned cmove float\n\t" %}
   ins_encode %{
-    Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
-    __ fcseld(as_FloatRegister($dst$$reg),
-              as_FloatRegister($src2$$reg),
-              as_FloatRegister($src1$$reg),
-              cond);
+    __ eor(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// ============================================================================
-// Arithmetic Instructions
-//
-// TODO
-// these currently employ operations which do not set CR and hence are
-// not flagged as killing CR but we would like to isolate the cases
-// where we want to set flags from those where we don't. need to work
-// out how to do that.
-
-// Integer Addition
-
-instruct addI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (AddI src1 src2));
+instruct XorI_reg_RShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (XorI src1 (RShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "addw  $dst, $src1, $src2" %}
+  format %{ "eorw  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ addw(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg));
+    __ eorw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct addI_reg_imm(iRegINoSp dst, iRegI src1, immIAddSub src2) %{
-  match(Set dst (AddI src1 src2));
+instruct XorL_reg_RShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (XorL src1 (RShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "addw $dst, $src1, $src2" %}
-
-  // use opcode to indicate that this is an add not a sub
-  opcode(0x0);
+  format %{ "eor  $dst, $src1, $src2, ASR $src3" %}

-  ins_encode(aarch64_enc_addsubw_imm(dst, src1, src2));
+  ins_encode %{
+    __ eor(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
+  %}

   ins_pipe(pipe_class_default);
 %}

-instruct addI_reg_imm_i2l(iRegINoSp dst, iRegL src1, immIAddSub src2) %{
-  match(Set dst (AddI (ConvL2I src1) src2));
+instruct XorI_reg_LShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (XorI src1 (LShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "addw $dst, $src1, $src2" %}
+  format %{ "eorw  $dst, $src1, $src2, LSL $src3" %}

-  // use opcode to indicate that this is an add not a sub
-  opcode(0x0);
-
-  ins_encode(aarch64_enc_addsubw_imm(dst, src1, src2));
+  ins_encode %{
+    __ eorw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
+  %}

   ins_pipe(pipe_class_default);
 %}

-// Pointer Addition
-instruct addP_reg_reg(iRegPNoSp dst, iRegP src1, iRegL src2) %{
-  match(Set dst (AddP src1 src2));
+instruct XorL_reg_LShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (XorL src1 (LShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "add $dst, $src1, $src2\t# ptr" %}
+  format %{ "eor  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ add(as_Register($dst$$reg),
-           as_Register($src1$$reg),
-           as_Register($src2$$reg));
+    __ eor(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Pointer Immediate Addition
-// n.b. this needs to be more expensive than using an indirect memory
-// operand
-instruct addP_reg_imm(iRegPNoSp dst, iRegP src1, immLAddSub src2) %{
-  match(Set dst (AddP src1 src2));
+instruct OrI_reg_URShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (OrI src1 (URShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "add $dst, $src1, $src2\t# ptr" %}
-
-  // use opcode to indicate that this is an add not a sub
-  opcode(0x0);
+  format %{ "orrw  $dst, $src1, $src2, LSR $src3" %}

-  ins_encode( aarch64_enc_addsub_imm(dst, src1, src2) );
+  ins_encode %{
+    __ orrw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
+  %}

   ins_pipe(pipe_class_default);
 %}

-// Long Addition
-instruct addL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
-
-  match(Set dst (AddL src1 src2));
+instruct OrL_reg_URShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (OrL src1 (URShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "add  $dst, $src1, $src2" %}
+  format %{ "orr  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ add(as_Register($dst$$reg),
-           as_Register($src1$$reg),
-           as_Register($src2$$reg));
+    __ orr(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// No constant pool entries requiredLong Immediate Addition.
-instruct addL_reg_imm(iRegLNoSp dst, iRegL src1, immLAddSub src2) %{
-  match(Set dst (AddL src1 src2));
+instruct OrI_reg_RShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (OrI src1 (RShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "add $dst, $src1, $src2" %}
-
-  // use opcode to indicate that this is an add not a sub
-  opcode(0x0);
+  format %{ "orrw  $dst, $src1, $src2, ASR $src3" %}

-  ins_encode( aarch64_enc_addsub_imm(dst, src1, src2) );
+  ins_encode %{
+    __ orrw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
+  %}

   ins_pipe(pipe_class_default);
 %}

-// Integer Subtraction
-instruct subI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (SubI src1 src2));
+instruct OrL_reg_RShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (OrL src1 (RShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "subw  $dst, $src1, $src2" %}
+  format %{ "orr  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ subw(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg));
+    __ orr(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Immediate Subtraction
-instruct subI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immIAddSub src2) %{
-  match(Set dst (SubI src1 src2));
+instruct OrI_reg_LShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (OrI src1 (LShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "subw $dst, $src1, $src2" %}
+  format %{ "orrw  $dst, $src1, $src2, LSL $src3" %}

-  // use opcode to indicate that this is a sub not an add
-  opcode(0x1);
-
-  ins_encode(aarch64_enc_addsubw_imm(dst, src1, src2));
+  ins_encode %{
+    __ orrw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
+  %}

   ins_pipe(pipe_class_default);
 %}

-// Long Subtraction
-instruct subL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) %{
-
-  match(Set dst (SubL src1 src2));
+instruct OrL_reg_LShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (OrL src1 (LShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "sub  $dst, $src1, $src2" %}
+  format %{ "orr  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ sub(as_Register($dst$$reg),
-           as_Register($src1$$reg),
-           as_Register($src2$$reg));
+    __ orr(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// No constant pool entries requiredLong Immediate Subtraction.
-instruct subL_reg_imm(iRegLNoSp dst, iRegL src1, immLAddSub src2) %{
-  match(Set dst (SubL src1 src2));
+instruct AddI_reg_URShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AddI src1 (URShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "sub$dst, $src1, $src2" %}
+  format %{ "addw  $dst, $src1, $src2, LSR $src3" %}

-  // use opcode to indicate that this is a sub not an add
-  opcode(0x1);
-
-  ins_encode( aarch64_enc_addsub_imm(dst, src1, src2) );
+  ins_encode %{
+    __ addw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
+  %}

   ins_pipe(pipe_class_default);
 %}

-// Integer Negation (special case for sub)
-
-instruct negI_reg(iRegINoSp dst, iRegIorL2I src, immI0 zero, rFlagsReg cr) %{
-  match(Set dst (SubI zero src));
-
-  effect(KILL cr);
+instruct AddL_reg_URShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AddL src1 (URShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "negsw $dst, $src\t# int" %}
+  format %{ "add  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ negsw(as_Register($dst$$reg),
-             as_Register($src$$reg));
+    __ add(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Long Negation
-
-instruct negL_reg(iRegLNoSp dst, iRegIorL2I src, immL0 zero, rFlagsReg cr) %{
-  match(Set dst (SubL zero src));
-
-  effect(KILL cr);
+instruct AddI_reg_RShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AddI src1 (RShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "negs $dst, $src\t# long" %}
+  format %{ "addw  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ negs(as_Register($dst$$reg),
-            as_Register($src$$reg));
+    __ addw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Integer Multiply
-
-instruct mulI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (MulI src1 src2));
+instruct AddL_reg_RShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AddL src1 (RShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "mulw  $dst, $src1, $src2" %}
+  format %{ "add  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ mulw(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg));
+    __ add(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Long Multiply
-
-instruct mulL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
-  match(Set dst (MulL src1 src2));
+instruct AddI_reg_LShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AddI src1 (LShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "mul  $dst, $src1, $src2" %}
+  format %{ "addw  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ mul(as_Register($dst$$reg),
-           as_Register($src1$$reg),
-           as_Register($src2$$reg));
+    __ addw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Combined Integer Multiply & Add/Sub
-
-instruct maddI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, iRegIorL2I src3) %{
-  match(Set dst (AddI (MulI src1 src2) src3));
+instruct AddL_reg_LShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (AddL src1 (LShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "madd  $dst, $src1, $src2, $src3" %}
+  format %{ "add  $dst, $src1, $src2, LSL $src3" %}

   ins_encode %{
-    __ maddw(as_Register($dst$$reg),
-             as_Register($src1$$reg),
-             as_Register($src2$$reg),
-             as_Register($src3$$reg));
+    __ add(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct msubI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, iRegIorL2I src3) %{
-  match(Set dst (SubI (MulI src1 src2) src3));
+instruct SubI_reg_URShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (SubI src1 (URShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "msub  $dst, $src1, $src2, $src3" %}
+  format %{ "subw  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ msubw(as_Register($dst$$reg),
-             as_Register($src1$$reg),
-             as_Register($src2$$reg),
-             as_Register($src3$$reg));
+    __ subw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Combined Long Multiply & Add/Sub
-
-instruct maddL(iRegLNoSp dst, iRegL src1, iRegL src2, iRegL src3) %{
-  match(Set dst (AddL (MulL src1 src2) src3));
+instruct SubL_reg_URShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (SubL src1 (URShiftL src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "madd  $dst, $src1, $src2, $src3" %}
+  format %{ "sub  $dst, $src1, $src2, LSR $src3" %}

   ins_encode %{
-    __ madd(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg),
-            as_Register($src3$$reg));
+    __ sub(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-instruct msubL(iRegLNoSp dst, iRegL src1, iRegL src2, iRegL src3) %{
-  match(Set dst (SubL (MulL src1 src2) src3));
+instruct SubI_reg_RShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (SubI src1 (RShiftI src2 src3)));

   ins_cost(DEFAULT_COST);
-  format %{ "msub  $dst, $src1, $src2, $src3" %}
+  format %{ "subw  $dst, $src1, $src2, ASR $src3" %}

   ins_encode %{
-    __ msub(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg),
-            as_Register($src3$$reg));
+    __ subw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Integer Divide
+instruct SubL_reg_RShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (SubL src1 (RShiftL src2 src3)));

-instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (DivI src1 src2));
+  ins_cost(DEFAULT_COST);
+  format %{ "sub  $dst, $src1, $src2, ASR $src3" %}

-  ins_cost(10*DEFAULT_COST);
-  format %{ "cmpw   $src1, #0x80000000\t# idiv\n\t"
-            "bne    normal\n\t"
-            "cmnw   $src2, #1\n\t"
-            "beq    normal\n\t"
-            "movw   $dst, $src1\n\t"
-            "b      done\n"
-    "normal: sdivw  $dst, $src1, $src2\n"
-    "done:" %}
+  ins_encode %{
+    __ sub(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::ASR,
+              $src3$$constant & 0x3f);
+  %}

-  ins_encode(aarch64_enc_divw(dst, src1, src2));
   ins_pipe(pipe_class_default);
 %}

-// Long Divide
+instruct SubI_reg_LShift_reg(iRegINoSp dst,
+                         iRegI src1, iRegI src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (SubI src1 (LShiftI src2 src3)));

-instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
-  match(Set dst (DivL src1 src2));
+  ins_cost(DEFAULT_COST);
+  format %{ "subw  $dst, $src1, $src2, LSL $src3" %}

-  ins_cost(10*DEFAULT_COST);
-  format %{ "cmp    $src1, #0x8000000000000000\t# ldiv\n\t"
-            "bne    normal\n\t"
-            "cmn    $src2, #1\n\t"
-            "beq    normal\n\t"
-            "mov    $dst, $src1\n\t"
-            "b      done\n"
-    "normal: sdiv   $dst, $src1, $src2\n"
-    "done:" %}
+  ins_encode %{
+    __ subw(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
+  %}

-  ins_encode(aarch64_enc_div(dst, src1, src2));
   ins_pipe(pipe_class_default);
 %}

-// Integer Remainder
+instruct SubL_reg_LShift_reg(iRegLNoSp dst,
+                         iRegL src1, iRegL src2,
+                         immI src3, rFlagsReg cr) %{
+  match(Set dst (SubL src1 (LShiftL src2 src3)));

-instruct modI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (ModI src1 src2));
+  ins_cost(DEFAULT_COST);
+  format %{ "sub  $dst, $src1, $src2, LSL $src3" %}

-  format %{ "cmpw   $src1, #0x80000000\t# imod\n\t"
-            "bne    normal\n\t"
-            "cmnw   $src2, #1\n\t"
-            "beq    normal\n\t"
-            "movw   $dst, zr\n\t"
-            "b      done\n"
-    "normal: sdivw  rscratch1, $src1, $src2\n\t"
-            "msubw($dst, rscratch1, $src2, $src1"
-    "done:" %}
+  ins_encode %{
+    __ sub(as_Register($dst$$reg),
+              as_Register($src1$$reg),
+              as_Register($src2$$reg),
+              Assembler::LSL,
+              $src3$$constant & 0x3f);
+  %}

-  ins_encode(aarch64_enc_modw(dst, src1, src2));
   ins_pipe(pipe_class_default);
 %}

-// Long Remainder

-instruct modL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
-  match(Set dst (ModL src1 src2));

-  ins_cost(10*DEFAULT_COST);
-  format %{ "cmp    $src1, #0x8000000000000000\t# lmod\n\t"
-            "bne    normal\n\t"
-            "cmn    $src2, #1\n\t"
-            "beq    normal\n\t"
-            "mov    $dst, zr\n\t"
-            "b      done\n"
-    "normal: sdiv   rscratch1, $src1, $src2\n"
-            "msub($dst, rscratch1, $src2, $src1"
-    "done:" %}
+// Shift Left followed by Shift Right.
+// This idiom is used by the compiler for the i2b bytecode etc.
+instruct sbfmL(iRegLNoSp dst, iRegL src, immI lshift_count, immI rshift_count)
+%{
+  match(Set dst (RShiftL (LShiftL src lshift_count) rshift_count));
+  // Make sure we are not going to exceed what sbfm can do.
+  predicate((unsigned int)n->in(2)->get_int() <= 63
+            && (unsigned int)n->in(1)->in(2)->get_int() <= 63);
+
+  ins_cost(DEFAULT_COST);
+  format %{ "sbfm  $dst, $src, $rshift_count - $lshift_count, #63 - $lshift_count" %}
+  ins_encode %{
+    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int s = 63 - lshift;
+    int r = (rshift - lshift) & 63;
+    __ sbfm(as_Register($dst$$reg),
+	    as_Register($src$$reg),
+	    r, s);
+  %}

-  ins_encode(aarch64_enc_mod(dst, src1, src2));
   ins_pipe(pipe_class_default);
 %}

-// Integer Shifts
-
-// Shift Left Register
-instruct lShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (LShiftI src1 src2));
+// Shift Left followed by Shift Right.
+// This idiom is used by the compiler for the i2b bytecode etc.
+instruct sbfmwI(iRegINoSp dst, iRegI src, immI lshift_count, immI rshift_count)
+%{
+  match(Set dst (RShiftI (LShiftI src lshift_count) rshift_count));
+  // Make sure we are not going to exceed what sbfmw can do.
+  predicate((unsigned int)n->in(2)->get_int() <= 31
+            && (unsigned int)n->in(1)->in(2)->get_int() <= 31);

   ins_cost(DEFAULT_COST);
-  format %{ "lslvw  $dst, $src1, $src2" %}
-
+  format %{ "sbfmw  $dst, $src, $rshift_count - $lshift_count, #31 - $lshift_count" %}
   ins_encode %{
-    __ lslvw(as_Register($dst$$reg),
-             as_Register($src1$$reg),
-             as_Register($src2$$reg));
+    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int s = 31 - lshift;
+    int r = (rshift - lshift) & 31;
+    __ sbfmw(as_Register($dst$$reg),
+	    as_Register($src$$reg),
+	    r, s);
   %}

   ins_pipe(pipe_class_default);
 %}

-// Shift Left Immediate
-instruct lShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
-  match(Set dst (LShiftI src1 src2));
+// Shift Left followed by Shift Right.
+// This idiom is used by the compiler for the i2b bytecode etc.
+instruct ubfmL(iRegLNoSp dst, iRegL src, immI lshift_count, immI rshift_count)
+%{
+  match(Set dst (URShiftL (LShiftL src lshift_count) rshift_count));
+  // Make sure we are not going to exceed what ubfm can do.
+  predicate((unsigned int)n->in(2)->get_int() <= 63
+            && (unsigned int)n->in(1)->in(2)->get_int() <= 63);

-  format %{ "lslw $dst, $src1, ($src2 & 0x1f)" %}
+  ins_cost(DEFAULT_COST);
+  format %{ "ubfm  $dst, $src, $rshift_count - $lshift_count, #63 - $lshift_count" %}
+  ins_encode %{
+    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int s = 63 - lshift;
+    int r = (rshift - lshift) & 63;
+    __ ubfm(as_Register($dst$$reg),
+	    as_Register($src$$reg),
+	    r, s);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Shift Left followed by Shift Right.
+// This idiom is used by the compiler for the i2b bytecode etc.
+instruct ubfmwI(iRegINoSp dst, iRegI src, immI lshift_count, immI rshift_count)
+%{
+  match(Set dst (URShiftI (LShiftI src lshift_count) rshift_count));
+  // Make sure we are not going to exceed what ubfmw can do.
+  predicate((unsigned int)n->in(2)->get_int() <= 31
+            && (unsigned int)n->in(1)->in(2)->get_int() <= 31);

+  ins_cost(DEFAULT_COST);
+  format %{ "ubfmw  $dst, $src, $rshift_count - $lshift_count, #31 - $lshift_count" %}
   ins_encode %{
-    __ lslw(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            $src2$$constant & 0x1f);
+    int lshift = $lshift_count$$constant, rshift = $rshift_count$$constant;
+    int s = 31 - lshift;
+    int r = (rshift - lshift) & 31;
+    __ ubfmw(as_Register($dst$$reg),
+	    as_Register($src$$reg),
+	    r, s);
   %}

   ins_pipe(pipe_class_default);
 %}
+// Bitfield extract with shift & mask

-// Shift Right Logical Register
-instruct urShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (URShiftI src1 src2));
+instruct ubfxwI(iRegINoSp dst, iRegI src, immI rshift, immI_bitmask mask)
+%{
+  match(Set dst (AndI (URShiftI src rshift) mask));

   ins_cost(DEFAULT_COST);
-  format %{ "lsrvw  $dst, $src1, $src2" %}
+  format %{ "ubfxw $dst, $src, $mask" %}
+  ins_encode %{
+    int rshift = $rshift$$constant;
+    long mask = $mask$$constant;
+    int width = exact_log2(mask+1);
+    __ ubfxw(as_Register($dst$$reg),
+	    as_Register($src$$reg), rshift, width);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+instruct ubfxL(iRegLNoSp dst, iRegL src, immI rshift, immL_bitmask mask)
+%{
+  match(Set dst (AndL (URShiftL src rshift) mask));

+  ins_cost(DEFAULT_COST);
+  format %{ "ubfx $dst, $src, $mask" %}
   ins_encode %{
-    __ lsrvw(as_Register($dst$$reg),
-             as_Register($src1$$reg),
-             as_Register($src2$$reg));
+    int rshift = $rshift$$constant;
+    long mask = $mask$$constant;
+    int width = exact_log2(mask+1);
+    __ ubfx(as_Register($dst$$reg),
+	    as_Register($src$$reg), rshift, width);
   %}
+  ins_pipe(pipe_class_default);
+%}
+
+// We can use ubfx when extending an And with a mask when we know mask
+// is positive.  We know that because immI_bitmask guarantees it.
+instruct ubfxIConvI2L(iRegLNoSp dst, iRegI src, immI rshift, immI_bitmask mask)
+%{
+  match(Set dst (ConvI2L (AndI (URShiftI src rshift) mask)));

+  ins_cost(DEFAULT_COST);
+  format %{ "ubfx $dst, $src, $mask" %}
+  ins_encode %{
+    int rshift = $rshift$$constant;
+    long mask = $mask$$constant;
+    int width = exact_log2(mask+1);
+    __ ubfx(as_Register($dst$$reg),
+	    as_Register($src$$reg), rshift, width);
+  %}
   ins_pipe(pipe_class_default);
 %}
+// Rotations

-// Shift Right Logical Immediate
-instruct urShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
-  match(Set dst (URShiftI src1 src2));
+instruct extrOrL(iRegLNoSp dst, iRegL src1, iRegL src2, immI lshift, immI rshift, rFlagsReg cr)
+%{
+  match(Set dst (OrL (LShiftL src1 lshift) (URShiftL src2 rshift)));
+  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 63));

-  format %{ "lsrw $dst, $src1, ($src2 & 0x1f)" %}
+  ins_cost(DEFAULT_COST);
+  format %{ "extr $dst, $src1, $src2, #$rshift" %}

   ins_encode %{
-    __ lsrw(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            $src2$$constant & 0x1f);
+    __ extr(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg),
+            $rshift$$constant & 63);
   %}
-
   ins_pipe(pipe_class_default);
 %}

-// Shift Right Arithmetic Register
-instruct rShiftI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
-  match(Set dst (RShiftI src1 src2));
+instruct extrOrI(iRegINoSp dst, iRegI src1, iRegI src2, immI lshift, immI rshift, rFlagsReg cr)
+%{
+  match(Set dst (OrI (LShiftI src1 lshift) (URShiftI src2 rshift)));
+  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31));

   ins_cost(DEFAULT_COST);
-  format %{ "asrvw  $dst, $src1, $src2" %}
+  format %{ "extr $dst, $src1, $src2, #$rshift" %}

   ins_encode %{
-    __ asrvw(as_Register($dst$$reg),
-             as_Register($src1$$reg),
-             as_Register($src2$$reg));
+    __ extrw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg),
+            $rshift$$constant & 31);
   %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct extrAddL(iRegLNoSp dst, iRegL src1, iRegL src2, immI lshift, immI rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddL (LShiftL src1 lshift) (URShiftL src2 rshift)));
+  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 63));
+
+  ins_cost(DEFAULT_COST);
+  format %{ "extr $dst, $src1, $src2, #$rshift" %}

+  ins_encode %{
+    __ extr(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg),
+            $rshift$$constant & 63);
+  %}
   ins_pipe(pipe_class_default);
 %}

-// Shift Right Arithmetic Immediate
-instruct rShiftI_reg_imm(iRegINoSp dst, iRegIorL2I src1, immI src2) %{
-  match(Set dst (RShiftI src1 src2));
+instruct extrAddI(iRegINoSp dst, iRegI src1, iRegI src2, immI lshift, immI rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddI (LShiftI src1 lshift) (URShiftI src2 rshift)));
+  predicate(0 == ((n->in(1)->in(2)->get_int() + n->in(2)->in(2)->get_int()) & 31));

-  format %{ "asrw $dst, $src1, ($src2 & 0x1f)" %}
+  ins_cost(DEFAULT_COST);
+  format %{ "extr $dst, $src1, $src2, #$rshift" %}

   ins_encode %{
-    __ asrw(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            $src2$$constant & 0x1f);
+    __ extrw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg),
+            $rshift$$constant & 31);
   %}
+  ins_pipe(pipe_class_default);
+%}
+
+// Add/subtract (extended)
+
+
+instruct AddExtI(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg cr)
+%{
+  match(Set dst (AddI src1 (ConvI2L src2)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1,  $src2" %}
+
+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::sxtw);
+   %}
+  ins_pipe(pipe_class_default);
+%};
+
+instruct SubExtI(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg cr)
+%{
+  match(Set dst (SubI src1 (ConvI2L src2)));
+  ins_cost(DEFAULT_COST);
+  format %{ "sub  $dst, $src1,  $src2" %}
+
+   ins_encode %{
+     __ sub(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::sxtw);
+   %}
+  ins_pipe(pipe_class_default);
+%};
+
+
+instruct AddExtI_sxth(iRegINoSp dst, iRegI src1, iRegI src2, immI_16 lshift, immI_16 rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, sxth $src2" %}

+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::sxth);
+   %}
   ins_pipe(pipe_class_default);
 %}

-// Combined Int Mask and Right Shift (using UBFM)
-// TODO
+instruct AddExtI_sxtb(iRegINoSp dst, iRegI src1, iRegI src2, immI_24 lshift, immI_24 rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, sxtb $src2" %}

-// Long Shifts
+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::sxtb);
+   %}
+  ins_pipe(pipe_class_default);
+%}

-// Shift Left Register
-instruct lShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
-  match(Set dst (LShiftL src1 src2));
+instruct AddExtI_uxtb(iRegINoSp dst, iRegI src1, iRegI src2, immI_24 lshift, immI_24 rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddI src1 (URShiftI (LShiftI src2 lshift) rshift)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, uxtb $src2" %}
+
+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtb);
+   %}
+  ins_pipe(pipe_class_default);
+%}

+instruct AddExtL_sxth(iRegLNoSp dst, iRegL src1, iRegL src2, immI_48 lshift, immI_48 rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift)));
   ins_cost(DEFAULT_COST);
-  format %{ "lslv  $dst, $src1, $src2" %}
+  format %{ "add  $dst, $src1, sxth $src2" %}

-  ins_encode %{
-    __ lslv(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg));
-  %}
+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::sxth);
+   %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct AddExtL_sxtw(iRegLNoSp dst, iRegL src1, iRegL src2, immI_32 lshift, immI_32 rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, sxtw $src2" %}

+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::sxtw);
+   %}
   ins_pipe(pipe_class_default);
 %}

-// Shift Left Immediate
-instruct lShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
-  match(Set dst (LShiftL src1 src2));
+instruct AddExtL_sxtb(iRegLNoSp dst, iRegL src1, iRegL src2, immI_56 lshift, immI_56 rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, sxtb $src2" %}

-  format %{ "lsl $dst, $src1, ($src2 & 0x3f)" %}
+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::sxtb);
+   %}
+  ins_pipe(pipe_class_default);
+%}

-  ins_encode %{
-    __ lsl(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            $src2$$constant & 0x3f);
-  %}
+instruct AddExtL_uxtb(iRegLNoSp dst, iRegL src1, iRegL src2, immI_56 lshift, immI_56 rshift, rFlagsReg cr)
+%{
+  match(Set dst (AddL src1 (URShiftL (LShiftL src2 lshift) rshift)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, uxtb $src2" %}

+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtb);
+   %}
   ins_pipe(pipe_class_default);
 %}

-// Shift Right Logical Register
-instruct urShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
-  match(Set dst (URShiftL src1 src2));

+instruct AddExtI_uxtb_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_255 mask, rFlagsReg cr)
+%{
+  match(Set dst (AddI src1 (AndI src2 mask)));
   ins_cost(DEFAULT_COST);
-  format %{ "lsrv  $dst, $src1, $src2" %}
+  format %{ "addw  $dst, $src1, $src2, uxtb" %}

-  ins_encode %{
-    __ lsrv(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg));
-  %}
+   ins_encode %{
+     __ addw(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtb);
+   %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct AddExtI_uxth_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_65535 mask, rFlagsReg cr)
+%{
+  match(Set dst (AddI src1 (AndI src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "addw  $dst, $src1, $src2, uxth" %}

+   ins_encode %{
+     __ addw(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxth);
+   %}
   ins_pipe(pipe_class_default);
 %}

-// Shift Right Logical Immediate
-instruct urShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
-  match(Set dst (URShiftL src1 src2));
+instruct AddExtL_uxtb_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_255 mask, rFlagsReg cr)
+%{
+  match(Set dst (AddL src1 (AndL src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, $src2, uxtb" %}

-  format %{ "lsr $dst, $src1, ($src2 & 0x3f)" %}
+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtb);
+   %}
+  ins_pipe(pipe_class_default);
+%}

-  ins_encode %{
-    __ lsr(as_Register($dst$$reg),
-           as_Register($src1$$reg),
-           $src2$$constant & 0x3f);
-  %}
+instruct AddExtL_uxth_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_65535 mask, rFlagsReg cr)
+%{
+  match(Set dst (AddL src1 (AndL src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, $src2, uxth" %}

+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxth);
+   %}
   ins_pipe(pipe_class_default);
 %}

-// Shift Right Arithmetic Register
-instruct rShiftL_reg_reg(iRegLNoSp dst, iRegL src1, iRegIorL2I src2) %{
-  match(Set dst (RShiftL src1 src2));
+instruct AddExtL_uxtw_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295 mask, rFlagsReg cr)
+%{
+  match(Set dst (AddL src1 (AndL src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "add  $dst, $src1, $src2, uxtw" %}
+
+   ins_encode %{
+     __ add(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtw);
+   %}
+  ins_pipe(pipe_class_default);
+%}

+instruct SubExtI_uxtb_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_255 mask, rFlagsReg cr)
+%{
+  match(Set dst (SubI src1 (AndI src2 mask)));
   ins_cost(DEFAULT_COST);
-  format %{ "asrv  $dst, $src1, $src2" %}
+  format %{ "subw  $dst, $src1, $src2, uxtb" %}

-  ins_encode %{
-    __ asrv(as_Register($dst$$reg),
-            as_Register($src1$$reg),
-            as_Register($src2$$reg));
-  %}
+   ins_encode %{
+     __ subw(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtb);
+   %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct SubExtI_uxth_and(iRegINoSp dst, iRegI src1, iRegI src2, immI_65535 mask, rFlagsReg cr)
+%{
+  match(Set dst (SubI src1 (AndI src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "subw  $dst, $src1, $src2, uxth" %}

+   ins_encode %{
+     __ subw(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxth);
+   %}
   ins_pipe(pipe_class_default);
 %}

-// Shift Right Arithmetic Immediate
-instruct rShiftL_reg_imm(iRegLNoSp dst, iRegL src1, immI src2) %{
-  match(Set dst (RShiftL src1 src2));
+instruct SubExtL_uxtb_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_255 mask, rFlagsReg cr)
+%{
+  match(Set dst (SubL src1 (AndL src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "sub  $dst, $src1, $src2, uxtb" %}

-  format %{ "asr $dst, $src1, ($src2 & 0x3f)" %}
+   ins_encode %{
+     __ sub(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtb);
+   %}
+  ins_pipe(pipe_class_default);
+%}

-  ins_encode %{
-    __ asr(as_Register($dst$$reg),
-           as_Register($src1$$reg),
-           $src2$$constant & 0x3f);
-  %}
+instruct SubExtL_uxth_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_65535 mask, rFlagsReg cr)
+%{
+  match(Set dst (SubL src1 (AndL src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "sub  $dst, $src1, $src2, uxth" %}

+   ins_encode %{
+     __ sub(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxth);
+   %}
   ins_pipe(pipe_class_default);
 %}

+instruct SubExtL_uxtw_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295 mask, rFlagsReg cr)
+%{
+  match(Set dst (SubL src1 (AndL src2 mask)));
+  ins_cost(DEFAULT_COST);
+  format %{ "sub  $dst, $src1, $src2, uxtw" %}
+
+   ins_encode %{
+     __ sub(as_Register($dst$$reg), as_Register($src1$$reg),
+            as_Register($src2$$reg), ext::uxtw);
+   %}
+  ins_pipe(pipe_class_default);
+%}
+// END This section of the file is automatically generated. Do not edit --------------
 // Combined Long Mask and Right Shift (using UBFM)
 // TODO

@@ -7870,6 +9275,7 @@
 instruct xorL_reg_imm(iRegLNoSp dst, iRegL src1, immLLog src2) %{
   match(Set dst (XorL src1 src2));

+  ins_cost(DEFAULT_COST);
   format %{ "eor  $dst, $src1, $src2\t# int" %}

   ins_encode %{
@@ -7881,12 +9287,11 @@
   ins_pipe(pipe_class_default);
 %}

-// Arithmetic Conversion Instructions
-
 instruct convI2L_reg_reg(iRegLNoSp dst, iRegI src)
 %{
   match(Set dst (ConvI2L src));

+  ins_cost(DEFAULT_COST);
   format %{ "sxtw  $dst, $src\t# i2l" %}
   ins_encode %{
     __ sbfm($dst$$Register, $src$$Register, 0, 31);
diff -ur hs-tmp/src/cpu/aarch64/vm/assembler_aarch64.hpp /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
--- hs-tmp/src/cpu/aarch64/vm/assembler_aarch64.hpp	2013-10-25 16:34:20.469631919 +0100
+++ /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp	2013-10-16 17:07:08.484228081 +0100
@@ -1286,7 +1286,7 @@
     f(kind, 23, 22);
   }

-  // Logical (shifted regsiter)
+  // Logical (shifted register)
 #define INSN(NAME, size, op, N)					\
   void NAME(Register Rd, Register Rn, Register Rm,		\
 	    enum shift_kind kind = LSL, unsigned shift = 0) {	\
@@ -1316,7 +1316,7 @@

 #undef INSN

-  // Add/subtract (shifted regsiter)
+  // Add/subtract (shifted register)
 #define INSN(NAME, size, op)				\
   void NAME(Register Rd, Register Rn, Register Rm,	\
 	    enum shift_kind kind, unsigned shift = 0) {	\
diff -ur hs-tmp/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
--- hs-tmp/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	2013-10-25 16:34:20.473631794 +0100
+++ /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	2013-10-17 18:55:50.887377607 +0100
@@ -1295,7 +1295,8 @@
   for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) {
     Label next_test;
     // See if the receiver is receiver[n].
-    __ ldr(rscratch1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))));
+    __ lea(rscratch2, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))));
+    __ ldr(rscratch1, Address(rscratch2));
     __ cmp(recv, rscratch1);
     __ br(Assembler::NE, next_test);
     Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)));
@@ -1307,12 +1308,15 @@
   // Didn't find receiver; find next empty slot and fill it in
   for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) {
     Label next_test;
-    Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)));
+    __ lea(rscratch2,
+	   Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))));
+    Address recv_addr(rscratch2);
     __ ldr(rscratch1, recv_addr);
     __ cbnz(rscratch1, next_test);
     __ str(recv, recv_addr);
     __ mov(rscratch1, DataLayout::counter_increment);
-    __ str(rscratch1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))));
+    __ lea(rscratch2, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))));
+    __ str(rscratch1, Address(rscratch2));
     __ b(*update_done);
     __ bind(next_test);
   }
@@ -2586,7 +2590,8 @@
         if (receiver == NULL) {
           Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)));
 	  __ mov_metadata(rscratch1, known_klass->constant_encoding());
-          __ str(rscratch1, recv_addr);
+	  __ lea(rscratch2, recv_addr);
+          __ str(rscratch1, Address(rscratch2));
           Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
 	  __ addptr(counter_addr, DataLayout::counter_increment);
           return;
diff -ur hs-tmp/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- hs-tmp/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	2013-10-25 16:34:20.486631387 +0100
+++ /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	2013-10-25 16:29:15.924131639 +0100
@@ -2078,7 +2078,7 @@
   }
 }

-void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
+void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
   if (use_XOR_for_compressed_class_base) {
     if (Universe::narrow_klass_shift() != 0) {
       eor(dst, src, (uint64_t)Universe::narrow_klass_base());
@@ -2089,29 +2089,29 @@
     return;
   }

-#ifdef ASSERT
-  verify_heapbase("MacroAssembler::encode_klass_not_null2: heap base corrupted?");
-#endif
+#ifdef ASSERT
+  verify_heapbase("MacroAssembler::encode_klass_not_null2: heap base corrupted?");
+#endif

   Register rbase = dst;
-  if (dst == src) rbase = rheapbase;
-  mov(rbase, (uint64_t)Universe::narrow_klass_base());
-  sub(dst, src, rbase);
-  if (Universe::narrow_klass_shift() != 0) {
-    assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
-    lsr(dst, dst, LogKlassAlignmentInBytes);
-  }
-  if (dst == src) reinit_heapbase();
-}
-
-void MacroAssembler::encode_klass_not_null(Register r) {
-  encode_klass_not_null(r, r);
-}
-
-void  MacroAssembler::decode_klass_not_null(Register dst, Register src) {
-  Register rbase = dst;
-  assert(Universe::narrow_klass_base() != NULL, "Base should be initialized");
-  assert (UseCompressedClassPointers, "should only be used for compressed headers");
+  if (dst == src) rbase = rheapbase;
+  mov(rbase, (uint64_t)Universe::narrow_klass_base());
+  sub(dst, src, rbase);
+  if (Universe::narrow_klass_shift() != 0) {
+    assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
+    lsr(dst, dst, LogKlassAlignmentInBytes);
+  }
+  if (dst == src) reinit_heapbase();
+}
+
+void MacroAssembler::encode_klass_not_null(Register r) {
+  encode_klass_not_null(r, r);
+}
+
+void  MacroAssembler::decode_klass_not_null(Register dst, Register src) {
+  Register rbase = dst;
+  assert(Universe::narrow_klass_base() != NULL, "Base should be initialized");
+  assert (UseCompressedClassPointers, "should only be used for compressed headers");

   if (use_XOR_for_compressed_class_base) {
     if (Universe::narrow_klass_shift() != 0) {
@@ -2123,23 +2123,23 @@
     return;
   }

-  // Cannot assert, unverified entry point counts instructions (see .ad file)
-  // vtableStubs also counts instructions in pd_code_size_limit.
-  // Also do not verify_oop as this is called by verify_oop.
-  if (dst == src) rbase = rheapbase;
-  mov(rbase, (uint64_t)Universe::narrow_klass_base());
-  if (Universe::narrow_klass_shift() != 0) {
-    assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
-    add(dst, rbase, src, Assembler::LSL, LogKlassAlignmentInBytes);
-  } else {
-    add(dst, rbase, src);
-  }
-  if (dst == src) reinit_heapbase();
-}
-
-void  MacroAssembler::decode_klass_not_null(Register r) {
-  decode_klass_not_null(r, r);
-}
+  // Cannot assert, unverified entry point counts instructions (see .ad file)
+  // vtableStubs also counts instructions in pd_code_size_limit.
+  // Also do not verify_oop as this is called by verify_oop.
+  if (dst == src) rbase = rheapbase;
+  mov(rbase, (uint64_t)Universe::narrow_klass_base());
+  if (Universe::narrow_klass_shift() != 0) {
+    assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
+    add(dst, rbase, src, Assembler::LSL, LogKlassAlignmentInBytes);
+  } else {
+    add(dst, rbase, src);
+  }
+  if (dst == src) reinit_heapbase();
+}
+
+void  MacroAssembler::decode_klass_not_null(Register r) {
+  decode_klass_not_null(r, r);
+}

 // TODO
 //
diff -ur hs-tmp/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
--- hs-tmp/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	2013-10-25 16:34:20.486631387 +0100
+++ /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	2013-10-25 16:30:09.186473470 +0100
@@ -89,15 +89,16 @@

   void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true);

+  // Maximum size of class area in Metaspace when compressed
   uint64_t use_XOR_for_compressed_class_base;

  public:
   MacroAssembler(CodeBuffer* code) : Assembler(code) {
     use_XOR_for_compressed_class_base
       = (operand_valid_for_logical_immediate(false /*is32*/,
-                                            (uint64_t)Universe::narrow_klass_base())
-        && ((uint64_t)Universe::narrow_klass_base()
-            > (1u << log2_intptr(CompressedClassSpaceSize))));
+					     (uint64_t)Universe::narrow_klass_base())
+	 && ((uint64_t)Universe::narrow_klass_base()
+	     > (1u << log2_intptr(CompressedClassSpaceSize))));
   }

   // Biased locking support
@@ -1022,10 +1023,12 @@
   // Arithmetics

   void addptr(Address dst, int32_t src) {
-    ldr(rscratch1, dst);
+    lea(rscratch2, dst);
+    ldr(rscratch1, Address(rscratch2));
     add(rscratch1, rscratch1, src);
-    str(rscratch1, dst);
-}
+    str(rscratch1, Address(rscratch2));
+  }
+
   // unimplemented
 #if 0
   void addptr(Address dst, Register src);
diff -ur hs-tmp/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
--- hs-tmp/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	2013-10-25 16:34:20.492631199 +0100
+++ /local/aarch64/jdk8/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	2013-10-25 11:18:53.470583457 +0100
@@ -281,7 +281,7 @@
     Label parameters_done;
     // parameter count is still in c_rarg6
     // and parameter pointer identifying param 1 is in c_rarg5
-    __ cbz(c_rarg6, parameters_done);
+    __ cbzw(c_rarg6, parameters_done);

     address loop = __ pc();
     __ ldr(rscratch1, Address(__ post(c_rarg5, wordSize)));



More information about the aarch64-port-dev mailing list