8204473: AARCH64: register post-index addressing mode is not supported directly
authordpochepk
Tue, 19 Jun 2018 18:14:25 +0300
changeset 50640 a92d5b312116
parent 50639 c12c79a49ca2
child 50641 66aa15778c5a
8204473: AARCH64: register post-index addressing mode is not supported directly Reviewed-by: aph
src/hotspot/cpu/aarch64/assembler_aarch64.cpp
src/hotspot/cpu/aarch64/assembler_aarch64.hpp
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.cpp	Tue Jun 19 16:44:41 2018 +0200
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.cpp	Tue Jun 19 18:14:25 2018 +0300
@@ -58,6 +58,28 @@
 
 static float unpack(unsigned value);
 
+short Assembler::SIMD_Size_in_bytes[] = {
+  // T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q
+       8,   16,   8,  16,   8,  16,   8,  16,  16
+};
+
+#ifdef ASSERT
+static void asm_check(const unsigned int *insns, const unsigned int *insns1, size_t len) {
+    bool ok = true;
+    for (unsigned int i = 0; i < len; i++) {
+      if (insns[i] != insns1[i]) {
+        ok = false;
+        printf("Ours:\n");
+        Disassembler::decode((address)&insns1[i], (address)&insns1[i+1]);
+        printf("Theirs:\n");
+        Disassembler::decode((address)&insns[i], (address)&insns[i+1]);
+        printf("\n");
+      }
+    }
+    assert(ok, "Assembler smoke test failed");
+  }
+#endif // ASSERT
+
 void entry(CodeBuffer *cb) {
 
   // {
@@ -1155,31 +1177,24 @@
   };
 // END  Generated code -- do not edit
 
+  asm_check((unsigned int *)entry, insns, sizeof insns / sizeof insns[0]);
+
   {
-    bool ok = true;
-    unsigned int *insns1 = (unsigned int *)entry;
-    for (unsigned int i = 0; i < sizeof insns / sizeof insns[0]; i++) {
-      if (insns[i] != insns1[i]) {
-        ok = false;
-        printf("Ours:\n");
-        Disassembler::decode((address)&insns1[i], (address)&insns1[i+1]);
-        printf("Theirs:\n");
-        Disassembler::decode((address)&insns[i], (address)&insns[i+1]);
-        printf("\n");
-      }
-    }
-    assert(ok, "Assembler smoke test failed");
+    address PC = __ pc();
+    __ ld1(v0, __ T16B, Address(r16));      // No offset
+    __ ld1(v0, __ T8H, __ post(r16, 16));   // Post-index
+    __ ld2(v0, v1, __ T8H, __ post(r24, 16 * 2));   // Post-index
+    __ ld1(v0, __ T16B, __ post(r16, r17)); // Register post-index
+    static const unsigned int vector_insns[] = {
+       0x4c407200, // ld1   {v0.16b}, [x16]
+       0x4cdf7600, // ld1   {v0.8h}, [x16], #16
+       0x4cdf8700, // ld2   {v0.8h, v1.8h}, [x24], #32
+       0x4cd17200, // ld1   {v0.16b}, [x16], x17
+      };
+    asm_check((unsigned int *)PC, vector_insns,
+              sizeof vector_insns / sizeof vector_insns[0]);
   }
 
-#ifndef PRODUCT
-
-  address PC = __ pc();
-  __ ld1(v0, __ T16B, Address(r16)); // No offset
-  __ ld1(v0, __ T16B, __ post(r16, 0)); // Post-index
-  __ ld1(v0, __ T16B, Address(r16, r17)); //
-
-
-#endif // PRODUCT
 #endif // ASSERT
 }
 
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp	Tue Jun 19 16:44:41 2018 +0200
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp	Tue Jun 19 18:14:25 2018 +0300
@@ -305,8 +305,11 @@
   Pre(Register reg, int o) : PrePost(reg, o) { }
 };
 class Post : public PrePost {
+  Register _idx;
 public:
-  Post(Register reg, int o) : PrePost(reg, o) { }
+  Post(Register reg, int o) : PrePost(reg, o) { _idx = NULL; }
+  Post(Register reg, Register idx) : PrePost(reg, 0) { _idx = idx; }
+  Register idx_reg() { return _idx; }
 };
 
 namespace ext
