]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
x86 and amd64 back ends: when generating transfers back to the
authorJulian Seward <jseward@acm.org>
Sun, 29 May 2011 09:29:18 +0000 (09:29 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 29 May 2011 09:29:18 +0000 (09:29 +0000)
dispatcher, generate a jump either to the unassisted (GSP unchanged,
the common case) or assisted (GSP changed, request some action before
continuing) dispatcher.  This removes two instructions per dispatch
for the common case.  Changes for all other targets are interface-only
changes due to change in type of the emit_XXInstr functions.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2155

12 files changed:
VEX/priv/host_amd64_defs.c
VEX/priv/host_amd64_defs.h
VEX/priv/host_arm_defs.c
VEX/priv/host_arm_defs.h
VEX/priv/host_ppc_defs.c
VEX/priv/host_ppc_defs.h
VEX/priv/host_s390_defs.c
VEX/priv/host_s390_defs.h
VEX/priv/host_x86_defs.c
VEX/priv/host_x86_defs.h
VEX/priv/main_main.c
VEX/pub/libvex.h

index 3510927cd92c3e2635bcebec74562b6071690f8d..90119f2b172d596f5603a93d1f9177a3a18989ce 100644 (file)
@@ -2303,7 +2303,9 @@ static UChar* do_ffree_st ( UChar* p, Int n )
    imperative to emit position-independent code. */
 
 Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i, 
-                      Bool mode64, void* dispatch )
+                      Bool mode64,
+                      void* dispatch_unassisted,
+                      void* dispatch_assisted )
 {
    UInt /*irno,*/ opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
    UInt   xtra;
@@ -2716,7 +2718,11 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i,
       goto done;
    }
 
-   case Ain_Goto:
+   case Ain_Goto: {
+      void* dispatch_to_use = NULL;
+      vassert(dispatch_unassisted != NULL);
+      vassert(dispatch_assisted != NULL);
+
       /* Use ptmp for backpatching conditional jumps. */
       ptmp = NULL;
 
@@ -2732,7 +2738,10 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i,
       /* If a non-boring, set %rbp (the guest state pointer)
          appropriately.  Since these numbers are all small positive
          integers, we can get away with "movl $N, %ebp" rather than
-         the longer "movq $N, %rbp". */
+         the longer "movq $N, %rbp".  Also, decide which dispatcher we
+         need to use. */
+      dispatch_to_use = dispatch_assisted;
+
       /* movl $magic_number, %ebp */
       switch (i->Ain.Goto.jk) {
          case Ijk_ClientReq: 
@@ -2771,6 +2780,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i,
          case Ijk_Ret:
          case Ijk_Call:
          case Ijk_Boring:
+            dispatch_to_use = dispatch_unassisted;
             break;
          default: 
             ppIRJumpKind(i->Ain.Goto.jk);
@@ -2798,19 +2808,18 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i,
          after the load of %rax since %rdx might be carrying the value
          destined for %rax immediately prior to this Ain_Goto. */
       vassert(sizeof(ULong) == sizeof(void*));
-      vassert(dispatch != NULL);
 
-      if (fitsIn32Bits(Ptr_to_ULong(dispatch))) {
+      if (fitsIn32Bits(Ptr_to_ULong(dispatch_to_use))) {
          /* movl sign-extend(imm32), %rdx */
          *p++ = 0x48;
          *p++ = 0xC7;
          *p++ = 0xC2;
-         p = emit32(p, (UInt)Ptr_to_ULong(dispatch));
+         p = emit32(p, (UInt)Ptr_to_ULong(dispatch_to_use));
       } else {
          /* movabsq $imm64, %rdx */
          *p++ = 0x48;
          *p++ = 0xBA;
-         p = emit64(p, Ptr_to_ULong(dispatch));
+         p = emit64(p, Ptr_to_ULong(dispatch_to_use));
       }
       /* jmp *%rdx */
       *p++ = 0xFF;
@@ -2823,6 +2832,7 @@ Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i,
          *ptmp = toUChar(delta-1);
       }
       goto done;
+   }
 
    case Ain_CMov64:
       vassert(i->Ain.CMov64.cond != Acc_ALWAYS);
index cf19bac109407867cfc7cac7f0486ceedea25a7a..eecb24bbf5a434a9d1cdae815085e611fc773edc 100644 (file)
@@ -734,7 +734,9 @@ extern void         getRegUsage_AMD64Instr ( HRegUsage*, AMD64Instr*, Bool );
 extern void         mapRegs_AMD64Instr     ( HRegRemap*, AMD64Instr*, Bool );
 extern Bool         isMove_AMD64Instr      ( AMD64Instr*, HReg*, HReg* );
 extern Int          emit_AMD64Instr        ( UChar* buf, Int nbuf, AMD64Instr*, 
-                                             Bool, void* dispatch );
+                                             Bool,
+                                             void* dispatch_unassisted,
+                                             void* dispatch_assisted );
 
 extern void genSpill_AMD64  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
                               HReg rreg, Int offset, Bool );
