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


; handle deallocate reason code

; entry:
;     R0 = 1 (reason code 1)
;     R2 = handle
;
; exit -


deallocate
        Push    "R0-R3,LR"

      [ AMB_Debug
        DebugReg r2,"deallocate "
      ]

      [ ValidateAMBHandles
        ;validate handle
        LDR     R0,AMBNhandles
        CMP     R2,R0
        BGT     badhandle_dealloc
        CMP     R2,#1
        BLT     badhandle_dealloc
      ]

        LDR     R0,AMBNodeHandles   ; R0 -> handle array
        LDR     R1,[R0,R2,LSL #2]   ; R1 -> node

      [ ValidateAMBHandles
        ;check we have a proper id for node handle
        LDR     R3,=AMBMagicNodeID
        LDR     LR,[R1,#AMBNode_id]
        CMP     LR,R3
        BNE     badhandle_dealloc
      ]

        Push    "R1-R2"
        MOV     R2,R1               ;node ptr
        MOV     R1,#0               ;shrink to 0 pages
        BL      shrinkpages         ;do actual MMU page deallocate
        Pull    "R1-R2"
        BVS     dealloc_done

;put handle on free list
        LDR     R3,[R0]            ;current first free handle
        STR     R3,[R0,R2,LSL #2]  ;attach
        STR     R2,[R0]            ;new first free handle

;remove node from list
        MOV     R2,R1                   ; R2 -> node
        LDR     R0,[R2,#AMBNode_prev]   ; R0 -> prev_node
        LDR     R1,[R2,#AMBNode_next]   ; R1 -> next_node
        STR     R1,[R0,#AMBNode_next]   ; prev_next := next_node
        STR     R0,[R1,#AMBNode_prev]   ; next_prev := prev_node
        LDR     R0,AMBNtasks
        SUB     R0,R0,#1
        STR     R0,AMBNtasks

;if this is the mapped-in node, then nothing is now mapped in
        LDR     R0,AMBMappedInNode
        CMP     R0,R2
        MOVEQ   R0,#0
        STREQ   R0,AMBMappedInNode

;free node (at R2)
        BL      AMB_BlockFree

dealloc_done
        STRVS   R0,[SP]
        Pull    "R0-R3,LR"
        B       SLVK_TestV

        LTORG

      [ ValidateAMBHandles
badhandle_dealloc
        Pull    "R0-R3,LR"
badhandle
        ADR     R0,err_badhandle
        B       SLVK_SetV
err_badhandle
        DCD     0
        DCB     "AMBControl bad handle",0
        ALIGN
      ]


    END