@@ -341,7 +344,7 @@
 class Address {
  public:
 
-  enum mode { no_mode, base_plus_offset, pre, post, pcrel,
+  enum mode { no_mode, base_plus_offset, pre, post, post_reg, pcrel,
               base_plus_offset_reg, literal };
 
   // Shift and extend for base reg + reg offset addressing
@@ -413,7 +416,8 @@
   Address(Pre p)
     : _mode(pre), _base(p.reg()), _offset(p.offset()) { }
   Address(Post p)
-    : _mode(post), _base(p.reg()), _offset(p.offset()), _target(0) { }
+    : _mode(p.idx_reg() == NULL ? post : post_reg), _base(p.reg()),
+      _offset(p.offset()), _target(0), _index(p.idx_reg()) { }
   Address(address target, RelocationHolder const& rspec)
     : _mode(literal),
       _rspec(rspec),
@@ -436,7 +440,7 @@
 
   Register base() const {
     guarantee((_mode == base_plus_offset | _mode == base_plus_offset_reg
-               | _mode == post),
+               | _mode == post | _mode == post_reg),
               "wrong mode");
     return _base;
   }
@@ -660,10 +664,14 @@
     return adjust(base, offset, true);
   }
 
-  Address post (Register base, int offset) {
+  Address post(Register base, int offset) {
     return adjust(base, offset, false);
   }
 
+  Address post(Register base, Register idx) {
+    return Address(Post(base, idx));
+  }
+
   Instruction_aarch64* current;
 
   void set_current(Instruction_aarch64* i) { current = i; }
@@ -2032,6 +2040,10 @@
        B, H, S, D, Q
   };
 
+private:
+  static short SIMD_Size_in_bytes[];
+
+public:
 #define INSN(NAME, op)                                            \
   void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) {   \
     ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
@@ -2051,7 +2063,8 @@
     f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0);
   }
   void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,
-             int imm, int op1, int op2) {
+             int imm, int op1, int op2, int regs) {
+    guarantee(T <= T1Q && imm == SIMD_Size_in_bytes[T] * regs, "bad offset");
     starti;
     f(0,31), f((int)T & 1, 30);
     f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12);
@@ -2065,34 +2078,34 @@
     f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0);
   }
 
- void ld_st(FloatRegister Vt, SIMD_Arrangement T, Address a, int op1, int op2) {
-   switch (a.getMode()) {
-   case Address::base_plus_offset:
-     guarantee(a.offset() == 0, "no offset allowed here");
-     ld_st(Vt, T, a.base(), op1, op2);
-     break;
-   case Address::post:
-     ld_st(Vt, T, a.base(), a.offset(), op1, op2);
-     break;
-   case Address::base_plus_offset_reg:
-     ld_st(Vt, T, a.base(), a.index(), op1, op2);
-     break;
-   default:
-     ShouldNotReachHere();
-   }
- }
+  void ld_st(FloatRegister Vt, SIMD_Arrangement T, Address a, int op1, int op2, int regs) {
+    switch (a.getMode()) {
+    case Address::base_plus_offset:
+      guarantee(a.offset() == 0, "no offset allowed here");
+      ld_st(Vt, T, a.base(), op1, op2);
+      break;
+    case Address::post:
+      ld_st(Vt, T, a.base(), a.offset(), op1, op2, regs);
+      break;
+    case Address::post_reg:
+      ld_st(Vt, T, a.base(), a.index(), op1, op2);
+      break;
+    default:
+      ShouldNotReachHere();
+    }
+  }
 
  public:
 
-#define INSN1(NAME, op1, op2)                                   \
+#define INSN1(NAME, op1, op2)                                           \
   void NAME(FloatRegister Vt, SIMD_Arrangement T, const Address &a) {   \
-   ld_st(Vt, T, a, op1, op2);                                           \
+    ld_st(Vt, T, a, op1, op2, 1);                                       \
  }
 
 #define INSN2(NAME, op1, op2)                                           \
   void NAME(FloatRegister Vt, FloatRegister Vt2, SIMD_Arrangement T, const Address &a) { \
     assert(Vt->successor() == Vt2, "Registers must be ordered");        \
-    ld_st(Vt, T, a, op1, op2);                                          \
+    ld_st(Vt, T, a, op1, op2, 2);                                       \
   }
 
 #define INSN3(NAME, op1, op2)                                           \
@@ -2100,7 +2113,7 @@
             SIMD_Arrangement T, const Address &a) {                     \
     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3,           \
            "Registers must be ordered");                                \
-    ld_st(Vt, T, a, op1, op2);                                          \
+    ld_st(Vt, T, a, op1, op2, 3);                                       \
   }
 
 #define INSN4(NAME, op1, op2)                                           \
@@ -2108,7 +2121,7 @@
             FloatRegister Vt4, SIMD_Arrangement T, const Address &a) {  \
     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 &&         \
            Vt3->successor() == Vt4, "Registers must be ordered");       \
-    ld_st(Vt, T, a, op1, op2);                                          \
+    ld_st(Vt, T, a, op1, op2, 4);                                       \
   }
 
   INSN1(ld1,  0b001100010, 0b0111);