.iif ndf $$$lst, .nlist .iif ndf $$$lst, .dsabl crf .enabl lc .nlist bex,me,ttm .list meb .dsabl gbl .title cmacs Common Macro Definitions ; version 0-0 ;+ ; ; Usage ; ; Cmacs is a macro library for all tos system and user ; programs. There are several types of macros defined, ; including C subroutine management, NanoC/tos structure ; definitions, and system program macros. ; ; callc function, ; ; Call a C function from a C-compatible function. ; ; calls function, ; ; Call a C function from any subroutine. ; ; csub name, arglist ; ; Define the entry to a C-callable routine. ; ; cbegin ; ; Start of code for the C-callable routine. ; ; centry name, join ; ; An alternate entry to the current routine. ; ; cret value ; ; Return from a C-callable routine. ; ; c.stru size_name, allo_name, psect=.data. ; ; Define a C-style structure. ; ; c.int variable, size=1 ; c.char variable, size=1 ; c.ptr size_name, variable, size=1 ; ; Define an integer or byte offset. C.ptr defines ; pointers to other structures. ; ; c.ends name ; ; Terminate a C-style structure allocation. ; ; defbit start=0, range=NOGLOBAL ; ; Begin a bit-mask definition block. ; ; bitflg name ; ; Define name as a bit-mask. ; ; efadr offset, result=r0, base=r5 ; ; Get the effective address of a pointer. ; ; call routine ; ; General subroutine call (= jsr pc, routine) ; ; callr routine ; ; Call a subroutine and return to the original ; caller (= jmp routine). ; ; .br label ; ; Generate an assembly error if the next location ; is not the specified symbol. The symbol may not ; be a local label (10$, etc.) ; ; assume symbol, condition, value ; ; Verify assembly conditions. ; ; default symbol, value=0 ; ; Initialize symbol if not already defined. ; ; $psect section, attribute_list ; ; Define a program section with the specified ; attributes, remembering the section for later ; use by the .save and .restore macros. ; ; .save ; ; Remember the current $psect. ; ; .restore ; ; Return to the remembered $psect. ; ; prpush ; ; Push current priority, lock out interrupts. ; ; prpop ; Pop priority from the top of the stack. ; ; Description ; ; Cmacs contains a set of macro's for defining C callable routines in ; macro and for calling C callable routines from macro. It also ; contains the necessary support macros for the nanoC/tos operating ; system kernel. For more information, see the listing of tos.mac. ; ; Cmacs defines the following local symbols: ; ; C$$EIS 1 if inline EIS code ; ?? ; The macro's are used as follows: ; ; callc function, ; ; Call a subruttine, such as C function with the indicated parameter ; list. As the expansion of pushes data onto the stack, ; your program will work differently on various PDP-11's if any ; parameter is a stack variable. ; ; NOTE: Callc may only be used from ; subroutines that have executed the standard C setup (macro's ; csub and cbegin). ; ; calls function, ; ; Call a subruttine, such as C function with the indicated parameter ; list. As the expansion of pushes data onto the stack, ; your program will work differently on various PDP-11's if any ; parameter is a stack variable. Calls may be invoked in any program, ; even if the C setup sequence has not been invoked. ; ; csub name, arglist ; ; Define the entry to a C-callable routine. The name will ; be globalized and the program will begin with a call to ; the C register save routine, CSV$. The argument list will ; be defined as offsets to the the frame pointer (r5). After ; the csub macro, the program may define local variables using ; the c.stru macro. ; ; cbegin ; ; This defines the main (or only) entry to a C-callable ; routine. It expands to the proper stack subtract to ; define space for any local variables. Note that cbegin ; enables local symbol blocks (.enabl lsb). ; ; centry name, join ; ; This defines an alternate entry to a C-callable routine. ; The routine name is globalized, registers are saved by ; calling CSV$, and the necessary stack space obtained. ; if join is defined, a branch to join will be generated ; before the entry-specific code is expanded. If the ; join argument is missing, a branch around the centry code ; will be expanded. For example, ; ; csub foo ; c.int local1 ; A local variable ; c.int local2 ; Another local variable ; ; cbegin ; ; Unique code for foo ; ; centry bar, common ; ; Unique code for bar ; ; common: ; ; Normal code ; ; ; cret value ; ; Return from a C-callable routine, calling CRET$. If value ; is present, a "mov value, r0" will be expanded. ; ; c.stru size_name, allo_name, psect=.data. ; ; Define a C structure. The argument will be equated to the ; size of the structure in bytes. If an optional allocation ; name argument is given, storage will be allocated for the ; structure in the indicated program section (or the default ; read-write section, .data., if no psect argument is given. ; (Note, this use of the allo_name and psect arguments is ; needed only for nested structure definitions. It allocates ; the part of the structure already defined, without terminating ; the entire structure definition.) ; ; The general format of a structure definition is: ; ; c.stru size_name ; c.int ... ; Allocate an integer ; c.char ... ; Allocate a character ; c.ends allocation_name ; ; Note that structure definitions may be nested. ; ; c.int variable, size=NN ; c.char variable, size=NN ; c.ptr size_name, variable, size=NN ; ; Define an integer or byte offset into the current structure ; or a local variable for the current function. If the size ; parameter is given, it will indicate the number of elements ; (words or bytes) to be defined. If not present, one element ; will be defined. C.ptr defines a pointer to a structure ; defined as ; ; c.stru size_name ; ; Internally, c.ptr is equivalent to c.int. ; ; c.ends name, psect=.data. ; ; Terminate the definition of a structure. If the name is ; given, storage will be allocated for the structure in ; the indicated .psect, saving and restoring the default ; .psect (which was established using the $psect macro). Note that ; the default allocation is to the .data. (read-write) section. ; ; defbit start=0, range=NOGLOBAL ; ; Begin a bit-mask definition block. If start is specified, it will ; indicate the first bit to be defined. The bit values will normally ; be defined locally (within this compilation). To define them ; globally, specify "range=GLOBAL". ; ; bitflg name ; ; Define name as a bit-mask. For example, ; ; defbit 3 ; bitflg is0100 ; bitflg is0200 ; ; efadr offset, result=r0, base=fp ; ; Get the effective address of a local value or a pramameter. If ; the result parameter is not specified, r0 will point to the ; address of the offset. ; ; call routine ; ; General subroutine call (= jsr pc, routine) ; ; callr routine ; ; Call a subroutine and return to the original ; caller (= jmp routine). ; ; .br label ; ; Generate an assembly error if the next location is not ; the one specified by the parameter. Note, label may not ; be a "local label", such as 50$. ; ; assume symbol, condition, value ; ; Verify assembly conditions. If the test fails, the assembler ; will generate an error. ; ; default symbol, value=0 ; ; Initialize symbol if not already defined. ; ; $psect section, attribute_list ; ; Define a program section with the specified ; attributes. ($psect remembers the section for ; later use by the .save and .restore macros.) ; This macro is needed because .save and .restore are ; not implemented in some versions of the PDP-11 macro ; assembler. $psect should be invoked before executing ; the .save macro. ; ; .save ; ; Remember the current $psect for later use by the .restore ; operation. .save may be nested. The number of .save and ; .restore macros must match. Many strange errors will ; occur if this is not the case. ; ; .restore ; ; Return to the remembered $psect that was previously .save'd. ; ; prpush ; ; Push the current CPU priority onto the stack and raise the ; priority to level 7, locking out interrupts. Note that ; this macro assumes the existance of the the MFPS and MTPS ; instructions. ; ; prpop ; ; Reload the CPU priority register from the stack, popping ; the value off of the stack. Note that this macro assumes ; the existance of the MTPS instruction. ; ;- ; .sbttl common register definitions ; register assignment pdp-11 use c use ;r0 = %0 ;general register 0 (function value) ;r1 = %1 ; 1 (scratch register) ;r2 = %2 ; 2 (local register variable) ;r3 = %3 ; 3 " " ;r4 = %4 ; 4 " " ;r5 = %5 ; 5 fp = %5 ; 5 (stack frame pointer) ;sp = %6 ;stack pointer (stack pointer) ;pc = %7 ;program counter (program counter) ; ; Define C parameter access offsets ; C$PMTR = 4 C$AUTO = -6 ; misc. constants psw.p0 = 0 ;priority 0 psw.p1 = 40 ; 1 psw.p2 = 100 ; 2 psw.p3 = 140 ; 3 psw.p4 = 200 ; 4 psw.p5 = 240 ; 5 psw.p6 = 300 ; 6 psw.p7 = 340 ; 7 psw.c = 1 ;carry flag psw.v = 2 ;overflow flag psw.z = 4 ;equal zero flag psw.n = 10 ;less than flag psw.t = 20 ;trace trap mode flag ; global variables needed for stack discipline .globl csv$ ;register save routine .globl cret$ ;register restore and subroutine return .sbttl Some general-purpose macros ;+ ; call ; ; Names the jsr pc,routine sequence ; ;- .macro call name jsr pc,name .endm call ;+ ; callr ; ; Names the jmp routine sequence ; ;- .macro callr name jmp name .endm ;+ ; .br ; ; This macro verifies that an assumed code flow branch really goes ; to the next location. It generates an error message if the ; label argument is missing or not equal to the next location. ; ;- .macro .br label .iif ndf label .error ;label argument needed .if ne label-. .error ;label must be the next location .endc .endm .br ;+ ; assume ; ; This macro is used to force the assembler to verify assumptions ; made about the values of symbols. It should be used whenever code ; is written that depends on a symbol being a definite value. ; ; Form: ; ; assume symbol condition value ; ; Example: ; ; assume foo EQ 200 ; tstb r0 ; Is foo set in r0? ; bmi 10$ ; Branch if so ; ;- .macro assume a1,cnd,a2 .if cnd - .iff .error ;The assumption "a1 cnd a2" is FALSE .endc .endm assume ;+ ; default ; ; Establish a default value for a symbol which may or may not be ; conditionally defined during the assembly. If no value is given, ; the symbol will be defaulted to zero. The symbol is not globalized. ; ; Example: ; ; default foo, 200 ; ;- .macro default symbol, value=0 .dsabl CRF .if ndf symbol symbol = value .endc .enabl CRF .irp x,<\symbol> symbol = x .endr .endm default ;+ ; $psect ; .save ; .restore ; ; These three macros allow for program section nesting. To establish ; a program section, invoke the $psect macro, using the same arguments ; you would use for .psect. ; ; To save the current $psect name, use the .save macro. ; To return to the saved $psect, use the .restore macro. ; Many strange errors will occur if .save and .restore don't match. ; Note that you can do the following: ; ; $psect foo ; .save ;saves "foo" ; .psect bar ;temporary switch to "bar" ; .restore ;restores "foo" ; ;- .macro $psect section,list .list bex .iif ndf $$pl$$ $$pl$$ = 0 .irp $$$$$$,<\$$pl$$> .macro $$p'$$$$$$'$$ .list bex $psect section, .nlist bex .endm $$p'$$$$$$'$$ .endr .if nb .psect section,list .iff .psect section .endc .nlist bex .endm $psect .macro .save .if ndf $$pl$$ ; force undefined .psect $psect .endc $$pl$$ = $$pl$$ + 1 .endm .macro .restore .if ndf $$pl$$ .error ;I Can't .restore if you won't .save .iff $$pl$$ = $$pl$$ - 1 .if ge $$pl$$ .irp $$$$$$,<\$$pl$$> $$p'$$$$$$'$$ .endr .iff .error ;Too many .restore calls .endc .endc .endm .sbttl call and push and pop routines for subroutine calls ;+ ; callc ; calls ; ; permits a macro routine to call a c routine. r0,r1 returns value of the ; function in all cases (c convention). arguments to call should be ; enclosed in angle brackets. DO NOT use a stack offset as an ; argument to callc or calls. Callc must only be used from programs ; that have issued the standard C function initialization: ; ; jsr r5,csv$ ;- .macro callc func,list $call$ = 1 $pushc list jsr pc,func $popc $cnt$-1 ; don't pop one argument .ntype $$t$$,func .if eq <$$t$$-67> .globl func .endc .if eq <$$t$$-37> .globl func .endc .endm .macro calls func,list $call$ = 0 $pushc list jsr pc,func $popc $cnt$ .ntype $$t$$,func .if eq <$$t$$-67> .globl func .endc .if eq <$$t$$-37> .globl func .endc .endm ;+ ;$pushc ; ; pushes arguments on stack for a call to a c routine. up to 10 arguments ; are permited. sets the variable $cnt$ to number of args pushed. ; The variable $call$ is set to flag callc vs. calls invocations ;- .macro $pushc a,b,c,d,e,f,g,h,i,j $cnt$=0 .irp $var$, .if nb <$var$> .if ne $call$ mov $var$,(sp) $call$ = 0 .iff mov $var$,-(sp) .endc .endc .endm .narg $cnt$ .endm $pushc ;+ ;$popc ; ; pops arguments off stack after subroutine call. note, arg is count of ; variables to pop. ;- .macro $popc cnt .if eq tst (sp)+ .endc .if eq cmp (sp)+,(sp)+ .endc .if gt add #2*,sp .endc .endm $popc .sbttl c callable routine definitions ;+ ; set of macros to permit a macro 11 routine to be callable by c. ; ; format for defining c callable subroutine ; ; csub name, ; ; local variable definitions ; ; cbegin ; ; code ; ; cret ; ; arguments and local variables are defined as offsets to the frame pointer ; (r5) to be compatible with c. arguments are defined implicity in the csub ; macro starting at offset 4 and going up by increments of 2 per argument. ; local variables are defined using the c.int and c.char directives. they ; are negative offsets on the stack starting at -10 and going down (ie more ; negative). pointers are defined to be c.int, since macro is not typed ; anyway. cret is the return (in a c compatible manner). ;- .sbttl macros for c callable routines .macro csub name,arg .dsabl lsb name:: jsr r5,csv$ $off$=4 .irp $arg$, $arg$=$off$ $off$=$off$+2 .endm $off$=-6 $lev$=1 $dir$=-1 .endm csub .macro cbegin $ent$=<-6>-<<$off$+1>&177776> .if eq <$ent$-4> tst -(sp) .endc .if eq <$ent$-6> cmp -(sp),-(sp) .endc .if gt <$ent$-6> sub #$ent$-2,sp .endc .enabl lsb $lev$=0 .endm cbegin .macro centry,name,join,?tmp .if nb br join .endc .if b br tmp .endc name:: jsr r5,csv$ $ent$=<-6>-<<$off$+1>&177776> .if eq <$ent$-4> tst -(sp) .endc .if eq <$ent$-6> cmp -(sp),-(sp) .endc .if gt <$ent$-6> sub #$ent$-2,sp .endc tmp: .endm centry .macro cret,value .if nb .if dif value <#0> mov value,r0 .endc .if idn value <#0> clr r0 .endc .endc jmp cret$ .endm cret .sbttl structure definition macros ;+ ; c.stru arg ; ; Define a "C" structure using the c.int and c.char macros. arg is the ; name of s structure. the general format for use is ; ; c.stru name ; c.int ; c.char ; c.ends alname ; ; at the c.ends statement the symbol name gets equated to the structure ; size. if alname is non-blank, then allocate a structure of that size. ; if structure is previously defined, c.stru name alname will also ; allocate a block of memory correctly (either in local area or on stack) ;- .macro c.stru sizname, alname, psname=.data. .if nb .if eq <$lev$> .save .psect psname alname: .blkb siznam .restore .iff c.char alname,siznam .endc .iff .if df $lev$ .iif ne <$lev$> .error ?illegal structure nesting .endc $off$ = 0 $lev$ = 1 $dir$ = 1 .macro c.ends arg1, psect=.data. .if ndf siznam siznam = $off$ .endc .iif ne siznam-$off$ .error ;Inconsistant definition of siznam $lev$=0 .if nb .save .psect psect arg1:: .blkb $off$ .restore .endc .endm c.ends .endc .endm c.stru .sbttl offset definers ;+ ; c.int ; ; defines an integer variable as offset on stack or in a structure ;- .macro c.int arg,size=1 $inc$=size+size .iif ne <$off$&1> .error ?word allignment .iif lt $dir$, $off$=$off$-$inc$ arg = $off$ .iif gt $dir$, $off$=$off$+$inc$ .endm c.int ;+ ; c.char ; ; defines character variable as offset on stack or in a structure ;- .macro c.char arg,size=1 $inc$=size .iif lt $dir$, $off$=$off$-$inc$ arg = $off$ .iif gt $dir$, $off$=$off$+$inc$ .endm c.char ;+ ; c.ptr ; ; defines a pointer variable as offset on stack or in a structure ;- .macro c.ptr siznam,arg,size=1 $inc$=size+size .iif ne <$off$&1> .error ?word allignment .iif lt $dir$, $off$=$off$-$inc$ arg = $off$ .iif gt $dir$, $off$=$off$+$inc$ .endm c.ptr .sbttl misc. macros ;+ ; defbit start=0, range=NOGLOBAL ; ; begin bitflag definition block ;- .macro defbit start=0, range=noglobal $gbl$=0 .dsabl lc .iif idn ,GLOBAL $gbl$=1 .enabl lc $boff$=1 .rept $boff$=$boff$+$boff$ .endr .endm defbit ;+ ; bitflg ; ; define a bitflg ;- .macro bitflg bitnm .iif eq $boff$, .error ?overflow .if ne $gbl$ bitnm == $boff$ .iff bitnm = $boff$ .endc $boff$=$boff$+$boff$ .endm bitflg ;+ ; efadr ; ; get effective address of an offset to a pointer ;- .macro efadr offs,result=r0,base=r5 mov #offs,result add base,result .endm efadr .sbttl macro definitions for processes .macro prpush ;push priority, set current to 7 mfps -(sp) mtps #psw.p7 .endm prpush .macro prpop ;pop priority mtps (sp)+ .endm prpop .sbttl end of cmacs file .list meb,bex .iif ndf $$$lst, .enabl crf .iif ndf $$$lst, .list $psect .prog.