; 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Ž' 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