.TITLE CALL calling standard macros .IDENT /01.05/ ; ; This file implements the GRUMPF calling standard. ; The calling standard uses R5 as frame pointer, arguments on ; the stack in reversed order and the MARK instruction for stack ; cleanup. R0 and R1 can be used to return values from a subroutine, ; other registers are not affected by a subroutine call. ; A macro to create an image header is provided, too. ; ; macros: ; .CALL calls a subroutine with up to 9 arguments ; .ENTRY used upon subroutine entry, saves registers ; .RETURN returns from a subroutine ; .IMAGE enters the image name in the locations 10 and 12 ; ; routines: ; $ENTRY register save routine for .ENTRY ; $RETRN register restore routine for .RETRN ; ; stack layout after .ENTRY: ; | ... | ; | old R5 | ; | argument n | ; | argument n-1 | ; | ... | ; | argument 2 | ; | argumetn 1 | ; | MARK n | <--+ ; | return PC | | ; R5 -> | address of | ---+ ; | R4 | ; | R3 | ; SP -> | R2 | ; | ... | ; ; usage: ; ... ; .CALL ROUTINE,ARG1,ARG2,ARG3,...,ARG9 ; ... ; ROUTINE: ; .ENTRY ; ... ; .RETRN ; ... ; ; 09-AUG-2005 H. Rosenfeld new .IMAGE macro will only set image name ; 20-APR-2005 H. Rosenfeld setting the stack in .IMAGE macro used wrong ; addressing mode ; 08-APR-2005 H. Rosenfeld changed .IMAGE macro to contain the program ; name and code to set up the stack pointer ; 06-MAR-2005 H. Rosenfeld added .IMAGE macro ; 25-JAN-2005 H. Rosenfeld split .ARGS off .CALL so that it can be used by ; syscalls too ; 23-JAN-2005 H. Rosenfeld ; .LIST ME .NLIST CND .ENABL REG .MACRO .ARGS P1,P2,P3,P4,P5,P6,P7,P8,P9 .NARG C$ARGC .IF EQ C$ARGC MOV #MARK,-(SP) .MEXIT .ENDC .IF NB MOV P9,-(SP) .ENDC .IF NB MOV P8,-(SP) .ENDC .IF NB MOV P7,-(SP) .ENDC .IF NB MOV P6,-(SP) .ENDC .IF NB MOV P5,-(SP) .ENDC .IF NB MOV P4,-(SP) .ENDC .IF NB MOV P3,-(SP) .ENDC .IF NB MOV P2,-(SP) .ENDC .IF NB MOV P1,-(SP) .ENDC MOV #MARK!C$ARGC,-(SP) .ENDM .MACRO .CALL SBR,P1,P2,P3,P4,P5,P6,P7,P8,P9 .MCALL .ARGS MOV R5,-(SP) .ARGS P1 P2 P3 P4 P5 P6 P7 P8 P9 MOV SP,R5 JSR PC,SBR .ENDM .MACRO .ENTRY .GLOBL $ENTRY JSR R5,$ENTRY .ENDM .MACRO .RETRN .GLOBL $RETRN JMP $RETRN .ENDM .MACRO .IMAGE NAME .ASECT .=10 .RAD50 /NAME/ .ENDM .CSECT ; $ENTRY ; saves registers R2-R4, sets up correct frame pointer, destroys R0 $ENTRY::MOV R5,R0 ; save return PC in R0 MOV SP,R5 ; set up new frame pointer MOV R4,-(SP) ; save general registers MOV R3,-(SP) MOV R2,-(SP) JMP (R0) ; jump to return address ; $RETRN ; $RETRN ; restores registers R2-R5, leaving R0, R1 and the carry flag intact $RETRN::MOV R5,R2 ; use frame pointer to restore registers MOV -(R2),R4 MOV -(R2),R3 MOV -(R2),R2 MOV R5,SP ; restore SP MOV (SP)+,R5 ; restore old frame pointer RTS R5 .END