powermac-rom/NanoKernel/NKSync.s

3115 lines
75 KiB
ArmAsm

; AUTO-GENERATED SYMBOL LIST
; IMPORTS:
; NKIndex
; DeleteID
; LookupID
; MakeID
; NKMPCalls
; BlockMPCall
; ReleaseAndReturnMPCall
; ReleaseAndReturnMPCallBlueBlocking
; ReleaseAndReturnMPCallInvalidIDErr
; ReleaseAndReturnMPCallOOM
; ReleaseAndReturnMPCallTaskAborted
; ReleaseAndReturnParamErrFromMPCall
; ReleaseAndReturnZeroFromMPCall
; ReleaseAndScrambleMPCall
; ReleaseAndTimeoutMPCall
; ReturnMPCallOOM
; ReturnZeroFromMPCall
; ScrambleMPCall
; NKPoolAllocator
; PoolAlloc
; PoolAllocClear
; PoolFree
; NKScheduler
; CalculateTimeslice
; FlagSchEvaluationIfTaskRequires
; SchRdyTaskLater
; SchRdyTaskNow
; SchTaskUnrdy
; NKThud
; panic
; NKTimers
; DequeueTimer
; EnqueueTimer
; GetTime
; TimebaseTicksPerPeriod
; EXPORTS:
; CauseNotification (=> NKAddressSpaces, NKInterrupts, NKPrimaryIntHandlers)
; EnqueueMessage (=> NKInterrupts, NKTasks, NKTimers)
; SetEvent (=> NKAddressSpaces, NKTimers)
; SignalSemaphore (=> NKTimers)
; UnblockBlueIfCouldBePolling (=> NKInterrupts)
####### ## ## ######## ## ## ######## ######
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ##
## ## ## ## ###### ## ## ###### ######
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
##### ## ####### ######## ####### ######## ######
## ######## ####### ###### ######## ######## ### ######## ########
#### ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
## ####### ## ## ## ######## ###### ## ## ## ######
## ## ## ## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
###### ###### ##### ## ###### ## ## ######## ## ## ## ########
; RET OSStatus r3, QueueID r4
DeclareMPCall 15, MPCreateQueue
MPCreateQueue
li r8, Queue.Size
bl PoolAlloc
mr. r31, r8
beq ScrambleMPCall
; List of messages waiting for tasks
InitList r8, 'MSGQ', scratch=r16
; List of blocked tasks waiting to be notified of messages
addi r9, r8, Queue.Messages
InitList r9, 'NOTQ', scratch=r16
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
li r9, Queue.kIDClass
bl MakeID
cmpwi r8, 0
bne+ @nofail
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
@nofail
mfsprg r30, 0
lwz r30, EWA.PA_CurTask(r30)
stw r8, Queue.BlockedTasks + LLL.Freeform(r31)
lwz r17, Task.ProcessID(r30)
stw r17, Queue.ProcessID(r31)
mr r4, r8
li r17, 0
stw r17, Queue.ReserveCount(r31)
stw r17, Queue.ReservePtr(r31)
stw r17, Queue.BlockedTaskCount(r31)
stw r17, Queue.MessageCount(r31)
b ReleaseAndReturnZeroFromMPCall
## ####### ####### ######## ######## ## ######## ######## ########
#### ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
## ######## ## ## ## ## ###### ## ###### ## ######
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
###### ####### ##### ## ######## ######## ######## ######## ## ########
; Delete a message queue:
; 1. Delete its messages.
; 2. Call UnblockBlueIfCouldBePolling on the queue?
; 3. Unblock waiting tasks with kMPDeletedErr, calling FlagSchEvaluationIfTaskRequires on each.
; 4. Delete the queue structure and its ID.
; ARG QueueID r3
; RET OSStatus r3
DeclareMPCall 16, MPDeleteQueue
MPDeleteQueue
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Queue.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
; Delete all auto-allocated messages
@note_free_loop
addi r30, r31, Queue.Messages
lwz r8, Queue.Messages + LLL.Next(r31)
cmpw r8, r30
beq @exit_note_free_loop
RemoveFromList r8, scratch1=r16, scratch2=r17
bl PoolFree
b @note_free_loop
@exit_note_free_loop
; Delete all pre-allocated messages
lwz r30, Queue.ReservePtr(r31)
@notr_free_loop
mr. r8, r30
beq @exit_notr_free_loop
lwz r30, Message.LLL + LLL.Next(r30)
bl PoolFree
b @notr_free_loop
@exit_notr_free_loop
mr r8, r3
bl UnblockBlueIfCouldBePolling
; UNBLOCK the tasks that are blocked waiting on this queue.
; From the task's perspective, MPWaitOnQueue will return
; kMPDeletedErr, because we tweak the task's ContextBlock.
@task_unblock_loop
; Peek at our MSGQ queue of blocked tasks
addi r30, r31, Queue.BlockedTasks
lwz r16, Queue.BlockedTasks + LLL.Next(r31)
cmpw r16, r30
subi r8, r16, Task.QueueMember
beq @exit_task_loop
; Manipulate its r3 from afar
lwz r17, Task.ContextBlockPtr(r8)
li r18, kMPDeletedErr
stw r18, ContextBlock.r3(r17)
; If blocked with timeout, dequeue task's internal timer
lbz r17, Task.Timer + Timer.Byte3(r8)
cmpwi r17, 1
bne @no_timeout
addi r8, r8, Task.Timer
bl DequeueTimer
@no_timeout
; Remove from this MSGQ
lwz r16, Queue.BlockedTasks + LLL.Next(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
; Put RDYQ
subi r8, r16, Task.QueueMember
bl SchRdyTaskNow
bl FlagSchEvaluationIfTaskRequires
b @task_unblock_loop
@exit_task_loop
; Delete the actual Queue structure and its ID
mr r8, r31
bl PoolFree
mr r8, r3
bl DeleteID
b ReleaseAndReturnZeroFromMPCall
####### ####### ####### ######## ######## ###### ######## ######## ## ## ########
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
####### ######## ## ## ######## ###### ###### ###### ######## ## ## ######
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
####### ####### ##### ## ## ## ######## ###### ######## ## ## ### ########
; Reserve space for messages for this queue.
; (guarantees message delivery)
; Reserved messages have signature 'notr' (vs. 'note').
; ARG QueueID r3, ItemCount r4
; RET OSStatus r3
DeclareMPCall 39, MPSetQueueReserve
MPSetQueueReserve
cmpwi r4, 0
blt ReturnMPCallOOM
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Queue.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
lwz r29, Queue.ReserveCount(r31)
lwz r30, Queue.ReservePtr(r31)
cmpw r29, r4
beq ReleaseAndReturnZeroFromMPCall
blt @make_more
; NEW < OLD
@free_loop
mr. r8, r30
beq @free_loop_failed
subi r29, r29, 1
lwz r30, LLL.Next(r30)
bl PoolFree
cmpw r29, r4
bgt @free_loop
;free loop succeeded
stw r4, Queue.ReserveCount(r31)
stw r30, Queue.ReservePtr(r31)
b ReleaseAndReturnZeroFromMPCall
@free_loop_failed
stw r29, Queue.ReserveCount(r31)
stw r30, Queue.ReservePtr(r31)
b ReleaseAndReturnMPCallOOM
; NEW > OLD
@make_more
@alloc_loop
li r8, Message.Size
bl PoolAlloc
cmpwi r8, 0
beq ReleaseAndScrambleMPCall
addi r29, r29, 1
lisori r17, Message.kReservedSignature
stw r17, Message.LLL + LLL.Signature(r8)
stw r30, Message.LLL + LLL.Next(r8)
stw r29, Queue.ReserveCount(r31)
cmpw r29, r4
stw r8, Queue.ReservePtr(r31)
mr r30, r8
blt @alloc_loop
b ReleaseAndReturnZeroFromMPCall
## ######## ####### ## ## ####### ######## #### ######## ## ##
#### ## ## ## ## ### ## ## ## ## ## ## ## ##
## ## ## ## #### ## ## ## ## ## ## ####
## ## ## ## ## ## ## ## ## ## ## ###### ##
## ## ## ## ## ## #### ## ## ## ## ## ##
## ## ## ## ## ### ## ## ## ## ## ##
###### ## ##### ## ## ## ####### ## #### ## ##
; Sends a 12-byte message to the specified queue
; ARG QueueID r3, long r4, long r5, long r6
DeclareMPCall 17, MPNotifyQueue
MPNotifyQueue
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Queue.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
lwz r16, Queue.ReserveCount(r31)
li r8, Message.Size
cmpwi r16, 0
bne @try_reserve
;no reservation available
bl PoolAlloc
cmpwi r8, 0
beq ReleaseAndScrambleMPCall
lisori r17, Message.kSignature
stw r17, Message.LLL + LLL.Signature(r8)
b @common
@try_reserve
lwz r17, Queue.ReservePtr(r31)
mr. r8, r17
beq ReleaseAndReturnMPCallOOM
lwz r17, Message.LLL + LLL.Next(r17)
stw r17, Queue.ReservePtr(r31)
@common
; Got a message ptr in r8!
; Fill it with lies
lwz r16, ContextBlock.r6(r6)
stw r4, Message.Word1(r8)
stw r5, Message.Word2(r8)
stw r16, Message.Word3(r8)
bl EnqueueMessage ; Message *r8, Queue *r31
b ReleaseAndReturnZeroFromMPCall
### ####### ## ## ###### ###### ###
## ## ## ### ### ## ## ## ## ##
## ## ## #### #### ## ## ##
## ## ## ## ### ## ###### ## #### ##
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
### ##### ## ## ## ###### ###### ###
; Enqueue a note/notr object.
; Odd way of unblocking task (does not touch r3 directly):
; 1. Add message to queue.
; 2. If task waiting, unblock with rewound PC to retry syscall.
; ARG Message *r8, Queue *r31
EnqueueMessage
addi r17, r31, Queue.Messages
stw r17, LLL.Freeform(r8)
InsertAsPrev r8, r17, scratch=r16
lwz r18, Queue.MessageCount(r31)
addi r18, r18, 1
stw r18, Queue.MessageCount(r31)
mflr r27
lwz r8, Queue.BlockedTasks + LLL.Freeform(r31)
bl UnblockBlueIfCouldBePolling
; Got a task to unblock straight away?
lwz r16, Queue.BlockedTasks + LLL.Next(r31)
cmpw r16, r31
subi r8, r16, Task.QueueMember
beq @no_task
; Saves us special-casing
lwz r17, Task.ContextBlockPtr(r8)
lwz r18, ContextBlock.CodePtr(r17)
subi r18, r18, 4
stw r18, ContextBlock.CodePtr(r17)
; De-fang the task's blocking timeout
lbz r17, Task.Timer + Timer.Byte3(r8)
cmpwi r17, 1
bne @no_timeout
addi r8, r8, Task.Timer
bl DequeueTimer
@no_timeout
; Remove the task from this MSGQ
lwz r16, Queue.BlockedTasks + LLL.Next(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
lwz r18, Queue.BlockedTaskCount(r31)
subi r18, r18, 1
stw r18, Queue.BlockedTaskCount(r31)
subi r8, r16, Task.QueueMember
; And add it back to the latency-protection RDYQ
li r17, Task.kLatencyProtectPriority
stb r17, Task.Priority(r8)
bl SchRdyTaskNow
bl CalculateTimeslice
bl FlagSchEvaluationIfTaskRequires
@no_task
mtlr r27
blr
## ####### ####### ## ## ### #### ########
#### ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
## ####### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ##
###### ####### ##### ## ### ### ## ## #### ##
; Get a message from the specified queue, or fail.
; Abbreviated summary of cases:
; 1. Return a pending message
; 2. Time out instantly
; 3. Move task to MSGQ from RDYQ and arm timer
; 4. Move task to MSGQ from RDYQ, no timeout
; ARG QueueID r3, Duration r7
; RET OSStatus r3, long r4, long r5, long r6
DeclareMPCall 18, MPWaitOnQueue
MPWaitOnQueue
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Queue.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, Queue.Messages + LLL.Next(r31)
addi r17, r31, Queue.Messages
cmpw r16, r17
beq @no_messages_pending
;messages pending
lwz r4, Message.Word1(r16)
lwz r5, Message.Word2(r16)
lwz r17, Message.Word3(r16)
stw r17, ContextBlock.r6(r6)
RemoveFromList r16, scratch1=r17, scratch2=r18
lwz r18, Queue.MessageCount(r31)
subi r18, r18, 1
stw r18, Queue.MessageCount(r31)
lbz r17, Message.LLL + LLL.Signature + 3(r16) ; 'r' if mem-reserved message, else 'e'
mr r8, r16
cmpwi r17, Message.kReservedSignature & 0xFF
beq @immediate_msg_was_reserved
;immediate message was not reserved ... return noErr
bl PoolFree
b ReleaseAndReturnZeroFromMPCall
@immediate_msg_was_reserved ; ... return noErr
lwz r17, Queue.ReservePtr(r31)
stw r16, Queue.ReservePtr(r31)
stw r17, LLL.Next(r16)
b ReleaseAndReturnZeroFromMPCall
; The blocking case (eew!)
@no_messages_pending
lwz r17, ContextBlock.r7(r6)
mfsprg r30, 0
;special case: zero timeout ... return
cmpwi r17, 0
lwz r19, EWA.PA_CurTask(r30)
beq ReleaseAndTimeoutMPCall
;special case: blue may not block
lwz r16, Task.Flags(r19)
rlwinm. r16, r16, 0, Task.kFlagBlue, Task.kFlagBlue
beq @bot_blue
stw r3, PSA.BlueSpinningOn(r1)
b ReleaseAndReturnMPCallBlueBlocking
@bot_blue
;committed to blocking the calling task
; Remove from ready queue
mr r8, r19
bl SchTaskUnrdy
; Add to this queue
lwz r19, EWA.PA_CurTask(r30)
addi r16, r31, Queue.BlockedTasks
addi r17, r19, Task.QueueMember
stw r16, LLL.FreeForm(r17)
InsertAsPrev r17, r16, scratch=r18
lwz r18, Queue.BlockedTaskCount(r31)
addi r18, r18, 1
stw r18, Queue.BlockedTaskCount(r31)
; Decide whether call can time out
_lstart r16, 0x7fffffff ; "forever"
lwz r17, ContextBlock.r7(r6)
_lfinish
addi r30, r19, Task.Timer
cmpw r17, r16
li r16, 2
beq @wait_forever
;committed to arming task's built-in timer (finite timeout)
stb r16, Timer.Kind(r30)
stw r19, Timer.ParentTaskPtr(r30)
mr r8, r17
; Convert that timeout to a tick count
bl TimebaseTicksPerPeriod
mr r27, r8
mr r28, r9
bl GetTime
mfxer r16
addc r9, r9, r28
adde r8, r8, r27
mtxer r16
; Now r8/r9 = absolute timeout date
stw r8, Timer.Time(r30)
stw r9, Timer.Time+4(r30)
mr r8, r30
bl EnqueueTimer
@wait_forever
b BlockMPCall
## ####### ####### ####### ## ## ######## ######## ## ##
#### ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ####
## ######## ## ## ## ## ## ## ###### ######## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
###### ####### ##### ## ##### ## ####### ######## ## ## ##
; Non-blocking peek at contents of queue (undocumented)
; Returns timeout if empty, noErr if non-empty
; ARG QueueID r3
; RET OSStatus r3
DeclareMPCall 19, MPQueryQueue
MPQueryQueue
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Queue.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, Queue.Messages + LLL.Next(r31)
addi r17, r31, Queue.Messages
cmpw r16, r17
beq ReleaseAndTimeoutMPCall
b ReleaseAndReturnZeroFromMPCall
###### ######## ## ## ### ######## ## ## ####### ######## ######## ######
## ## ## ### ### ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## #### #### ## ## ## ## ## ## ## ## ## ## ## ##
###### ###### ## ### ## ## ## ######## ######### ## ## ######## ###### ######
## ## ## ## ######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
###### ######## ## ## ## ## ## ## ## ####### ## ## ######## ######
####### ##### ###### ###### ######## ######## ### ######## ########
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
####### ## ## ###### ## ######## ###### ## ## ## ######
## ## ## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
######### ##### ###### ###### ## ## ######## ## ## ## ########
; ARG maxValue r3, initialValue r4
; RET OSStatus r3, SemaphoreID r5
DeclareMPCall 20, MPCreateSemaphore
MPCreateSemaphore
cmpw r4, r3
bgt ReturnMPCallOOM
li r8, Semaphore.Size
bl PoolAlloc
mr. r31, r8
beq ScrambleMPCall
InitList r31, Semaphore.kSignature, scratch=r16
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
li r9, Semaphore.kIDClass
bl MakeID
cmpwi r8, 0
bne+ @nofail
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
@nofail
li r18, 0x00
stw r8, 0x0000(r31)
mfsprg r30, 0
lwz r30, EWA.PA_CurTask(r30)
stw r3, Semaphore.MaxValue(r31)
stw r4, Semaphore.Value(r31)
lwz r17, Task.ProcessID(r30)
stw r18, Semaphore.BlockedTaskCount(r31)
stw r17, Semaphore.ProcessID(r31)
mr r5, r8
b ReleaseAndReturnZeroFromMPCall
####### ####### ###### ## ## ### #### ########
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
####### ####### ###### ## ## ## ## ## ## ##
## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ##
######### ####### ###### ### ### ## ## #### ##
; Wait on a semaphore, or fail (similar to MPWaitOnQueue)
; Abbreviated summary of cases:
; 1. Decrement and return instantly
; 2. Time out instantly
; 3. Move task to SEMA from RDYQ and arm timer
; 4. Move task to SEMA from RDYQ, no timeout
; ARG SemaphoreID r3, Duration r4
DeclareMPCall 23, MPWaitOnSemaphore
MPWaitOnSemaphore
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Semaphore.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, Semaphore.Value(r31)
cmpwi r16, 0
subi r16, r16, 1
ble @must_wait
;easiest case ... decrement and return
stw r16, Semaphore.Value(r31)
b ReleaseAndReturnZeroFromMPCall
@must_wait
;next easiest case ... instant timeout
cmpwi r4, 0
mfsprg r30, 0
beq ReleaseAndTimeoutMPCall
lwz r8, EWA.PA_CurTask(r30)
;special case: blue may not block
lwz r16, Task.Flags(r8)
rlwinm. r16, r16, 0, Task.kFlagBlue, Task.kFlagBlue
beq @bot_blue
stw r3, PSA.BlueSpinningOn(r1)
b ReleaseAndReturnMPCallBlueBlocking
@bot_blue
;committed to blocking the calling task
; Remove from ready queue
bl SchTaskUnrdy
; Add to this queue
addi r16, r31, Semaphore.BlockedTasks
addi r17, r8, Task.QueueMember
stw r16, LLL.FreeForm(r17)
InsertAsPrev r17, r16, scratch=r18
lwz r18, Semaphore.BlockedTaskCount(r31)
addi r18, r18, 1
stw r18, Semaphore.BlockedTaskCount(r31)
_lstart r16, 0x7fffffff
addi r30, r8, Task.Timer
_lfinish
cmpw r4, r16
li r17, 2
beq @wait_forever
;committed to creating a timer (finite timeout)
stb r17, Timer.Kind(r30)
stw r8, Timer.ParentTaskPtr(r30)
mr r8, r4
; Convert that timeout to a tick count
bl TimebaseTicksPerPeriod
mr r27, r8
mr r28, r9
bl GetTime
mfxer r16
addc r9, r9, r28
adde r8, r8, r27
mtxer r16
; Now r8/r9 = absolute timeout date
stw r8, Timer.Time(r30)
stw r9, Timer.Time+4(r30)
mr r8, r30
bl EnqueueTimer
@wait_forever
li r3, 0x00
b BlockMPCall
####### ## ###### ####### ## ## ######## ######## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ####
####### ## ## ###### ## ## ## ## ###### ######## ##
## ######### ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
######### ## ###### ##### ## ####### ######## ## ## ##
; Non-blocking peek at semaphore (undocumented)
; Returns timeout if empty, noErr if non-empty
; ARG SemaphoreID r3
; RET OSStatus r3
DeclareMPCall 24, MPQuerySemaphore
MPQuerySemaphore
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Semaphore.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, Semaphore.Value(r31)
cmpwi r16, 0
ble ReleaseAndTimeoutMPCall
b ReleaseAndReturnZeroFromMPCall
####### ####### ###### ###### #### ###### ## ## ### ##
## ## ## ## ## ## ## ## ## ## ## ### ## ## ## ##
## ## ## ## ## ## #### ## ## ## ##
####### ####### ###### ###### ## ## #### ## ## ## ## ## ##
## ## ## ## ## ## ## ## #### ######### ##
## ## ## ## ## ## ## ## ## ## ### ## ## ##
######### ######### ###### ###### #### ###### ## ## ## ## ########
; ARG SemaphoreID r3
; RET OSStatus r3
DeclareMPCall 22, MPSignalSemaphore
MPSignalSemaphore
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Semaphore.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
bl SignalSemaphore
mr r3, r8
b ReleaseAndReturnMPCall
### ###### ###### #### ###### ## ## ### ## ###
## ## ## ## ## ## ## ## ### ## ## ## ## ##
## ## ## ## ## #### ## ## ## ## ##
## ###### ###### ## ## #### ## ## ## ## ## ## ##
## ## ## ## ## ## ## #### ######### ## ##
## ## ## ## ## ## ## ## ## ### ## ## ## ##
### ###### ###### #### ###### ## ## ## ## ######## ###
; ARG Semaphore *r31
SignalSemaphore ; OUTSIDE REFERER
mflr r27
lwz r8, Semaphore.BlockedTasks + LLL.Freeform(r31)
bl UnblockBlueIfCouldBePolling
lwz r16, 0x0008(r31)
cmpw r16, r31
beq SignalSemaphore_0x80
addi r8, r16, -0x08
lbz r17, 0x0037(r8)
cmpwi r17, 0x01
bne SignalSemaphore_0x30
addi r8, r8, 0x20
bl DequeueTimer
SignalSemaphore_0x30
lwz r16, 0x0008(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
lwz r18, 0x001c(r31)
addi r18, r18, -0x01
stw r18, 0x001c(r31)
addi r8, r16, -0x08
li r17, 0x01
stb r17, 0x0019(r8)
bl SchRdyTaskNow
bl CalculateTimeslice
bl FlagSchEvaluationIfTaskRequires
mtlr r27
li r8, 0x00
blr
SignalSemaphore_0x80
mtlr r27
lwz r16, 0x0010(r31)
lwz r17, 0x0014(r31)
cmpw r16, r17
addi r16, r16, 0x01
li r8, kMPInsufficientResourcesErr
bgelr
stw r16, 0x0010(r31)
li r8, 0x00
blr
####### ## ###### ######## ######## ## ######## ######## ########
## ## #### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
####### ## ###### ## ## ###### ## ###### ## ######
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
######### ###### ###### ######## ######## ######## ######## ## ########
DeclareMPCall 21, MPDeleteSemaphore
MPDeleteSemaphore
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Semaphore.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r3
bl UnblockBlueIfCouldBePolling
MPCall_21_0x34
addi r30, r31, Semaphore.BlockedTasks
lwz r16, LLL.Next(r31)
cmpw r16, r30
addi r8, r16, -0x08
beq MPCall_21_0x98
lwz r17, 0x0088(r8)
li r18, kMPDeletedErr
stw r18, 0x011c(r17)
lbz r17, 0x0037(r8)
cmpwi r17, 0x01
bne MPCall_21_0x68
addi r8, r8, 0x20
bl DequeueTimer
MPCall_21_0x68
lwz r16, 0x0008(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
addi r8, r16, -0x08
bl SchRdyTaskNow
bl FlagSchEvaluationIfTaskRequires
b MPCall_21_0x34
MPCall_21_0x98
mr r8, r31
bl PoolFree
mr r8, r3
bl DeleteID
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
###### ######## #### ######## #### ###### ### ##
## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
## ######## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ######### ##
## ## ## ## ## ## ## ## ## ## ## ##
###### ## ## #### ## #### ###### ## ## ########
######## ######## ###### #### ####### ## ## ######
## ## ## ## ## ## ## ## ### ## ## ##
## ## ## ## ## ## ## #### ## ##
######## ###### ## #### ## ## ## ## ## ## ######
## ## ## ## ## ## ## ## ## #### ##
## ## ## ## ## ## ## ## ## ### ## ##
## ## ######## ###### #### ####### ## ## ######
####### ######## ######## ###### ######## ######## ### ######## ########
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
####### ####### ######## ## ######## ###### ## ## ## ######
## ## ## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
######### ###### ## ## ###### ## ## ######## ## ## ## ########
DeclareMPCall 25, MPCreateCriticalRegion
MPCreateCriticalRegion
li r8, 0x24
bl PoolAlloc
mr. r31, r8
beq ScrambleMPCall
InitList r31, CriticalRegion.kSignature, scratch=r16
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
li r9, 0x06
; r1 = kdp
; r9 = kind
bl MakeID
cmpwi r8, 0x00
bne+ MPCall_25_0x58
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
MPCall_25_0x58
li r18, 0x00
mfsprg r30, 0
lwz r30, -0x0008(r30)
li r16, 0x00
stw r8, 0x0000(r31)
stw r16, 0x0014(r31)
stw r16, 0x001c(r31)
stw r16, 0x0018(r31)
lwz r17, 0x0060(r30)
stw r18, 0x0020(r31)
stw r17, 0x0010(r31)
mr r4, r8
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
####### ######## ######## ######## ## ## ######## ######## ########
## ## ## ## ## ## ## ### ## ## ## ## ##
## ## ## ## ## #### ## ## ## ## ##
####### ## ######## ###### ## ## ## ## ###### ########
## ## ## ## ## ## #### ## ## ## ##
## ## ## ## ## ## ### ## ## ## ##
######### ## ## ## ######## ## ## ## ######## ## ##
DeclareMPCall 27, MPEnterCriticalRegion
MPEnterCriticalRegion
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, CriticalRegion.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
mfsprg r17, 0
lwz r18, 0x0014(r31)
lwz r30, -0x0008(r17)
cmpwi r18, 0x00
lwz r16, 0x0018(r31)
beq MPCall_27_0x64
lwz r17, 0x001c(r31)
cmpw r16, r30
cmpw cr1, r17, r5
bne MPCall_27_0x78
bne cr1, MPCall_27_0x78
addi r18, r18, 0x01
stw r18, 0x0014(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPCall_27_0x64
addi r18, r18, 0x01
stw r30, 0x0018(r31)
stw r5, 0x001c(r31)
stw r18, 0x0014(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPCall_27_0x78
lwz r8, 0x0000(r16)
; r8 = id
bl LookupID
cmpwi r9, Task.kIDClass
bne ReleaseAndReturnMPCallTaskAborted
lwz r8, 0x001c(r31)
; r8 = id
bl LookupID
cmpwi r9, Process.kIDClass
bne ReleaseAndReturnMPCallTaskAborted
cmpwi r4, 0x00
;special case: blue may not block
lwz r16, Task.Flags(r30)
beq ReleaseAndTimeoutMPCall
rlwinm. r16, r16, 0, Task.kFlagBlue, Task.kFlagBlue
beq @bot_blue
stw r3, PSA.BlueSpinningOn(r1)
b ReleaseAndReturnMPCallBlueBlocking
@bot_blue
MPCall_27_0xb4
mr r8, r30
bl SchTaskUnrdy
lis r16, 0x7fff
addi r18, r30, 0x08
ori r16, r16, 0xffff
stw r31, 0x0000(r18)
InsertAsPrev r18, r31, scratch=r19
lwz r18, 0x0020(r31)
addi r18, r18, 0x01
stw r18, 0x0020(r31)
cmpw r4, r16
beq MPCall_27_0x138
addi r29, r30, 0x20
li r8, 0x02
stw r30, 0x0018(r29)
stb r8, 0x0014(r29)
mr r8, r4
; r1 = kdp
; r8 = multiple (pos: /250; neg: /250000)
bl TimebaseTicksPerPeriod
; r8 = hi
; r9 = lo
mr r27, r8
mr r28, r9
bl GetTime
mfxer r16
addc r9, r9, r28
adde r8, r8, r27
mtxer r16
stw r8, 0x0038(r29)
stw r9, 0x003c(r29)
mr r8, r29
bl EnqueueTimer
MPCall_27_0x138
b BlockMPCall
####### ####### ######## ####### ## ## ######## ######## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ####
####### ######## ######## ## ## ## ## ###### ######## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
######### ####### ## ## ##### ## ####### ######## ## ## ##
DeclareMPCall 29, MPQueryCriticalRegion
MPQueryCriticalRegion
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, CriticalRegion.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
mfsprg r17, 0
lwz r18, 0x0014(r31)
cmpwi r18, 0x00
; r1 = kdp
beq ReleaseAndReturnZeroFromMPCall
lwz r30, -0x0008(r17)
lwz r16, 0x0018(r31)
lwz r17, 0x001c(r31)
cmpw r16, r30
cmpw cr1, r17, r4
bne ReleaseAndTimeoutMPCall
bne cr1, ReleaseAndTimeoutMPCall
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
####### ####### ######## ######## ## ## #### ########
## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
####### ####### ######## ###### ### ## ##
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
######### ####### ## ## ######## ## ## #### ##
DeclareMPCall 28, MPExitCriticalRegion
MPExitCriticalRegion
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, CriticalRegion.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
mfsprg r17, 0
lwz r16, 0x0018(r31)
lwz r30, -0x0008(r17)
lwz r18, 0x0014(r31)
lwz r17, 0x001c(r31)
cmpw r16, r30
cmpw cr1, r17, r4
bne ReleaseAndReturnMPCallOOM
bne cr1, ReleaseAndReturnMPCallOOM
addi r18, r18, -0x01
cmpwi r18, 0x00
stw r18, 0x0014(r31)
; r1 = kdp
bne ReleaseAndReturnZeroFromMPCall
stw r18, 0x0018(r31)
stw r18, 0x001c(r31)
mr r8, r3
bl UnblockBlueIfCouldBePolling
lwz r16, 0x0008(r31)
cmpw r16, r31
; r1 = kdp
beq ReleaseAndReturnZeroFromMPCall
addi r8, r16, -0x08
lbz r17, 0x0037(r8)
cmpwi r17, 0x01
bne MPCall_28_0x94
addi r8, r8, 0x20
bl DequeueTimer
MPCall_28_0x94
lwz r16, 0x0008(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
lwz r18, 0x0020(r31)
addi r18, r18, -0x01
stw r18, 0x0020(r31)
addi r8, r16, -0x08
lwz r17, 0x0088(r8)
lwz r18, 0x00fc(r17)
subi r18, r18, 4
stw r18, 0x00fc(r17)
li r17, 0x01
stb r17, 0x0019(r8)
bl SchRdyTaskNow
bl CalculateTimeslice
bl FlagSchEvaluationIfTaskRequires
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
####### ####### ######## ######## ######## ## ######## ######## ########
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
####### ######## ######## ## ## ###### ## ###### ## ######
## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
######### ####### ## ## ######## ######## ######## ######## ## ########
DeclareMPCall 26, MPDeleteCriticalRegion
MPDeleteCriticalRegion
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, CriticalRegion.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r3
bl UnblockBlueIfCouldBePolling
MPCall_26_0x34
addi r30, r31, 0x00
lwz r16, 0x0008(r31)
cmpw r16, r30
addi r8, r16, -0x08
beq MPCall_26_0x98
lwz r17, 0x0088(r8)
li r18, kMPDeletedErr
stw r18, 0x011c(r17)
lbz r17, 0x0037(r8)
cmpwi r17, 0x01
bne MPCall_26_0x68
addi r8, r8, 0x20
bl DequeueTimer
MPCall_26_0x68
lwz r16, 0x0008(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
addi r8, r16, -0x08
bl SchRdyTaskNow
bl FlagSchEvaluationIfTaskRequires
b MPCall_26_0x34
MPCall_26_0x98
mr r8, r31
bl PoolFree
mr r8, r3
bl DeleteID
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
######## ## ## ######## ## ## ########
## ## ## ## ### ## ##
## ## ## ## #### ## ##
###### ## ## ###### ## ## ## ##
## ## ## ## ## #### ##
## ## ## ## ## ### ##
######## ### ######## ## ## ##
###### ######## ####### ## ## ######## ######
## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
## #### ######## ## ## ## ## ######## ######
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
###### ## ## ####### ####### ## ######
;_______________________________________________________________________
; Lifted from docs:
;
; An event group is essentially a group of binary semaphores. You can use
; event groups to indicate a number of simple events. For example, a task
; running on a server may need to be aware of multiple message queues.
; Instead of trying to poll each one in turn, the server task can wait on
; an event group. Whenever a message is posted on a queue, the poster can
; also set the bit corresponding to that queue in the event group. Doing
; so notifies the task, and it then knows which queue to access to extract
; the message. In Multiprocessing Services, an event group consists of
; thirty-two 1-bit flags, each of which may be set independently. When a
; task receives an event group, it receives all 32-bits at once (that is,
; it cannot poll individual bits), and all the bits in the event group are
; subsequently cleared.
;_______________________________________________________________________
## ####### ######## ###### ######## ######## ### ######## ########
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ######## ###### ## ######## ###### ## ## ## ######
######### ## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ####### ######## ###### ## ## ######## ## ## ## ########
DeclareMPCall 49, MPCreateEvent
; RET OSStatus r3, MPEventID r4
; called using the FE1F trap by the 68k ROM
MPCreateEvent
li r8, EventGroup.Size
bl PoolAllocClear
mr. r31, r8
beq ScrambleMPCall
InitList r8, EventGroup.kSignature, scratch=r16
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
li r9, EventGroup.kIDClass
bl MakeID
cmpwi r8, 0
bne+ @success
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
@success
mfsprg r30, 0
lwz r30, EWA.PA_CurTask(r30)
stw r8, EventGroup.LLL + LLL.Freeform(r31)
lwz r17, Task.ProcessID(r30)
stw r17, EventGroup.ProcessID(r31)
mr r4, r8
b ReleaseAndReturnZeroFromMPCall
######## ##### ######## ######## ######## ## ######## ######## ########
## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
####### ## ## ###### ## ## ###### ## ###### ## ######
## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
###### ##### ######## ######## ######## ######## ######## ## ########
DeclareMPCall 50, MPDeleteEvent
; ARG MPEventID r3
; RET OSStatus r3
MPDeleteEvent
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, EventGroup.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r3
bl UnblockBlueIfCouldBePolling
MPDeleteEvent_0x34
addi r30, r31, 0x00
lwz r16, 0x0008(r31)
cmpw r16, r30
addi r8, r16, -0x08
beq MPDeleteEvent_0x98
lwz r17, 0x0088(r8)
li r18, kMPDeletedErr
stw r18, 0x011c(r17)
lbz r17, 0x0037(r8)
cmpwi r17, 0x01
bne MPDeleteEvent_0x68
addi r8, r8, 0x20
bl DequeueTimer
MPDeleteEvent_0x68
lwz r16, 0x0008(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
addi r8, r16, -0x08
bl SchRdyTaskNow
bl FlagSchEvaluationIfTaskRequires
b MPDeleteEvent_0x34
MPDeleteEvent_0x98
mr r8, r31
bl PoolFree
mr r8, r3
bl DeleteID
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
######## ## ######## ###### ######## ########
## #### ## ## ## ## ##
## ## ## ## ## ##
####### ## ###### ###### ###### ##
## ## ## ## ## ##
## ## ## ## ## ## ## ##
###### ###### ######## ###### ######## ##
DeclareMPCall 51, MPSetEvent
; ARG MPEventID r3, MPEventFlags r4
; RET OSStatus r3
MPSetEvent
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, EventGroup.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r4
bl SetEvent
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
### ######## ###### ######## ######## ###
## ## ## ## ## ## ##
## ## ## ## ## ##
## ###### ###### ###### ## ##
## ## ## ## ## ##
## ## ## ## ## ## ##
### ######## ###### ######## ## ###
; ARG Event *r31, flags r8
SetEvent
lwz r16, EventGroup.Flags(r31)
or r16, r16, r8
stw r16, EventGroup.Flags(r31)
mflr r27
lwz r8, EventGroup.LLL + LLL.Freeform(r31)
bl UnblockBlueIfCouldBePolling
;
lwz r16, EventGroup.LLL + LLL.Next(r31)
cmpw r16, r31
subi r8, r16, Task.QueueMember
beq @no_task_waiting
; CASE 1: task needs unblocking
; Rerun SC instruction in task context
lwz r17, Task.ContextBlockPtr(r8)
lwz r18, ContextBlock.CodePtr(r17)
subi r18, r18, 4
stw r18, ContextBlock.CodePtr(r17)
; Cancel timeout
lbz r17, Task.Timer + Timer.Byte3(r8)
cmpwi r17, 1
bne @timer_not_armed
addi r8, r8, Task.Timer
bl DequeueTimer
@timer_not_armed
; Remove this task from my wait queue
lwz r16, EventGroup.LLL + LLL.Next(r31)
RemoveFromList r16, scratch1=r17, scratch2=r18
lwz r18, EventGroup.Counter(r31)
subi r18, r18, 1
stw r18, EventGroup.Counter(r31)
; Latency protection priority
subi r8, r16, Task.QueueMember
li r17, Task.kLatencyProtectPriority
stb r17, Task.Priority(r8)
bl SchRdyTaskNow
bl CalculateTimeslice
bl FlagSchEvaluationIfTaskRequires
@no_task_waiting
lwz r16, EventGroup.SWI(r31)
rlwinm. r17, r16, 0, 27, 27
; CASE 2: no task waiting.
beq @return
; CASE 3: SOFTWARE INTERRUPT
lwz r17, KDP.PA_ECB(r1)
lwz r26, PSA.PA_BlueTask(r1)
lwz r18, ContextBlock.EDPOffsetSWIRelated(r17)
lwz r19, ContextBlock.SWIEventGroupID(r17)
cmpwi cr1, r18, 0
cmpwi r19, 0
bne cr1, @do_not_save_swi_event_id
bne @return
lwz r8, EventGroup.LLL + LLL.Freeform(r31) ; contains my ID
stw r8, ContextBlock.SWIEventGroupID(r17)
b @common_case
@do_not_save_swi_event_id
; There is an EDP table of SWI-EventGroup IDs... set ours, cancel if already set
lwz r9, KDP.PA_EmulatorData(r1)
rlwinm r16, r16, 2, 26, 29
add r18, r18, r9
lwzx r19, r16, r18
cmpwi r19, 0
bne @return
; Set!
lwz r8, EventGroup.LLL + LLL.Freeform(r31) ; my ID
stwx r8, r16, r18
; Find the highest interrupt level with a nonzero thing
li r19, 7*4
li r9, 4
@loop
lwzx r8, r19, r18
cmpwi r8, 0
bne @exit_loop
subf. r19, r9, r19
bgt @loop
bl panic
@exit_loop
; Can I interrupt the current interrupt?
cmplw r16, r19
srwi r16, r16, 2
blt @return
stw r16, ContextBlock.SWIEventGroupID(r17)
@common_case
lwz r16, Task.Flags(r26)
lbz r19, Task.State(r26)
ori r16, r16, (1 << (31 - Task.kFlagSchToInterruptEmu))
stw r16, Task.Flags(r26)
; But what *is* MCR?
lwz r17, PSA.MCR(r1)
lwz r16, KDP.PostIntMaskInit(r1)
lwz r8, KDP.ClearIntMaskInit(r1)
and r16, r16, r8
or r17, r17, r16
stw r17, PSA.MCR(r1)
cmpwi r19, 0
addi r16, r26, Task.QueueMember
bne @task_already_running
; De-fang the blocking timeout
RemoveFromList r16, scratch1=r17, scratch2=r18
lbz r17, Task.Timer + Timer.Byte3(r26)
cmpwi r17, 1
bne @timer_not_armed_2
addi r8, r26, Task.Timer
bl DequeueTimer
@timer_not_armed_2
lwz r18, PSA.PA_BlueTask(r1)
li r16, Task.kCriticalPriority
stb r16, Task.Priority(r26)
mr r8, r26
bl SchRdyTaskLater
mr r8, r26
bl CalculateTimeslice
@task_already_running
mr r8, r26
bl FlagSchEvaluationIfTaskRequires
@return
mtlr r27
blr
######## ####### ######## ## ## ### #### ########
## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
####### ####### ###### ## ## ## ## ## ## ##
## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ##
###### ######### ######## ### ### ## ## #### ##
DeclareMPCall 52, MPWaitForEvent
; ARG MPEventID r3, Duration r5
; RET OSStatus r3, MPEventFlags r4
; called using the FE1F trap by the 68k ROM
MPWaitForEvent
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; Check that the Event Group ID in r3 is valid.
bl LookupID
cmpwi r9, EventGroup.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, 0x0010(r31)
cmpwi r16, 0
beq MPWaitForEvent_field_10_was_zero
mr r4, r16
li r16, 0
stw r16, 0x0010(r31)
lwz r16, 0x0018(r31)
lwz r17, KDP.PA_ECB(r1)
rlwinm. r18, r16, 0, 27, 27
rlwinm r16, r16, 2, 26, 29
beq ReleaseAndReturnZeroFromMPCall
lwz r18, 0x00c8(r17)
lwz r9, 0x0634(r1)
cmpwi r18, 0x00
add r18, r18, r9
bne MPWaitForEvent_0x84
lwz r18, 0x00d0(r17)
cmpw r18, r3
li r18, 0x00
; r1 = kdp
bne ReleaseAndReturnZeroFromMPCall
stw r18, 0x00d0(r17)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPWaitForEvent_0x84
lwzx r19, r16, r18
cmpw r19, r3
li r19, 0x00
; r1 = kdp
bne ReleaseAndReturnZeroFromMPCall
stwx r19, r16, r18
li r19, 0x1c
li r9, 0x04
MPWaitForEvent_0xa0
lwzx r8, r19, r18
cmpwi r8, 0x00
bne MPWaitForEvent_0xb4
subf. r19, r9, r19
bgt MPWaitForEvent_0xa0
MPWaitForEvent_0xb4
srwi r19, r19, 2
stw r19, 0x00d0(r17)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPWaitForEvent_field_10_was_zero
mfsprg r30, 0
cmpwi r5, 0
lwz r19, EWA.PA_CurTask(r30)
beq ReleaseAndTimeoutMPCall
;special case: blue may not block
lwz r16, Task.Flags(r19)
rlwinm. r16, r16, 0, Task.kFlagBlue, Task.kFlagBlue
beq @bot_blue
stw r3, PSA.BlueSpinningOn(r1)
b ReleaseAndReturnMPCallBlueBlocking
@bot_blue
; MOVE TASK OUT OF QUEUE AND INTO EVENT GROUP
mr r8, r19
bl SchTaskUnrdy
lwz r19, EWA.PA_CurTask(r30)
addi r16, r31, EventGroup.LLL
addi r17, r19, Task.QueueMember
stw r16, LLL.FreeForm(r17)
InsertAsPrev r17, r16, scratch=r18
lwz r18, EventGroup.Counter(r31)
addi r18, r18, 1
stw r18, EventGroup.Counter(r31)
lisori r16, 0x7fffffff ; LONG_MAX
addi r30, r19, Task.Timer
cmpw r5, r16
li r16, 2
beq @wait_forever ; never trigger max-wait timers
stb r16, Timer.Kind(r30)
stw r19, Timer.ParentTaskPtr(r30)
mr r8, r5
bl TimebaseTicksPerPeriod
mr r27, r8
mr r28, r9
bl GetTime
mfxer r16
addc r9, r9, r28
adde r8, r8, r27
mtxer r16
stw r8, Timer.Time(r30)
stw r9, Timer.Time+4(r30)
mr r8, r30
bl EnqueueTimer
@wait_forever
b BlockMPCall
######## ####### ######## ####### ## ## ######## ######## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ####
####### ####### ###### ## ## ## ## ###### ######## ##
## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
###### ####### ######## ##### ## ####### ######## ## ## ##
DeclareMPCall 53, MPQueryEvent
; Returns Timeout if no flags are set, otherwise NoErr
; ARG MPEventID r3
; RET OSStatus r3
MPQueryEvent
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, EventGroup.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
lwz r16, 0x0010(r31)
cmpwi r16, 0x00
beq ReleaseAndTimeoutMPCall
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
######## ## ######## ###### ######## ######## ###### ## ## ####
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ##
####### ## ## ###### ###### ###### ## ###### ## ## ## ##
## ######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ##
###### ## ######## ###### ######## ## ###### ### ### ####
DeclareMPCall 54, MPSetSWIEvent
; ARG MPEventID r3, int r4 swi
; called using the FE1F trap by the 68k ROM
MPSetSWIEvent
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, EventGroup.kIDClass
bne ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8
li r17, 1
cmpwi r4, 0
cmplwi cr1, r4, 8
lwz r16, EventGroup.SWI(r31)
beq @use_1
bgt cr1, @use_1
mr r17, r4
@use_1
; r17 = 1 if outside 1-8 (inc) range
ori r16, r16, 0x10
rlwimi r16, r17, 0, 28, 31
stw r16, EventGroup.SWI(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
######## #### ## ## ######## ######## ######
## ## ### ### ## ## ## ## ##
## ## #### #### ## ## ## ##
## ## ## ### ## ###### ######## ######
## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ##
## #### ## ## ######## ## ## ######
## ##### ######## ###### ######## ######## ### ######## ########
## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ######## ###### ## ## ## ######
######### ## ## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ##### ## ###### ## ## ######## ## ## ## ########
DeclareMPCall 40, NKCreateTimer
NKCreateTimer ; OUTSIDE REFERER
li r8, 0x40
; r1 = kdp
; r8 = size
bl PoolAllocClear
; r8 = ptr
mr. r31, r8
beq ScrambleMPCall
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r31
li r9, 0x03
; r1 = kdp
; r9 = kind
bl MakeID
cmpwi r8, 0x00
bne NKCreateTimer_0x48
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
NKCreateTimer_0x48
mfsprg r30, 0
stw r8, 0x0000(r31)
lwz r30, -0x0008(r30)
mr r4, r8
lwz r17, 0x0060(r30)
stw r17, 0x0010(r31)
bl GetTime
stw r8, 0x0038(r31)
stw r9, 0x003c(r31)
lis r17, 0x5449
ori r17, r17, 0x4d45
stw r17, 0x0004(r31)
li r17, 0x03
stb r17, 0x0014(r31)
li r17, 0x00
stb r17, 0x0016(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
## ## ######## ######## ######## ## ######## ######## ########
## ## #### ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ###### ## ###### ## ######
######### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
## ###### ## ######## ######## ######## ######## ## ########
DeclareMPCall 41, NKDeleteTimer
NKDeleteTimer ; OUTSIDE REFERER
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, Timer.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r3
bl DeleteID
lwz r16, 0x0008(r31)
cmpwi r16, 0x00
beq NKDeleteTimer_0x48
mr r8, r31
bl DequeueTimer
NKDeleteTimer_0x48
_AssertAndRelease PSA.SchLock, scratch=r16
lwz r8, 0x001c(r31)
cmpwi r8, 0x00
bnel PoolFree
mr r8, r31
bl PoolFree
b ReturnZeroFromMPCall
####### ##### ######## ###### ######## ######## ## ## ####### ######## #### ######## ## ##
## ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## #### ## ## ## ## ## ## ####
####### ## ## ## ###### ###### ## ## ## ## ## ## ## ## ###### ##
## ## ## ## ## ## ## ## #### ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ### ## ## ## ## ## ##
####### ##### ## ###### ######## ## ## ## ####### ## #### ## ##
; ARG TimerID r3, EventGroup/Queue/SemaphoreID r4, long r5, long r6, long r7
; RET OSStatus r3
DeclareMPCall 30, NKSetTimerNotify
NKSetTimerNotify
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Timer.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
lbz r16, Timer.Kind(r31)
cmpwi r16, 3
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r4
bl LookupID
cmpwi r9, Semaphore.kIDClass
cmpwi cr2, r9, Queue.kIDClass
beq @SEMAPHORE
cmpwi r9, EventGroup.kIDClass
beq cr2, @QUEUE
bne ReleaseAndReturnMPCallInvalidIDErr
@EVENTGROUP
stw r4, Timer.EventGroupID(r31)
stw r5, Timer.EventGroupFlags(r31)
b ReleaseAndReturnZeroFromMPCall
@QUEUE
stw r4, Timer.MessageQueueID(r31)
lwz r16, ContextBlock.r6(r6)
lwz r17, ContextBlock.r7(r6)
stw r5, Timer.Message1(r31) ; notifyParam1
stw r16, Timer.Message2(r31) ; notifyParam2
stw r17, Timer.Message3(r31) ; notifyParam3
b ReleaseAndReturnZeroFromMPCall
@SEMAPHORE
stw r4, Timer.SemaphoreID(r31)
b ReleaseAndReturnZeroFromMPCall
####### ## ######## ### ######## ## ##
## ## #### ## ## ## ## ## ### ###
## ## ## ## ## ## ## #### ####
####### ## ## ## ## ######## ## ### ##
## ## ## ######### ## ## ## ##
## ## ## ## ## ## ## ## ## ##
####### ###### ## ## ## ## ## ## ##
; Time can be absolute or delta, and a duration (r4)
; or timebase time (r4/r5).
; ARG TimerID r3, long r4, long r5, OptionBits r6
; RET OSStatus r3
DeclareMPCall 31, MPArmTimer
MPArmTimer
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Timer.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
lbz r16, Timer.Kind(r31)
cmpwi r16, Timer.kKind3
bne ReleaseAndReturnMPCallInvalidIDErr
; Disarm if armed
lwz r16, Timer.QueueLLL + LLL.Freeform(r31)
cmpwi r16, 0
mr r8, r31
beq @no_disarm
bl DequeueTimer
@no_disarm
; Ah... reserve a note if a message is to be sent
lwz r9, Timer.ReservedMessage(r31)
lwz r8, Timer.MessageQueueID(r31)
cmpwi r9, 0
cmpwi cr1, r8, 0
bne @already_got_note
beq cr1, @no_queue
bl LookupID
cmpwi r9, Queue.kIDClass
bne @no_queue
lwz r9, Queue.ReserveCount(r8)
li r8, Message.Size
cmpwi r9, 0
bne @already_got_notr
bl PoolAllocClear
mr. r30, r8
beq ReleaseAndScrambleMPCall
lisori r8, 'note'
stw r8, Message.LLL + LLL.Signature(r30)
stw r30, 0x001c(r31)
@already_got_note
@already_got_notr
@no_queue
; Calculate firing solution
lwz r16, ContextBlock.r6(r6)
rlwinm. r9, r16, 0, kMPTimeIsDurationMask
mr r8, r4
beq @not_duration
bl TimebaseTicksPerPeriod
mr r4, r8
mr r5, r9
@not_duration
lwz r16, ContextBlock.r6(r6)
rlwinm. r8, r16, 0, kMPTimeIsDeltaMask
mfxer r17
beq @not_delta
lwz r19, Timer.Time + 4(r31)
lwz r18, Timer.Time(r31)
addc r5, r5, r19
adde r4, r4, r18
mtxer r17
@not_delta
stw r4, Timer.Time(r31)
stw r5, Timer.Time + 4(r31)
; Teensy little option: keep after firing?
lwz r16, ContextBlock.r6(r6)
rlwinm. r16, r16, 0, kMPPreserveTimerIDMask
li r17, 0
beq @no_preserve
li r17, 1
@no_preserve
stb r17, Timer.KeepAfterFiring(r31)
mr r8, r31
bl EnqueueTimer
b ReleaseAndReturnZeroFromMPCall
####### ####### ######## ###### ### ## ## ###### ######## ##
## ## ## ## ## ## ## ## ## ### ## ## ## ## ##
## ## ## ## ## ## #### ## ## ## ##
####### ####### ## ## ## ## ## ## ## ## ###### ##
## ## ## ## ######### ## #### ## ## ##
## ## ## ## ## ## ## ## ## ### ## ## ## ##
####### ######### ## ###### ## ## ## ## ###### ######## ########
; ARG TimerID r3
; RET OSStatus r3, AbsoluteTime r4/r5
DeclareMPCall 32, MPCancelTimer
MPCancelTimer
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Timer.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
lbz r16, Timer.Byte3(r31)
cmpwi r16, 1
bne @say_no_time_remained
lwz r4, Timer.Time(r31)
lwz r5, Timer.Time + 4(r31)
bl GetTime
mfxer r16
subfc r5, r9, r5
subfe. r4, r8, r4
mtxer r16
bge+ @can_return_time_remaining
@say_no_time_remained
li r4, 0
li r5, 0
@can_return_time_remaining
lwz r16, Timer.QueueLLL + LLL.Freeform(r31)
cmpwi r16, 0
mr r8, r31
beq @not_queued
bl DequeueTimer
@not_queued
b ReleaseAndReturnZeroFromMPCall
## ## ####### ######## #### ######## #### ###### ### ######## #### ####### ## ## ######
### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ### ## ## ##
#### ## ## ## ## ## ## ## ## ## ## ## ## ## ## #### ## ##
## ## ## ## ## ## ## ###### ## ## ## ## ## ## ## ## ## ## ## ######
## #### ## ## ## ## ## ## ## ######### ## ## ## ## ## #### ##
## ### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ### ## ##
## ## ####### ## #### ## #### ###### ## ## ## #### ####### ## ## ######
####### ## ## ## ###### ######## ######## ### ######## ########
## ## ## ## ### ## ## ## ## ## ## ## ## ## ##
## ## ## #### ## ## ## ## ## ## ## ## ##
######## ## ## ## ## ## ## ######## ###### ## ## ## ######
## ## ######### ## #### ## ## ## ## ######### ## ##
## ## ## ## ### ## ## ## ## ## ## ## ## ##
####### ## ## ## ###### ## ## ######## ## ## ## ########
; RET OSErr r3, NotificationID r4
DeclareMPCall 64, MPCreateNotification
MPCreateNotification
li r8, Notification.Size
bl PoolAllocClear
mr. r31, r8
beq ScrambleMPCall
lisori r16, Notification.kSignature
stw r16, Notification.Signature(r31)
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
li r9, Notification.kIDClass
bl MakeID
cmpwi r8, 0
bne+ @nofail
mr r8, r31
bl PoolFree
b ReleaseAndScrambleMPCall
@nofail
mfsprg r30, 0
lwz r30, EWA.PA_CurTask(r30)
stw r8, Notification.TaskPtr(r31)
lwz r17, Task.ProcessID(r30)
stw r17, Notification.ProcessID(r31)
mr r4, r8
b ReleaseAndReturnZeroFromMPCall
####### ######## ## ## ######## ######## ## ######## ######## ########
## ## ## ### ## ## ## ## ## ## ## ##
## ## #### ## ## ## ## ## ## ## ##
######## ####### ## ## ## ## ## ###### ## ###### ## ######
## ## ## ## #### ## ## ## ## ## ## ##
## ## ## ## ## ### ## ## ## ## ## ## ##
####### ###### ## ## ######## ######## ######## ######## ## ########
; ARG NotificationID r3
; RET OSErr r3
DeclareMPCall 65, MPDeleteNotification
MPDeleteNotification
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Notification.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r31
bl PoolFree
mr r8, r3
bl DeleteID
b ReleaseAndReturnZeroFromMPCall
####### ######## ## ## ###### ### ## ## ###### ########
## ## ## ## ### ## ## ## ## ## ## ## ## ## ##
## ## #### ## ## ## ## ## ## ## ##
######## ## ## ## ## ## ## ## ## ## ###### ######
## ## ## ## #### ## ######### ## ## ## ##
## ## ## ## ### ## ## ## ## ## ## ## ## ##
####### ## ## ## ###### ## ## ####### ###### ########
DeclareMPCall 67, MPCauseNotification
MPCauseNotification
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
cmpwi r9, Notification.kIDClass
mr r30, r8
bne ReleaseAndReturnMPCallInvalidIDErr
bl CauseNotification
mr r3, r8
b ReleaseAndReturnMPCall
### ## ## ###### ### ## ## ###### ######## ###
## ### ## ## ## ## ## ## ## ## ## ## ##
## #### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ###### ###### ##
## ## #### ## ######### ## ## ## ## ##
## ## ### ## ## ## ## ## ## ## ## ## ##
### ## ## ###### ## ## ####### ###### ######## ###
; ARG Notification *r30
; RET OSStatus r8
CauseNotification
mflr r29
lwz r16, 0x000c(r30)
lwz r17, 0x0024(r30)
cmplwi r16, 0x00
cmplwi cr1, r17, 0x00
bne @0x28
bne cr1, @0x28
lwz r18, 0x001c(r30)
cmplwi r18, 0x00
beq @fail_insufficient_resources
@0x28
; SEND MESSAGE TO QUEUE
lwz r8, Notification.QueueID(r30)
cmplwi r8, 0
beq @NO_QUEUE
bl LookupID
cmpwi r9, Queue.kIDClass
mr r31, r8
bne @fail_invalid_id
lwz r16, Queue.ReserveCount(r31)
cmpwi r16, 0
lwz r17, Queue.ReservePtr(r31)
beq @no_notr
;use notr
mr. r8, r17
lwz r17, Message.LLL + LLL.Next(r17)
beq @fail_insufficient_resources
stw r17, Queue.ReservePtr(r31)
b @queue_common
@no_notr ; ... allocate message anew
li r8, Message.Size
bl PoolAlloc
cmpwi r8, 0
beq @fail_unknown_err
@queue_common
lwz r16, Notification.MsgWord1(r30)
lwz r17, Notification.MsgWord2(r30)
lwz r18, Notification.MsgWord3(r30)
stw r16, Message.Word1(r8)
stw r17, Message.Word2(r8)
stw r18, Message.Word3(r8)
bl EnqueueMessage ; Message *r8, Queue *r31
@NO_QUEUE
; SIGNAL SEMAPHORE
lwz r8, Notification.SemaphoreID(r30)
cmplwi r8, 0
beq @NO_SEMAPHORE
bl LookupID
cmpwi r9, Semaphore.kIDClass
mr r31, r8
bne @fail_invalid_id
bl SignalSemaphore
@NO_SEMAPHORE
; SET EVENT
lwz r8, Notification.EventGroupID(r30)
cmplwi r8, 0
beq @NO_EVENT_GROUP
bl LookupID
cmpwi r9, EventGroup.kIDClass
mr r31, r8
bne @fail_invalid_id
lwz r8, Notification.EventFlags(r30)
bl SetEvent
@NO_EVENT_GROUP ; ... fall thru to success
@succeed
mtlr r29
li r8, 0x00
blr
@fail_unknown_err
mtlr r29
li r8, -29294
blr
@fail_insufficient_resources
mtlr r29
li r8, kMPInsufficientResourcesErr
blr
@fail_invalid_id
mtlr r29
li r8, kMPInvalidIDErr
blr
####### ####### ## ## ## ## ####### ######## #### ######## ## ##
## ## ## ## ### ## ### ### ## ## ## ## ## ## ## ##
## ## #### ## #### #### ## ## ## ## ## ## ####
######## ######## ## ## ## ## ### ## ## ## ## ## ## ###### ##
## ## ## ## ## #### ## ## ## ## ## ## ## ## ##
## ## ## ## ## ### ## ## ## ## ## ## ## ## ##
####### ####### ## ## ## ## ####### ######## #### ## ##
DeclareMPCall 66, MPModifyNotification
MPModifyNotification
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, Notification.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
mr r8, r4
; r8 = id
bl LookupID
cmpwi r9, Semaphore.kIDClass
cmpwi cr2, r9, 0x04
beq MPCall_66_0x74
cmpwi r9, 0x09
beq cr2, MPCall_66_0x58
bne ReleaseAndReturnMPCallInvalidIDErr
stw r4, 0x001c(r31)
stw r5, 0x0020(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPCall_66_0x58
stw r4, 0x000c(r31)
lwz r16, ContextBlock.r6(r6)
lwz r17, ContextBlock.r7(r6)
stw r5, 0x0010(r31)
stw r16, 0x0014(r31)
stw r17, 0x0018(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPCall_66_0x74
stw r4, 0x0024(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
## ####### ####### ## ## ## ## ####### ######## ######## ### ######## ### ## ## ######
#### ## ## ## ## ### ## ### ### ## ## ## ## ## ## ## ## ## ## ## ## ### ### ## ##
## ## ## ## #### ## #### #### ## ## ## ## ## ## ## ## ## ## ## ## #### #### ##
## ####### ####### ## ## ## ## ### ## ## ## ## ## ######## ## ## ######## ## ## ## ### ## ######
## ## ## ## ## #### ## ## ## ## ## ## ## ######### ## ## ######### ## ## ##
## ## ## ## ## ### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
###### ######### ####### ## ## ## ## ####### ######## ## ## ## ## ## ## ## ## ## ######
DeclareMPCall 128, MPCall_128
MPCall_128 ; OUTSIDE REFERER
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
; r8 = id
bl LookupID
cmpwi r9, Notification.kIDClass
mr r31, r8
bne ReleaseAndReturnMPCallInvalidIDErr
cmpwi r4, 0x04
cmpwi cr1, r4, 0x09
beq MPCall_128_0x40
beq cr1, MPCall_128_0x58
b ReleaseAndReturnParamErrFromMPCall
MPCall_128_0x40
lwz r16, ContextBlock.r6(r6)
lwz r17, ContextBlock.r7(r6)
stw r5, 0x0010(r31)
stw r16, 0x0014(r31)
stw r17, 0x0018(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
MPCall_128_0x58
stw r5, 0x0020(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
### ######## ## ## ## ## ######## ## ## ## ######## ###
## ## ## ## ## ### ## ## ## ## ## ## ## ##
## ## ## ## ## #### ## ## ## ## ## ## ## ##
## ######## ## ## ## ## ## ######## ## ## ## ###### ##
## ## ## ## ## ## #### ## ## ## ## ## ## ##
## ## ## ## ## ## ### ## ## ## ## ## ## ##
### ## ## ####### ## ## ######## ######## ####### ######## ###
; ARG OpaqueID r8
; MP calls by blue return kMPBlueBlockingErr instead of blocking,
; in order to maintain system responsiveness. Blue might poll these
; calls, e.g. at SysTask time. This function, called when a
; blocking object becomes "available", unblocks blue to give it
; another shot.
UnblockBlueIfCouldBePolling
lwz r9, PSA.BlueSpinningOn(r1)
lwz r19, PSA.PA_BlueTask(r1)
cmpw r8, r9
bnelr
li r9, -1
mflr r24
stw r9, PSA.BlueSpinningOn(r1)
lbz r17, Task.State(r19)
cmpwi r17, 0
addi r16, r19, Task.QueueMember
bne @blue_already_running
RemoveFromList r16, scratch1=r17, scratch2=r18
lbz r17, Task.Timer + Timer.Byte3(r19)
cmpwi r17, 1
bne @no_timer_to_dequeue
addi r8, r19, Task.Timer
bl DequeueTimer
lwz r19, PSA.PA_BlueTask(r1)
@no_timer_to_dequeue
li r16, Task.kLatencyProtectPriority
stb r16, Task.Priority(r19)
lwz r8, PSA.PA_BlueTask(r1)
bl SchRdyTaskNow
@blue_already_running
lwz r8, PSA.PA_BlueTask(r1)
mtlr r24
b FlagSchEvaluationIfTaskRequires
## ####### ##### ######## #### ###### ###### ### ## ##
#### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
## ####### ## ## ######## ## ## #### ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
###### ######### ##### ######## #### ###### ###### ## ## ######## ########
DeclareMPCall 120, MPCall_120
MPCall_120
_Lock PSA.SchLock, scratch1=r16, scratch2=r17
mr r8, r3
bl LookupID
mr r31, r8
cmpwi r9, Semaphore.kIDClass
cmpwi cr1, r9, Queue.kIDClass
beq @SEMAPHORE
beq cr1, @QUEUE
cmpwi r9, EventGroup.kIDClass
cmpwi cr1, r9, CriticalRegion.kIDClass
beq @EVENT_GROUP
beq cr1, @CRITICAL_REGION
cmpwi r9, Notification.kIDClass
cmpwi cr1, r9, AddressSpace.kIDClass
beq @NOTIFICATION
beq cr1, @ADDRESS_SPACE
b ReleaseAndReturnParamErrFromMPCall
@NOTIFICATION
lisori r8, Notification.kFirstID
cmpw r8, r4
bne ReleaseAndReturnParamErrFromMPCall
cmplwi r5, 0
bne @notification_not_0
; r5 == 0
lisori r16, Notification.kFirstID
stw r16, ContextBlock.r6(r6)
lwz r16, Notification.ProcessID(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, Notification.Signature(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x000c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 16
stw r16, ContextBlock.r10(r6)
b ReleaseAndReturnZeroFromMPCall
@notification_not_0
cmplwi r5, 16
bne @notification_not_16
; r5 == 16
lwz r16, 0x0010(r31)
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0014(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0018(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x001c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 16
stw r16, ContextBlock.r10(r6)
b ReleaseAndReturnZeroFromMPCall
@notification_not_16
cmplwi r5, 32
bne @notification_not_32
; r5 == 32
lwz r16, 0x0020(r31)
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0024(r31)
stw r16, ContextBlock.r7(r6)
li r16, 8
stw r16, ContextBlock.r10(r6)
b ReleaseAndReturnZeroFromMPCall
@notification_not_32
cmpwi r5, 40
bne ReleaseAndReturnParamErrFromMPCall
; r5 == 40
li r16, 0x00
stw r16, ContextBlock.r10(r6)
b ReleaseAndReturnZeroFromMPCall
@CRITICAL_REGION
lisori r8, 0x00060001
cmpw r8, r4
bne ReleaseAndReturnParamErrFromMPCall
cmplwi r5, 0x00
bne @154
lis r16, 0x06
ori r16, r16, 0x01
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0010(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0004(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x0020(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@154
cmplwi r5, 0x10
bne @1a0
addi r17, r31, 0x00
lwz r18, 0x0008(r31)
li r16, 0x00
cmpw r17, r18
beq @174
lwz r16, -0x0008(r18)
@174
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0018(r31)
cmpwi r16, 0x00
beq @188
lwz r16, 0x0000(r16)
@188
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0014(r31)
stw r16, ContextBlock.r8(r6)
li r16, 0x0c
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@1a0
cmpwi r5, 0x1c
bne ReleaseAndReturnParamErrFromMPCall
li r16, 0x00
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@EVENT_GROUP
lis r8, 0x09
ori r8, r8, 0x01
cmpw r8, r4
bne ReleaseAndReturnParamErrFromMPCall
cmplwi r5, 0x00
bne @1fc
lis r16, 0x09
ori r16, r16, 0x01
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0014(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0004(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x001c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@1fc
cmplwi r5, 0x10
bne @234
addi r17, r31, 0x00
lwz r18, 0x0008(r31)
li r16, 0x00
cmpw r17, r18
beq @21c
lwz r16, -0x0008(r18)
@21c
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0010(r31)
stw r16, ContextBlock.r7(r6)
li r16, 0x08
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@234
cmpwi r5, 0x18
bne ReleaseAndReturnParamErrFromMPCall
li r16, 0x00
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@QUEUE
lis r8, 0x04
ori r8, r8, 0x01
cmpw r8, r4
bne ReleaseAndReturnParamErrFromMPCall
cmplwi r5, 0x00
bne @290
lis r16, 0x04
ori r16, r16, 0x01
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0020(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0004(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x002c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@290
cmplwi r5, 0x10
bne @2ec
addi r17, r31, 0x00
lwz r18, 0x0008(r31)
li r16, 0x00
cmpw r17, r18
beq @2b0
lwz r16, -0x0008(r18)
@2b0
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0030(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0024(r31)
stw r16, ContextBlock.r8(r6)
lwz r18, 0x0018(r31)
addi r17, r31, 0x10
li r16, 0x00
cmpw r17, r18
beq @2dc
lwz r16, 0x0010(r18)
@2dc
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@2ec
cmplwi r5, 0x20
bne @328
lwz r18, 0x0018(r31)
addi r17, r31, 0x10
li r16, 0x00
cmpw r17, r18
li r17, 0x00
beq @314
lwz r16, 0x0014(r18)
lwz r17, 0x0018(r18)
@314
stw r16, ContextBlock.r6(r6)
stw r17, ContextBlock.r7(r6)
li r16, 0x08
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@328
cmpwi r5, 0x28
bne ReleaseAndReturnParamErrFromMPCall
li r16, 0x00
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@SEMAPHORE
lis r8, 0x05
ori r8, r8, 0x01
cmpw r8, r4
bne ReleaseAndReturnParamErrFromMPCall
cmplwi r5, 0x00
bne @384
lis r16, 0x05
ori r16, r16, 0x01
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0018(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0004(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x001c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@384
cmplwi r5, 0x10
bne @3c4
addi r17, r31, 0x00
lwz r18, 0x0008(r31)
li r16, 0x00
cmpw r17, r18
beq @3a4
lwz r16, -0x0008(r18)
@3a4
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0014(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0010(r31)
stw r16, ContextBlock.r8(r6)
li r16, 0x0c
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@3c4
cmpwi r5, 0x1c
bne ReleaseAndReturnParamErrFromMPCall
li r16, 0x00
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@ADDRESS_SPACE
lisori r8, 0x00080001
cmpw r8, r4
bne ReleaseAndReturnParamErrFromMPCall
cmplwi r5, 0x00
bne @420
lisori r16, 0x00080001
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0074(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0070(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x000c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@420
cmplwi r5, 0x10
bne @454
lwz r16, 0x0030(r31)
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0034(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0038(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x003c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@454
cmplwi r5, 0x20
bne @488
lwz r16, 0x0040(r31)
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0044(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0048(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x004c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@488
cmplwi r5, 0x30
bne @4bc
lwz r16, 0x0050(r31)
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0054(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0058(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x005c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@4bc
cmplwi r5, 0x40
bne @4f0
lwz r16, 0x0060(r31)
stw r16, ContextBlock.r6(r6)
lwz r16, 0x0064(r31)
stw r16, ContextBlock.r7(r6)
lwz r16, 0x0068(r31)
stw r16, ContextBlock.r8(r6)
lwz r16, 0x006c(r31)
stw r16, ContextBlock.r9(r6)
li r16, 0x10
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall
@4f0
cmpwi r5, 0x50
bne ReleaseAndReturnParamErrFromMPCall
li r16, 0x00
stw r16, ContextBlock.r10(r6)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall