home *** CD-ROM | disk | FTP | other *** search
- ;
- ; (C) Copyright 1987-1992; MetaWare Incorporated
- ;
- ifdef mach386
- include chip386.inc
- else
- ifdef machx86
- include chip86.inc
- else
- %out1 >>>> Target machine not specified for macros file.
- %out1 >>>> You must define either "mach386" or "machx86"
- %out1 >>>> on the assembler command line.
- .err
- endif
- endif
-
- ifndef GOC
- ifndef LOC
- %out1 >>>> Target compiler type not specified for macros file.
- %out1 >>>> You must specify either "LOC" for a LOC compiler,
- %out1 >>>> or "GOC" for a GOC compiler
- .err
- endif
- endif
-
- ; Known Anomolies: Currently won't support automatic variables ie [bp-x]
- ; unless expilitly coded
-
- ; Set pointer size.
- PUSH_COUNT = 0 ; currently you have not pushed anything.
- NO_BP_V = 0
-
- ifdef Large_data
- Ptr_size equ Word_size * 2 ; pass 8 bytes at a time for a 6-byte ptr.
- Ptr_reg equ es ; Use es.
- Stack_reg equ ss ; Use ss.
- else
- Ptr_size equ Word_size
- Ptr_reg equ ds ; Can use ds, since = es.
- Stack_reg equ ds ; Can use ds, since = ss.
- endif
-
- ifdef Small_code
- Pbase = Word_size ; Location of first parameter.
- Routine_size= Word_size ; link + offset.
-
- return macro Pop_bytes
- ifb <Pop_bytes>
- db 0c3h ; ret near
- else
- db 0c2h ; ret near N bytes
- dw Pop_bytes
- endif
- endm
- extrnf macro name
- extrn name:near
- endm
- else
- Pbase = Word_size * 2 ; Location of first parameter.
- Routine_size= Word_size * 2 ; Link + offset + segment.
-
- return macro Pop_bytes
- ifb <Pop_bytes>
- db 0cbh ;ret far
- else
- db 0cah ; ret far N bytes
- dw Pop_bytes
- endif
- endm
- extrnf macro name
- extrn name:far
- endm
- endif
-
- PROLOG_PUSH macro p_reg
- ifidn <ebx>,<p_reg>
- PUSH_EBX = 1
- else
- ifidn <edi>,<p_reg>
- PUSH_EDI = 1
- else
- ifidn <esi>,<p_reg>
- PUSH_ESI = 1
- else
- ifidn <es>,<p_reg>
- PUSH_ES = 1
- else
- ifidn <ds>,<p_reg>
- PUSH_DS = 1
- else
- ifidn <ebp>,<p_reg>
- if NO_BP_V eq 1
- PUSH_EBP = 1
- else
- mov ax,ERROR ; ebp already used in prolog. Option is only valid with:
- mov ax,ERROR ; prolog no_bp [,<regs, can include ebp>]
- endif
- endif
- endif
- endif
- endif
- endif
- endif
- endm
-
- PUSH_IT macro reg
- if NO_BP_V eq 1
- PUSH_COUNT = Word_size + PUSH_COUNT
- endif
- push reg
- endm
-
- POP_IT macro reg
- if NO_BP_V eq 1
- PUSH_COUNT = PUSH_COUNT - Word_size
- endif
- pop reg
- endm
-
- PUSH_REGS macro
- if Word_size eq 2
- if PUSH_EBX eq 1
- PUSH_IT bx
- endif
- if PUSH_EDI eq 1
- PUSH_IT di
- endif
- if PUSH_ESI eq 1
- PUSH_IT si
- endif
-
- if PUSH_EBP eq 1
- if NO_BP_V eq 1
- PUSH_IT bp
- else
- mov ax,ERROR ;pushing ebp invalid without prolog no_bp [,<regs>]
- endif
- endif
- else
- if PUSH_EBX eq 1
- PUSH_IT ebx
- endif
- if PUSH_EDI eq 1
- PUSH_IT edi
- endif
- if PUSH_ESI eq 1
- PUSH_IT esi
- endif
- if PUSH_EBP eq 1
- if NO_BP_V eq 1
- PUSH_IT ebp
- else
- mov ax,ERROR ;pushing ebp invalid without prolog no_bp [,<regs>]
- endif
- endif
- endif
- if PUSH_DS eq 1
- PUSH_IT ds
- endif
- if PUSH_ES eq 1
- PUSH_IT es
- endif
- endm
-
- prolog macro r1,r2,r3,r4,r5,r6,r7,r8,r9
- L_DATA_V = 0
- PUSH_EBX = 0
- PUSH_EDI = 0
- PUSH_ESI = 0
- PUSH_DS = 0
- PUSH_ES = 0
- PUSH_EBP = 0
-
- align 4
- ifidn <>,<r1>
- push ebp
- mov ebp,esp
- NO_BP_V = 0
- PUSH_ESI = 1
- PUSH_EDI = 1
- PUSH_EBX = 1
- ifdef Large_data ; Save DS whether or not 1 DS, in case we modify it.
- PUSH_DS = 1
- endif
- else
- ifdif <no_bp>,<r1>
- push ebp
- mov ebp,esp
- NO_BP_V = 0
- else
- NO_BP_V = 1
- endif
- irp Reg,<r1,r2,r3,r4,r5,r6,r7,r8,r9>
- ifnb <Reg>
- ifdif <l_data>,<reg>
- ifdif <no_bp>,<reg>
- ifdef Large_data
- PROLOG_PUSH <Reg>
- else
- if L_DATA_V eq 0
- PROLOG_PUSH <Reg>
- else
- endif
- endif
- endif
- else
- L_DATA_V = 1
- endif
- endif
- endm
- endif
- PUSH_REGS
- endm
-
- POP_REGS macro
- if PUSH_ES eq 1
- POP_IT es
- endif
- if PUSH_DS eq 1
- POP_IT ds
- endif
- if Word_size eq 2
- if PUSH_EBP eq 1
- POP_IT bp
- endif
- if PUSH_ESI eq 1
- POP_IT si
- endif
- if PUSH_EDI eq 1
- POP_IT di
- endif
- if PUSH_EBX eq 1
- POP_IT bx
- endif
- else
- if PUSH_EBP eq 1
- POP_IT ebp
- endif
- if PUSH_ESI eq 1
- POP_IT esi
- endif
- if PUSH_EDI eq 1
- POP_IT edi
- endif
- if PUSH_EBX eq 1
- POP_IT ebx
- endif
- endif
- endm
-
- epilog macro r1
- POP_REGS
- if PUSH_COUNT eq 0
- else
- mov ax,ERROR ;YOU HAVE AN UNBALANCED STACK, FIX it or adjust PUSH_COUNT
- int PUSH_COUNT ; The number after int is how many bytes you are off
- endif
- if NO_BP_V eq 0
- pop ebp
- endif
- ifidn <r1>,<>
- return
- else
- return <r1>
- endif
- endm
-
- ; We would have preferred a procbeg and procend macro, but
- ; the "proc" directive can't go inside a macro -- yet another
- ; of the many bugs in the flaky Microsoft assembler.
- publab macro procname
- public _mw&procname
- _mw&procname:
- endm
- cseg macro segname,status
- name &segname
- ifb <status>
- _MW&segname segment dword 'CODE'
- else
- _MW&segname segment dword 'CODE' public
- endif
- assume cs:_MW&segname
- ifdef Small_code
- CGROUP group _MW&segname
- assume cs:CGROUP
- endif
- endm
- endcseg macro segname
- _MW&segname ends
- endm
- pubnames macro names
- irp name,<names>
- ifdef USING_MASM
- public _mw&&name
- else
- public _mw&name
- endif
- endm
- endm
- pubname macro name
- public _mw&name
- endm
- def macro x,y,z
- _mw&x y z
- endm
- defequ macro x,y,z
- _mw&x y z
- x equ _mw&x
- endm
- extequ macro x,type
- extrn _mw&x:type
- x equ _mw&x
- endm
- ext macro x,type
- extrn _mw&x:type
- endm
- ; Macros for parameter set-up that take care of small vs. large code
- ; and to some extent small vs. large data.
- ; Calling sequence:
- ; parms <<N1,T1>,<N2,T2>,...>
- ; where Ni are the names and Ti the types.
- ; This expands into
- ; Ni equ T1 ptr offset[bp]
- ; where offset starts at the appropriate value for a procedure
- ; (assuming BP has been pushed, and taking into account small vs lg code)
- ; and is incremented as follows:
- ; if Ti = "ptr" then increment by Ptr_size
- ; otherwise increment by 2.
- ; For example:
- ; parms <<Src,word>,<Dest,ptr>,<Cnt,word>>
- ; generates
- ; Src equ word ptr 6[bp]
- ; Dest equ dword ptr 8[bp]
- ; Cnt equ word ptr 12[bp]
- ; assuming parms start at 6.
-
- parm macro P,Type
- local Offset
- Offset equ Poff+0 ; +0 avoids alias; forces pass1 computation of expn.
- ifidn <Type>,<ptr> ; Type = "ptr"?
- ifdef Small_data
- if NO_BP_V eq 0
- P equ dword ptr Offset[ebp+Word_size]
- else
- P equ dword ptr Offset[esp+PUSH_COUNT]
- endif
- else
- if NO_BP_V eq 0
- P equ qword ptr Offset[ebp+Word_size]
- else
- P equ qword ptr Offset[esp+PUSH_COUNT]
- endif
- endif
- Poff = Poff + Ptr_size
- else
- ifidn <Type>,<routine> ; Type = "routine"?
- ifdef Small_code
- if NO_BP_V eq 0
- P equ word ptr Offset[ebp+Word_size]
- else
- P equ word ptr Offset[esp+PUSH_COUNT]
- endif
- else
- if NO_BP_V eq 0
- P equ dword ptr Offset[ebp+Word_size]
- else
- P equ dword ptr Offset[esp+PUSH_COUNT]
- endif
- endif
- Poff = Poff + Routine_size - Word_size ; DOES NOT skip link.
- else
- if NO_BP_V eq 0
- P equ Type ptr Offset[ebp+Word_size]
- else
- P equ Type ptr Offset[esp+PUSH_COUNT]
- endif
- Poff = Poff + Word_size
- endif
- endif
- endm
-
- parmreg macro P,Type,Offset
- ifidn <Type>,<ptr> ; Type = "ptr"?
- if NO_BP_V eq 0
- P equ dword ptr Offset[ebp+Word_size]
- else
- P equ dword ptr Offset[esp+PUSH_COUNT]
- endif
- else
- ifidn <Type>,<routine> ; Type = "routine"?
- if NO_BP_V eq 0
- P equ word ptr Offset[ebp+Word_size]
- else
- P equ word ptr Offset[esp+PUSH_COUNT]
- endif
- else
- if NO_BP_V eq 0
- P equ Type ptr Offset[ebp+Word_size]
- else
- P equ Type ptr Offset[esp+PUSH_COUNT]
- endif
- endif
- endif
- endm
-
- parms macro Parmlist
- Poff = Pbase ; ret addr + pushed bp.
- pdummy = 2
- irp P,<Parmlist>
- ; ife pdummy
- ; int 255
- ; parmreg P,-4
- ; else
- ; int 254
- ; ife pdummy-1
- ; int 253
- ; parmreg P,-8
- ; else
- ; int 252
- parm P
- ; endif
- ; endif
- pdummy = pdummy+1
- endm
- endm
-
- parm386 macro parmlist
- parms <parmlist>
- endm
- parm86 macro parmlist
- endm
-
- ; Load a pointer.
- ifdef Small_data
- loadptr macro Seginstr,Ireg,Operand
- mov Ireg,Operand
- endm
- else
- loadptr macro Seginstr,Ireg,Operand
- Seginstr Ireg,dword ptr Operand
- endm
- endif
-
- ; Load a formal routine parameter.
- ifdef Small_code
- loadrout macro Segreg,Ireg,Operand
- mov Ireg,Operand
- PUSH_IT cs
- POP_IT Segreg
- endm
- else
- loadrout macro Segreg,Ireg,Operand
- L&Segreg Ireg,dword ptr Operand
- endm
- endif
-
- ; Call a procedure.
- ifdef Small_code
- pcall macro procname
- ifdef USING_MASM
- call procname ; MASM 5.1 BUG!!
- ; MASM doesn't put out proper LEdata for the call below.
- else
- call CGROUP:(near ptr procname)
- endif
- endm
- else
- pcall macro procname
- call far ptr procname
- endm
- endif
-
- MWINT21 macro
- call _mwint21
- endm
-
- extrnf _mwint21
-
- ; For GOC, the constructor entries consist of a 4-byte order field, a
- ; 4-byte function address, and a 4-byte reserved field. For LOC, only
- ; the address is used.
- addinit macro i1
-
- _MWIFC segment public word 'DATA'
- _MWIFC ends
- _MWIMC segment public word 'DATA'
-
- ifdef GOC
- dd 128
- endif
-
- dd i1
-
- ifdef GOC
- dd 0
- endif
-
- _MWIMC ends
- _MWILC segment public word 'DATA'
- _MWILC ends
-
- endm
-
- adddest macro i1
-
- _MWDFC segment public word 'DATA'
- _MWDFC ends
- _MWDMC segment public word 'DATA'
-
- ifdef GOC
- dd 128
- endif
-
- dd i1
-
- ifdef GOC
- dd 0
- endif
-
- _MWDMC ends
- _MWDLC segment public word 'DATA'
- _MWDLC ends
-
- endm
-
-