;===========================================================================
; File:  L4ASM.inc
; Project: MUNGA
; Contents: Assembler-dependent macros
;---------------------------------------------------------------------------
;   Date    Who  Modification
; --------  ---  -----------------------------------------------------------
; 03/01/95  CPB  Initial coding
;---------------------------------------------------------------------------
; Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved
;                      PROPRIETARY and CONFIDENTIAL
;===========================================================================
.xcref
?insideprocdef = 0
?insidelocal = 0

;-----------------------------------------------------------------
; Generate assembler error message, stop assembly   
;-----------------------------------------------------------------   
.xcref ?error
?error macro msg
   %out E R R O R ----- msg
   .err
endm

   .386p
	.model flat,c		;; just now added ,c

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
; HIDEOUS UGLY HACK to get around borland bug!!!!!!!!!!!!!
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ifndef __WATCOMC__
   __BCPLUSPLUS__ = 1
endif

;-----------------------------------------------------------------
; Begin the data segment   
;-----------------------------------------------------------------   
BEGIN_DATA MACRO
   _DATA SEGMENT DWORD USE32
ENDM

;-----------------------------------------------------------------
; End the data segment   
;-----------------------------------------------------------------   
END_DATA MACRO
   _DATA ENDS
ENDM

;-----------------------------------------------------------------
; Begin the code segment   
;-----------------------------------------------------------------   
BEGIN_CODE MACRO
   _TEXT SEGMENT DWORD USE32
ENDM
;-----------------------------------------------------------------
; End the code segment   
;-----------------------------------------------------------------   
END_CODE MACRO
   if ?insideprocdef
      ?error <missing 'END_C_PROC'>
   endif

   _TEXT ENDS
ENDM

;-----------------------------------------------------------------
; Parse/Save/Restore multiple registers   
;-----------------------------------------------------------------   
?ax  = 0000000000000001b
?eax = 0000000000000010b
?bx  = 0000000000000100b
?ebx = 0000000000001000b
?cx  = 0000000000010000b
?ecx = 0000000000100000b
?dx  = 0000000001000000b
?edx = 0000000010000000b
?si  = 0000000100000000b
?esi = 0000001000000000b
?di  = 0000010000000000b
?edi = 0000100000000000b
?ds  = 0001000000000000b
?es  = 0010000000000000b
?fs  = 0100000000000000b
?gs  = 1000000000000000b


BUILDREGS MACRO reglist,bitval
   ifb <reglist>
      exitm
   endif

   irp areg,<reglist>
      ifidni <areg>,<AX> 
         bitval = bitval or ?ax
      elseifidni <areg>,<EAX> 
         bitval = bitval or ?eax 
      elseifidni <areg>,<BX> 
         bitval = bitval or ?bx  
      elseifidni <areg>,<EBX>
         bitval = bitval or ?ebx  
      elseifidni <areg>,<CX>
         bitval = bitval or ?cx  
      elseifidni <areg>,<ECX>
         bitval = bitval or ?ecx  
      elseifidni <areg>,<DX>
         bitval = bitval or ?dx  
      elseifidni <areg>,<EDX>
         bitval = bitval or ?edx  
      elseifidni <areg>,<SI>
         bitval = bitval or ?si  
      elseifidni <areg>,<ESI>
         bitval = bitval or ?esi  
      elseifidni <areg>,<DI>
         bitval = bitval or ?di  
      elseifidni <areg>,<EDI>
         bitval = bitval or ?edi  
      elseifidni <areg>,<DS>
         bitval = bitval or ?ds  
      elseifidni <areg>,<ES>
         bitval = bitval or ?es  
      elseifidni <areg>,<FS>
         bitval = bitval or ?fs  
      elseifidni <areg>,<GS>
         bitval = bitval or ?gs  
      else
         ?error <Illegal register &areg&>
      endif
   endm
ENDM

PUSHREGS MACRO bits
   if (bits and ?ax)
      push    ax  
   endif
   if (bits and ?eax)
      push    eax
   endif
   if (bits and ?bx)
      push    bx
   endif
   if (bits and ?ebx)
      push    ebx
   endif
   if (bits and ?cx)
      push    cx
   endif
   if (bits and ?ecx)
      push    ecx
   endif
   if (bits and ?dx)
      push    dx
   endif
   if (bits and ?edx)
      push    edx
   endif
   if (bits and ?si)
      push    si
   endif
   if (bits and ?esi)
      push    esi
   endif
   if (bits and ?di)
      push    di
   endif
   if (bits and ?edi)
      push    edi
   endif
   if (bits and ?ds)
      push    ds
   endif
   if (bits and ?es)
      push    es
   endif
   if (bits and ?fs)
      push    fs
   endif
   if (bits and ?gs)
      push    gs
   endif
ENDM   

