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
|