; 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.growp


;grow slot by taking pages from FreePool; add them to AppSpace


; entry:
;     R1 =  new number of pages for slot (more than current value)
;     R2 -> AMB node (page table already allocated/grown to size)
;
; exit: -

growpages ROUT
        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

        LDR     R1,=ZeroPage+FreePoolDANode ;R1 := source for pages
        LDR     R2,=ZeroPage+AppSpaceDANode ;R2 := dest for pages

        LDR     R7,[R0,#AMBNode_Npages]    ;R7 := current no. of pages
        SUB     R3,R6,R7                   ;no. of pages required from FreePool
        LDR     R4,[R1,#DANode_PMPSize]    ;no. of pages in FreePool
        CMP     R3,R4
  [ ShrinkableDAs
        BLHI    growp_TryToShrinkShrinkables
  ]
        MOVHI   R3,R4                      ;R3 := no. of pages we will move
        CMP     R3,#0
        BEQ     %FT90                      ;done if can't move any pages
        ADD     R4,R3,R7
        STR     R4,[R0,#AMBNode_Npages]    ;new no. of pages

        ADD     R4,R0,#AMBNode_pages
        ADD     R4,R4,R7,LSL #2            ;R4 -> 1st page table entry for grow
        LDR     R5,[R1,#DANode_PMP]
        LDR     LR,[R1,#DANode_PMPSize]
        ADD     R5,R5,LR,LSL #2            ;current end of FreePool

        ;R3 = no. of pages, R4 -> buffer for page entries,
        ;R5 -> end of free pool PMP
        ; Reverse the order as we copy in order to match OS_ChangeDynamicArea
        ; (helps ensure pages are physically contiguous - to help with any
        ; potential DMA)
        MOV     R2,R3
        MOV     R6,#-1
10
        LDR     LR,[R5,#-4]!
        SUBS    R2,R2,#1
        STR     LR,[R4],#4
        STR     R6,[R5]
        BNE     %BT10
        SUB     R4,R4,R3,LSL #2
        LDR     R2,=ZeroPage+AppSpaceDANode ;R2 := dest for pages

  [ AMB_LazyMapIn
        LDR     R5,AMBFlags
        TST     R5,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend
        ;
        MOVEQ   R5,#-1                     ;map the pages to Nowhere initially
        MOVEQ   R6,#AreaFlags_Duff
        LDRNE   R5,[R0,#AMBNode_startaddr]
        ADDNE   R5,R5,R7,LSL #Log2PageSize ;R5 := first new page new address
        LDRNE   R6,[R0,#AMBNode_PPL]       ;R6 := dest PPL flags
  |
        LDR     R5,[R0,#AMBNode_startaddr]
        ADD     R5,R5,R7,LSL #Log2PageSize ;R5 := first new page new address
        LDR     R6,[R0,#AMBNode_PPL]       ;R6 := dest PPL flags
  ]
        ;
        ;entry: R3 = no. of pages, R4 -> list of page entries,
        ;       R5 = start logical address, R6 = PPL
        BL      AMB_SetMemMapEntries       ;remap

        LDR     R5,[R1,#DANode_PMPSize]
        SUB     R5,R5,R3
        STR     R5,[R1,#DANode_PMPSize]    ;new FreePool size

        LDR     R5,[R2,#DANode_Size]
        ADD     R5,R5,R3,LSL #Log2PageSize
        STR     R5,[R2,#DANode_Size]       ;new AppSpace size
        LDR     R6,=ZeroPage
        STR     R5,[R6,#MemLimit]          ;update MemLimit

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

  [ ShrinkableDAs
;
; growp_TryToShrinkShrinkables - try to shrink shrinkable DAs, to grow free pool
;
; entry:
;   R1 -> FreePool DANode
;   R3 = no. of pages required in FreePool
;   R4 = no. of pages in FreePool (must be less than R3)
;
; exit:
;   R4 = new no. of pages in FreePool
;   condition code GT is true if still less than required (ie. R3 > R4 on exit)
;
growp_TryToShrinkShrinkables ROUT
        Entry   "R1-R2,R11,R12"
        MOV     R11,R1
        MOV     R12,#0                          ; dest node irrelevant
        MOV     R1,R3
        MOV     R2,R4
        CLC
        BL      TryToShrinkShrinkables
        MOV     R4,R2
        CMP     R3,R2
        EXIT

  ] ;ShrinkableDAs

    END