POPREGS MACRO bits
   if (bits and ?gs)
      pop gs
   endif
   if (bits and ?fs)
      pop fs
   endif
   if (bits and ?es)
      pop es
   endif
   if (bits and ?ds)
      pop ds
   endif
   if (bits and ?edi)
      pop edi
   endif
   if (bits and ?di)
      pop di
   endif
   if (bits and ?esi)
      pop esi
   endif
   if (bits and ?si)
      pop si
   endif
   if (bits and ?edx)
      pop edx
   endif
   if (bits and ?dx)
      pop dx
   endif
   if (bits and ?ecx)
      pop ecx
   endif
   if (bits and ?cx)
      pop cx
   endif
   if (bits and ?ebx)
      pop ebx
   endif
   if (bits and ?bx)
      pop bx
   endif
   if (bits and ?eax)
      pop eax
   endif
   if (bits and ?ax)
      pop ax  
   endif
ENDM   

;-----------------------------------------------------------------
; Begin a public "C" accessable routine   
;-----------------------------------------------------------------   
BEGIN_C_PROC MACRO name,regs

   if ?insideprocdef
      ?error <missing 'END_C_PROC'>
   endif

   ifdef __BCPLUSPLUS__
;;      _&name& PROC C NEAR
		name PROC C NEAR
;;		PUBLIC _&name&
		PUBLIC name

      ENDNAME &macro
;;			_&name& &ENDP
			name &ENDP
		&endm
   endif

   ifdef __WATCOMC__
      &name&_ PROC C NEAR     ; NOTE no trailing '_' for stack-based fcn!
      PUBLIC &name&_

      ENDNAME &macro
         &name&_ &ENDP
      &endm
   endif

   ?argoffset = 8
   ?localoffset = 0
   ?regbits = 0
   ?insideprocdef = 1
   ?stackframerequired = 0
   ?stackframebuilt = 0
   BUILDREGS <regs>,<?regbits>
ENDM

;-----------------------------------------------------------------
; Declare an input parameter   
;-----------------------------------------------------------------
?DEF_ARG1 macro argname,argtype,ofst
   argname EQU <argtype ss:&ofst&[ebp]>
   ?stackframerequired = 1
endm

?DEF_ARG macro argname,argtype,argsize
   ife ?insideprocdef
      ?error <parameter "&argname" declared outside proc def>
   else
      .xcref
      ?DEF_ARG1 argname,<argtype>,%?argoffset
      ?argoffset = ?argoffset+argsize
      .cref
   endif
endm

ARG_BYTE macro n
      ?DEF_ARG <n>,<byte ptr>,4      ;; NOTE: promoted to 32-bit INT
ENDM

ARG_WORD macro n
?DEF_ARG <n>,<word ptr>,4            ;; NOTE: promoted to 32-bit INT
endm

ARG_DWORD macro n
		?DEF_ARG <n>,<dword ptr>,4     ;; NOTE: promoted to 32-bit INT
endm

ARG_CPTR macro n
		?DEF_ARG <n>,<dword ptr>,4     ;; NOTE: promoted to 32-bit INT
endm

ARG_DPTR macro n
		?DEF_ARG <n>,<dword ptr>,4     ;; NOTE: promoted to 32-bit INT
endm

;-----------------------------------------------------------------
; Declare a local variable   
;-----------------------------------------------------------------
?DEF_LOCAL1 macro lname,argtype,ofst
   lname EQU <argtype ss:-&ofst&[ebp]>
   ?stackframerequired = 1
endm

?DEF_LOCAL macro localname,localtype,localsize
   ife ?insideprocdef
      ?error <local "&localname" declared outside local definition block>
   else
      .xcref
      ?localoffset = ?localoffset+localsize
      ?DEF_LOCAL1 localname,<localtype>,%?localoffset
      .cref
   endif
endm

LOCAL_BYTE macro n
   ?DEF_LOCAL <n>,<byte ptr>,4
endm

LOCAL_WORD macro n
   ?DEF_LOCAL <n>,<word ptr>,4
endm

LOCAL_DWORD macro n
   ?DEF_LOCAL <n>,<dword ptr>,4
endm

LOCAL_CPTR macro n
   ?DEF_LOCAL <n>,<dword ptr>,4
endm

LOCAL_DPTR macro n
   ?DEF_LOCAL <n>,<dword ptr>,4
endm

BUILD_STACK_FRAME macro
   ife ?insideprocdef
      ?error <stack frame declared outside proc def>
   else
      ENTER ?localoffset,0
      PUSHREGS ?regbits
      ?stackframebuilt = 1
   endif
ENDM

;-----------------------------------------------------------------
; End a public "C" accessable routine   
;-----------------------------------------------------------------
END_C_PROC MACRO
   ife ?insideprocdef
      ?error <'END_C_PROC' mismatch>
   else
      if ?stackframerequired
         ife ?stackframebuilt
            ?error <'BUILD_STACK_FRAME' required in procedure>
         endif
      endif

      POPREGS ?regbits
      if ?stackframebuilt
         LEAVE
  endif
      ret

      ENDNAME
      purge ENDNAME
      ?insideprocdef = 0
	endif
ENDM