index bf994d60cbebbd316f0f38f1aeac06310b8f2078..fd3719756b1517320a0a0066e49101c7a97369b9 100644 (file)
@@ -2672,14 +2672,13 @@ static UInt* imm32_to_iregNo ( UInt* p, Int rD, UInt imm32 )
 
 
 Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
-                    Bool mode64, void* dispatch ) 
+                    Bool mode64,
+                    void* dispatch_unassisted, void* dispatch_assisted ) 
 {
    UInt* p = (UInt*)buf;
    vassert(nbuf >= 32);
    vassert(mode64 == False);
    vassert(0 == (((HWord)buf) & 3));
-   /* since we branch to lr(r13) to get back to dispatch: */
-   vassert(dispatch == NULL);
 
    switch (i->tag) {
       case ARMin_Alu: {
@@ -2867,6 +2866,9 @@ Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
          ARMCondCode cond  = i->ARMin.Goto.cond;
          UInt        rnext = iregNo(i->ARMin.Goto.gnext);
          Int         trc   = -1;
+         /* since we branch to lr(r13) to get back to dispatch: */
+         vassert(dispatch_unassisted == NULL);
+         vassert(dispatch_assisted == NULL);
          switch (jk) {
             case Ijk_Ret: case Ijk_Call: case Ijk_Boring:
                break; /* no need to set GST in these common cases */
index e65203c2815d057ad23a21cdeb47aab521019624..b96ec3ab23e7cab4d1cf53a4a89dc2394d2864ad 100644 (file)
@@ -960,7 +960,9 @@ extern void getRegUsage_ARMInstr ( HRegUsage*, ARMInstr*, Bool );
 extern void mapRegs_ARMInstr     ( HRegRemap*, ARMInstr*, Bool );
 extern Bool isMove_ARMInstr      ( ARMInstr*, HReg*, HReg* );
 extern Int  emit_ARMInstr        ( UChar* buf, Int nbuf, ARMInstr*, 
-                                   Bool, void* dispatch );
+                                   Bool,
+                                   void* dispatch_unassisted,
+                                   void* dispatch_assisted );
 
 extern void genSpill_ARM  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
                             HReg rreg, Int offset, Bool );
index c28fc62159af4ada0ef4742c394a197f70021ed8..6fc8902f6b1f56296ad0dbc35056fbfece5ccc8f 100644 (file)
@@ -2653,7 +2653,8 @@ static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
    code and back.
 */
 Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i, 
-                    Bool mode64, void* dispatch )
+                    Bool mode64,
+                    void* dispatch_unassisted, void* dispatch_assisted )
 {
    UChar* p = &buf[0];
    UChar* ptmp = p;
@@ -3042,7 +3043,8 @@ Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i,
       UInt r_dst;
       ULong imm_dst;
 
-      vassert(dispatch == NULL);
+      vassert(dispatch_unassisted == NULL);
+      vassert(dispatch_assisted == NULL);
       
       /* First off, if this is conditional, create a conditional
          jump over the rest of it. */
index ba9e96315a297c3e27f1a83fd0914330241ad95c..f4ac9bbe67c9b140900fb8cee3dd8f273f12506a 100644 (file)
@@ -847,7 +847,9 @@ extern void         getRegUsage_PPCInstr ( HRegUsage*, PPCInstr*, Bool mode64 );
 extern void         mapRegs_PPCInstr     ( HRegRemap*, PPCInstr* , Bool mode64);
 extern Bool         isMove_PPCInstr      ( PPCInstr*, HReg*, HReg* );
 extern Int          emit_PPCInstr        ( UChar* buf, Int nbuf, PPCInstr*, 
-                                           Bool mode64, void* dispatch );
+                                           Bool mode64,
+                                           void* dispatch_unassisted,
+                                           void* dispatch_assisted );
 
 extern void genSpill_PPC  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
                             HReg rreg, Int offsetB, Bool mode64 );
