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

; routines hanging on (kernel direct equiv. of) memory service calls


;Service_MemoryMoved
;
;  if there is a mapped-in node then recheck which and how many pages it owns
;
;  it is only necessary to:
;    1) reset node's idea of Npages to agree with no. of pages in app space
;    2) if Npages has increased, find the page numbers for new pages [and update
;       the mapped in list, if LazyMapIn]
;  ie. page numbers of existing pages are not messed with
;
AMBsrv_memorymoved ROUT
        Push   "R3-R6,R12,LR"

        LDR     R12,=ZeroPage+AMBControl_ws
        LDR     R12,[R12]
        CMP     R12,#0
        Pull    "R3-R6,R12,PC",EQ          ;AMBControl not initialised yet!

        LDR     R4,AMBMappedInNode
        CMP     R4,#0
        Pull    "R3-R6,R12,PC",EQ          ;done if nothing mapped in

        LDR     R3,[R4,#AMBNode_Npages]

        LDR     R6,=ZeroPage+AppSpaceDANode
        LDR     R6,[R6,#DANode_Size]
        SUB     R6,R6,#ApplicationStart
        MOV     R6,R6,LSR #Log2PageSize

        CMP     R6,R3
        STRNE   R6,[R4,#AMBNode_Npages]    ;update Npages
  [ AMB_LazyMapIn
        Pull    "R3-R6,R12,PC",EQ          ;done if Npages same
        BLT     %FT22                      ;shrink
  |
        Pull    "R3-R6,R12,PC",LE          ;done if Npages same, or shrink
  ]

        MOV     R5,#ApplicationStart
        ADD     R5,R5,R3,LSL #Log2PageSize ;first logical address to find
        ADD     R4,R4,#AMBNode_pages
        ADD     R4,R4,R3,LSL #2            ;first page number word to use
        SUB     R3,R6,R3                   ;no. of pages to find (grow number)
        BL      AMB_FindMemMapEntries

  [ AMB_LazyMapIn
        ;if Npages has grown, update AMBMappedInNpages and set bits in bitmap for
        ;new pages, since these will be mapped in.
        ;
;  Debug AMB,"AMBsrv +Npages ",R3
    [ AMB_ChocTrace
        LDR     R5,AMBNmemmovegrow
        ADD     R5,R5,#1
        STR     R5,AMBNmemmovegrow
    ]
        LDR     R5,AMBFlags
        TST     R5,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend
        BNE     %FT21
        LDR     R5,AMBMappedInNpages
        ADD     R5,R5,R3
        STR     R5,AMBMappedInNpages
        LDR     R4,AMBMappedInNode
        LDR     R5,[R4,#AMBNode_Npages]
        SUB     R5,R5,R3
        ADR     R6,AMBMappedInRegister
        ADD     R6,R6,R5,LSR #5-2        ;first word of bitmap affected
        BIC     R6,R6,#3
        AND     R5,R5,#31                ;first bit of word
        MOV     R4,#1
        MOV     R5,R4,LSL R5             ;bitmap mask
        LDR     R4,[R6],#4
10
        ORR     R4,R4,R5
        SUBS    R3,R3,#1
        STREQ   R4,[R6,#-4]
        BEQ     %FT20
        MOVS    R5,R5,LSL #1
        BNE     %BT10
        STR     R4,[R6,#-4]
        MOV     R4,#-1
12
        CMP     R3,#32
        BLT     %FT14
        STR     R4,[R6],#4
        SUBS    R3,R3,#32
        BEQ     %FT20
        B       %BT12
14
        MOV     R5,#1
        LDR     R4,[R6],#4
        B       %BT10
20
21
        Pull    "R3-R6,R12,PC"

22
        SUB     R3,R3,R6                 ;no. of pages removed from app space (known unsparse before removal)
;  Debug AMB,"AMBsrv -Npages ",R3
    [ AMB_ChocTrace
        LDR     R5,AMBNmemmoveshrink
        ADD     R5,R5,#1
        STR     R5,AMBNmemmoveshrink
    ]
        LDR     R5,AMBFlags
        TST     R5,#AMBFlag_LazyMapIn_disable :OR: AMBFlag_LazyMapIn_suspend
        BNE     %FT41
        LDR     R5,AMBMappedInNpages
        SUB     R5,R5,R3
        STR     R5,AMBMappedInNpages
        LDR     R4,AMBMappedInNode
        LDR     R5,[R4,#AMBNode_Npages]
        ADR     R6,AMBMappedInRegister
        ADD     R6,R6,R5,LSR #5-2        ;first word of bitmap affected
        BIC     R6,R6,#3
        AND     R5,R5,#31                ;first bit of word
        MOV     R4,#1
        MOV     R5,R4,LSL R5             ;bitmap mask
        LDR     R4,[R6],#4
30
        BIC     R4,R4,R5
        SUBS    R3,R3,#1
        STREQ   R4,[R6,#-4]
        BEQ     %FT40
        MOVS    R5,R5,LSL #1
        BNE     %BT30
        STR     R4,[R6,#-4]
        MOV     R4,#0
32
        CMP     R3,#32
        BLT     %FT34
        STR     R4,[R6],#4
        SUBS    R3,R3,#32
        BEQ     %FT40
        B       %BT32
34
        MOV     R5,#1
        LDR     R4,[R6],#4
        B       %BT30
40
41
  ] ;AMB_LazyMapIn

        Pull    "R3-R6,R12,PC"


;Service_PagesSafe
;  entry: R2 =  no. pages involved,
;         R3 -> page block describing state before
;         R4 -> page block describing state after
;
; action: fix-up page numbers in page lists of nodes as necessary
;
AMBsrv_pagessafe ROUT
        Push   "R0-R1,R5-R10,R12,LR"

        LDR     R12,=ZeroPage+AMBControl_ws
        LDR     R12,[R12]
        CMP     R12,#0
        Pull   "R0-R1,R5-R10,R12,PC",EQ    ;AMBControl not initialised yet!

        LDR    R0,AMBNtasks
        CMP    R0,#0
        Pull   "R0-R1,R5-R10,R12,PC",EQ    ;no nodes to check

;speed-up - list of pages tends to span a narrow range of page numbers, so
;            use min,max limits to skip search
        MOV    R9,#&7FFFFFFF
        MOV    R10,#0
        MOV    R0,R3
        MOV    R1,R2
00
        LDR    R5,[R0],#12
        CMP    R9,R5
        MOVGT  R9,R5         ;remember minimum 'before' page no. in R9
        CMP    R10,R5
        MOVLT  R10,R5        ;remember maximum 'before' page no. in R10
        SUBS   R1,R1,#1
        BNE    %BT00

        ADR    R0,AMBAnchorNode
        MOV    R1,R0
        Push   "R0,R1"
        B      %FT03
01
;check pages for this node
        LDR    R5,[R0,#AMBNode_Npages]
        CMP    R5,#0
        BEQ    %FT04         ;skip if node has zero pages
        ADD    R6,R0,#AMBNode_pages
        Push   "R0,R1"
02
;for each page in node
        LDR     R7,[R6]      ;page no. from node
        CMP     R7,R9
        BLT     %FT13        ;not in list ( < 'before' min)
        CMP     R7,R10
        BGT     %FT13        ;not in list ( > 'before' max)
;oh dear! search of before,after lists required
        MOV     LR,R2
        MOV     R0,R3
        MOV     R1,R4
11
        LDR     R8,[R0],#12  ;next page from before list
        CMP     R8,R7        ;matches node page?
        BEQ     %FT12
        ADD     R1,R1,#12    ;step the after list
        SUBS    LR,LR,#1
        BNE     %BT11
        B       %FT13        ;done pages in node,not matched
12
        LDR     R8,[R1]      ;fetch new page number from after list
        STR     R8,[R6]      ;store it for node
13
        ADD    R6,R6,#4      ;next page in node
        SUBS   R5,R5,#1
        BNE    %BT02
03
        Pull   "R0,R1"
04
;next node
        LDR    R0,[R0,#AMBNode_next]
        CMP    R0,R1                 ;done if back at anchor node
        BNE    %BT01
        Pull    "R0-R1,R5-R10,R12,PC"

    END