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
|