index 5e50d8f472e8e3c763156e67ddefc8e84289d7db..4067de1aef0bdb3995fbf6da2eab2f01794f497f 100644 (file)
@@ -7021,7 +7021,8 @@ s390_insn_mfence_emit(UChar *buf, const s390_insn *insn)
 
 Int
 emit_S390Instr(UChar *buf, Int nbuf, struct s390_insn *insn,
-               Bool mode64, void *dispatch)
+               Bool mode64,
+               void *dispatch_unassisted, void *dispatch_assisted)
 {
    UChar *end;
 
@@ -7087,6 +7088,8 @@ emit_S390Instr(UChar *buf, Int nbuf, struct s390_insn *insn,
       break;
 
    case S390_INSN_BRANCH:
+      vassert(dispatch_unassisted == NULL);
+      vassert(dispatch_assisted == NULL);
       end = s390_insn_branch_emit(buf, insn);
       break;
 
index 3067172e7a3196dfd68d53df781ebd2f7869b93a..475e2eb1eafd1e96237a47b46d6d94aacc1b2088 100644 (file)
@@ -474,7 +474,8 @@ void ppHRegS390(HReg);
 void  getRegUsage_S390Instr( HRegUsage *, struct s390_insn *, Bool );
 void  mapRegs_S390Instr    ( HRegRemap *, struct s390_insn *, Bool );
 Bool  isMove_S390Instr     ( struct s390_insn *, HReg *, HReg * );
-Int   emit_S390Instr       ( UChar *, Int, struct s390_insn *, Bool, void * );
+Int   emit_S390Instr       ( UChar *, Int, struct s390_insn *, Bool,
+                             void *, void * );
 void  getAllocableRegs_S390( Int *, HReg **, Bool );
 void  genSpill_S390        ( HInstr **, HInstr **, HReg , Int , Bool );
 void  genReload_S390       ( HInstr **, HInstr **, HReg , Int , Bool );
index 9a6d6515c9c836c35cc8b05f08acace187c85db0..f6ea911ff669f9e7597553956676870d37e4519c 100644 (file)
@@ -1989,7 +1989,9 @@ static UChar* push_word_from_tags ( UChar* p, UShort tags )
    imperative to emit position-independent code. */
 
 Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i, 
-                    Bool mode64, void* dispatch )
+                    Bool mode64,
+                    void* dispatch_unassisted,
+                    void* dispatch_assisted )
 {
    UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
 
@@ -2304,7 +2306,11 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i,
       *p++ = toUChar(0xD0 + irno);
       goto done;
 
-   case Xin_Goto:
+   case Xin_Goto: {
+      void* dispatch_to_use = NULL;
+      vassert(dispatch_unassisted != NULL);
+      vassert(dispatch_assisted != NULL);
+
       /* Use ptmp for backpatching conditional jumps. */
       ptmp = NULL;
 
@@ -2318,7 +2324,10 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i,
       }
 
       /* If a non-boring, set %ebp (the guest state pointer)
-         appropriately. */
+         appropriately.  Also, decide which dispatcher we need to
+         use. */
+      dispatch_to_use = dispatch_assisted;
+
       /* movl $magic_number, %ebp */
       switch (i->Xin.Goto.jk) {
          case Ijk_ClientReq: 
@@ -2363,6 +2372,7 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i,
          case Ijk_Ret:
         case Ijk_Call:
          case Ijk_Boring:
+            dispatch_to_use = dispatch_unassisted;
             break;
          default: 
             ppIRJumpKind(i->Xin.Goto.jk);
@@ -2387,10 +2397,10 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i,
          after the load of %eax since %edx might be carrying the value
          destined for %eax immediately prior to this Xin_Goto. */
       vassert(sizeof(UInt) == sizeof(void*));
-      vassert(dispatch != NULL);
+      vassert(dispatch_to_use != NULL);
       /* movl $imm32, %edx */
       *p++ = 0xBA;
-      p = emit32(p, (UInt)Ptr_to_ULong(dispatch));
+      p = emit32(p, (UInt)Ptr_to_ULong(dispatch_to_use));
 
       /* jmp *%edx */
       *p++ = 0xFF;
@@ -2403,6 +2413,7 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i,
          *ptmp = toUChar(delta-1);
       }
       goto done;
+   }
 
    case Xin_CMov32:
       vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
