]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Translation chaining for s390. To be debugged.
authorFlorian Krohm <florian@eich-krohm.de>
Fri, 13 Apr 2012 04:04:44 +0000 (04:04 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Fri, 13 Apr 2012 04:04:44 +0000 (04:04 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/branches/TCHAIN@12502

coregrind/m_dispatch/dispatch-s390x-linux.S

index 80036d683dc7c36a9a19c79b02286cbc8c447280..5cc517fd89aa4fa909c7fb8ba0d602c9a3fafe7d 100644 (file)
@@ -9,7 +9,8 @@
   framework.
 
   Copyright IBM Corp. 2010-2011
-
+  Copyright 2011-2012, Florian Krohm (britzel@acm.org)
+        
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
 
 #if defined(VGA_s390x)
 
+/*
+#define XINDIR_STATS
+*/
+
 /*------------------------------------------------------------*/
 /*---                                                      ---*/
-/*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
-/*--- run all translations except no-redir ones.           ---*/
+/*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
+/*--- used to run all translations,                        ---*/
+/*--- including no-redir ones.                             ---*/
 /*---                                                      ---*/
 /*------------------------------------------------------------*/
 
 /* Location of valgrind's saved FPC register */
 #define S390_LOC_SAVED_FPC_V S390_OFFSET_SAVED_FPC_V(SP)
 
-/* Location of saved guest state pointer */
-#define S390_LOC_SAVED_GSP S390_OFFSET_SAVED_GSP(SP)
-
 /* Location of saved R2 register */
 #define S390_LOC_SAVED_R2 S390_OFFSET_SAVED_R2(SP)
 
+
 /*----------------------------------------------------*/
-/*--- Preamble (set everything up)                 ---*/
+/*--- Entry and preamble (set everything up)       ---*/
 /*----------------------------------------------------*/
 
 /* signature:
-UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
+void VG_(disp_run_translations)( UWord* two_words,
+                                 void*  guest_state, 
+                                 Addr   host_addr );
+
+        Return results are placed in two_words:
+        
+        two_words[0] is set to the TRC
+        two_words[1] is set to the address to patch (in case two_words[0] is
+                     VG_TRC_CHAIN_ME_TO_{SLOW,FAST}_EP). Otherwise, it is 0.
 */
+        .text
+        .align   4
+        .globl   VG_(disp_run_translations)
+        .type    VG_(disp_run_translations), @function
+VG_(disp_run_translations):
 
-.text
-.align   4
-.globl VG_(run_innerloop)
-VG_(run_innerloop):
-        /* r2 holds address of guest_state */
-        /* r3 holds do_profiling (a flag) */
+        /* r2 holds two_words */
+        /* r3 holds pointer to guest_state */
+        /* r4 holds host_addr, i.e. the address of the translation to run */
 
         /* Save gprs   ABI: r6...r13 and r15 */
-        stmg %r6,%r15,48(SP)
+        stmg  %r6,%r15,48(SP)
 
         /* New stack frame */
-        aghi SP,-S390_INNERLOOP_FRAME_SIZE
+        aghi  SP,-S390_INNERLOOP_FRAME_SIZE
 
         /* Save fprs:   ABI: f8...f15 */
-        std  %f8,160+0(SP)
-        std  %f9,160+8(SP)
-        std  %f10,160+16(SP)
-        std  %f11,160+24(SP)
-        std  %f12,160+32(SP)
-        std  %f13,160+40(SP)
-        std  %f14,160+48(SP)
-        std  %f15,160+56(SP)
+        std   %f8,160+0(SP)
+        std   %f9,160+8(SP)
+        std   %f10,160+16(SP)
+        std   %f11,160+24(SP)
+        std   %f12,160+32(SP)
+        std   %f13,160+40(SP)
+        std   %f14,160+48(SP)
+        std   %f15,160+56(SP)
 
         /* Load address of guest state into guest state register (r13) */
-        lgr  %r13,%r2
+        lgr   %r13,%r3
 
-        /* Store address of guest state pointer on stack.
-           It will be needed later because upon return from a VEX translation
-           r13 may contain a special value. So the old value will be used to
-           determine whether r13 contains a special value. */
-        stg  %r13,S390_LOC_SAVED_GSP
-
-        /* Save valgrind's FPC on stack so run_innerloop_exit can restore
+        /* Save R2 on stack. In postamble it will be restored such that the
+           return values can be written */
+        stg   %r2,S390_LOC_SAVED_R2
+        
+        /* Save valgrind's FPC on stack so postamble can restore
            it later . */
         stfpc S390_LOC_SAVED_FPC_V
 
         /* Load the FPC the way the client code wants it. I.e. pull the
            value from the guest state. */
-        lfpc OFFSET_s390x_fpc(%r13)
-
-        /* Get the IA from the guest state */
-        lg   %r2,OFFSET_s390x_IA(%r13)
+        lfpc  OFFSET_s390x_fpc(%r13)
 
-        /* Get VG_(dispatch_ctr) -- a 32-bit value -- and store it in a reg */
-        larl %r6,VG_(dispatch_ctr)
-        l    S390_REGNO_DISPATCH_CTR,0(%r6)
+        /* Jump into the code cache.  Chained translations in
+           the code cache run, until for whatever reason, they can't
+           continue.  When that happens, the translation in question
+           will jump (or call) to one of the continuation points
+           VG_(cp_...) below. */
+        br    %r4
 
-        /* Fall into main loop (the right one) */
-
-        /* r3 = 1 --> do_profiling. We may trash r3 later on. That's OK,
-           because it's a volatile register (does not need to be preserved). */
-        ltgr %r3,%r3
-        je   run_innerloop__dispatch_unprofiled
-        j    run_innerloop__dispatch_profiled
 
 /*----------------------------------------------------*/
-/*--- NO-PROFILING (standard) dispatcher           ---*/
+/*--- Postamble and return to C code.              ---*/
 /*----------------------------------------------------*/
 
-run_innerloop__dispatch_unprofiled:
-        /* Load the link register with the address the jitted code will
-           return to when it's done executing. The link register is loaded
-           exactly once per loop. This is safe, because the jitted code 
-           cannot possibly modify the LR. How else would it be able to return
-           to the location in the LR otherwise? */
-        basr LR,0
+postamble:
+        /* At this point, %r0 and %r1 contain two
+           words to be returned to the caller.  %r0
+           holds a TRC value, and %r1 optionally may
+           hold another word (for CHAIN_ME exits, the
+           address of the place to patch.) */
+
+        /* We're leaving. AMD has some code here to check invariants.
+           We don't have (need) that, as we save and restore the FPC register
+           whenever we switch between valgrind proper to client code. */
+
+       /* Restore valgrind's FPC, as client code may have changed it. */
+        lfpc S390_LOC_SAVED_FPC_V
+
+        /* Restore %r2 from stack; holds address of two_words */
+        lg   %r2,S390_LOC_SAVED_R2
 
-        /* Loop begins here */
+        stg  %r0,0(%r2)         /* Store %r0 to two_words[0] */
+        stg  %r1,8(%r2)         /* Store %r1 to two_words[1] */
         
-        /* This is the story:
+        /* Restore callee-saved registers... */
 
-           r2  = IA = next guest address
-           r12 = VG_(dispatch_ctr)
-           r13 = guest state pointer or (upon return from guest code) some
-                 special value
-           r15 = stack pointer (as usual)
-        */
-innermost_loop: 
-        /* Has the guest state pointer been messed with? If yes, exit.
-           The mess is recognised by r13 containing an odd value. */
-        tmll %r13,1
-        jne  gsp_changed
+        /* Floating-point regs */
+        ld   %f8,160+0(SP)
+        ld   %f9,160+8(SP)
+        ld   %f10,160+16(SP)
+        ld   %f11,160+24(SP)
+        ld   %f12,160+32(SP)
+        ld   %f13,160+40(SP)
+        ld   %f14,160+48(SP)
+        ld   %f15,160+56(SP)
+
+        /* Remove stack frame */
+        aghi SP,S390_INNERLOOP_FRAME_SIZE
+
+        /* General-purpose regs. This also restores the original link
+           register (r14) and stack pointer (r15). */
+        lmg  %r6,%r15,48(SP)
 
-        /* Save the jump address in the guest state */
-        stg  %r2,OFFSET_s390x_IA(%r13)
+        /* Return */
+        br   LR
+        
+        
+/*----------------------------------------------------*/
+/*--- Continuation points                          ---*/
+/*----------------------------------------------------*/
 
+/* ------ Chain me to slow entry point ------ */
+        .global VG_(disp_cp_chain_me_to_slowEP)
+VG_(disp_cp_chain_me_to_slowEP):
+        /* We got called via  BASR  %r1,tchain_scratch, i.e. %r1 is the return
+           address. Collect it, compute the place to patch and return to C land.
+           The return values (TRC, address-to-patch) are stored here in %r0 and %r1,
+           respectively */
+        lghi    %r0,VG_TRC_CHAIN_ME_TO_SLOW_EP
+        /* Recover the address where patching needs to happen */
+        /* FIXME: this is not good as it implies that LOAD64_LEN is fixed. But
+           we want it to be variable such that newer machines can take advantage
+           of hardware capabilities. So it would be better if this adjustment is
+           done before transfering control to here. */
+        aghi    %r1,-(S390_TCHAIN_LOAD64_LEN + S390_TCHAIN_CALL_LEN)
+        j       postamble
+
+
+/* ------ Chain me to fast entry point ------ */
+        .global VG_(disp_cp_chain_me_to_fastEP)
+VG_(disp_cp_chain_me_to_fastEP):
+        /* Identical to VG_(disp_cp_chain_me_to_slowEP), except value of %r0. */
+
+        lghi    %r0,VG_TRC_CHAIN_ME_TO_FAST_EP
+        aghi    %r1,-(S390_TCHAIN_LOAD64_LEN + S390_TCHAIN_CALL_LEN)
+        j       postamble
+
+
+/* ------ Indirect but boring jump ------ */
+        .global VG_(disp_cp_xindir)
+VG_(disp_cp_xindir):
+       /* Where are we going? */
+        lg      %r2, OFFSET_s390x_IA(%r13)
+
+#ifdef XINDIR_STATS
+        /* Increment VG_(stats__n_xindirs), an ULong value */
+        larl    %r8, VG_(stats__n_xindirs)
+        lg      %r10,0(%r8)
+        aghi    %r10,1
+        stg     %r10,0(%r8)
+#endif
 
        /* Try a fast lookup in the translation cache:
            Compute offset (not index) into VT_(tt_fast):
@@ -168,204 +233,61 @@ innermost_loop:
            which is
            offset = ((addr & (VG_TT_FAST_MASK << 1) ) << 3
         */
-        larl  %r8, VG_(tt_fast)
-        llill %r5,( VG_TT_FAST_MASK << 1) & 0xffff
+        larl    %r8, VG_(tt_fast)
+        llill   %r5,(VG_TT_FAST_MASK << 1) & 0xffff
 #if ((( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16 != 0)
-        iilh %r5,(( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16
+        iilh    %r5,((VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16
 #endif
-        ngr  %r5,%r2
-        sllg %r7,%r5,3
-
-       /* Are we out of timeslice?  If yes, defer to scheduler. */
-        ahi  S390_REGNO_DISPATCH_CTR,-1
-        jz   counter_is_zero
-
-        lg   %r11, 8(%r8,%r7)      /* .host */
-        cg   %r2,  0(%r8,%r7)      /* next guest address == .guest ? */
-        jne  fast_lookup_failed
-
+        ngr     %r5,%r2
+        sllg    %r7,%r5,3
+        lg      %r11, 8(%r8,%r7)      /* .host */
+        cg      %r2,  0(%r8,%r7)      /* next guest address == .guest ? */
+        jne     fast_lookup_failed
+        
         /* Found a match.  Call .host.
            r11 is an address. There we will find the instrumented client code.
            That code may modify the guest state register r13. The client code
            will return to the beginning of this loop start by issuing br LR.
            We can simply branch to the host code */
-        br %r11
-
-
-/*----------------------------------------------------*/
-/*--- PROFILING dispatcher (can be much slower)    ---*/
-/*----------------------------------------------------*/
-
-run_innerloop__dispatch_profiled:
-        stg  %r2,S390_LOC_SAVED_R2
-
-        /* Load the link register with the address the jitted code will
-           return to when it's done executing. */
-        bras LR,innermost_loop
-
-        /* Jitted code returns here. Update profile counter for previous IA */
-
-        llill %r5,( VG_TT_FAST_MASK << 1) & 0xffff
-#if ((( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16 != 0)
-        iilh %r5,(( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16
-#endif
-        ng   %r5,S390_LOC_SAVED_R2
-        sllg %r7,%r5,2
-
-        /* Increment bb profile counter */
-        larl %r8, VG_(tt_fastN)
-        lg   %r9,0(%r8,%r7)
-        l    %r10,0(%r9)
-        ahi  %r10,1
-        st   %r10,0(%r9)
-
-        j    run_innerloop__dispatch_profiled
-
-/*----------------------------------------------------*/
-/*--- exit points                                  ---*/
-/*----------------------------------------------------*/
-
-gsp_changed:
-       /* Someone messed with the gsp (in r13).  Have to
-           defer to scheduler to resolve this.  The register
-           holding VG_(dispatch_ctr) is not yet decremented,
-           so no need to increment. */
-
-        /* Update the IA in the guest state */
-        lg  %r6,S390_LOC_SAVED_GSP       /* r6 = original guest state pointer */
-        stg %r2,OFFSET_s390x_IA(%r6)
-
-        /* Return the special guest state pointer value */
-        lgr %r2, %r13
-       j   run_innerloop_exit
-
-
-counter_is_zero:
-       /* IA is up to date */
-
-       /* Back out decrement of the dispatch counter */
-        ahi S390_REGNO_DISPATCH_CTR,1
-
-        /* Set return value for the scheduler */
-        lghi %r2,VG_TRC_INNER_COUNTERZERO
-        j    run_innerloop_exit
-
+        // FIXME Update comment
+        br      %r11
+        .long   0x0   /* persuade insn decoders not to speculate past here */
 
 fast_lookup_failed:
-       /* IA is up to date */
-
-       /* Back out decrement of the dispatch counter */
-        ahi S390_REGNO_DISPATCH_CTR,1
-
-        /* Set return value for the scheduler */
-        lghi %r2,VG_TRC_INNER_FASTMISS
-        j    run_innerloop_exit
-
-
-        /* All exits from the dispatcher go through here.
-           When we come here r2 holds the return value. */
-run_innerloop_exit:
-
-       /* Restore valgrind's FPC, as client code may have changed it. */
-        lfpc S390_LOC_SAVED_FPC_V
-
-        /* Write ctr to VG_(dispatch_ctr) (=32bit value) */
-        larl %r6,VG_(dispatch_ctr)
-        st   S390_REGNO_DISPATCH_CTR,0(%r6)
-
-        /* Restore callee-saved registers... */
-
-        /* Floating-point regs */
-        ld  %f8,160+0(SP)
-        ld  %f9,160+8(SP)
-        ld  %f10,160+16(SP)
-        ld  %f11,160+24(SP)
-        ld  %f12,160+32(SP)
-        ld  %f13,160+40(SP)
-        ld  %f14,160+48(SP)
-        ld  %f15,160+56(SP)
-
-        /* Remove atack frame */
-        aghi SP,S390_INNERLOOP_FRAME_SIZE
-
-        /* General-purpose regs. This also restores the original link
-           register (r14) and stack pointer (r15). */
-        lmg %r6,%r15,48(SP)
-
-        /* Return */
-        br  LR
-
-/*------------------------------------------------------------*/
-/*---                                                      ---*/
-/*--- A special dispatcher, for running no-redir           ---*/
-/*--- translations.  Just runs the given translation once. ---*/
-/*---                                                      ---*/
-/*------------------------------------------------------------*/
-
-/* signature:
-void VG_(run_a_noredir_translation) ( UWord* argblock );
-*/
-
-/* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
-   and 2 to carry results:
-      0: input:  ptr to translation
-      1: input:  ptr to guest state
-      2: output: next guest PC
-      3: output: guest state pointer afterwards (== thread return code)
-*/
-.text
-.align   4
-.globl VG_(run_a_noredir_translation)
-VG_(run_a_noredir_translation):
-        stmg %r6,%r15,48(SP)
-        aghi SP,-S390_INNERLOOP_FRAME_SIZE
-        std  %f8,160+0(SP)
-        std  %f9,160+8(SP)
-        std  %f10,160+16(SP)
-        std  %f11,160+24(SP)
-        std  %f12,160+32(SP)
-        std  %f13,160+40(SP)
-        std  %f14,160+48(SP)
-        std  %f15,160+56(SP)
-
-        /* Load address of guest state into guest state register (r13) */
-        lg   %r13,8(%r2)
-
-        /* Get the IA */
-        lg   %r11,0(%r2)
-
-        /* save r2 (argblock) as it is clobbered */
-       stg  %r2,160+64(SP)
-
-        /* the call itself */
-        basr LR,%r11
-
-        /* restore argblock */
-       lg   %r1,160+64(SP)
-       /* save the next guest PC */
-       stg  %r2,16(%r1)
+#ifdef XINDIR_STATS
+        /* Increment VG_(stats__n_xindir_misses), an ULong value */
+        larl    %r8, VG_(stats__n_xindir_misses)
+        lg      %r10,0(%r8)
+        aghi    %r10,1
+        stg     %r10,0(%r8)
+#endif
+        lghi    %r0,VG_TRC_INNER_FASTMISS
+        lghi    %r1,0
+        j       postamble
 
-       /* save the guest state */
-       stg  %r13,24(%r1)
+        
+/* ------ Assisted jump ------ */
+        .global VG_(disp_cp_xassisted)
+VG_(disp_cp_xassisted):
+        /* guest-state-pointer contains the TRC. Put the value into the
+           return register */
+        lgr     %r0,%r13
+        lghi    %r1,0
+        j       postamble
 
-        /* Restore Floating-point regs */
-        ld  %f8,160+0(SP)
-        ld  %f9,160+8(SP)
-        ld  %f10,160+16(SP)
-        ld  %f11,160+24(SP)
-        ld  %f12,160+32(SP)
-        ld  %f13,160+40(SP)
-        ld  %f14,160+48(SP)
-        ld  %f15,160+56(SP)
 
-        aghi SP,S390_INNERLOOP_FRAME_SIZE
+/* ------ Event check failed ------ */
+        .global VG_(disp_cp_evcheck_fail)
+VG_(disp_cp_evcheck_fail):
+        lghi    %r0,VG_TRC_INNER_COUNTERZERO
+        lghi    %r1,0
+        j       postamble
 
-        lmg %r6,%r15,48(SP)
-       br  %r14
 
+        .size VG_(disp_run_translations), .-VG_(disp_run_translations)
 
 /* Let the linker know we don't need an executable stack */
-.section .note.GNU-stack,"",@progbits
+        .section .note.GNU-stack,"",@progbits
 
 #endif /* VGA_s390x */