; Copyright 1999 Pace Micro Technology plc
;
; 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.
;
; > Hdr:APCS.Common

OldOpt  SETA    {OPT}
        OPT     OptNoList+OptNoP1List

 [ :LNOT: :DEF: Included_Hdr_APCS
        GBLL    Included_Hdr_APCS
Included_Hdr_APCS SETL {TRUE}

; All the following macros use {CONFIG} to determine the APCS in force.
; This means they are NOT directly affected by the APCS variable.
; This allows them to work when the APCS has been overridden - for example
; the SharedCLibrary will build using APCS-R to keep 26-bit compatibility
; where possible.

; This also means that these macros are not AAsm compatible.


; *****************************************
; ***  Pull registers given in reglist  ***
; *****************************************
        MACRO
$label  PullAPCS $reglist, $cond
        [ "$reglist" :RIGHT: 2 <> "pc" :LAND: "$reglist" :RIGHT: 2 <> "PC"
        ! 1, "PullAPCS must pull PC at the end. Use Pull instead"
        ]
 [ {CONFIG}=26
$label  Pull    "$reglist", $cond, ^
 |
$label  Pull    "$reglist", $cond
 ]
        MEND

; *****************************
; ***  APCS function entry  ***
; *****************************
        MACRO
        FunctionEntry $SaveList, $MakeFrame
        LCLS    Temps
        LCLS    TempsC
Temps   SETS    "$SaveList"
TempsC  SETS    ""
 [ Temps <> ""
TempsC SETS Temps :CC: ","
 ]

 [ "$MakeFrame" = ""
   [ TempsC = ""
        STR     lr, [sp, #-4]!
   |
        Push    "$TempsC.lr"
   ]
 |
        MOV     ip, sp
        Push    "$TempsC.fp,ip,lr,pc"
        SUB     fp, ip, #4
 ]
        MEND

; ******************************
; ***  APCS function return  ***
; ******************************
        MACRO
        Return  $ReloadList, $Base, $CC, $linkreg
        LCLS    Temps
        LCLS    Tempr
Temps   SETS    "$ReloadList"
Tempr   SETS    "$linkreg"

 [ "$Base"<>"LinkNotStacked" :LAND: "$Base"<>"" :LAND: "$Base"<>"fpbased"
 ! 1, "Unrecognised value for $Base"
 ]

 [ "$Base"="LinkNotStacked" :LAND: "$ReloadList"=""
   [ "$Tempr" = ""
Tempr   SETS    "lr"
   ]
 |
   [ "$Tempr" <> ""
   ! 1, "Return address cannot be held in register when LR is stacked"
   ]
 ]

 [ {CONFIG} = 26
   [ "$Base" = "LinkNotStacked" :LAND: "$ReloadList"=""
        MOV$CC.S pc, $Tempr
   |
     [ Temps <> ""
Temps   SETS    Temps :CC: ","
     ]
     [ "$Base" = "fpbased"
        LDM$CC.DB fp, {$Temps.fp,sp,pc}^
     |
        LDM$CC.FD sp!, {$Temps.pc}^
     ]
   ]
 |
   [ "$Base" = "LinkNotStacked" :LAND: "$ReloadList"=""
        MOV$CC  pc, $Tempr
   |
     [ Temps <> ""
Temps   SETS    Temps :CC: ","
     ]
     [ "$Base" = "fpbased"
      [ {UAL}
        LDMDB$CC  fp, {$Temps.fp,sp,pc}
      |
        LDM$CC.DB fp, {$Temps.fp,sp,pc}
      ]
     |
        Pull    "$Temps.pc", $CC
     ]
   ]
 ]
        MEND

; This function goes with those in Hdr:Proc

; *****************************************************************************
; *** Exit procedure, restore stack and saved registers to values on entry. ***
; *** Restore PSR if APCS-R in force.                                       ***
; *****************************************************************************
        MACRO
$label  EXITAPCS $cond
$label
 [ Proc_SavedCPSR
        ! 1, "Don't use EntryS with EXITAPCS"
 ]
 [ Proc_LocalStack <> 0
        ADD$cond sp, sp, #Proc_LocalStack
 ]
 [ APCS_Type = "APCS-R"
 [ "$Proc_RegList" = ""
        Pull    "pc",$cond,^
 |
        Pull    "$Proc_RegList, pc",$cond,^
 ]
 |
 [ "$Proc_RegList" = ""
        LDR$cond pc, [sp], #4
 |
        Pull    "$Proc_RegList, pc",$cond
 ]
 ]
        MEND

 ] ; :LNOT::DEF:Included_Hdr_APCS

        OPT     OldOpt
        END
