; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > s.shrinkp


;shrink slot by taking pages (from AppSpace); add them to FreePool


; entry:
;     R1 = new number of pages for slot (less than current value)
;     R2 -> AMB Node

shrinkpages
        Push    "R0-R7,LR"

        MOV     R6,R1                   ;save entry R1
        LDR     R5,[R2,#AMBNode_Npages]
        CMP     R5,R6
        Pull    "R0-R7,PC",EQ           ;done if no. of pages unchanged

        MOV     R0,R2     ;R0 -> AMB node

;set R3 to 1 if deallocate is from mapped-in slot (so AppSpace needs update)
        LDR     R5,AMBMappedInNode
        CMP     R5,R0
        MOVEQ   R3,#1                   ;flag this is the mapped-in node
        MOVNE   R3,#0                   ;flag is not

  [ AMB_LazyMapIn
        ;first make sure the current mapping of mapped in node is simple,
        ;so that main mapping can cope - easiest thing is to do a sparse map out
        ;
        BNE     %FT02
        Push    "R3,R6"
        LDR     R3,AMBFlags
        TST     R3,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend
        BNE     %FT01
        LDR     R3,AMBMappedInNpages
        ADD     R4,R5,#AMBNode_pages
        LDR     R6,[R5,#AMBNode_Npages]
        ADR     R5,AMBMappedInRegister
        BL      AMB_SetMemMapEntries_SparseMapOut
        MOV     R3,#0
        STR     R3,AMBMappedInNpages
01
        Pull    "R3,R6"
02
  ]

        TST     R3,#1                      ;check flag
        MOVEQ   R1,#0                      ;source is not App space
        LDRNE   R1,=ZeroPage+AppSpaceDANode ;source is App space
        LDR     R2,=ZeroPage+FreePoolDANode ;dest

        LDR     R7,[R0,#AMBNode_Npages]    ;R7 := current number of pages
        SUBS    R3,R7,R6                   ;R3 := no. of pages to move
        BEQ     %FT02                      ;done if no pages to move
        STR     R6,[R0,#AMBNode_Npages]    ;new no. of pages

        ADD     R4,R0,#AMBNode_pages
        ADD     R4,R4,R6,LSL #2            ;R4 -> 1st page table entry for shrink
        LDR     R6,[R2,#DANode_Flags]
        LDR     LR,=DynAreaFlags_AccessMask
        MOV     R5,#-1                     ;map pages out
        AND     R6,R6,LR                   ;R6 = dest PPL flags

        ;entry: R3 = no. of pages, R4 -> list of page entries,
        ;       R5 = start logical address, R6 = PPL
        BL      AMB_SetMemMapEntries_MyPPL ;remap

        LDR     R5,[R2,#DANode_PMP]
        LDR     R6,[R2,#DANode_PMPSize]
        LDR     R7,=ZeroPage
        LDR     R7,[R7,#CamEntriesPointer]
        ADD     R7,R7,#CAM_PMP
        ADD     R4,R4,R3,LSL #2
        MOV     R0,R3
        ; Reverse the page order as we copy, to match the reverse we performed
        ; on grow (try and keep free pool pages in optimal order for future
        ; grows)
10
        LDR     LR,[R4,#-4]!
        SUBS    R0,R0,#1
        STR     LR,[R5,R6,LSL #2]          ;add to free pool PMP
        ADD     LR,R7,LR,LSL #CAM_EntrySizeLog2
        ASSERT  CAM_PMPIndex=CAM_PMP+4
        STMIA   LR,{R2,R6}                 ;update PMP reference in CAM
        ADD     R6,R6,#1
        BNE     %BT10

        STR     R6,[R2,#DANode_PMPSize]

;update Application Space kernel values, if required
        CMP     R1,#0
        LDRNE   R0,[R1,#DANode_Size]
        SUBNE   R0,R0,R3,LSL #Log2PageSize
        STRNE   R0,[R1,#DANode_Size]
        LDRNE   R5,=ZeroPage
        STRNE   R0,[R5,#MemLimit]          ;update MemLimit

02
;;;        STRVS   R0,[SP]
        CLRV
        Pull    "R0-R7,PC"


    END