powermac-rom/NanoKernel/NKScheduler.s

2293 lines
49 KiB
ArmAsm
Raw Permalink Blame History

; AUTO-GENERATED SYMBOL LIST
; IMPORTS:
; NKConsoleLog
; printh
; printw
; NKInterrupts
; SIGP
; NKPaging
; PagingFlushTLB
; NKTasks
; TasksFuncThatIsNotAMPCall
; NKThud
; panic
; NKTimers
; GetTime
; SetTimesliceFromCurTime
; TimebaseTicksPerPeriod
; EXPORTS:
; CalculateTimeslice (=> NKInit, NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKTimers)
; FlagSchEval (=> NKInit, NKInterrupts, NKMPCalls, NKTasks)
; FlagSchEvaluationIfTaskRequires (=> NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKTimers)
; NewCpuEntryPoint (=> NKMPCalls)
; Restore_v0_v31 (=> NKInterrupts)
; Save_f0_f31 (=> NKSleep)
; Save_v0_v31 (=> NKInterrupts, NKMPCalls, NKSleep)
; SchEval (=> NKInterrupts, NKMPCalls)
; SchExitInterrupt (=> NKInterrupts)
; SchFiddlePriorityShifty (=> NKInterrupts)
; SchIdleTask (=> NKInit, NKMPCalls)
; SchIdleTaskStopper (=> NKMPCalls)
; SchInit (=> NKInit)
; SchRdyTaskLater (=> NKMPCalls, NKPrimaryIntHandlers, NKSync)
; SchRdyTaskNow (=> NKInit, NKInterrupts, NKMPCalls, NKSync, NKTasks, NKTimers)
; SchRestoreStartingAtR14 (=> NKInit, NKInterrupts, NKMPCalls, NKPrimaryIntHandlers, NKVMCalls)
; SchRestoreStartingAtR20 (=> NKPrimaryIntHandlers)
; SchReturn (=> NKInterrupts)
; SchSaveStartingAtR14 (=> NKInterrupts, NKMPCalls, NKVMCalls)
; SchSaveStartingAtR20 (=> NKPrimaryIntHandlers)
; SchSwitchSpace (=> NKInit, NKInterrupts, NKSleep)
; SchTaskUnrdy (=> NKInterrupts, NKMPCalls, NKPrimaryIntHandlers, NKSync, NKTasks, NKTimers)
; clear_cr0_lt (=> NKTimers)
; major_0x149d4 (=> NKTimers)
Local_Panic set *
b panic
#### ## ## #### ######## ######## ######## ## ## ####### ######
## ### ## ## ## ## ## ## ## ## ## ## ## ## ##
## #### ## ## ## ## ## ## ## #### ## ## ##
## ## ## ## ## ## ######## ## ## ## ## ## ######
## ## #### ## ## ## ## ## ## ## ## ## ## ##
## ## ### ## ## ## ## ## ## ## ## ## ## ##
#### ## ## #### ## ## ## ######## ## ##### ## ######
; Create the queues that hold unblocked tasks ready to be run.
; There are four ready queues (RDYQs), all in the PSA:
; 1. critical
; 2. latency protection (newly unblocked tasks)
; 3. nominal
; 4. idle
; Each one has a "time cake" that gets divided among its tasks.
; For critical it is ~1ms, successively multiplying by 8.
SchInit
li r16, 0
stw r16, KDP.NanoKernelInfo + NKNanoKernelInfo.TaskCount(r1)
mflr r20
; Get a time doubleword approximating 1ms (for critical priority)
li r8, -1042 ; negative args are in usec
bl TimebaseTicksPerPeriod
mr r16, r8 ; hi
mr r17, r9 ; lo
mtlr r20
; These priority flags (top 4 bits) denote the state of each queue
li r23, 0
stw r23, PSA.PriorityFlags(r1)
; Populate one RDYQ for each of the four task priorities
addi r9, r1, PSA.ReadyQueues
; r23 = index of queue, r16/r17 = time cake
@loop
; Empty linked list
lisori r8, ReadyQueue.kSignature
stw r8, LLL.Signature(r9)
stw r9, LLL.Next(r9)
stw r9, LLL.Prev(r9)
; ... with a priority flag in its freeform field!
lis r8, 0x8000 ; ...0000
srw r8, r8, r23
stw r8, LLL.Freeform(r9)
; Zero some shit
li r8, 0
stw r8, ReadyQueue.Counter(r9) ; incremented by SchRdyTaskNow/Next
stw r8, ReadyQueue.TotalWeight(r9)
; 1ms for critical, successively 8x for other queues
stw r16, ReadyQueue.Timecake(r9)
stw r17, ReadyQueue.Timecake + 4(r9)
; Show off a bit
mflr r20
_log 'Init ready queue '
mr r8, r23 ; the priority (1,2,3,4)
bl printw
mr r8, r16 ; the time cake
bl printw
mr r8, r17
bl printw
_log '^n'
mtlr r20
; Multiply time by 8 for the next iteration
slwi r16, r16, 3
rlwimi r16, r17, 3, 29, 31
slwi r17, r17, 3
; Only do four of these
addi r23, r23, 1
cmpwi r23, 4
addi r9, r9, 32 ;ReadyQueue.Size
blt @loop
; DO SOMETHING ELSE:
; If the low nybble is empty, set ContextBlock.PriorityShifty to 2.
lwz r16, KDP.PA_ECB(r1)
lwz r17, ContextBlock.PriorityShifty(r16)
andi. r9, r17, 0xF
li r17, 2
bnelr
stw r17, ContextBlock.PriorityShifty(r16)
blr
###### ### ## ## ######## ###### ######## ######## ######
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
###### ## ## ## ## ###### ## #### ######## ######## ######
## ######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
###### ## ## ### ######## ###### ## ## ## ######
; ...to (ECB *)r6
; (and also copy SPRG0 to r8)
SchSaveStartingAtR14
li r8, ContextBlock.r16 & -32
dcbtst r8, r6
stw r14, ContextBlock.r14(r6)
stw r15, ContextBlock.r15(r6)
SchSaveStartingAtR16
li r8, ContextBlock.r20 & -32
stw r16, ContextBlock.r16(r6)
dcbtst r8, r6
stw r17, ContextBlock.r17(r6)
stw r18, ContextBlock.r18(r6)
stw r19, ContextBlock.r19(r6)
SchSaveStartingAtR20
li r8, ContextBlock.r24 & -32
stw r20, ContextBlock.r20(r6)
dcbtst r8, r6
stw r21, ContextBlock.r21(r6)
stw r22, ContextBlock.r22(r6)
stw r23, ContextBlock.r23(r6)
SchSaveStartingAtR24
li r8, ContextBlock.r28 & -32
stw r24, ContextBlock.r24(r6)
dcbtst r8, r6
stw r25, ContextBlock.r25(r6)
stw r26, ContextBlock.r26(r6)
stw r27, ContextBlock.r27(r6)
stw r28, ContextBlock.r28(r6)
stw r29, ContextBlock.r29(r6)
stw r30, ContextBlock.r30(r6)
stw r31, ContextBlock.r31(r6)
mfsprg r8, 0
blr
## ####### ### ######## ###### ######## ######## ######
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## #### ######## ######## ######
## ## ## ######### ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
######## ####### ## ## ######## ###### ## ## ## ######
; ...from (ECB *)r6
SchRestoreStartingAtR14
li r31, ContextBlock.r16 & -32
dcbt r31, r6
lwz r14, ContextBlock.r14(r6)
lwz r15, ContextBlock.r15(r6)
SchRestoreStartingAtR16
li r31, ContextBlock.r20 & -32
lwz r16, ContextBlock.r16(r6)
dcbt r31, r6
lwz r17, ContextBlock.r17(r6)
lwz r18, ContextBlock.r18(r6)
lwz r19, ContextBlock.r19(r6)
SchRestoreStartingAtR20
li r31, ContextBlock.r24 & -32
lwz r20, ContextBlock.r20(r6)
dcbt r31, r6
lwz r21, ContextBlock.r21(r6)
lwz r22, ContextBlock.r22(r6)
lwz r23, ContextBlock.r23(r6)
SchRestoreStartingAtR24
li r31, ContextBlock.r28 & -32
lwz r24, ContextBlock.r24(r6)
dcbt r31, r6
lwz r25, ContextBlock.r25(r6)
lwz r26, ContextBlock.r26(r6)
lwz r27, ContextBlock.r27(r6)
lwz r28, ContextBlock.r28(r6)
lwz r29, ContextBlock.r29(r6)
lwz r30, ContextBlock.r30(r6)
lwz r31, ContextBlock.r31(r6)
blr
###### ### ## ## ######## ######## ######## ######## ######
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
###### ## ## ## ## ###### ###### ######## ######## ######
## ######### ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
###### ## ## ### ######## ## ## ## ## ######
; ...to (ECB *)r6
; (but first set the MSR_FP bit in MSR, but *unset* it in r11)
Save_f0_f31
mfmsr r8
rlwinm r11, r11, 0, MSR_FPbit+1, MSR_FPbit-1
_bset r8, r8, MSR_FPbit
mtmsr r8
isync
li r8, 0x220
stfd f0, 0x0200(r6)
dcbtst r8, r6
stfd f1, 0x0208(r6)
stfd f2, 0x0210(r6)
stfd f3, 0x0218(r6)
li r8, 0x240
stfd f4, 0x0220(r6)
dcbtst r8, r6
stfd f5, 0x0228(r6)
stfd f6, 0x0230(r6)
stfd f7, 0x0238(r6)
li r8, 0x260
stfd f8, 0x0240(r6)
dcbtst r8, r6
stfd f9, 0x0248(r6)
stfd f10, 0x0250(r6)
stfd f11, 0x0258(r6)
li r8, 640
stfd f12, 0x0260(r6)
dcbtst r8, r6
stfd f13, 0x0268(r6)
stfd f14, 0x0270(r6)
stfd f15, 0x0278(r6)
li r8, 0x2a0
stfd f16, 0x0280(r6)
dcbtst r8, r6
stfd f17, 0x0288(r6)
stfd f18, 0x0290(r6)
stfd f19, 0x0298(r6)
li r8, 0x2c0
stfd f20, 0x02a0(r6)
dcbtst r8, r6
stfd f21, 0x02a8(r6)
stfd f22, 0x02b0(r6)
stfd f23, 0x02b8(r6)
li r8, 0x2e0
stfd f24, 0x02c0(r6)
dcbtst r8, r6
stfd f25, 0x02c8(r6)
stfd f26, 0x02d0(r6)
stfd f27, 0x02d8(r6)
mffs f0
stfd f28, 0x02e0(r6)
stfd f29, 0x02e8(r6)
stfd f30, 0x02f0(r6)
stfd f31, 0x02f8(r6)
stfd f0, 0x00e0(r6)
blr
## ####### ### ######## ## ## ######## ######
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ######## ######
## ## ## ######### ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
######## ####### ## ## ######## ### ## ## ######
Restore_v0_v31 ; OUTSIDE REFERER
li r8, 0x200
mfspr r11, vrsave
lvxl v0, r8, r10
mtcr r11
mtvscr v0
lwz r8, -0x0004(r1)
li r9, PSA.VectorRegInitWord
lvx v31, r8, r9
vor v0, v31, v31
bge major_0x13988_0x108
li r8, 0x00
lvx v0, r8, r10
major_0x13988_0x108
vor v1, v31, v31
ble major_0x13988_0x118
li r9, 0x10
lvx v1, r9, r10
major_0x13988_0x118
vor v2, v31, v31
bne major_0x13988_0x128
li r8, 0x20
lvx v2, r8, r10
major_0x13988_0x128
vor v3, v31, v31
bns major_0x13988_0x138
li r9, 0x30
lvx v3, r9, r10
major_0x13988_0x138
vor v4, v31, v31
bge cr1, major_0x13988_0x148
li r8, 0x40
lvx v4, r8, r10
major_0x13988_0x148
vor v5, v31, v31
ble cr1, major_0x13988_0x158
li r9, 0x50
lvx v5, r9, r10
major_0x13988_0x158
vor v6, v31, v31
bne cr1, major_0x13988_0x168
li r8, 0x60
lvx v6, r8, r10
major_0x13988_0x168
vor v7, v31, v31
bns cr1, major_0x13988_0x178
li r9, 0x70
lvx v7, r9, r10
major_0x13988_0x178
vor v8, v31, v31
bge cr2, major_0x13988_0x188
li r8, 0x80
lvx v8, r8, r10
major_0x13988_0x188
vor v9, v31, v31
ble cr2, major_0x13988_0x198
li r9, 0x90
lvx v9, r9, r10
major_0x13988_0x198
vor v10, v31, v31
bne cr2, major_0x13988_0x1a8
li r8, 160
lvx v10, r8, r10
major_0x13988_0x1a8
vor v11, v31, v31
bns cr2, major_0x13988_0x1b8
li r9, 0xb0
lvx v11, r9, r10
major_0x13988_0x1b8
vor v12, v31, v31
bge cr3, major_0x13988_0x1c8
li r8, 0xc0
lvx v12, r8, r10
major_0x13988_0x1c8
vor v13, v31, v31
ble cr3, major_0x13988_0x1d8
li r9, 0xd0
lvx v13, r9, r10
major_0x13988_0x1d8
vor v14, v31, v31
bne cr3, major_0x13988_0x1e8
li r8, 0xe0
lvx v14, r8, r10
major_0x13988_0x1e8
vor v15, v31, v31
bns cr3, major_0x13988_0x1f8
li r9, 240
lvx v15, r9, r10
major_0x13988_0x1f8
vor v16, v31, v31
bge cr4, major_0x13988_0x208
li r8, 0x100
lvx v16, r8, r10
major_0x13988_0x208
vor v17, v31, v31
ble cr4, major_0x13988_0x218
li r9, 0x110
lvx v17, r9, r10
major_0x13988_0x218
vor v18, v31, v31
bne cr4, major_0x13988_0x228
li r8, 0x120
lvx v18, r8, r10
major_0x13988_0x228
vor v19, v31, v31
bns cr4, major_0x13988_0x238
li r9, 0x130
lvx v19, r9, r10
major_0x13988_0x238
vor v20, v31, v31
bge cr5, major_0x13988_0x248
li r8, 320
lvx v20, r8, r10
major_0x13988_0x248
vor v21, v31, v31
ble cr5, major_0x13988_0x258
li r9, 0x150
lvx v21, r9, r10
major_0x13988_0x258
vor v22, v31, v31
bne cr5, major_0x13988_0x268
li r8, 0x160
lvx v22, r8, r10
major_0x13988_0x268
vor v23, v31, v31
bns cr5, major_0x13988_0x278
li r9, 0x170
lvx v23, r9, r10
major_0x13988_0x278
vor v24, v31, v31
bge cr6, major_0x13988_0x288
li r8, 0x180
lvx v24, r8, r10
major_0x13988_0x288
vor v25, v31, v31
ble cr6, major_0x13988_0x298
li r9, 400
lvx v25, r9, r10
major_0x13988_0x298
vor v26, v31, v31
bne cr6, major_0x13988_0x2a8
li r8, 0x1a0
lvx v26, r8, r10
major_0x13988_0x2a8
vor v27, v31, v31
bns cr6, major_0x13988_0x2b8
li r9, 0x1b0
lvx v27, r9, r10
major_0x13988_0x2b8
vor v28, v31, v31
bge cr7, major_0x13988_0x2c8
li r8, 0x1c0
lvx v28, r8, r10
major_0x13988_0x2c8
vor v29, v31, v31
ble cr7, major_0x13988_0x2d8
li r9, 0x1d0
lvx v29, r9, r10
major_0x13988_0x2d8
vor v30, v31, v31
bne cr7, major_0x13988_0x2e8
li r8, 480
lvx v30, r8, r10
major_0x13988_0x2e8
vor v31, v31, v31
bns cr7, major_0x13988_0x2f8
li r9, 0x1f0
lvx v31, r9, r10
major_0x13988_0x2f8
blr
###### ### ## ## ######## ## ## ######## ######
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
###### ## ## ## ## ###### ## ## ######## ######
## ######### ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
###### ## ## ### ######## ### ## ## ######
align 4 ; ????
Save_v0_v31 ; OUTSIDE REFERER
mfspr r5, vrsave
lwz r2, 0x00d8(r6)
cmplwi r2, 0x00
beqlr
andis. r3, r11, 0x200
stw r5, 0x0210(r2)
beqlr
mfmsr r3
rlwinm r11, r11, 0, 7, 5
oris r3, r3, 0x200
mtmsr r3
isync
li r3, 0x00
li r4, 0x10
mtcr r5
stvx v0, r3, r2
stvxl v1, r4, r2
mfvscr v0
li r3, 0x200
stvx v0, r3, r2
bne Save_v0_v31_0x5c
li r3, 0x20
stvx v2, r3, r2
Save_v0_v31_0x5c
bns Save_v0_v31_0x68
li r4, 0x30
stvx v3, r4, r2
Save_v0_v31_0x68
bge cr1, Save_v0_v31_0x74
li r3, 0x40
stvx v4, r3, r2
Save_v0_v31_0x74
ble cr1, Save_v0_v31_0x80
li r4, 0x50
stvx v5, r4, r2
Save_v0_v31_0x80
bne cr1, Save_v0_v31_0x8c
li r3, 0x60
stvx v6, r3, r2
Save_v0_v31_0x8c
bns cr1, Save_v0_v31_0x98
li r4, 0x70
stvx v7, r4, r2
Save_v0_v31_0x98
bge cr2, Save_v0_v31_0xa4
li r3, 0x80
stvx v8, r3, r2
Save_v0_v31_0xa4
ble cr2, Save_v0_v31_0xb0
li r4, 0x90
stvx v9, r4, r2
Save_v0_v31_0xb0
bne cr2, Save_v0_v31_0xbc
li r3, 160
stvx v10, r3, r2
Save_v0_v31_0xbc
bns cr2, Save_v0_v31_0xc8
li r4, 0xb0
stvx v11, r4, r2
Save_v0_v31_0xc8
bge cr3, Save_v0_v31_0xd4
li r3, 0xc0
stvx v12, r3, r2
Save_v0_v31_0xd4
ble cr3, Save_v0_v31_0xe0
li r4, 0xd0
stvx v13, r4, r2
Save_v0_v31_0xe0
bne cr3, Save_v0_v31_0xec
li r3, 0xe0
stvx v14, r3, r2
Save_v0_v31_0xec
bns cr3, Save_v0_v31_0xf8
li r4, 240
stvx v15, r4, r2
Save_v0_v31_0xf8
bge cr4, Save_v0_v31_0x104
li r3, 0x100
stvx v16, r3, r2
Save_v0_v31_0x104
ble cr4, Save_v0_v31_0x110
li r4, 0x110
stvx v17, r4, r2
Save_v0_v31_0x110
bne cr4, Save_v0_v31_0x11c
li r3, 0x120
stvx v18, r3, r2
Save_v0_v31_0x11c
bns cr4, Save_v0_v31_0x128
li r4, 0x130
stvx v19, r4, r2
Save_v0_v31_0x128
bge cr5, Save_v0_v31_0x134
li r3, 320
stvx v20, r3, r2
Save_v0_v31_0x134
ble cr5, Save_v0_v31_0x140
li r4, 0x150
stvx v21, r4, r2
Save_v0_v31_0x140
bne cr5, Save_v0_v31_0x14c
li r3, 0x160
stvx v22, r3, r2
Save_v0_v31_0x14c
bns cr5, Save_v0_v31_0x158
li r4, 0x170
stvx v23, r4, r2
Save_v0_v31_0x158
bge cr6, Save_v0_v31_0x164
li r3, 0x180
stvx v24, r3, r2
Save_v0_v31_0x164
ble cr6, Save_v0_v31_0x170
li r4, 400
stvx v25, r4, r2
Save_v0_v31_0x170
bne cr6, Save_v0_v31_0x17c
li r3, 0x1a0
stvx v26, r3, r2
Save_v0_v31_0x17c
bns cr6, Save_v0_v31_0x188
li r4, 0x1b0
stvx v27, r4, r2
Save_v0_v31_0x188
bge cr7, Save_v0_v31_0x194
li r3, 0x1c0
stvx v28, r3, r2
Save_v0_v31_0x194
ble cr7, Save_v0_v31_0x1a0
li r4, 0x1d0
stvx v29, r4, r2
Save_v0_v31_0x1a0
bne cr7, Save_v0_v31_0x1ac
li r3, 480
stvx v30, r3, r2
Save_v0_v31_0x1ac
bns cr7, Save_v0_v31_0x1b8
li r4, 0x1f0
stvx v31, r4, r2
Save_v0_v31_0x1b8
blr
######## ### ###### ## ## ## ## ## ## ######## ######## ## ##
## ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## #### ## ## ## ## ## ####
## ## ## ###### ##### ## ## ## ## ## ######## ## ## ##
## ######### ## ## ## ## ## ## #### ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ### ## ## ## ## ##
## ## ## ###### ## ## ####### ## ## ## ## ######## ##
; Remove a task from its RDYQ, cleaning up the queue structures behind me.
; If a queue is empty, unset the priority flag of the queue in
; PSA.PriorityFlags. Also set the mysterious EWA.SchEvalFlag to 1.
; ARG Task *r8
; CLOB r16, r17, r18
SchTaskUnrdy
lwz r17, Task.QueueMember + LLL.Next( r8)
lbz r18, Task.State( r8)
addi r16, r8, Task.QueueMember
; Panic if State==0, return early if this task is not enqueued (i.e. LLL.Next==0)
cmpwi cr1, r18, 0
cmpwi r17, 0
beq cr1, Local_Panic
beq @return_early
RemoveFromList r16, scratch1=r17, scratch2=r18
; The queue of which this task was formerly a member
lwz r17, LLL.Freeform(r16)
; Tidy up by subtracting this tasks weight from the Q weight
lwz r16, Task.Weight(r8)
lwz r18, ReadyQueue.TotalWeight(r17)
subf r18, r16, r18
stw r18, ReadyQueue.TotalWeight(r17)
; Decrement the Q counter
lwz r18, ReadyQueue.Counter(r17)
subi r18, r18, 1
stw r18, ReadyQueue.Counter(r17)
; Optimised below: a bit confusing
cmpwi r18, 0 ; Crash if we popped from an empty queue!
lwz r16, PSA.PriorityFlags(r1)
blt Local_Panic
bne @return_early
lwz r18, ReadyQueue.LLL + LLL.Freeform(r17)
andc r16, r16, r18 ; If this queue is empty then unset the corresponding
stw r16, PSA.PriorityFlags(r1) ; bit in PSA.PriorityFlags
@return_early
li r16, 0
stb r16, Task.State(r8)
mfsprg r17, 0
li r16, 1
stb r16, EWA.SchEvalFlag(r17)
blr
######## ### ###### ## ## ######## ######## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ####
## ## ## ###### ##### ######## ## ## ##
## ######### ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ###### ## ## ## ## ######## ##
; These two entry cases specify different directions of queue insertion
; ARG Task *r8
; CLOB r16, r17, r18
SchRdyTaskLater
crclr cr1_eq
b _SchRdyTaskCommon
SchRdyTaskNow ; not much point in doing this unless you then flag a scheduler evaluation
crset cr1_eq
_SchRdyTaskCommon
lwz r16, Task.QueueMember + LLL.Next(r8)
lis r17, 0x8000 ; ...0000
cmpwi r16, 0
lbz r18, Task.Priority(r8)
bne Local_Panic
; Set the KDP priority flag for this task.
; Leave pointer to target RDYQ in r17.
lwz r16, PSA.PriorityFlags(r1)
srw r17, r17, r18
mulli r18, r18, 32 ;ReadyQueue.Size
or r16, r16, r17
addi r17, r1, PSA.ReadyQueues
stw r16, PSA.PriorityFlags(r1)
add r17, r17, r18
; What decrements this counter?
lwz r18, ReadyQueue.Counter(r17)
addi r18, r18, 1
stw r18, ReadyQueue.Counter(r17)
lwz r16, Task.Weight(r8)
lwz r18, ReadyQueue.TotalWeight(r17)
add r18, r18, r16
stw r18, ReadyQueue.TotalWeight(r17)
addi r16, r8, Task.QueueMember
bne cr1, @as_next
stw r17, LLL.Freeform(r16)
InsertAsPrev r16, r17, scratch=r18
b @endif
@as_next
stw r17, LLL.Freeform(r16)
InsertAsNext r16, r17, scratch=r18
@endif
li r16, 1
stb r16, Task.State(r8)
blr
###### ######## ######## ### ######## ###### ######## ########
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
###### ######## ###### ######## ## ## ## ###### ###### ##
## ## ## ## ## ## ######### ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
###### ## ## ######## ## ## ## ###### ######## ##
; Set the segment and block allocation table registers according to the
; SPAC structure passed in. On non-601 machines, unset the "guarded" bit
; of the WIMG field of each lower BAT register.
;
; And apparently there is a second, undocumented batch of BAT registers!
; ARG AddressSpace *r8, AddressSpace *r9 (can be zero?)
SchSwitchSpace
; This is the only function that hits this counter
lwz r17, KDP.NanoKernelInfo + NKNanoKernelInfo.AddrSpcSetCtr(r1)
addi r17, r17, 1
stw r17, KDP.NanoKernelInfo + NKNanoKernelInfo.AddrSpcSetCtr(r1)
; Check that we have the right guy (a 'SPAC')
lwz r16, AddressSpace.Signature(r8)
lisori r17, AddressSpace.kSignature
cmpw r16, r17
bne Local_Panic
; Intend to skip the dssall instruction if Altivec is... present? absent?
rlwinm. r16, r7, 0, EWA.kFlagVec, EWA.kFlagVec ; seems to be leftover from Init.s Altivec testing
; Apply the address space to the segment registers
isync
lwz r16, AddressSpace.SRs + 0(r8)
lwz r17, AddressSpace.SRs + 4(r8)
mtsr 0, r16
mtsr 1, r17
lwz r16, AddressSpace.SRs + 8(r8)
lwz r17, AddressSpace.SRs + 12(r8)
mtsr 2, r16
mtsr 3, r17
lwz r16, AddressSpace.SRs + 16(r8)
lwz r17, AddressSpace.SRs + 20(r8)
mtsr 4, r16
mtsr 5, r17
lwz r16, AddressSpace.SRs + 24(r8)
lwz r17, AddressSpace.SRs + 28(r8)
mtsr 6, r16
mtsr 7, r17
lwz r16, AddressSpace.SRs + 32(r8)
lwz r17, AddressSpace.SRs + 36(r8)
mtsr 8, r16
mtsr 9, r17
lwz r16, AddressSpace.SRs + 40(r8)
lwz r17, AddressSpace.SRs + 44(r8)
mtsr 10, r16
mtsr 11, r17
lwz r16, AddressSpace.SRs + 48(r8)
lwz r17, AddressSpace.SRs + 52(r8)
mtsr 12, r16
mtsr 13, r17
lwz r16, AddressSpace.SRs + 56(r8)
lwz r17, AddressSpace.SRs + 60(r8)
mtsr 14, r16
mtsr 15, r17
beq @skip_dssall
dssall ; flush pending vector ops?
@skip_dssall
; Point KDP at this SPAC
mfsprg r16, 0 ; paranoid
isync
stw r8, EWA.PA_CurAddressSpace(r16)
; The 601 has a special code path for populating the BATs
mfpvr r16
rlwinm. r16, r16, 0, 0, 14
cmpwi cr1, r9, 0 ; arg r9 is 0 when called from Init.s
beq @is_601
; Fill the BATs on "real" PowerPC CPUs
lwz r16, AddressSpace.BAT0U(r8)
lwz r17, AddressSpace.BAT0U(r9)
cmplw r16, r17
lwz r17, AddressSpace.BAT0L(r8)
beq cr1, @definitely_set_BAT0
beq @skip_setting_BAT0
@definitely_set_BAT0 ; r9 is zero or the addrspc bats match low physical memory
mtspr dbat0u, r0
mtspr dbat0l, r17
rlwinm r17, r17, 0, 29, 27
mtspr dbat0u, r16
mtspr ibat0u, r0
mtspr ibat0l, r17
mtspr ibat0u, r16
@skip_setting_BAT0
lwz r16, AddressSpace.BAT1U(r8)
lwz r17, AddressSpace.BAT1U(r9)
cmplw r16, r17
lwz r17, AddressSpace.BAT1L(r8)
beq cr1, @definitely_set_BAT1
beq @skip_setting_BAT1
@definitely_set_BAT1
mtspr dbat1u, r0
mtspr dbat1l, r17
rlwinm r17, r17, 0, 29, 27
mtspr dbat1u, r16
mtspr ibat1u, r0
mtspr ibat1l, r17
mtspr ibat1u, r16
@skip_setting_BAT1
lwz r16, AddressSpace.BAT2U(r8)
lwz r17, AddressSpace.BAT2U(r9)
cmplw r16, r17
lwz r17, AddressSpace.BAT2L(r8)
beq cr1, @definitely_set_BAT2
beq @skip_setting_BAT2
@definitely_set_BAT2
mtspr dbat2u, r0
mtspr dbat2l, r17
rlwinm r17, r17, 0, 29, 27
mtspr dbat2u, r16
mtspr ibat2u, r0
mtspr ibat2l, r17
mtspr ibat2u, r16
@skip_setting_BAT2
lwz r16, AddressSpace.BAT3U(r8)
lwz r17, AddressSpace.BAT3U(r9)
cmplw r16, r17
lwz r17, AddressSpace.BAT3L(r8)
beq cr1, @definitely_set_BAT3
beq @skip_setting_BAT3
@definitely_set_BAT3
mtspr dbat3u, r0
mtspr dbat3l, r17
rlwinm r17, r17, 0, 29, 27
mtspr dbat3u, r16
mtspr ibat3u, r0
mtspr ibat3l, r17
mtspr ibat3u, r16
@skip_setting_BAT3
; This is weird. If the hasExtraBATs flag (my name) is set in ProcessorInfo,
; populate a second (undocumented?) set of BATs from the same struct.
lwz r17, KDP.ProcessorInfo + NKProcessorInfo.ProcessorFlags(r1)
lwz r16, AddressSpace.ExtraBAT0U(r8)
rlwinm. r17, r17, 0, 31-NKProcessorInfo.hasExtraBATs, 31-NKProcessorInfo.hasExtraBATs
lwz r17, AddressSpace.ExtraBAT0U(r9)
beq @return
cmplw r16, r17
lwz r17, AddressSpace.ExtraBAT0L(r8)
beq cr1, @definitely_set_ExtraBAT0
beq @skip_setting_ExtraBAT0
@definitely_set_ExtraBAT0
mtspr 0x238, r0
mtspr 0x239, r17
mtspr 0x238, r16
mtspr 0x230, r0
mtspr 0x231, r17
mtspr 0x230, r16
@skip_setting_ExtraBAT0
lwz r16, AddressSpace.ExtraBAT1U(r8)
lwz r17, AddressSpace.ExtraBAT1U(r9)
cmplw r16, r17
lwz r17, AddressSpace.ExtraBAT1L(r8)
beq cr1, @definitely_set_ExtraBAT1
beq @skip_setting_ExtraBAT1
@definitely_set_ExtraBAT1
mtspr 0x23a, r0
mtspr 0x23b, r17
mtspr 0x23a, r16
mtspr 0x232, r0
mtspr 0x233, r17
mtspr 0x232, r16
@skip_setting_ExtraBAT1
lwz r16, AddressSpace.ExtraBAT2U(r8)
lwz r17, AddressSpace.ExtraBAT2U(r9)
cmplw r16, r17
lwz r17, AddressSpace.ExtraBAT2L(r8)
beq cr1, @definitely_set_ExtraBAT2
beq @skip_setting_ExtraBAT2
@definitely_set_ExtraBAT2
mtspr 0x23c, r0
mtspr 0x23d, r17
mtspr 0x23c, r16
mtspr 0x234, r0
mtspr 0x235, r17
mtspr 0x234, r16
@skip_setting_ExtraBAT2
lwz r16, AddressSpace.ExtraBAT3U(r8)
lwz r17, AddressSpace.ExtraBAT3U(r9)
cmplw r16, r17
lwz r17, AddressSpace.ExtraBAT3L(r8)
beq cr1, @definitely_set_ExtraBAT3
beq @skip_setting_ExtraBAT3
@definitely_set_ExtraBAT3
mtspr 0x23e, r0
mtspr 0x23f, r17
mtspr 0x23e, r16
mtspr 0x236, r0
mtspr 0x237, r17
mtspr 0x236, r16
@skip_setting_ExtraBAT3
@return
blr
; This is the crazy cpu case
@is_601
lwz r16, 0x0080(r8)
lwz r17, 0x0080(r9)
cmplw r16, r17
lwz r17, 0x0084(r8)
beq cr1, SetAddrSpcRegisters_0x284
beq SetAddrSpcRegisters_0x29c
SetAddrSpcRegisters_0x284:
rlwimi r16, r17, 0, 25, 31
mtspr ibat0u, r16
lwz r16, 0x0080(r8)
rlwimi r17, r16, 30, 26, 31
rlwimi r17, r16, 6, 25, 25
mtspr ibat0l, r17
SetAddrSpcRegisters_0x29c:
lwz r16, 0x0088(r8)
lwz r17, 0x0088(r9)
cmplw r16, r17
lwz r17, 0x008c(r8)
beq cr1, SetAddrSpcRegisters_0x2b4
beq SetAddrSpcRegisters_0x2cc
SetAddrSpcRegisters_0x2b4:
rlwimi r16, r17, 0, 25, 31
mtspr ibat1u, r16
lwz r16, 0x0088(r8)
rlwimi r17, r16, 30, 26, 31
rlwimi r17, r16, 6, 25, 25
mtspr ibat1l, r17
SetAddrSpcRegisters_0x2cc:
lwz r16, 0x0090(r8)
lwz r17, 0x0090(r9)
cmplw r16, r17
lwz r17, 0x0094(r8)
beq cr1, SetAddrSpcRegisters_0x2e4
beq SetAddrSpcRegisters_0x2fc
SetAddrSpcRegisters_0x2e4:
rlwimi r16, r17, 0, 25, 31
mtspr ibat2u, r16
lwz r16, 0x0090(r8)
rlwimi r17, r16, 30, 26, 31
rlwimi r17, r16, 6, 25, 25
mtspr ibat2l, r17
SetAddrSpcRegisters_0x2fc:
lwz r16, 0x0098(r8)
lwz r17, 0x0098(r9)
cmplw r16, r17
lwz r17, 0x009c(r8)
beq cr1, SetAddrSpcRegisters_0x314
beqlr
SetAddrSpcRegisters_0x314:
rlwimi r16, r17, 0, 25, 31
mtspr ibat3u, r16
lwz r16, 0x0098(r8)
rlwimi r17, r16, 30, 26, 31
rlwimi r17, r16, 6, 25, 25
mtspr ibat3l, r17
blr
; Always and only jumped to by IntReturn
SchReturn
lbz r8, EWA.SchEvalFlag(r1)
rlwinm. r9, r7, 0, 16, 16
lwz r1, EWA.PA_KDP(r1)
cmpwi cr1, r8, 0
bne SchExitInterrupt
beq+ cr1, SchExitInterrupt
bl SchSaveStartingAtR14
_Lock PSA.SchLock, scratch1=r27, scratch2=r28
; Either fallen through from SchReturn, or jumped to by
; TrulyCommonMPCallReturnPath when it wants to block the caller
; SchLock should be acquired before now!
SchEval
mfsprg r14, 0
li r8, 0
stb r8, EWA.SchEvalFlag(r14)
lwz r31, EWA.PA_CurTask(r14)
lwz r1, EWA.PA_KDP(r14)
lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.SchEvalCount(r1)
addi r9, r9, 1
stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.SchEvalCount(r1)
bl SchFiddlePriorityShifty
lbz r27, 0x0019(r31)
blt major_0x142dc_0x58
li r26, 0x01
beq major_0x142dc_0x38
li r26, 0x00
major_0x142dc_0x38
cmpw r27, r26
mr r8, r31
beq major_0x142dc_0x58
bl SchTaskUnrdy
stb r26, 0x0019(r31)
mr r8, r31
bl SchRdyTaskNow
bl CalculateTimeslice
major_0x142dc_0x58 ; OUTSIDE REFERER
lwz r27, PSA.PriorityFlags(r1)
major_0x142dc_0x5c
mr r30, r31
cmpwi r27, 0x00
cntlzw r26, r27
beq major_0x142dc_0x140
addi r25, r1, PSA.CriticalReadyQ
mulli r26, r26, 0x20
add r26, r26, r25
lwz r29, 0x0008(r26)
addi r30, r29, -0x08
major_0x142dc_0x80
lhz r28, EWA.CPUIndex(r14)
lwz r24, 0x0064(r30)
lhz r25, 0x001a(r30)
rlwinm. r8, r24, 0, 25, 26
cmpw cr1, r25, r28
beq major_0x142dc_0xb8
beq cr1, major_0x142dc_0xb8
lwz r29, 0x0008(r29)
addi r30, r29, -0x08
cmpw r29, r26
bne major_0x142dc_0x80
lwz r25, 0x0000(r26)
andc r27, r27, r25
b major_0x142dc_0x5c
major_0x142dc_0xb8
lbz r25, 0x0018(r31)
lbz r28, 0x0019(r30)
lbz r27, 0x0019(r31)
cmpwi cr1, r25, 0x02
cmpw cr2, r28, r27
bne cr1, major_0x142dc_0xd8
blt cr2, major_0x142dc_0xd8
mr r30, r31
major_0x142dc_0xd8 ; OUTSIDE REFERER
lwz r28, 0x0010(r30)
addi r29, r30, 0x08
cmpwi r28, 0x00
lwz r26, 0x0008(r30)
beq major_0x142dc_0x140
RemoveFromList r29, scratch1=r28, scratch2=r27
lwz r27, 0x001c(r30)
lwz r28, 0x0014(r26)
subf r28, r27, r28
stw r28, 0x0014(r26)
lwz r28, 0x0010(r26)
lwz r27, PSA.PriorityFlags(r1)
addi r28, r28, -0x01
cmpwi r28, 0x00
stw r28, 0x0010(r26)
bltl Local_Panic
bne major_0x142dc_0x140
lwz r28, 0x0000(r26)
andc r27, r27, r28
stw r27, PSA.PriorityFlags(r1)
major_0x142dc_0x140
lwz r25, 0x0064(r30)
li r26, 0x00
rlwinm. r8, r25, 0, 21, 22
andc r27, r25, r8
beq+ major_0x142dc_0x184
ori r27, r27, 0x200
stb r26, 0x0018(r30)
stw r27, 0x0064(r30)
addi r25, r1, PSA.DbugQueue
addi r26, r30, 0x08
stw r25, 0x0000(r26)
InsertAsPrev r26, r25, scratch=r27
b major_0x142dc_0x58
major_0x142dc_0x184
cmpw cr3, r30, r31
rlwinm. r8, r25, 0, 27, 27
bne cr3, _SchPreempt
bne _SchPreempt
; Don't preempt, keep running the same task
bl GetTime
bl major_0x148ec
lwz r27, 0x0064(r31)
mfsprg r14, 0
rlwinm. r8, r27, 0, 8, 8
rlwimi r11, r27, 24, 29, 29
beq+ major_0x142dc_0x1bc
lwz r10, 0x00fc(r6)
_bclr r27, r27, Task.kFlag8
stw r27, 0x0064(r31)
major_0x142dc_0x1bc
li r27, 0x02
lbz r28, 0x0019(r31)
stb r27, 0x0018(r31)
stb r28, -0x0117(r14)
_AssertAndRelease PSA.SchLock, scratch=r27
; r6 = ewa
bl SchRestoreStartingAtR14
; SchLock should be released before here
SchExitInterrupt
lwz r8, 0x0edc(r1)
mfsprg r1, 0
mtlr r12
mtspr srr0, r10
mtspr srr1, r11
rlwinm. r8, r8, 0, 27, 27
beq SchExitInterrupt_0x2c
mfxer r8
rlwinm r8, r8, 0, 23, 21
rlwimi r8, r7, 19, 23, 23
mtxer r8
SchExitInterrupt_0x2c
mtcr r13
lwz r10, 0x0154(r6)
lwz r11, 0x015c(r6)
lwz r12, 0x0164(r6)
lwz r13, 0x016c(r6)
lwz r7, 0x013c(r6)
lwz r8, 0x0144(r6)
lwz r9, 0x014c(r6)
lwz r0, 0x0104(r6)
lwz r6, 0x0018(r1)
lwz r1, 0x0004(r1)
rfi
dcb.b 32, 0
; ARG outgoing_cb *r6, EWA *r14, incoming_task *r30, task_to_save_to *r31
_SchPreempt
; Save info for the previous task
lwz r16, Task.Flags(r31)
stw r30, EWA.SchSavedIncomingTask(r14) ; will clobber r30
_bclr r16, r16, Task.kFlag26
stw r6, Task.ContextBlockPtr(r31)
mfsprg r8, 3
stw r16, Task.Flags(r31)
stw r8, Task.VecBase(r31)
; Spam its context block
lwz r8, EWA.Enables(r14)
stw r7, ContextBlock.Flags(r6)
stw r8, ContextBlock.Enables(r6)
mfxer r8
stw r13, ContextBlock.CR(r6)
stw r8, ContextBlock.XER(r6)
stw r12, ContextBlock.LR(r6)
mfctr r8
stw r10, ContextBlock.CodePtr(r6)
stw r8, ContextBlock.KernelCTR(r6)
mfspr r8, pvr
rlwinm. r8, r8, 0, 0, 14
bne @not_601
mfspr r8, mq
stw r8, ContextBlock.MQ(r6)
@not_601
lwz r8, EWA.r1(r14)
stw r8, ContextBlock.r1(r6)
stw r2, ContextBlock.r2(r6)
stw r3, ContextBlock.r3(r6)
andi. r8, r11, MSR_FP
stw r4, ContextBlock.r4(r6)
lwz r8, EWA.r6(r14)
stw r5, ContextBlock.r5(r6)
stw r8, ContextBlock.r6(r6)
bnel Save_f0_f31
lwz r31, EWA.PA_CurTask(r14) ; sly aside: r30 = new, r31 = current
lwz r30, EWA.SchSavedIncomingTask(r14)
rlwinm. r8, r7, 0, EWA.kFlagVec, EWA.kFlagVec
bnel Save_v0_v31
stw r11, ContextBlock.MSR(r6)
; Bump current task's preemption ctr
lwz r8, Task.PreemptCtr(r31)
addi r8, r8, 1
stw r8, Task.PreemptCtr(r31)
; No clue
bl GetTime
bl major_0x148ec
; Update EWA global to match this task, and set task's state to 2
mfsprg r14, 0
li r27, 2
lbz r28, Task.Priority(r30)
stb r27, Task.State(r30)
stb r28, EWA.TaskPriority(r14)
; If incoming task is not already running, and running task is not in a queue, re-ready the running task
cmplw r30, r31
lwz r16, Task.QueueMember + LLL.Next(r31)
beq @no
cmpwi r16, 0
mr r8, r31
beql SchRdyTaskNow
@no
; Play more with the incoming task
mfsprg r19, 0
li r8, 0
stb r8, EWA.SchEvalFlag(r19)
lhz r8, EWA.CPUIndex(r19)
lwz r6, Task.ContextBlockPtr(r30)
lwz r28, EWA.CPUBase + CPU.ID(r19)
sth r8, Task.CPUIndex(r30)
stw r28, Task.CpuID(r30)
stw r30, EWA.PA_CurTask(r19)
stw r6, EWA.PA_ContextBlock(r19)
lwz r7, ContextBlock.Flags(r6)
lwz r28, ContextBlock.Enables(r6)
stw r7, EWA.Flags(r19)
stw r28, EWA.Enables(r19)
lwz r27, Task.Flags(r30)
lwz r13, ContextBlock.CR(r6)
ori r27, r27, 1 << (31 - Task.kFlag26)
lwz r11, 0x00a4(r6)
lwz r8, 0x00f0(r30)
rlwimi r11, r27, 24, 29, 29
_bclr r27, r27, Task.kFlag8
mtsprg 3, r8
stw r27, Task.Flags(r30)
; Switch address space if necessary
lwz r18, Task.AddressSpacePtr(r30)
lwz r9, EWA.PA_CurAddressSpace(r19)
cmpw r18, r9
beq @same_space
mr r8, r18
bl SchSwitchSpace
@same_space
mfsprg r19, 0
; Is this the blue task? If so, do we need to interrupt it?
mtcr r7
lisori r28, 1 << (31 - Task.kFlagSchToInterruptEmu)
bc BO_IF_NOT, EWA.kFlagBlue, @NO_BLUE_INTERRUPT
and. r28, r28, r27
li r8, 0
beq @NO_BLUE_INTERRUPT
; TRIGGER AN INTERRUPT IN THE BLUE TASK
andc r27, r27, r28
lwz r29, PSA.MCR(r1)
stw r27, Task.Flags(r30) ; unset the task flag that got us here
stw r8, PSA.MCR(r1)
bc BO_IF, EWA.kFlagEmu, @already_in_system_context
bcl BO_IF, 27, Local_Panic
; Need to switch blue task from alternate context to system context
clrlwi r8, r7, 8
stw r8, ContextBlock.Flags(r6)
lwz r6, KDP.PA_ECB(r1)
addi r26, r1, KDP.VecBaseSystem
mtsprg 3, r26
stw r26, Task.VecBase(r30)
stw r6, EWA.PA_ContextBlock(r19)
stw r6, Task.ContextBlockPtr(r30)
lwz r7, ContextBlock.Flags(r6)
lwz r26, ContextBlock.Enables(r6)
mtcr r7
stw r26, EWA.Enables(r19)
lwz r13, ContextBlock.CR(r6)
lwz r11, ContextBlock.MSR(r6)
bcl BO_IF, 27, Local_Panic
rlwimi r11, r7, 0, 20, 23 ; apply MSR[FE0/SE/BE/FE1]
rlwimi r7, r8, 0, 9, 16 ; keep flags 9-16 from alternate context
rlwimi r11, r27, 24, 29, 29 ; MSR[PMM] = Task.kFlagPerfMon
stw r7, EWA.Flags(r19)
@already_in_system_context
; Blue task now (or was already) in system context (i.e. 68k emulator is running)
lwz r17, ContextBlock.PriorityShifty(r6)
ori r17, r17, 0x100
stw r17, ContextBlock.PriorityShifty(r6)
; EDP.INTM_L = PSA.Pending68kInt (presumably the emulator polls this)
lhz r17, PSA.Pending68kInt(r1)
lwz r18, KDP.PA_EmulatorIplValue(r1)
cmplwi r17, 0xffff ; i.e. (short)(-1)
lwz r26, KDP.PostIntMaskInit(r1)
beq @no_change_to_int_level ; would this ever happen?
sth r17, 0(r18)
li r17, -1
sth r17, PSA.Pending68kInt(r1)
@no_change_to_int_level
; Fiddle with the emulator's Condition Register ("int mask")
cmpwi r29, 0
or r13, r13, r29
bne @did_set_bits_in_mask
lwz r29, KDP.ClearIntMaskInit(r1)
and r13, r13, r29
@did_set_bits_in_mask
@NO_BLUE_INTERRUPT
; Back to the common path for preemption (pretty boring)
lwz r29, 0x00d8(r6)
cmpwi r29, 0x00
lwz r8, 0x0210(r29)
beq _SchPreempt_0x220
mtspr vrsave, r8
_SchPreempt_0x220
lwz r8, 0x00d4(r6)
lwz r12, 0x00ec(r6)
mtxer r8
lwz r8, 0x00f4(r6)
lwz r10, 0x00fc(r6)
mtctr r8
mfspr r8, pvr
rlwinm. r8, r8, 0, 0, 14
bne _SchPreempt_0x24c
lwz r8, 0x00c4(r6)
mtspr mq, r8
_SchPreempt_0x24c
li r9, 0x124
lwz r8, 0x010c(r6)
dcbt r9, r6
lwz r2, 0x0114(r6)
stw r8, 0x0004(r19)
lwz r3, 0x011c(r6)
li r9, 0x184
lwz r4, 0x0124(r6)
dcbt r9, r6
lwz r8, 0x0134(r6)
lwz r5, 0x012c(r6)
stw r8, 0x0018(r19)
lwz r14, 0x0174(r6)
lwz r15, 0x017c(r6)
li r9, 420
lwz r16, 0x0184(r6)
dcbt r9, r6
lwz r17, 0x018c(r6)
lwz r18, 0x0194(r6)
lwz r19, 0x019c(r6)
li r9, 0x1c4
lwz r20, 0x01a4(r6)
dcbt r9, r6
lwz r21, 0x01ac(r6)
lwz r22, 0x01b4(r6)
lwz r23, 0x01bc(r6)
li r9, 0x1e4
lwz r24, 0x01c4(r6)
dcbt r9, r6
lwz r25, 0x01cc(r6)
lwz r26, 0x01d4(r6)
lwz r27, 0x01dc(r6)
andi. r8, r11, 0x2900
lwz r28, 0x01e4(r6)
lwz r29, 0x01ec(r6)
lwz r30, 0x01f4(r6)
lwz r31, 0x01fc(r6)
beq _SchPreempt_0x380
mfmsr r8
ori r8, r8, 0x2000
ori r11, r11, 0x2000
mtmsr r8
isync
lfd f31, 0x00e0(r6)
lfd f0, 0x0200(r6)
lfd f1, 0x0208(r6)
lfd f2, 0x0210(r6)
lfd f3, 0x0218(r6)
lfd f4, 0x0220(r6)
lfd f5, 0x0228(r6)
lfd f6, 0x0230(r6)
lfd f7, 0x0238(r6)
mtfsf 0xff, f31
lfd f8, 0x0240(r6)
lfd f9, 0x0248(r6)
lfd f10, 0x0250(r6)
lfd f11, 0x0258(r6)
lfd f12, 0x0260(r6)
lfd f13, 0x0268(r6)
lfd f14, 0x0270(r6)
lfd f15, 0x0278(r6)
lfd f16, 0x0280(r6)
lfd f17, 0x0288(r6)
lfd f18, 0x0290(r6)
lfd f19, 0x0298(r6)
lfd f20, 0x02a0(r6)
lfd f21, 0x02a8(r6)
lfd f22, 0x02b0(r6)
lfd f23, 0x02b8(r6)
lfd f24, 0x02c0(r6)
lfd f25, 0x02c8(r6)
lfd f26, 0x02d0(r6)
lfd f27, 0x02d8(r6)
lfd f28, 0x02e0(r6)
lfd f29, 0x02e8(r6)
lfd f30, 0x02f0(r6)
lfd f31, 0x02f8(r6)
_SchPreempt_0x380
_AssertAndRelease PSA.SchLock, scratch=r8
b SchExitInterrupt
major_0x148ec ; OUTSIDE REFERER
mfxer r20
mfsprg r21, 0
lwz r19, 0x00cc(r31)
lwz r18, 0x00c8(r31)
subfc r19, r19, r9
subfe r18, r18, r8
lwz r17, 0x00c4(r31)
lwz r16, 0x00c0(r31)
addc r17, r17, r19
adde r16, r16, r18
stw r17, 0x00c4(r31)
stw r16, 0x00c0(r31)
lwz r17, 0x00dc(r31)
lwz r16, 0x00d8(r31)
andi. r22, r17, 0x01
bne major_0x148ec_0x58
subfc r17, r19, r17
subfe. r16, r18, r16
bge major_0x148ec_0x54
li r16, 0x00
li r17, 0x00
major_0x148ec_0x54
stw r16, 0x00d8(r31)
major_0x148ec_0x58
rlwinm r17, r17, 0, 0, 30
stw r17, 0x00dc(r31)
lwz r17, 0x00fc(r31)
andi. r22, r17, 0x01
bne major_0x148ec_0x78
subf. r17, r19, r17
bge major_0x148ec_0x78
li r17, 0x00
major_0x148ec_0x78
rlwinm r17, r17, 0, 0, 30
stw r17, 0x00fc(r31)
stw r8, 0x00c8(r30)
stw r9, 0x00cc(r30)
lwz r18, 0x0008(r30)
lbz r19, 0x0019(r30)
lwz r18, 0x0010(r18)
cmpwi cr1, r19, 0x02
cmpwi r18, 0x00
bge cr1, major_0x148ec_0xb0
lwz r16, 0x00fc(r30)
lwz r17, 0x00fc(r30)
srawi r16, r16, 31
b major_0x148ec_0xc8
major_0x148ec_0xb0
lwz r16, 0x00d8(r30)
lwz r17, 0x00dc(r30)
bgt major_0x148ec_0xc8
bne cr1, major_0x148ec_0xc8
li r16, 0x00
lwz r17, 0x0f2c(r1)
major_0x148ec_0xc8
addc r17, r17, r9
adde r16, r16, r8
stw r17, -0x02e4(r21)
stw r16, -0x02e8(r21)
mtxer r20
li r16, 0x01
stb r16, -0x0309(r21)
b SetTimesliceFromCurTime
; Almost certain this was hand-written. Has a typo, and some
; instructions the compiler rarely touched, and is in hot path.
; ARG Task *r8
major_0x149d4 ; OUTSIDE REFERER
crset cr1_eq
b major_0x149d4_0xc
CalculateTimeslice ; OUTSIDE REFERER
crclr cr1_eq
major_0x149d4_0xc:
; CALCULATE TASK'S TIMESLICE
; Get task info
lwz r18, Task.QueueMember + LLL.Next(r8)
lwz r16, Task.QueueMember + LLL.Freeform(r8) ; points to RDYQ
cmpwi r18, 0
lwz r17, Task.Weight(r8)
beq Local_Panic
; Get queue info
lwz r18, ReadyQueue.TotalWeight(r16)
lwz r19, ReadyQueue.Timecake(r16)
lwz r20, ReadyQueue.Timecake + 4(r16)
; Skip calculation if only task in queue
cmpw r18, r17
rlwinm r17, r17, 10, 0, 22 ; r17 *= 1024, but with minor masking typo?
beq @is_only_weighted_task
divw. r18, r17, r18 ; r8 = my share of this queue's weight, out of 1024
ble @no_time ; if not specified, fall back on 1/1024
; t = t * r18 = my share of queue's time, out of 1024
mulhw r17, r20, r18
mullw r19, r19, r18
mullw r20, r20, r18
add r19, r19, r17
@no_time
; t = t / 1024 = my share of queue's time
srwi r20, r20, 10
rlwimi r20, r19, 22, 0, 9
srwi r19, r19, 10
@is_only_weighted_task
; NOW: r19 || r20 == task's slice of queue Timecake, in TB/DEC units
lbz r18, Task.Priority(r8)
cmpwi r18, Task.kNominalPriority
ori r20, r20, 1 ; why make this odd?
bge @nominal_or_idle
;critical or latency protected
stw r20, 0x00fc(r8)
blr
@nominal_or_idle
lwz r16, 0x00d8(r8)
lwz r17, 0x00dc(r8)
bc BO_IF, cr1_eq, @definitely_do_the_thing
cmpwi r16, 0
cmplwi cr2, r17, 0
blt @definitely_do_the_thing
bgtlr
bgtlr cr2
@definitely_do_the_thing
;double-int is negative or zero
mfxer r18
addc r20, r20, r17
adde r19, r19, r16
mtxer r18
rlwinm r20, r20, 0, 0, 30
li r18, 1
stw r19, 0x00d8(r8)
stw r20, 0x00dc(r8)
stw r18, 0x00fc(r8)
blr
clear_cr0_lt ; OUTSIDE REFERER
crclr cr0_lt
blr
SchFiddlePriorityShifty ; OUTSIDE REFERER
rlwinm r8, r7, EWA.kFlagBlue, 0, 0
lwz r18, KDP.PA_ECB(r1)
nand. r8, r8, r8
lwz r17, ContextBlock.PriorityShifty(r18)
bltlr ; return if flag 10 was unset
cmpwi r17, 0
rlwinm r9, r17, 0, 22, 22
blt @pshifty_high_bit_set
cmpwi r9, 0x200
lwz r16, ContextBlock.r25(r18)
beq @pshifty_bit_22_set
clrlwi r8, r16, 29
clrlwi r9, r17, 28
cmpwi r8, 6
bgt @pshifty_bit_22_set
cmpw r8, r9
bltlr
cmpw r8, r8
@pshifty_bit_22_set
ori r17, r17, 0x100
stw r17, ContextBlock.PriorityShifty(r18)
blr
@pshifty_high_bit_set
clrlwi r17, r17, 1
stw r17, ContextBlock.PriorityShifty(r18)
blr
######## ## ### ###### ######## ## ## ### ##
## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
###### ## ## ## ## #### ###### ## ## ## ## ##
## ## ######### ## ## ## ## ## ######### ##
## ## ## ## ## ## ## ## ## ## ## ##
## ######## ## ## ###### ######## ### ## ## ########
; ARG Task *r8
FlagSchEvaluationIfTaskRequires ; OUTSIDE REFERER
lwz r16, Task.Flags(r8)
mfsprg r15, 0
rlwinm. r16, r16, 0, Task.kFlag25, Task.kFlag26
bne FlagSchEval
addi r16, r15, EWA.CPUBase
lbz r17, Task.Priority(r8)
lwz r19, CPU.LLL + LLL.Freeform(r16)
; Uniprocessor systems:
; Flag a reevaluation on this, the only CPU
lwz r14, CoherenceGroup.ScheduledCpuCount(r19)
cmpwi r14, 2
blt FlagSchEval
; Multiprocessor systems:
; Find the best CPU to flag a
lwz r14, CoherenceGroup.CpuCount(r19)
mr r18, r16
b @loopentry
; r19 = motherboard coherence group
; r14 = loop counter
; r16 = current CPU pointer
@loop_hit_the_coherence_group
lwz r16, CoherenceGroup.CPUList + LLL.Next(r19)
@loop
subi r16, r16, CPU.LLL
@loopentry
subi r14, r14, 1
lbz r20, CPU.EWA + EWA.TaskPriority(r16)
lwz r21, CPU.Flags(r16)
cmpw cr1, r17, r20
rlwinm. r21, r21, 0, CPU.kFlagScheduled, CPU.kFlagScheduled
bge cr1, @cpu_not_best_for_task
beq @cpu_not_best_for_task
mr r17, r20
mr r18, r16
@cpu_not_best_for_task
lwz r16, CPU.LLL + LLL.Next(r16) ; next element
cmpwi cr1, r14, 0
cmpw r16, r19
ble cr1, @exit_loop
beq @loop_hit_the_coherence_group ; skip the owner of the linked list
b @loop
@exit_loop
; r17 = least-important priority being executed on any CPU
; r18 = pointer to that CPU
; No suitable CPU found (all running important-er tasks)
lbz r16, Task.Priority(r8)
cmpw r17, r16
blelr
; Was this CPU the most suitable?
lhz r17, EWA.CPUIndex(r15)
lhz r18, CPU.EWA + EWA.CPUIndex(r18)
cmpw r18, r17
bne AlertSchEvalOnOtherCPU
; otherwise fall through to FlagSchEvalOnThisCPU
; RETURN PATHS
; To force a scheduler evaluation to run on *this* CPU when returning from
; *this* interrupt, just raise a flag.
FlagSchEvalOnThisCPU
li r16, 1
stb r16, EWA.SchEvalFlag(r15)
blr
; Public function! Can go to FlagSchEvalOnThisCPU or AlertSchEvalOnOtherCPU
FlagSchEval
mfsprg r15, 0
lhz r18, Task.CPUIndex(r8)
lhz r17, EWA.CPUIndex(r15)
cmpw r17, r18
beq FlagSchEvalOnThisCPU
; To force a scheduler evaluation to run on *another* CPU, we interrupt it
AlertSchEvalOnOtherCPU
lwz r9, KDP.NanoKernelInfo + NKNanoKernelInfo.AlertCount(r1)
addi r9, r9, 1
stw r9, KDP.NanoKernelInfo + NKNanoKernelInfo.AlertCount(r1)
li r16, kAlert
stw r16, EWA.SIGPSelector(r15)
stw r18, EWA.SIGPCallR4(r15)
li r8, 2
b SIGP ; returns to link register
NewCpuEntryPoint
; This func gets passed its CPU struct in r3,
; which lets us find its real EWA pointer.
addi r1, r3, CPU.EWA
mtsprg 0, r1
; Get KDP
lwz r1, EWA.PA_KDP(r1)
lwz r8, KDP.HTABORG(r1)
lwz r9, KDP.PTEGMask(r1)
; Set SDR1 (same as the main ones)
srwi r9, r9, 16
or r9, r8, r9
sync
mtspr sdr1, r9
sync
_log 'Sch: Symmetric Multiprocessing^n'
_log 'Sch: On CPU '
lhz r8, CPU.EWA + EWA.CPUIndex(r3)
bl Printh
_log ' ID-'
lwz r8, -0x0340(r3)
bl Printw
_log ' SDR1: '
mr r8, r9
bl Printw
_log ' CpuDescriptor: '
mr r8, r3
bl Printw
_log ' KDP: '
mr r8, r1
bl Printw
_log '^n'
bl PagingFlushTLB
; This is important to figure out:
_log 'Sch: Starting SMP idle task^n'
_Lock PSA.SchLock, scratch1=r27, scratch2=r28
mfsprg r14, 0
lwz r31, CPU.IdleTaskPtr(r3)
li r8, 0
stb r8, EWA.SchEvalFlag(r14)
lwz r6, Task.ContextBlockPtr(r31)
stw r31, EWA.PA_CurTask(r14)
stw r6, EWA.PA_ContextBlock(r14)
lwz r7, ContextBlock.Flags(r6)
lwz r28, ContextBlock.Enables(r6)
stw r7, EWA.Flags(r14)
stw r28, EWA.Enables(r14)
lwz r8, Task.VecBase(r31)
mtsprg 3, r8
lwz r10, ContextBlock.CodePtr(r6)
lwz r11, ContextBlock.MSR(r6)
lwz r13, ContextBlock.CR(r6)
lwz r12, ContextBlock.LR(r6)
_log 'EWA '
mr r8, r14
bl Printw
_log 'ContextPtr '
mr r8, r6
bl Printw
_log 'Flags '
mr r8, r7
bl Printw
_log 'Enables '
mr r8, r28
bl Printw
_log '^n'
addi r16, r31, Task.QueueMember
RemoveFromList r16, scratch1=r17, scratch2=r18
li r16, 2
stb r16, Task.State(r31)
lwz r16, Task.Flags(r31)
ori r16, r16, 0x20
stw r16, Task.Flags(r31)
mfsprg r14, 0
lbz r8, Task.Priority(r31)
stb r8, EWA.TaskPriority(r14)
lwz r8, Task.AddressSpacePtr(r31)
li r9, 0
bl SchSwitchSpace
_log 'Adding idle task 0x'
mr r8, r31
bl Printw
_log 'to the ready queue^n'
mr r8, r31
bl SchRdyTaskNow
bl CalculateTimeslice
lwz r16, CPU.Flags(r3)
ori r16, r16, 8
stw r16, CPU.Flags(r3)
lwz r17, Task.QueueMember + LLL.Freeform(r3)
lwz r16, 0x0024(r17)
addi r16, r16, 0x01
stw r16, 0x0024(r17)
li r8, 1
mtspr dec, r8
_log 'Sch: Going to '
mr r8, r11 ; MSR
bl Printw
mr r8, r10 ; PC
bl Printw
_log '^n'
mr r30, r31
b major_0x142dc_0xd8
b major_0x142dc_0x58
SchIdleTask
li r31, 0
lisori r20, 'idle'
lisori r21, 'task'
lisori r22, 'Ren<EFBFBD>'
lisori r23, 'Alan'
lisori r24, 'Jim '
lisori r25, 'Alex'
lisori r26, 'Derr'
lisori r27, 'ick '
@loop
; Kill some time
mr r30, r1
mr r1, r2
mr r2, r5
mr r5, r6
mr r6, r7
mr r7, r8
mr r8, r9
mr r9, r10
mr r10, r11
mr r11, r12
mr r12, r13
mr r13, r14
mr r14, r15
mr r15, r16
mr r16, r17
mr r17, r18
mr r18, r19
mr r19, r20
mr r20, r21
mr r21, r22
mr r22, r23
mr r23, r24
mr r24, r25
mr r25, r26
mr r26, r27
mr r27, r28
mr r28, r29
mr r29, r30
; If the loop started with r31==0, make another round of syscalls
cmpwi r31, 0
beq @make_calls
; But if we counted down from >=1 to zero, then just do that again
subi r31, r31, 1
cmplwi r31, 0
bgt @startagain
@make_calls
; Check that CPU plugin trusts this CPU
li r3, kGetProcessorTemp
li r4, 1 ; 2nd arg ignored
li r0, 46 ; KCCpuPlugin
sc
cmpwi r3, 0
beq @startagain
li r3, 1
li r4, 0
twi 31, r31, 5 ; PowerCall(1)
cmpwi r3, 0
beq @startagain
lisori r31, 10*1000000
@startagain
b @loop
SchIdleTaskStopper
mfmsr r30
andi. r29, r30, 0x7fff
mtmsr r29
mfsprg r2, 0
lwz r1, -0x0004(r2)
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
addi r31, r2, -0x340
lwz r16, 0x0018(r31)
rlwinm r16, r16, 0, 29, 27
stw r16, 0x0018(r31)
sync
lwz r17, 0x0008(r31)
lwz r16, 0x0024(r17)
addi r16, r16, -0x01
stw r16, 0x0024(r17)
lwz r8, 0x001c(r31)
li r9, 0x00
stw r9, 0x001c(r31)
bl SchTaskUnrdy
addi r16, r1, PSA.DelayQueue
addi r17, r8, 0x08
stw r16, 0x0000(r17)
InsertAsPrev r17, r16, scratch=r18
bl TasksFuncThatIsNotAMPCall
_AssertAndRelease PSA.SchLock, scratch=r16
_log 'SIGP kStopProcessor^n'
li r3, kStopProcessor
lhz r4, CPU.EWA + EWA.CPUIndex(r31)
; Use twi to call MPCpuPlugin(3, myCpuID)
li r0, 46
twi 31, r31, 8
_log 'Stop didn''t work - going to sleep.^n'
SchIdleTaskStopper_0x10c
lis r5, 0x7fff
ori r5, r5, 0xffff
mtdec r5
li r3, 6
li r4, 0
twi 31, r31, 5
b SchIdleTaskStopper_0x10c