Reverse Area-related MP calls

- MPCreateArea
- MPCreateAliasArea
- MPSetAreaBackingProvider
- MPSetAreaAccess (only renamed from KC...)
This commit is contained in:
Elliot Nunn 2017-12-12 13:23:03 +08:00
parent 423b809e87
commit 4d5929ffd8

View File

@ -777,58 +777,83 @@ KCSetTaskAddressSpace ; OUTSIDE REFERER
DeclareMPCall 72, MPCall_72 ; This MP call does some of the heavy lifting for the MPLibrary function
; of the same name. No pages are mapped into the Area.
MPCall_72 ; OUTSIDE REFERER ; ARG AddressSpaceID r3 (optional)
; long r4 PTEConfig
; long r5 length
; long r6 LogicalSeparation
; long r7 flagsAndMinAlign
; char *r8 LogicalBase
; RET r3 OSErr
; char *r8 LogicalBase
; AreaID r9
; Hint: in the 9.2.2 System MPLibrary, MPCreateArea calls a syscall
; wrapper function at code offset 0x7fa8, with arguments pointing to save
; locations for r8 and r9.
DeclareMPCall 72, MPCreateArea
MPCreateArea
_Lock PSA.SchLock, scratch1=r16, scratch2=r17 _Lock PSA.SchLock, scratch1=r16, scratch2=r17
; If !r3 then use the current address space
mr. r8, r3 mr. r8, r3
mfsprg r28, 0 mfsprg r28, 0
lwz r30, EWA.PA_CurAddressSpace(r28) lwz r30, EWA.PA_CurAddressSpace(r28)
beq- MPCall_72_0x38 beq- @use_current_space
; r8 = id ; ... else use the one specified.
bl LookupID bl LookupID
cmpwi r9, AddressSpace.kIDClass cmpwi r9, AddressSpace.kIDClass
mr r30, r8 mr r30, r8
bne+ ReleaseAndReturnMPCallInvalidIDErr bne+ ReleaseAndReturnMPCallInvalidIDErr
@use_current_space
MPCall_72_0x38 ; Allocate the new Area
li r8, 160 li r8, Area.Size
; r1 = kdp
; r8 = size
bl PoolAlloc bl PoolAlloc
; r8 = ptr
mr. r31, r8 mr. r31, r8
beq+ major_0x0af60 beq+ major_0x0af60
; Populate
stw r30, Area.AddressSpacePtr(r31) stw r30, Area.AddressSpacePtr(r31)
stw r4, 0x001c(r31)
stw r4, Area.PTEConfig(r31)
stw r5, Area.Length(r31) stw r5, Area.Length(r31)
lwz r8, 0x0134(r6)
lwz r8, ContextBlock.r6(r6)
stw r8, Area.LogicalSeparation(r31) stw r8, Area.LogicalSeparation(r31)
lwz r8, 0x013c(r6)
stw r8, 0x0020(r31) lwz r8, ContextBlock.r7(r6)
lwz r8, 0x0144(r6) stw r8, Area.FlagsAndMinAlign(r31)
lwz r8, ContextBlock.r8(r6)
stw r8, Area.LogicalBase(r31) stw r8, Area.LogicalBase(r31)
; "Create" the area
mr r8, r31 mr r8, r31
bl createarea bl createarea
_AssertAndRelease PSA.SchLock, scratch=r16 _AssertAndRelease PSA.SchLock, scratch=r16
MPCall_72_0x90
stw r16, PSA.SchLock + Lock.Count(r1)
mr. r3, r9 mr. r3, r9
bne- MPCall_72_0xb0 bne- @error
; CreateArea returned successfully
lwz r8, Area.LogicalBase(r31) lwz r8, Area.LogicalBase(r31)
stw r8, 0x0144(r6) stw r8, ContextBlock.r8(r6)
lwz r8, Area.ID(r31) lwz r8, Area.ID(r31)
stw r8, 0x014c(r6) stw r8, ContextBlock.r9(r6)
b CommonMPCallReturnPath b CommonMPCallReturnPath
MPCall_72_0xb0 @error
bl PoolFree bl PoolFree
b CommonMPCallReturnPath b CommonMPCallReturnPath
@ -1475,9 +1500,28 @@ FindAreaAbove ; OUTSIDE REFERER
DeclareMPCall 73, MPCall_73 ; This MP call does most of the work for the same-named MPLibrary
; function. An "alias" Area is created from a template. This code is very
; similar to regular MPCreateArea above, so differences are commented.
MPCall_73 ; OUTSIDE REFERER ; ARG AreaID r3 ; Alias-specific
; long r4 PTEConfig
; long r5 length
; long r6 LogicalSeparation
; long r7 flagsAndMinAlign
; char *r8 LogicalBase
; long r9 unknown ; Alias-specific
; RET r3 OSErr
; char *r8 LogicalBase
; AreaID r10 ; Alias-specific
; Hint: in the 9.2.2 System MPLibrary, MPCreateAliasArea calls a syscall
; wrapper function at code offset 0x7fe8, with arguments pointing to save
; locations for r8 and r10.
DeclareMPCall 73, MPCreateAliasArea
MPCreateAliasArea
_Lock PSA.SchLock, scratch1=r16, scratch2=r17 _Lock PSA.SchLock, scratch1=r16, scratch2=r17
@ -1486,193 +1530,263 @@ MPCall_73 ; OUTSIDE REFERER
cmpwi r9, Area.kIDClass cmpwi r9, Area.kIDClass
bne+ ReleaseAndReturnMPCallInvalidIDErr bne+ ReleaseAndReturnMPCallInvalidIDErr
; Confirm that the template Area is not itself an alias
mr r30, r8 mr r30, r8
lwz r16, 0x0008(r30) lwz r16, Area.Flags(r30)
rlwinm. r8, r16, 0, 28, 28 rlwinm. r8, r16, 0, Area.kAliasFlag, Area.kAliasFlag
bne+ major_0x0b054 bne+ major_0x0b054
; Allocate the new Area
li r8, Area.Size li r8, Area.Size
bl PoolAlloc bl PoolAlloc
mr. r31, r8 mr. r31, r8
beq+ major_0x0af60 beq+ major_0x0af60
; Populate
mfsprg r28, 0 mfsprg r28, 0
lwz r8, EWA.PA_CurAddressSpace(r28) lwz r8, EWA.PA_CurAddressSpace(r28)
stw r8, Area.AddressSpacePtr(r31) stw r8, Area.AddressSpacePtr(r31)
stw r3, 0x0014(r31)
stw r30, 0x0044(r31) stw r3, Area.ParentAreaID(r31) ; Alias-specific
stw r4, 0x001c(r31)
stw r30, Area.AliasLLL + LLL.Freeform(r31) ; Alias-specific
stw r4, Area.PTEConfig(r31)
stw r5, Area.Length(r31) stw r5, Area.Length(r31)
lwz r8, 0x0134(r6)
lwz r8, ContextBlock.r6(r6)
stw r8, Area.LogicalSeparation(r31) stw r8, Area.LogicalSeparation(r31)
lwz r8, 0x013c(r6)
stw r8, 0x0020(r31) lwz r8, ContextBlock.r7(r6)
lwz r8, 0x0144(r6) stw r8, Area.FlagsAndMinAlign(r31)
lwz r8, ContextBlock.r8(r6)
stw r8, Area.LogicalBase(r31) stw r8, Area.LogicalBase(r31)
lwz r8, 0x014c(r6)
lwz r8, ContextBlock.r9(r6) ; Alias-specific
stw r8, 0x0080(r31) stw r8, 0x0080(r31)
li r8, 0x08
li r8, 1 << (31 - Area.kAliasFlag) ; Alias-specific
stw r8, Area.Flags(r31) stw r8, Area.Flags(r31)
; "Create" the area (everything after here is identical to MPCreateArea)
mr r8, r31 mr r8, r31
bl createarea bl createarea
_AssertAndRelease PSA.SchLock, scratch=r16 _AssertAndRelease PSA.SchLock, scratch=r16
MPCall_73_0xb0
stw r16, PSA.SchLock + Lock.Count(r1)
mr. r3, r9 mr. r3, r9
bne- MPCall_73_0xd0 bne- @error
; CreateArea returned successfully
lwz r8, Area.LogicalBase(r31) lwz r8, Area.LogicalBase(r31)
stw r8, 0x0144(r6) stw r8, ContextBlock.r8(r6)
lwz r8, Area.ID(r31) lwz r8, Area.ID(r31)
stw r8, 0x0154(r6) stw r8, ContextBlock.r10(r6) ; Alias-specific
b CommonMPCallReturnPath b CommonMPCallReturnPath
MPCall_73_0xd0 ; ...or not
@error
bl PoolFree bl PoolFree
b CommonMPCallReturnPath b CommonMPCallReturnPath
DeclareMPCall 74, MPCall_74 ; Delete an Area: the eponymous MPLibrary function is a simple wrapper
MPCall_74 ; OUTSIDE REFERER ; 1. Only works on unprivileged Areas with no mapped pages.
; 2. Remove from parent address space.
; 3. Remove from template Area's alias list if applicable.
; 4. Delete the "PageMap" array if present.
; 5. Delete the "Fault Counter" array if present.
; 6. Delete the structure from the pool.
; ARG AreaID r3
; RET OSErr r3
DeclareMPCall 74, MPDeleteArea
MPDeleteArea
_Lock PSA.SchLock, scratch1=r16, scratch2=r17 _Lock PSA.SchLock, scratch1=r16, scratch2=r17
; Look up and validate
mr r8, r3 mr r8, r3
; r8 = id
bl LookupID bl LookupID
cmpwi r9, Area.kIDClass cmpwi r9, Area.kIDClass
bne+ ReleaseAndReturnMPCallInvalidIDErr bne+ ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8 mr r31, r8
; If pages are still mapped in, fail with OOM
; If area is privileged, fail with privileged
lwz r17, Area.BytesMapped(r31) lwz r17, Area.BytesMapped(r31)
lwz r29, Area.Flags(r31) lwz r29, Area.Flags(r31)
cmpwi cr1, r17, 0x00 cmpwi cr1, r17, 0
rlwinm. r8, r29, 0, 29, 29 rlwinm. r8, r29, 0, Area.kPrivilegedFlag, Area.kPrivilegedFlag
bne+ cr1, ReleaseAndReturnMPCallOOM bne+ cr1, ReleaseAndReturnMPCallOOM
bne+ ReleaseAndReturnMPCallPrivilegedErr bne+ ReleaseAndReturnMPCallPrivilegedErr
rlwinm. r8, r29, 0, 28, 28
lwz r16, 0x004c(r31) ; If is alias area and is not at back of queue (???), fail with OOM
bne- MPCall_74_0x5c rlwinm. r8, r29, 0, Area.kAliasFlag, Area.kAliasFlag
addi r17, r31, 0x44 lwz r16, Area.AliasLLL + LLL.Next(r31)
bne- @dont_check_for_nonempty_alias
addi r17, r31, Area.AliasLLL
cmpw r16, r17 cmpw r16, r17
bne+ ReleaseAndReturnMPCallOOM bne+ ReleaseAndReturnMPCallOOM
@dont_check_for_nonempty_alias
MPCall_74_0x5c ; HTAB lock wraps around all Address Space structures?
_Lock PSA.HTABLock, scratch1=r18, scratch2=r9 _Lock PSA.HTABLock, scratch1=r18, scratch2=r9
addi r16, r31, 0x54 ; Remove from parent address space
lwz r17, 0x0008(r16) addi r16, r31, Area.LLL
lwz r18, 0x000c(r16) RemoveFromList r16, scratch1=r17, scratch2=r18
stw r17, 0x0008(r18)
stw r18, 0x000c(r17) ; Remove from template area's list of aliases, if necessary
li r17, 0x00 rlwinm. r8, r29, 0, Area.kAliasFlag, Area.kAliasFlag
stw r17, 0x0008(r16) addi r16, r31, Area.AliasLLL
stw r17, 0x000c(r16) beq- @not_alias_so_dont_remove_from_alias_list
rlwinm. r8, r29, 0, 28, 28 RemoveFromList r16, scratch1=r17, scratch2=r18
addi r16, r31, 0x44 @not_alias_so_dont_remove_from_alias_list
beq- MPCall_74_0xbc
lwz r17, 0x0008(r16)
lwz r18, 0x000c(r16)
stw r17, 0x0008(r18)
stw r18, 0x000c(r17)
li r17, 0x00
stw r17, 0x0008(r16)
stw r17, 0x000c(r16)
MPCall_74_0xbc
_AssertAndRelease PSA.HTABLock, scratch=r18 _AssertAndRelease PSA.HTABLock, scratch=r18
lwz r8, 0x0040(r31)
rlwinm. r16, r29, 0, 25, 25
cmpwi cr1, r8, 0x00
bne- MPCall_74_0x178
rlwinm. r16, r29, 0, 27, 27
beq- cr1, MPCall_74_0x178
bne- MPCall_74_0x174
; DELETE PAGEMAP (array of [array of] per-page data)
; There are a few cases here...
lwz r8, Area.PageMapArrayPtr(r31)
rlwinm. r16, r29, 0, Area.kDontOwnPageMapArray, Area.kDontOwnPageMapArray
cmpwi cr1, r8, 0
bne- @no_pagemap
rlwinm. r16, r29, 0, Area.kPageMapArrayInPool, Area.kPageMapArrayInPool
beq- cr1, @no_pagemap
bne- @pagemap_in_pool
; If PageMap occupies whole pages then return those pages
; directly to the free list without bothering the pool
; (Pool lock still protects free list)
_Lock PSA.PoolLock, scratch1=r18, scratch2=r9 _Lock PSA.PoolLock, scratch1=r18, scratch2=r9
rlwinm. r16, r29, 0, 26, 26 rlwinm. r16, r29, 0, Area.kPageMapArrayIs2D, Area.kPageMapArrayIs2D
beq- MPCall_74_0x14c beq- @pagemap_is_1d
; CASE: 2D array, all in whole pages
; r19 := size of ptr array in primary page
lwz r19, Area.Length(r31) lwz r19, Area.Length(r31)
mr r20, r8 mr r20, r8
srwi r19, r19, 12 srwi r19, r19, 12
addi r19, r19, 0x3ff addi r19, r19, 0x3ff
srwi r19, r19, 10 srwi r19, r19, 10
slwi r19, r19, 2 slwi r19, r19, 2
subi r19, r19, 4
MPCall_74_0x134 ; Free every second-level page
subi r19, r19, 4
@2d_pagemap_delete_loop
lwzx r8, r19, r20 lwzx r8, r19, r20
; r1 = kdp
; r8 = maybe the page
bl free_list_add_page bl free_list_add_page
cmpwi r19, 0x00 cmpwi r19, 0
subi r19, r19, 4 subi r19, r19, 4
bgt+ MPCall_74_0x134 bgt+ @2d_pagemap_delete_loop
mr r8, r20 mr r8, r20
MPCall_74_0x14c
; r1 = kdp
; r8 = maybe the page
bl free_list_add_page
_AssertAndRelease PSA.PoolLock, scratch=r18
b MPCall_74_0x178
MPCall_74_0x174 ; COMMON CASE: single first-level page of 2D or 1D-in-whole-page case
@pagemap_is_1d
bl free_list_add_page
_AssertAndRelease PSA.PoolLock, scratch=r18
b @pagemap_deleted
; CASE: 1D array in pool block (not whole page)
@pagemap_in_pool
bl PoolFree bl PoolFree
MPCall_74_0x178
lwz r8, 0x003c(r31)
clrlwi. r16, r29, 0x1f
cmpwi cr1, r8, 0x00
beq- cr1, MPCall_74_0x20c
bne- MPCall_74_0x208
@pagemap_deleted
@no_pagemap
; DELETE FAULT COUNTER ARRAY
; Again, the code to manage the cases is tricky.
lwz r8, Area.FaultCtrArrayPtr(r31)
rlwinm. r16, r29, 0, Area.kFaultCtrArrayInPool, Area.kFaultCtrArrayInPool
cmpwi cr1, r8, 0
beq- cr1, @no_faultctr
bne- @faultctr_in_pool
; Whole-page cases require us to get the Pool lock manually (for free list)
_Lock PSA.PoolLock, scratch1=r18, scratch2=r9 _Lock PSA.PoolLock, scratch1=r18, scratch2=r9
rlwinm. r16, r29, 0, 30, 30 rlwinm. r16, r29, 0, Area.kFaultCtrArrayIs2D, Area.kFaultCtrArrayIs2D
beq- MPCall_74_0x1e0 beq- @faultctr_is_1d
; CASE: 2D array, all in whole pages
; Once again, r19 = the size of the primary array
lwz r19, Area.Length(r31) lwz r19, Area.Length(r31)
mr r20, r8 mr r20, r8
srwi r19, r19, 12 srwi r19, r19, 12
addi r19, r19, 0x7ff addi r19, r19, 0x7ff
srwi r19, r19, 11 srwi r19, r19, 11
slwi r19, r19, 2 slwi r19, r19, 2
subi r19, r19, 4
MPCall_74_0x1c8 ; Free every second-level page
subi r19, r19, 4
@2d_faultctr_delete_loop
lwzx r8, r19, r20 lwzx r8, r19, r20
; r1 = kdp
; r8 = maybe the page
bl free_list_add_page bl free_list_add_page
cmpwi r19, 0x00 cmpwi r19, 0
subi r19, r19, 4 subi r19, r19, 4
bgt+ MPCall_74_0x1c8 bgt+ @2d_faultctr_delete_loop
mr r8, r20 mr r8, r20
MPCall_74_0x1e0
; r1 = kdp
; r8 = maybe the page
bl free_list_add_page
_AssertAndRelease PSA.PoolLock, scratch=r18
b MPCall_74_0x20c
MPCall_74_0x208 ; COMMON CASE: single first-level page of 2D or 1D-in-whole-page case
@faultctr_is_1d
bl free_list_add_page
_AssertAndRelease PSA.PoolLock, scratch=r18
b @faultctr_deleted
; CASE: 1D array in pool block (not whole page)
@faultctr_in_pool
bl PoolFree bl PoolFree
MPCall_74_0x20c
@faultctr_deleted
@no_faultctr
; Delete the struct from the pool
lwz r8, Area.ID(r31) lwz r8, Area.ID(r31)
bl DeleteID bl DeleteID
mr r8, r31 mr r8, r31
bl PoolFree bl PoolFree
; r1 = kdp
; Return noErr
b ReleaseAndReturnZeroFromMPCall b ReleaseAndReturnZeroFromMPCall
@ -1937,12 +2051,12 @@ MPCall_130_0x19c
; KCSetAreaAccess ; MPSetAreaAccess
DeclareMPCall 76, KCSetAreaAccess DeclareMPCall 76, MPSetAreaAccess
KCSetAreaAccess ; OUTSIDE REFERER MPSetAreaAccess ; OUTSIDE REFERER
_Lock PSA.SchLock, scratch1=r16, scratch2=r17 _Lock PSA.SchLock, scratch1=r16, scratch2=r17
@ -1975,21 +2089,21 @@ KCSetAreaAccess ; OUTSIDE REFERER
cmplw cr2, r28, r19 cmplw cr2, r28, r19
blt+ cr1, major_0x0b054 blt+ cr1, major_0x0b054
bgt+ cr2, major_0x0b054 bgt+ cr2, major_0x0b054
bne- KCSetAreaAccess_0x154 bne- MPSetAreaAccess_0x154
_Lock PSA.HTABLock, scratch1=r14, scratch2=r15 _Lock PSA.HTABLock, scratch1=r14, scratch2=r15
KCSetAreaAccess_0x9c MPSetAreaAccess_0x9c
mr r8, r29 mr r8, r29
bl MPCall_95_0x1e4 bl MPCall_95_0x1e4
beq+ Local_Panic beq+ Local_Panic
bl MPCall_95_0x2b0 bl MPCall_95_0x2b0
bns- cr7, KCSetAreaAccess_0xb8 bns- cr7, MPSetAreaAccess_0xb8
bltl- cr5, MPCall_95_0x2e0 bltl- cr5, MPCall_95_0x2e0
bltl- cr5, MPCall_95_0x348 bltl- cr5, MPCall_95_0x348
KCSetAreaAccess_0xb8 MPSetAreaAccess_0xb8
lwz r17, 0x0000(r30) lwz r17, 0x0000(r30)
bl major_0x10d38 bl major_0x10d38
and r8, r4, r5 and r8, r4, r5
@ -1998,40 +2112,40 @@ KCSetAreaAccess_0xb8
and r18, r18, r9 and r18, r18, r9
lwz r17, 0x0000(r30) lwz r17, 0x0000(r30)
rlwinm. r8, r18, 0, 26, 26 rlwinm. r8, r18, 0, 26, 26
bns- cr7, KCSetAreaAccess_0x118 bns- cr7, MPSetAreaAccess_0x118
bgt- cr6, KCSetAreaAccess_0x118 bgt- cr6, MPSetAreaAccess_0x118
beq- KCSetAreaAccess_0x118 beq- MPSetAreaAccess_0x118
rlwinm r9, r17, 0, 0, 19 rlwinm r9, r17, 0, 0, 19
lwz r8, 0x0068(r31) lwz r8, 0x0068(r31)
KCSetAreaAccess_0xec MPSetAreaAccess_0xec
addi r8, r8, -0x20 addi r8, r8, -0x20
dcbf r8, r9 dcbf r8, r9
cmpwi r8, 0x00 cmpwi r8, 0x00
bgt+ KCSetAreaAccess_0xec bgt+ MPSetAreaAccess_0xec
sync sync
lwz r8, 0x0068(r31) lwz r8, 0x0068(r31)
KCSetAreaAccess_0x104 MPSetAreaAccess_0x104
addi r8, r8, -0x20 addi r8, r8, -0x20
icbi r8, r9 icbi r8, r9
cmpwi r8, 0x00 cmpwi r8, 0x00
bgt+ KCSetAreaAccess_0x104 bgt+ MPSetAreaAccess_0x104
isync isync
KCSetAreaAccess_0x118 MPSetAreaAccess_0x118
bl major_0x10cb8 bl major_0x10cb8
lwz r19, 0x0068(r31) lwz r19, 0x0068(r31)
stw r17, 0x0000(r30) stw r17, 0x0000(r30)
add r29, r29, r19 add r29, r29, r19
subf. r8, r29, r28 subf. r8, r29, r28
bge+ KCSetAreaAccess_0x9c bge+ MPSetAreaAccess_0x9c
_AssertAndRelease PSA.HTABLock, scratch=r14 _AssertAndRelease PSA.HTABLock, scratch=r14
; r1 = kdp ; r1 = kdp
b ReleaseAndReturnZeroFromMPCall b ReleaseAndReturnZeroFromMPCall
KCSetAreaAccess_0x154 MPSetAreaAccess_0x154
bne+ cr1, major_0x0b054 bne+ cr1, major_0x0b054
lwz r18, 0x001c(r31) lwz r18, 0x001c(r31)
and r8, r4, r5 and r8, r4, r5
@ -2050,18 +2164,18 @@ KCSetAreaAccess_0x154
lwz r27, 0x0068(r31) lwz r27, 0x0068(r31)
mr r28, r19 mr r28, r19
KCSetAreaAccess_0x1a4 MPSetAreaAccess_0x1a4
mr r8, r29 mr r8, r29
lwz r9, Area.AddressSpacePtr(r31) lwz r9, Area.AddressSpacePtr(r31)
bl MPCall_95_0x45c bl MPCall_95_0x45c
beq- KCSetAreaAccess_0x1bc beq- MPSetAreaAccess_0x1bc
bl MPCall_95_0x2e0 bl MPCall_95_0x2e0
bl MPCall_95_0x348 bl MPCall_95_0x348
KCSetAreaAccess_0x1bc MPSetAreaAccess_0x1bc
add r29, r29, r27 add r29, r29, r27
subf. r8, r29, r28 subf. r8, r29, r28
bge+ KCSetAreaAccess_0x1a4 bge+ MPSetAreaAccess_0x1a4
_AssertAndRelease PSA.HTABLock, scratch=r14 _AssertAndRelease PSA.HTABLock, scratch=r14
; r1 = kdp ; r1 = kdp
@ -2259,34 +2373,39 @@ MPCall_123 ; OUTSIDE REFERER
DeclareMPCall 77, MPCall_77 ; Does the blue task always get these notifications?
MPCall_77 ; OUTSIDE REFERER ; (MPLibrary function is a simple wrapper.)
; ARG AreaID r3, NotificationID r4, long r5
; RET OSErr r3
DeclareMPCall 77, MPSetAreaBackingProvider
MPSetAreaBackingProvider
_Lock PSA.SchLock, scratch1=r16, scratch2=r17 _Lock PSA.SchLock, scratch1=r16, scratch2=r17
; Expect Area ID in r3
mr r8, r3 mr r8, r3
; r8 = id
bl LookupID bl LookupID
cmpwi r9, Area.kIDClass cmpwi r9, Area.kIDClass
bne+ ReleaseAndReturnMPCallInvalidIDErr bne+ ReleaseAndReturnMPCallInvalidIDErr
mr r31, r8 mr r31, r8
mr. r8, r4
beq- MPCall_77_0x40
; r8 = id ; r4 optionally contains...
mr. r8, r4
beq- @no_notification
; a Notification ID
bl LookupID bl LookupID
cmpwi r9, Notification.kIDClass cmpwi r9, Notification.kIDClass
bne+ ReleaseAndReturnMPCallInvalidIDErr bne+ ReleaseAndReturnMPCallInvalidIDErr
@no_notification
MPCall_77_0x40 stw r4, Area.BackingProviderID(r31)
stw r4, 0x0018(r31) stw r5, Area.BackingProviderMisc(r31)
stw r5, 0x0084(r31)
; r1 = kdp
b ReleaseAndReturnZeroFromMPCall b ReleaseAndReturnZeroFromMPCall