powermac-rom/NanoKernel/NKTimers.s

963 lines
17 KiB
ArmAsm

; AUTO-GENERATED SYMBOL LIST
; IMPORTS:
; NKConsoleLog
; getchar
; printb
; printd
; printh
; printw
; NKIndex
; DeleteID
; LookupID
; NKPoolAllocator
; PoolAllocClear
; PoolFree
; NKScheduler
; CalculateTimeslice
; FlagSchEvaluationIfTaskRequires
; SchRdyTaskNow
; SchTaskUnrdy
; clear_cr0_lt
; major_0x149d4
; NKSync
; EnqueueMessage
; SetEvent
; SignalSemaphore
; NKThud
; panic
; panic_non_interactive
; EXPORTS:
; DequeueTimer (=> NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks)
; EnqueueTimer (=> NKMPCalls, NKSync)
; GetTime (=> NKMPCalls, NKScheduler, NKSync, NKTasks)
; InitTMRQs (=> NKInit)
; SetTimesliceFromCurTime (=> NKScheduler)
; StartTimeslicing (=> NKInit)
; TimebaseTicksPerPeriod (=> NKScheduler, NKSync)
; TimerDispatch (=> NKInterrupts)
Local_Panic set *
b panic
InitTMRQs ; OUTSIDE REFERER
addi r9, r1, PSA.TimerQueue
lis r8, 0x544d
ori r8, r8, 0x5251
stw r8, 0x0004(r9)
stw r9, 0x0008(r9)
stw r9, 0x000c(r9)
li r8, 0x00
stb r8, 0x0014(r9)
li r8, 0x01
stb r8, 0x0016(r9)
stb r8, 0x0017(r9)
lis r8, 0x7fff
ori r8, r8, 0xffff
mtspr dec, r8
stw r8, 0x0038(r9)
oris r8, r8, 0xffff
stw r8, 0x003c(r9)
mfspr r8, pvr
rlwinm. r8, r8, 0, 0, 14
beq InitTMRQs_0x7c
mflr r30
li r8, 0x40
; r1 = kdp
; r8 = size
bl PoolAllocClear
; r8 = ptr
mr. r31, r8
beq Local_Panic
stw r31, PSA.OtherTimerQueuePtr(r1)
li r9, 0x07
stb r9, 0x0014(r31)
li r9, 0x01
stb r9, 0x0016(r31)
mtlr r30
InitTMRQs_0x7c
mfspr r8, pvr
rlwinm. r8, r8, 0, 0, 14
beq InitTMRQs_0xb4
mflr r30
li r8, 0x40
; r1 = kdp
; r8 = size
bl PoolAllocClear
; r8 = ptr
mr. r31, r8
beq Local_Panic
stw r31, PSA._364(r1)
li r9, 0x08
stb r9, 0x0014(r31)
li r9, 0x01
stb r9, 0x0016(r31)
mtlr r30
InitTMRQs_0xb4
; Activate the NanoDebugger (whatever that is...)
lwz r30, KDP.PA_ConfigInfo(r1)
lhz r31, NKConfigurationInfo.Debug(r30)
cmplwi r31, NKConfigurationInfo.DebugThreshold
blt @nodebug
lwz r31, NKConfigurationInfo.DebugFlags(r30)
rlwinm. r8, r31, 0, NKConfigurationInfo.NanodbgrFlagBit, NKConfigurationInfo.NanodbgrFlagBit
beq @nodebug
lwz r8, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)
_bset r8, r8, NKNanoKernelInfo.NanodbgrFlagBit
stw r8, KDP.NanoKernelInfo + NKNanoKernelInfo.ConfigFlags(r1)
mflr r30
li r8, Timer.Size
bl PoolAllocClear ; one of those weird queue structures
mr. r31, r8
beq Local_Panic
li r9, Timer.kKind6
stb r9, Timer.Kind(r31)
li r9, 1
stb r9, Timer.KeepAfterFiring(r31)
bl GetTime
stw r8, Timer.Time(r31)
stw r9, Timer.Time+4(r31)
mr r8, r31
bl EnqueueTimer
_log 'Nanodebugger activated.^n'
mtlr r30
@nodebug
blr
TimerTable
dc.l TimerFireUnknownKind - NKTop ; Timer.kKind0
dc.l TimerFire1 - NKTop ; Timer.kKind1
dc.l TimerFire2 - NKTop ; Timer.kKind2
dc.l TimerFire3 - NKTop ; Timer.kKind3
dc.l TimerFire4 - NKTop ; Timer.kKind4
dc.l TimerFire5 - NKTop ; Timer.kKind5
dc.l TimerFire6 - NKTop ; Timer.kKind6
dc.l TimerFire7 - NKTop ; Timer.kKind7
dc.l TimerFire8 - NKTop ; Timer.kKind8
TimerDispatch ; OUTSIDE REFERER
mflr r19
mfsprg r18, 0
stw r19, EWA.TimerDispatchLR(r18)
TimerDispatch_0x30 ; OUTSIDE REFERER
mfspr r8, pvr
rlwinm. r8, r8, 0, 0, 14
beq @is_601
;not 601
@gettime_loop_non_601
mftbu r8
mftb r9
mftbu r16
cmpw r8, r16
bne- @gettime_loop_non_601
b @common
@is_601
@gettime_loop_601
mfspr r8, rtcu
mfspr r9, rtcl
mfspr r16, rtcu
cmpw r8, r16
bne- @gettime_loop_601
dialect POWER
liu r16, 1000000000 >> 16
oril r16, r16, 1000000000 & 0xffff
mfmq r17
mul r8, r16, r8
mfmq r16
mtmq r17
mfxer r17
a r9, r16, r9
aze r8, r8
mtxer r17
dialect PowerPC
@common
lbz r19, EWA.GlobalTimeIsValid(r18)
addi r30, r18, EWA.Base
cmpwi r19, 1
lwz r16, EWA.GlobalTime - EWA.Base(r30)
bne timer_earlier_than_sometime
lwz r17, EWA.GlobalTime + 4 - EWA.Base(r30)
_b_if_time_gt r16, r8, timer_earlier_than_sometime
@skipbranch
li r19, 0x00
stw r30, -0x0254(r18)
stb r19, 0x0017(r30)
b TimerFire4_0x10
timer_earlier_than_sometime
lwz r30, PSA.TimerQueue + LLL.Next(r1)
lwz r16, 0x0038(r30)
lwz r17, 0x003c(r30)
_b_if_time_gt r16, r8, TimerDispatch_0x188
RemoveFromList r30, scratch1=r19, scratch2=r20
lwz r19, 0x064c(r1)
lbz r20, Timer.Kind(r30)
rlwimi r19, r20, 2, 23, 29
cmplwi r20, 0x09
llabel r20, TimerTable
li r21, 0x00
add r20, r20, r19
bgel Local_Panic
stb r21, 0x0017(r30)
lwz r20, 0x0000(r20)
add r20, r20, r19
mtlr r20
stw r30, -0x0254(r18)
blr
TimerDispatch_0x144
mfsprg r18, 0
lwz r30, -0x0254(r18)
lbz r19, 0x0016(r30)
cmpwi r19, 0x01
lwz r8, 0x0000(r30)
beq TimerDispatch_0x30
bl DeleteID
mr r8, r30
bl PoolFree
lwz r8, 0x001c(r30)
cmpwi r8, 0x00
beq TimerDispatch_0x180
bl PoolFree
li r8, 0x00
stw r8, 0x001c(r30)
TimerDispatch_0x180:
mfsprg r18, 0
b TimerDispatch_0x30
TimerDispatch_0x188
lwz r19, EWA.TimerDispatchLR(r18)
mtlr r19
b SetTimesliceFromCurTimeAndTripTime
StartTimeslicing ; OUTSIDE REFERER
mfsprg r19, 0
li r8, 1
stb r8, EWA.GlobalTimeIsValid(r19)
li r8, 0
stw r8, EWA.GlobalTime(r19)
stw r8, EWA.GlobalTime + 4(r19)
mflr r19
_log 'Starting timeslicing^n'
mtlr r19
; CLOB r8/r9, r16-r21
SetTimeslice
mflr r19
bl GetTime
mtlr r19
; ARG TimeBase r8/r9 curTime
; CLOB r16-r21
SetTimesliceFromCurTime
; This should get the most distant time???
lwz r18, PSA.TimerQueue + LLL.Next(r1)
lwz r16, Timer.Time(r18)
lwz r17, Timer.Time+4(r18)
; ARG TimeBase r8/r9 curTime, TimeBase r16/r17 TripTime
; CLOB r18-r21
SetTimesliceFromCurTimeAndTripTime
mfxer r20
mfsprg r19, 0
lis r21, 0x7fff
lbz r18, EWA.GlobalTimeIsValid(r19)
ori r21, r21, 0xffff
cmpwi r18, 1
; r16/r17 = soonest(last timer, global PSA time if available)
bne global_time_invalid
lwz r18, EWA.GlobalTime(r19)
lwz r19, EWA.GlobalTime+4(r19)
_b_if_time_le r16, r18, last_timer_fires_sooner
mr r17, r19
mr r16, r18
last_timer_fires_sooner
global_time_invalid
; Subtract the current time (or what we were passed in r8/r9) from that time
subfc r17, r9, r17
subfe. r16, r8, r16
mtxer r20
blt @that_time_has_passed ; hi bit of r16 = 1
bne @that_time_is_in_future ;
cmplw r16, r21 ; typo? should be r17???
bgt @that_time_is_in_future ; will never be taken...
; When the times are roughly equal?
mtspr dec, r17
blr
@that_time_is_in_future
mtspr dec, r21
blr
@that_time_has_passed
mtspr dec, r21
mtspr dec, r16 ; this makes nearly no sense!
blr
; TimerFire0
TimerFireUnknownKind
_log 'TimerInformation.kind is zero??^n'
; TimerFire1
TimerFire1 ; OUTSIDE REFERER
bl Local_Panic
lwz r18, 0x0018(r30)
stw r16, 0x0080(r18)
stw r17, 0x0084(r18)
lwz r8, 0x0018(r30)
li r16, 0x00
lbz r17, 0x0018(r8)
lwz r19, 0x0088(r8)
cmpwi r17, 0x00
stw r16, 0x011c(r19)
bne TimerFire1_0x64
addi r16, r8, 0x08
RemoveFromList r16, scratch1=r17, scratch2=r19
li r17, 0x01
stb r17, 0x0019(r8)
bl SchRdyTaskNow
bl CalculateTimeslice
bl FlagSchEvaluationIfTaskRequires
b TimerDispatch_0x144
TimerFire1_0x64
lwz r16, 0x0064(r8)
rlwinm. r16, r16, 0, 30, 30
; TimerFire2
TimerFire2 ; OUTSIDE REFERER
bne TimerDispatch_0x144
bl Local_Panic
lwz r18, 0x0018(r30)
stw r16, 0x0080(r18)
stw r17, 0x0084(r18)
lwz r8, 0x0018(r30)
li r16, -0x7270
lbz r17, 0x0018(r8)
lwz r18, 0x0088(r8)
cmpwi r17, 0x00
bne TimerFire3_0x8
stw r16, 0x011c(r18)
lwz r8, 0x0008(r8)
lwz r8, 0x0000(r8)
; r8 = id
bl LookupID
cmpwi r9, Queue.kIDClass
cmpwi cr1, r9, 0x05
beq TimerFire2_0x8c
beq cr1, TimerFire2_0x7c
cmpwi r9, 0x09
cmpwi cr1, r9, 0x06
beq TimerFire2_0x6c
bne cr1, Local_Panic
lwz r16, 0x0020(r8)
addi r16, r16, -0x01
stw r16, 0x0020(r8)
b TimerFire2_0x98
TimerFire2_0x6c
lwz r16, 0x001c(r8)
addi r16, r16, -0x01
stw r16, 0x001c(r8)
b TimerFire2_0x98
TimerFire2_0x7c
lwz r16, 0x001c(r8)
addi r16, r16, -0x01
stw r16, 0x001c(r8)
b TimerFire2_0x98
TimerFire2_0x8c
lwz r16, 0x002c(r8)
addi r16, r16, -0x01
stw r16, 0x002c(r8)
TimerFire2_0x98
lwz r8, 0x0018(r30)
addi r16, r8, 0x08
RemoveFromList r16, scratch1=r17, scratch2=r18
bl SchRdyTaskNow
; TimerFire3
TimerFire3 ; OUTSIDE REFERER
bl FlagSchEvaluationIfTaskRequires
b TimerDispatch_0x144
TimerFire3_0x8 ; OUTSIDE REFERER
b Local_Panic
; major_0x13258
; Dead code -- probably removed from TimerTable
lwz r8, 0x0018(r30)
; r8 = id
bl LookupID
cmpwi r9, Queue.kIDClass
mr r31, r8
bne major_0x13258_0x68
lwz r16, 0x0024(r31)
lwz r8, 0x001c(r30)
cmpwi r16, 0x00
cmpwi cr1, r8, 0x00
beq major_0x13258_0x40
lwz r17, 0x0028(r31)
mr. r8, r17
lwz r17, 0x0008(r17)
beq major_0x13258_0x68
stw r17, 0x0028(r31)
b major_0x13258_0x4c
major_0x13258_0x40
beq cr1, major_0x13258_0x68
li r16, 0x00
stw r16, 0x001c(r30)
major_0x13258_0x4c
lwz r16, 0x0020(r30)
lwz r17, 0x0024(r30)
lwz r18, 0x0028(r30)
stw r16, 0x0010(r8)
stw r17, 0x0014(r8)
stw r18, 0x0018(r8)
bl EnqueueMessage ; Message *r8, Queue *r31
major_0x13258_0x68
lwz r8, 0x0034(r30)
; r8 = id
bl LookupID
cmpwi r9, Semaphore.kIDClass
mr r31, r8
bne major_0x13258_0x80
bl SignalSemaphore
major_0x13258_0x80
lwz r8, 0x002c(r30)
; r8 = id
bl LookupID
cmpwi r9, EventGroup.kIDClass
mr r31, r8
; TimerFire4
TimerFire4 ; OUTSIDE REFERER
bne TimerFire4_0xc
lwz r8, 0x0030(r30)
bl SetEvent
TimerFire4_0xc
b TimerDispatch_0x144
TimerFire4_0x10 ; OUTSIDE REFERER
mfsprg r28, 0
lwz r29, -0x0008(r28)
mr r8, r29
bl SchTaskUnrdy
lbz r17, 0x0019(r29)
cmpwi r17, 0x02
bge TimerFire4_0x64
mr r8, r29
lwz r16, 0x0038(r30)
lwz r17, 0x003c(r30)
bl clear_cr0_lt
bge TimerFire4_0x50
mr r8, r29
bl SchRdyTaskNow
bl CalculateTimeslice
b TimerFire5_0x8
TimerFire4_0x50
li r18, 0x02
stb r18, 0x0019(r29)
mr r8, r29
bl SchRdyTaskNow
b TimerFire5_0x8
TimerFire4_0x64
mr r8, r29
; TimerFire5
TimerFire5 ; OUTSIDE REFERER
bl SchRdyTaskNow
bl major_0x149d4
TimerFire5_0x8 ; OUTSIDE REFERER
bl FlagSchEvaluationIfTaskRequires
mfsprg r18, 0
b TimerDispatch_0x30
; major_0x13364
; Dead code -- probably removed from TimerTable
_log 'Heartbeat: Ext '
lwz r16, KDP.NanoKernelInfo + NKNanoKernelInfo.ExternalIntCount(r1)
mr r8, r16
bl printd
_log 'Alerts '
lwz r16, KDP.NanoKernelInfo + NKNanoKernelInfo.AlertCount(r1)
mr r8, r16
bl printd
_log 'Blue cpu-'
lwz r17, PSA.PA_BlueTask(r1)
lhz r16, Task.CPUIndex(r17)
mr r8, r16
bl printb
_log 'state-'
lbz r16, Task.State(r17)
mr r8, r16
bl printb
_log 'scr-'
lwz r16, KDP.PA_ECB(r1)
lwz r18, KDP.PostIntMaskInit(r1)
lwz r16, ContextBlock.CR(r16)
and r16, r16, r18
mr r8, r16
bl printw
_log 'mcr-'
lwz r16, PSA.MCR(r1)
mr r8, r16
bl printw
_log 'IPL-'
lwz r16, KDP.PA_EmulatorIplValue(r1)
lhz r16, 0(r16)
mr r8, r16
bl printh
_log 'eSR-'
lwz r16, KDP.PA_ECB(r1)
lwz r16, ContextBlock.r25(r16)
andi. r16, r16, 7
mr r8, r16
bl printb
_log '^n'
mfxer r19
lwz r16, 0x0038(r30)
lwz r17, 0x003c(r30)
lwz r18, 0x0f2c(r1)
slwi r18, r18, 3
addc r17, r17, r18
; TimerFire7
TimerFire7 ; OUTSIDE REFERER
addze r16, r16
stw r16, 0x0038(r30)
stw r17, 0x003c(r30)
mtxer r19
mr r8, r30
bl EnqueueTimer
b TimerDispatch_0x144
; major_0x134d8
; Dead code -- probably removed from TimerTable
lwz r18, PSA.DecClockRateHzCopy(r1)
lwz r19, 0x0f88(r1)
subf. r19, r18, r19
ble TimerFire8_0x1c
srwi r19, r19, 11
mfxer r20
major_0x134d8_0x18
mftbu r16
mftb r17, 0x10c
mftbu r18
cmpw r16, r18
li r18, 0x00
bne- major_0x134d8_0x18
mttb r18
addc r17, r17, r19
addze r16, r16
mttbu r16
mttb r17
lwz r18, PSA.DecClockRateHzCopy(r1)
srwi r18, r18, 11
; TimerFire8
TimerFire8 ; OUTSIDE REFERER
addc r17, r17, r18
addze r16, r16
stw r16, 0x0038(r30)
stw r17, 0x003c(r30)
mtxer r20
mr r8, r30
bl EnqueueTimer
TimerFire8_0x1c ; OUTSIDE REFERER
b TimerDispatch_0x144
; major_0x13544
; Dead code -- probably removed from TimerTable
lwz r19, PSA._36c(r1)
mfxer r20
cmpwi cr1, r19, 0x00
srawi r8, r19, 31
beq cr1, TimerFire6_0x4
major_0x13544_0x14
mftbu r16
mftb r17, 0x10c
mftbu r18
cmpw r16, r18
li r18, 0x00
bne- major_0x13544_0x14
mttb r18
addc r19, r17, r19
adde r18, r16, r8
mttbu r18
mttb r19
bgt cr1, major_0x13544_0x64
major_0x13544_0x44
mftbu r18
mftb r19, 0x10c
mftbu r8
cmpw r18, r8
bne- major_0x13544_0x44
subfc r19, r17, r19
subfe. r18, r16, r18
blt major_0x13544_0x44
major_0x13544_0x64
lwz r18, PSA._368(r1)
addc r17, r17, r18
addze r16, r16
stw r16, 0x0038(r30)
; TimerFire6
TimerFire6 ; OUTSIDE REFERER
stw r17, 0x003c(r30)
TimerFire6_0x4 ; OUTSIDE REFERER
mtxer r20
beq cr1, TimerDispatch_0x144
mr r8, r30
bl EnqueueTimer
b TimerDispatch_0x144
; major_0x135d0
; Dead code -- probably removed from TimerTable
mfxer r19
lwz r16, 0x0038(r30)
lwz r17, 0x003c(r30)
lwz r18, 0x0f2c(r1)
srwi r18, r18, 1
addc r17, r17, r18
addze r16, r16
stw r16, 0x0038(r30)
stw r17, 0x003c(r30)
mtxer r19
mr r8, r30
bl EnqueueTimer
bl getchar
cmpwi r8, -0x01
beq TimerDispatch_0x144
bl panic_non_interactive
b TimerDispatch_0x144
; ARG Timer *r8
; CLOB r16-r20
EnqueueTimer ; OUTSIDE REFERER
; Keep the trip-time of this timer in r16/r17
lwz r16, Timer.Time(r8)
lwz r17, Timer.Time+4(r8)
; r20 = timer being considered
; r18/r19 = trip-time of timer being condidered
lwz r20, PSA.TimerQueue + TimerQueueStruct.LLL + LLL.Next(r1)
lwz r18, Timer.Time(r20)
lwz r19, Timer.Time+4(r20)
; First try to insert at head of global TMRQ
cmpw r16, r18
cmplw cr1, r17, r19
bgt @insert_further_ahead
blt @insert_at_tail
bge cr1, @insert_further_ahead
@insert_at_tail
addi r20, r1, PSA.TimerQueue + TimerQueueStruct.LLL
li r18, 1
stb r18, Timer.Byte3(r8)
; Insert at the very back of the queue
lwz r19, LLL.Freeform(r8)
lwz r9, LLL.Freeform(r20)
stw r9, LLL.Freeform(r8) ; my freeform = considered freeform
lwz r9, LLL.Next(r20)
stw r9, LLL.Next(r8) ; my next = next of considered
stw r20, LLL.Prev(r8) ; my prev = considered
stw r8, LLL.Prev(r9) ; prev of next of considered = me
stw r8, LLL.Next(r20) ; next of considered = me
stw r19, LLL.Freeform(r8) ; my freeform = my original freeform
b SetTimeslice
@insert_further_ahead
lwz r20, PSA.TimerQueue + TimerQueueStruct.LLL + LLL.Prev(r1)
@searchloop
lwz r18, Timer.Time(r20)
lwz r19, Timer.Time+4(r20)
cmpw r16, r18
cmplw cr1, r17, r19
bgt @insert_after_this_one
blt @next
bge cr1, @insert_after_this_one
@next
lwz r20, LLL.Prev(r20)
b @searchloop
@insert_after_this_one
li r18, 1
stb r18, Timer.Byte3(r8)
lwz r19, LLL.Freeform(r8)
lwz r9, LLL.Freeform(r20)
stw r9, LLL.Freeform(r8) ; my freeform = considered freeform
lwz r9, LLL.Next(r20)
stw r9, LLL.Next(r8) ; my next = next of considered
stw r20, LLL.Prev(r8) ; my prev = considered
stw r8, LLL.Prev(r9) ; prev of next of considered = me
stw r8, LLL.Next(r20) ; next of considered = me
stw r19, LLL.Freeform(r8) ; my freeform = my original freeform
blr
; Remove a Timer from the global timer firing queue (TMRQ).
; If the Timer was to be the next to fire, then perform the
; standard decrementer rollover adjustment.
; ARG Timer *r8
DequeueTimer
lwz r16, Timer.QueueLLL + LLL.FreeForm(r8)
cmpwi r16, 0
lwz r18, PSA.TimerQueue + TimerQueueStruct.LLL + LLL.Next(r1)
beq Local_Panic
RemoveFromList r8, scratch1=r16, scratch2=r17
li r16, 0
cmpw r18, r8
stb r16, Timer.Byte3(r8)
beq SetTimeslice
blr
; Get the number of timebase ticks in a specified period
; ARG long r8 period (positive for ms, negative for us)
TimebaseTicksPerPeriod
mr. r17, r8
li r19, 250
lwz r9, KDP.ProcessorInfo + NKProcessorInfo.DecClockRateHz(r1)
bgt+ @period_positive
blt+ @period_negative
li r8, 0
li r9, 0
blr ; fail
@period_negative
neg r17, r17
lisori r19, 250000
@period_positive
divw r19, r9, r19
mullw r9, r19, r17
mulhw r8, r19, r17
srwi r9, r9, 2
rlwimi r9, r8, 30, 0, 1
srwi r8, r8, 2
blr
; RET long r8 tbu, long r9 tbl
; CLOB r16, r17
GetTime
mfpvr r8
rlwinm. r8, r8, 0, 0, 14
beq @is_601
@retry_timebase:
mftbu r8
mftb r9
mftbu r16
cmpw r8, r16
bne- @retry_timebase
b @return
@is_601
dialect POWER ; disassembled this in POWER mode!
@retry_rtc
mfrtcu r8
mfrtcl r9
mfrtcu r16
cmp 0, r8, r16
dialect PowerPC
bne- @retry_rtc ; POWER chokes on hints?
dialect POWER
liu r16, 1000000000 >> 16
oril r16, r16, 1000000000 & 0xffff
mfmq r17
mul r8, r16, r8
mfmq r16
mtmq r17
mfxer r17
a r9, r16, r9
aze r8, r8
mtxer r17
dialect POWERPC
@return
blr