File: dec.S

package info (click to toggle)
mol 0.9.61-6
  • links: PTS
  • area: contrib
  • in suites: woody
  • size: 6,140 kB
  • ctags: 8,491
  • sloc: ansic: 50,560; asm: 2,826; sh: 458; makefile: 373; perl: 165; lex: 135; yacc: 131
file content (216 lines) | stat: -rw-r--r-- 5,077 bytes parent folder | download
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/* 
 *   Creation Date: <2001/06/21 17:10:35 samuel>
 *   Time-stamp: <2001/06/24 00:25:37 samuel>
 *   
 *	<dec.S>
 *	
 *	DEC / TimeBase stuff
 *   
 *   Copyright (C) 2001 Samuel Rydh (samuel@ibrium.se)
 *   
 *   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
 *   
 */

/************************************************************************/
/*	TBWU / TBWL							*/
/************************************************************************/
	
#if 0
spr_tbwu:
	blr				// read (won't come here)
	mr	r3,r0
	mftb	r4
	b	update_tb
		
spr_tbwl:
	blr				// read (won't come here)
	mftbu	r3
	mr	r4,r0
	// ...fall through...

// r3 = tbu, r4 = tbl, r0,r2,r5 free.
update_tb:
	lwz	r5,K_LOADED_DEC(r1)
	mfdec	r2
	sub	r5,r5,r2		// r5 = elapsed ticks
		
	li	r2,0			// Set timebase
	mttbl	r4
	mttbu	r3
	mttbl	r4
	
	mfxer	r2
	subfc	r4,r5,r4
	addme	r3,r3
	stw	r4,xTBL(r1)
	stw	r3,xTBU(r1)
	mtxer	r2
	b	emulation_done
#endif


/************************************************************************/
/*	Load/restore DEC and TB						*/
/************************************************************************/

	//////////////////////////////////////////////////////////////
	// recalc_int_stamp
	//
	// May modify: r0,r2-r5
	//
	
recalc_int_stamp:
	crclr	FBIT_RecalcDecInt
	lwz	r5,xTIMER_STAMP(r1)
	bf	FBIT_DecSeenZero, 2f		// FBIT_DecSeenZero must be set when DEC is loaded
	mftb	r3
	lwz	r4,xDEC_STAMP(r1)		// Has the xDEC overflown already?
	sub.	r0,r4,r3
	blt	3f
	sub.	r0,r4,r5
	bge	2f				// branch if xDEC > xTIMER
	mr	r5,r4
2:	stw	r5,K_INT_STAMP(r1)		// dec = xTIMER
	blr
	// We should consider a fb-bit to throw an exceptions direcltly instead.
	// All exceptions could be handled that way.
3:	stw	r4,K_INT_STAMP(r1)		// dec = 0
	blr

	//////////////////////////////////////////////////////////////
	// set_mol_dec 
	//
	// May modify: r0,r2-r5
	//
	// Old 2.4 kernels assume that linux-DEC never ticks faster
	// than the DEC interval measured from TB. Unfortunately,
	// it is virtually impossible to keep DEC/TB in sync.
	//
	// Experimentally, the "worst case" senario is a linux DEC tick
	// beeing delayed 0.04 ms (to be compare with the 20 ms period).
	//
	// Sequences similar to
	//
	//	1: mftb r2; mfdec r3; mftb r4; cmp r2,r4; bne 1b
	//
	// do *not* work - DEC and TB probably ticks on different edges.
	
set_mol_dec:
	lwz	r5,K_INT_STAMP(r1)		// DEC = K_INT_STAMP - tbl
	mfdec	r3				// Make sure linux interrupt *never*
	mftb	r2				// occur too fast
	
	sub	r4,r5,r2
	cmpw	r4,r3
	bgtlr
	add	r5,r3,r2			// K_DEC_STAMP = DEC + tbl
	mtdec	r4
	stw	r5,K_DEC_STAMP(r1)
	crset	FBIT_MolDecLoaded
	blr

	///////////////////////////////////////////////////////////////	
	// set_kernel_dec 
	//
	// May modify: r0,r2, cr
	//

set_kernel_dec:
	lwz	r0,K_DEC_STAMP(r1)
	crclr	FBIT_MolDecLoaded
	mftb	r2				// Keep linux-DEC coherent
	sub	r2,r0,r2			// DEC = stamp - tbl
	mtdec	r2
	blr

	

/************************************************************************/
/*	DEC read/write							*/
/************************************************************************/

spr_dec:
	b	_dec_read

	// dec write. r0 = spr_value
	// r2=sprn# (used after a blr)
	rlwinm.	r5,r0,0,0,0			// seen zero?
	mftb	r4
	cror	FBIT_DecSeenZero,FBIT_DecSeenZero,eq
	add	r5,r4,r0
	stw	r5,xDEC_STAMP(r1)		// set new dec value
	bf	FBIT_DecSeenZero, emulation_done
	bl	recalc_int_stamp		// M: r0,r2-r5
	btl	FBIT_MolDecLoaded, set_kernel_dec	// M: r0,r2
	bl	set_mol_dec			// M: r0,r2-r5
	b	emulation_done

	// r0 = ret value, r3,r4 = scratch
_dec_read:
	lwz	r4,xDEC_STAMP(r1)
	mftb	r3
	sub	r0,r4,r3
	blr


/************************************************************************/
/*	Decrementer Exception						*/
/************************************************************************/
	
	// __dec_VECTOR (non-MOL dec exception)
	//
	//	r3=cr, sprg1=saved_r1, sprg0=saved_r3
	//
	// An exception with DEC>=0 can occur if a mac-DEC overflows occurs 
	// just prior to a context switch. These exceptions should be 
	// dropped silently. 
	
__dec_VECTOR:
	mfdec	r1
	cmpwi	r1,0
	blt+	1f
	mtcr	r3				// Restore and exit
	mfsprg1	r1
	mfsprg0	r3
	rfi
1:
	mtcr	r3				// Restore and continue trap
	mfsprg1	r1
	mfsprg0	r3
	b	continue_trap_0x900
	
VECTOR_( 0x900, "Decrementer", secint_bad, __dec_VECTOR )
	EXCEPTION_PREAMBLE			// r0-r5, CR, LR
	TRACE(0x900, "Decrementer")
	mfdec	r4
	cmpwi	r4,0
	bge	exception_return
	bl	save_middle_regs		// We *will* take an exception

	bf	FBIT_MolDecLoaded, take_linux_dec_exception

	lis	r8,0x1000			// DEC rearm constant
	
	mftb	r3
	bf	FBIT_DecSeenZero, 1f		// check for xDEC overflow
	lwz	r4,xDEC_STAMP(r1)
	sub.	r6,r4,r3
	bge	1f
	crset	FBIT_DecINT
	crclr	FBIT_DecSeenZero
1:
	lwz	r5,xTIMER_STAMP(r1)		// check for xTIMER overflow
	sub.	r5,r5,r3
	bge	2f
	crset	FBIT_TimerINT
2:
	crset	FBIT_RecalcDecInt
	crset	FBIT_CheckFlags
	mtdec	r8				// rearm DEC	
	MAC_EXIT( RVEC_INTERRUPT )		// XXX: Something else?

take_linux_dec_exception:
	TAKE_EXCEPTION