index fde700a90b5d4869338c60cb48cb7e4fc93c42fa..e87cd4c22b2158bc2e916adfaacdb4832a609e47 100644 (file)
@@ -673,7 +673,9 @@ extern void         getRegUsage_X86Instr ( HRegUsage*, X86Instr*, Bool );
 extern void         mapRegs_X86Instr     ( HRegRemap*, X86Instr*, Bool );
 extern Bool         isMove_X86Instr      ( X86Instr*, HReg*, HReg* );
 extern Int          emit_X86Instr        ( UChar* buf, Int nbuf, X86Instr*, 
-                                           Bool, void* dispatch );
+                                           Bool,
+                                           void* dispatch_unassisted,
+                                           void* dispatch_assisted );
 
 extern void genSpill_X86  ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
                             HReg rreg, Int offset, Bool );
index 9d939017cd4c68495473b3181cb959a6eeecd77c..3924f95a167633c8c8e902aee918d698dfff9d06 100644 (file)
@@ -185,7 +185,7 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
    void         (*ppReg)        ( HReg );
    HInstrArray* (*iselSB)       ( IRSB*, VexArch, VexArchInfo*, 
                                                   VexAbiInfo* );
-   Int          (*emit)         ( UChar*, Int, HInstr*, Bool, void* );
+   Int          (*emit)         ( UChar*, Int, HInstr*, Bool, void*, void* );
    IRExpr*      (*specHelper)   ( HChar*, IRExpr**, IRStmt**, Int );
    Bool         (*preciseMemExnsFn) ( Int, Int );
 
@@ -252,11 +252,14 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          ppInstr      = (void(*)(HInstr*, Bool)) ppX86Instr;
          ppReg        = (void(*)(HReg)) ppHRegX86;
          iselSB       = iselSB_X86;
-         emit         = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
+         emit         = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+                        emit_X86Instr;
          host_is_bigendian = False;
          host_word_type    = Ity_I32;
          vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
-         vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
+         /* jump-to-dispatcher scheme */
+         vassert(vta->dispatch_unassisted != NULL);
+         vassert(vta->dispatch_assisted != NULL);
          break;
 
       case VexArchAMD64:
@@ -274,11 +277,14 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          ppInstr     = (void(*)(HInstr*, Bool)) ppAMD64Instr;
          ppReg       = (void(*)(HReg)) ppHRegAMD64;
          iselSB      = iselSB_AMD64;
-         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
+         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+                       emit_AMD64Instr;
          host_is_bigendian = False;
          host_word_type    = Ity_I64;
          vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
-         vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
+         /* jump-to-dispatcher scheme */
+         vassert(vta->dispatch_unassisted != NULL);
+         vassert(vta->dispatch_assisted != NULL);
          break;
 
       case VexArchPPC32:
@@ -293,11 +299,14 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          ppInstr     = (void(*)(HInstr*,Bool)) ppPPCInstr;
          ppReg       = (void(*)(HReg)) ppHRegPPC;
          iselSB      = iselSB_PPC;
-         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
+         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+                       emit_PPCInstr;
          host_is_bigendian = True;
          host_word_type    = Ity_I32;
          vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
