summaryrefslogtreecommitdiffstats
path: root/pk/ppe42/ppe42_timebase.S
blob: 43d64bb415227f0eec4946a59d470ca438d7ce17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/// \file ppe42_timebase.S
/// \brief PPE42-specific 64 bit timebase emulation
///
        .nolist
#include "pk.h"
        .list
        
/// \fn PkTimebase pk_timebase_get(void)
/// \brief Returns a 64 bit timebase
///
#ifdef DOXYGEN_ONLY
PkTimebase 
pk_timebase_get(void);
#endif
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2014
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------
        
/// \cond
        .global ppe42_64bit_timebase
        .global ppe42_tb_data
        .global_function pk_timebase_get

#ifdef APPCFG_USE_DEC_FOR_TIMEBASE

        /// Note that it is ok to use this function in a fast interrupt
        /// context
        .align 5
        .global_function pk_timebase32_get
pk_timebase32_get:

        //load the decrementer start time and change tag
        lvd     %r4, ppe42_tb_data@sda21(0)

        //load the lower 32 bits of the 64bit timebase accumulator
        lwz     %r3, ppe42_64bit_timebase+4@sda21(0)

        //load the current decrementer value
        mfdec   %r0

        //load the change tag again (should already be in the cache)
        lwz     %r6, ppe42_tb_data+4@sda21(0)

        //loop until the change tag is the same (typically should be same)
        cmplwbne %r5, %r6, pk_timebase32_get

        //calculate how much time has passed since the decrementer was started and store in r6
        subf    %r5, %r0, %r4

        //add the 32bit difference to our 32bit timebase accumulator
        add     %r3, %r5, %r3

        blr


/// Use the DEC for our timebase until we have a real timebase register (uses
/// 9 instructions).
/// Note: It is not ok to use this function in a fast interrupt context due to
///       its use of r7
        .align 5
pk_timebase_get:

        //load the decrementer start time and change tag
        lvd     %r5, ppe42_tb_data@sda21(0)

        //load 64bit timebase accumulator
        lvd     %r3, ppe42_64bit_timebase@sda21(0)


        //load the current decrementer value
        mfdec   %r0

        //load the change tag again (should already be in the cache)
        lwz     %r7, ppe42_tb_data+4@sda21(0)

        //loop until the change tag is the same
        cmplwbne %r6, %r7, pk_timebase_get

        //calculate how much time has passed since the decrementer was started and store in r6
        subf    %r6, %r0, %r5

        //add the 32bit difference to the 64bit timebase accumulator
        addc    %r4, %r6, %r4
        addze   %r3, %r3

        blr

//enable this once we have a local timebase register in the model
#else

// use the local timebase register to keep more accurate time with just 6 instructions
// in the common case and 7 otherwise.
        .align 5
pk_timebase_get:

        //load the 64bit timebase accumulator
        lvd         r3, ppe42_64bit_timebase@sda21(0)

        //read the local timebase register (2 instructions)
        _pk_timebase32_get r5, r5

        //increment the upper 32 bits if the lower 32 bits have flipped
        cmplwbgt r5, r4, update_lower_32

        //increment the upper 32 bits
        addi        r3, r3, 1

update_lower_32:
        //replace the lower 32bits with what we read from the local timebase register
        mr          r4, r5

        blr
#endif
/// \endcond
OpenPOWER on IntegriCloud