Implement unchainXDirect_ARM64.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2822 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_arm64_defs.c b/priv/host_arm64_defs.c
index 21e1281..44773b3 100644
--- a/priv/host_arm64_defs.c
+++ b/priv/host_arm64_defs.c
@@ -6264,6 +6264,7 @@
    vassert(is_imm64_to_iregNo_EXACTLY4(
               p, /*x*/9, Ptr_to_ULong(disp_cp_chain_me_EXPECTED)));
    vassert(p[4] == 0xD63F0120);
+
    /* And what we want to change it to is:
         movw x9, place_to_jump_to[15:0]
         movk x9, place_to_jump_to[31:15], lsl 16
@@ -6276,7 +6277,6 @@
 
       The replacement has the same length as the original.
    */
-
    (void)imm64_to_iregNo_EXACTLY4(
             p, /*x*/9, Ptr_to_ULong(place_to_jump_to));
    p[4] = 0xD61F0120;
@@ -6286,67 +6286,47 @@
 }
 
 
-//ZZ /* NB: what goes on here has to be very closely coordinated with the
-//ZZ    emitInstr case for XDirect, above. */
-//ZZ VexInvalRange unchainXDirect_ARM ( void* place_to_unchain,
-//ZZ                                    void* place_to_jump_to_EXPECTED,
-//ZZ                                    void* disp_cp_chain_me )
-//ZZ {
-//ZZ    /* What we're expecting to see is:
-//ZZ         (general case)
-//ZZ           movw r12, lo16(place_to_jump_to_EXPECTED)
-//ZZ           movt r12, lo16(place_to_jump_to_EXPECTED)
-//ZZ           bx   r12
-//ZZ         viz
-//ZZ           <8 bytes generated by imm32_to_iregNo_EXACTLY2>
-//ZZ           E1 2F FF 1C
-//ZZ       ---OR---
-//ZZ         in the case where the displacement falls within 26 bits
-//ZZ           b disp24; undef; undef
-//ZZ         viz
-//ZZ           EA <3 bytes == disp24>
-//ZZ           FF 00 00 00
-//ZZ           FF 00 00 00
-//ZZ    */
-//ZZ    UInt* p = (UInt*)place_to_unchain;
-//ZZ    vassert(0 == (3 & (HWord)p));
-//ZZ 
-//ZZ    Bool valid = False;
-//ZZ    if (is_imm32_to_iregNo_EXACTLY2(
-//ZZ           p, /*r*/12, (UInt)Ptr_to_ULong(place_to_jump_to_EXPECTED))
-//ZZ        && p[2] == 0xE12FFF1C) {
-//ZZ       valid = True; /* it's the long form */
-//ZZ       if (0)
-//ZZ          vex_printf("QQQ unchainXDirect_ARM: found long form\n");
-//ZZ    } else
-//ZZ    if ((p[0] >> 24) == 0xEA && p[1] == 0xFF000000 && p[2] == 0xFF000000) {
-//ZZ       /* It's the short form.  Check the displacement is right. */
-//ZZ       Int simm24 = p[0] & 0x00FFFFFF;
-//ZZ       simm24 <<= 8; simm24 >>= 8;
-//ZZ       if ((UChar*)p + (simm24 << 2) + 8 == (UChar*)place_to_jump_to_EXPECTED) {
-//ZZ          valid = True;
-//ZZ          if (0)
-//ZZ             vex_printf("QQQ unchainXDirect_ARM: found short form\n");
-//ZZ       }
-//ZZ    }
-//ZZ    vassert(valid);
-//ZZ 
-//ZZ    /* And what we want to change it to is:
-//ZZ         movw r12, lo16(disp_cp_chain_me)
-//ZZ         movt r12, hi16(disp_cp_chain_me)
-//ZZ         blx  r12
-//ZZ       viz
-//ZZ         <8 bytes generated by imm32_to_iregNo_EXACTLY2>
-//ZZ         E1 2F FF 3C
-//ZZ    */
-//ZZ    (void)imm32_to_iregNo_EXACTLY2(
-//ZZ             p, /*r*/12, (UInt)Ptr_to_ULong(disp_cp_chain_me));
-//ZZ    p[2] = 0xE12FFF3C;
-//ZZ    VexInvalRange vir = {(HWord)p, 12};
-//ZZ    return vir;
-//ZZ }
-//ZZ 
-//ZZ 
+/* NB: what goes on here has to be very closely coordinated with the
+   emitInstr case for XDirect, above. */
+VexInvalRange unchainXDirect_ARM64 ( void* place_to_unchain,
+                                     void* place_to_jump_to_EXPECTED,
+                                     void* disp_cp_chain_me )
+{
+   /* What we're expecting to see is:
+        movw x9, place_to_jump_to_EXPECTED[15:0]
+        movk x9, place_to_jump_to_EXPECTED[31:15], lsl 16
+        movk x9, place_to_jump_to_EXPECTED[47:32], lsl 32
+        movk x9, place_to_jump_to_EXPECTED[63:48], lsl 48
+        br   x9
+      viz
+        <16 bytes generated by imm64_to_iregNo_EXACTLY4>
+        D6 1F 01 20
+   */
+   UInt* p = (UInt*)place_to_unchain;
+   vassert(0 == (3 & (HWord)p));
+   vassert(is_imm64_to_iregNo_EXACTLY4(
+              p, /*x*/9, Ptr_to_ULong(place_to_jump_to_EXPECTED)));
+   vassert(p[4] == 0xD61F0120);
+
+   /* And what we want to change it to is:
+        movw x9, disp_cp_chain_me_to[15:0]
+        movk x9, disp_cp_chain_me_to[31:15], lsl 16
+        movk x9, disp_cp_chain_me_to[47:32], lsl 32
+        movk x9, disp_cp_chain_me_to[63:48], lsl 48
+        blr  x9
+      viz
+        <16 bytes generated by imm64_to_iregNo_EXACTLY4>
+        D6 3F 01 20
+   */
+   (void)imm64_to_iregNo_EXACTLY4(
+            p, /*x*/9, Ptr_to_ULong(disp_cp_chain_me));
+   p[4] = 0xD63F0120;
+
+   VexInvalRange vir = {(HWord)p, 20};
+   return vir;
+}
+
+
 //ZZ /* Patch the counter address into a profile inc point, as previously
 //ZZ    created by the ARMin_ProfInc case for emit_ARMInstr. */
 //ZZ VexInvalRange patchProfInc_ARM ( void*  place_to_patch,