-         vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+         /* return-to-dispatcher scheme */
+         vassert(vta->dispatch_unassisted == NULL);
+         vassert(vta->dispatch_assisted == NULL);
          break;
 
       case VexArchPPC64:
@@ -312,11 +321,14 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          ppInstr     = (void(*)(HInstr*, Bool)) ppPPCInstr;
          ppReg       = (void(*)(HReg)) ppHRegPPC;
          iselSB      = iselSB_PPC;
-         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
+         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+                       emit_PPCInstr;
          host_is_bigendian = True;
          host_word_type    = Ity_I64;
          vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
-         vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+         /* return-to-dispatcher scheme */
+         vassert(vta->dispatch_unassisted == NULL);
+         vassert(vta->dispatch_assisted == NULL);
          break;
 
       case VexArchS390X:
@@ -331,11 +343,14 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          ppInstr     = (void(*)(HInstr*, Bool)) ppS390Instr;
          ppReg       = (void(*)(HReg)) ppHRegS390;
          iselSB      = iselSB_S390;
-         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_S390Instr;
+         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+                       emit_S390Instr;
          host_is_bigendian = True;
          host_word_type    = Ity_I64;
          vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
-         vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+         /* return-to-dispatcher scheme */
+         vassert(vta->dispatch_unassisted == NULL);
+         vassert(vta->dispatch_assisted == NULL);
          break;
 
       case VexArchARM:
@@ -350,11 +365,14 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          ppInstr     = (void(*)(HInstr*, Bool)) ppARMInstr;
          ppReg       = (void(*)(HReg)) ppHRegARM;
          iselSB      = iselSB_ARM;
-         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr;
+         emit        = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+                       emit_ARMInstr;
          host_is_bigendian = False;
          host_word_type    = Ity_I32;
          vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
-         vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+         vassert(vta->dispatch_unassisted == NULL);
+         vassert(vta->dispatch_assisted == NULL);
+         /* return-to-dispatcher scheme */
          break;
 
       default:
@@ -683,7 +701,7 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
          vex_printf("\n");
       }
       j = (*emit)( insn_bytes, sizeof insn_bytes, rcode->arr[i], mode64,
-                   vta->dispatch );
+                   vta->dispatch_unassisted, vta->dispatch_assisted );
       if (vex_traceflags & VEX_TRACE_ASM) {
          for (k = 0; k < j; k++)
             if (insn_bytes[k] < 16)
index 1e2b386683a5d79ea88e83c668d8efb631c378ac..f9056401573c07a28dcca9cc8b59682ea9764993 100644 (file)
@@ -552,8 +552,8 @@ typedef
       /* IN: debug: trace vex activity at various points */
       Int     traceflags;
 
-      /* IN: address of the dispatcher entry point.  Describes the
-         place where generated code should jump to at the end of each
+      /* IN: address of the dispatcher entry points.  Describes the
+         places where generated code should jump to at the end of each
          bb.
 
          At the end of each translation, the next guest address is
@@ -567,19 +567,26 @@ typedef
          control; caller supplies this) in the following way:
 
          - On host archs which lack a link register (x86, amd64), by a
-           jump to the host address specified in 'dispatcher', which
-           must be non-NULL.
+           jump to the host address specified in
+           'dispatcher_assisted', if the guest state pointer has been
+           changed so as to request some action before the next block
+           is run, or 'dispatcher_unassisted' (the fast path), in
+           which it is assumed that the guest state pointer is
+           unchanged and we wish to continue directly with the next
+           translation.  Both of these must be non-NULL.
 
          - On host archs which have a link register (ppc32, ppc64), by
            a branch to the link register (which is guaranteed to be
            unchanged from whatever it was at entry to the
-           translation).  'dispatch' must be NULL.
+           translation).  'dispatch_assisted' and
+           'dispatch_unassisted' must be NULL.
 
          The aim is to get back and forth between translations and the
          dispatcher without creating memory traffic to store return
          addresses.
       */
-      void* dispatch;
+      void* dispatch_unassisted;
+      void* dispatch_assisted;
    }
    VexTranslateArgs;