diff --git a/priv/host_arm64_defs.h b/priv/host_arm64_defs.h
index b6e4da8..c841171 100644
--- a/priv/host_arm64_defs.h
+++ b/priv/host_arm64_defs.h
@@ -1116,10 +1116,10 @@
                                           void* disp_cp_chain_me_EXPECTED,
                                           void* place_to_jump_to );
 
-//ZZ extern VexInvalRange unchainXDirect_ARM ( void* place_to_unchain,
-//ZZ                                           void* place_to_jump_to_EXPECTED,
-//ZZ                                           void* disp_cp_chain_me );
-//ZZ 
+extern VexInvalRange unchainXDirect_ARM64 ( void* place_to_unchain,
+                                            void* place_to_jump_to_EXPECTED,
+                                            void* disp_cp_chain_me );
+
 //ZZ /* Patch the counter location into an existing ProfInc point. */
 //ZZ extern VexInvalRange patchProfInc_ARM ( void*  place_to_patch,
 //ZZ                                         ULong* location_of_counter );
diff --git a/priv/main_main.c b/priv/main_main.c
index 2ca1df1..93ca478 100644
--- a/priv/main_main.c
+++ b/priv/main_main.c
@@ -1048,6 +1048,8 @@
          unchainXDirect = unchainXDirect_AMD64; break;
       case VexArchARM:
          unchainXDirect = unchainXDirect_ARM; break;
+      case VexArchARM64:
+         unchainXDirect = unchainXDirect_ARM64; break;
       case VexArchS390X:
          unchainXDirect = unchainXDirect_S390; break;
       case VexArchPPC32: