****************************************************************************
*                    Modula-2 Software Construction Set                    *
****************************************************************************
* Filename: M2Lib.i                       Version: Amiga.00.00             *
* Created: 10/14/86   Updated: 01/27/87   Author: Leon Frenkel             *
* Desciption: Modula-2 Library Macros and equates                          *
****************************************************************************

	NOLIST
	SECTION	CODE_BLOCK,CODE
;---------------------------------------------------------------------------
; Usefull macros.
;---------------------------------------------------------------------------
AbsExecBase	equ	4

REFLIB	MACRO	<Function_Name>
	xref	_LVO\1
	ENDM

CALL	MACRO	<Function_Name>
	jsr	_LVO\1(A6)
	ENDM

;---------------------------------------------------------------------------
; Size of Modula-2 Types. Used when specifing variable type
;---------------------------------------------------------------------------
M2Type.INTEGER		EQU	2
M2Type.LONGINT		EQU	4
M2Type.CARDINAL		EQU	2
M2Type.LONGCARD		EQU	4
M2Type.REAL		EQU	4
M2Type.CHAR		EQU	1
M2Type.BOOLEAN		EQU	1
M2Type.ENUMERATION	EQU	1
M2Type.BITSET		EQU	2
M2Type.BYTE_SET		EQU	1
M2Type.WORD_SET		EQU	2
M2Type.LONG_SET		EQU	4
M2Type.ADDRESS		EQU	4
M2Type.POINTER		EQU	4
M2Type.PROCEDURE	EQU	4
M2Type.BYTE		EQU	1
M2Type.WORD		EQU	2
M2Type.LONGWORD		EQU	4
M2Type.ARRAY_OF		EQU	6

;---------------------------------------------------------------------------
; VAR_MODE:  PARAMETERS - Expecting Procedure Parameters
;            VARIABLES - Expecting local or global variables
;---------------------------------------------------------------------------
VAR_MODE.PARAMETERS	EQU	1
VAR_MODE.VARIABLES	EQU	2
VAR_MODE		SET	0

;---------------------------------------------------------------------------
; VAR - define a variable. This macro is used for defining global variables,
;  local variables or procedure parameters.
; TCOUNT = <Count> | 0
; TSIZE = <Type_Size>
; IF VAR_MODE = PARAMETERS AND TSIZE = 1 AND TCOUNT = 0 THEN 
;    VAR_OFFSET = VAR_OFFSET - 1
; END;
; IF TCOUNT = 0 THEN
;    IF TSIZE > 1 THEN Word_Align(VAR_OFFSET) END;
;    VAR_OFFSET = VAR_OFFSET - TSIZE
; END;
; IF TCOUNT # 0 THEN
;    VAR_OFFSET = Word_Align(VAR_OFFSET)
;    VAR_OFFSET = VAR_OFFSET - (TSIZE * TCOUNT)
;    VAR_OFFSET = Word_Align(VAR_OFFSET)
; END;
; <Identifier> = VAR_OFFSET
;---------------------------------------------------------------------------
VAR	MACRO	<Identifier>,<Type_Size>,<Count>
TCOUNT	SET	\3-0
TSIZE	SET	M2Type.\2

	IFEQ	(VAR_MODE-VAR_MODE.PARAMETERS)!(TSIZE-1)!TCOUNT
VAR_OFFSET	SET	VAR_OFFSET-1
	ENDC

	IFEQ	TCOUNT
	 IFGT	TSIZE-1
VAR_OFFSET	SET	(VAR_OFFSET&$FFFFFFFE)
	 ENDC
VAR_OFFSET	SET	VAR_OFFSET-(TSIZE)
	ENDC

	IFNE	TCOUNT
VAR_OFFSET	SET	(VAR_OFFSET&$FFFFFFFE)
VAR_OFFSET	SET	VAR_OFFSET-(TSIZE*TCOUNT)
VAR_OFFSET	SET	(VAR_OFFSET&$FFFFFFFE)
	ENDC

\1	EQU	VAR_OFFSET
	ENDM

;---------------------------------------------------------------------------
; NEXT_MODULE_STATE - Utility macro used in module definition macros to 
;  insure that the definition is proceeding correctly!
;---------------------------------------------------------------------------
NEXT_MODULE_STATE	MACRO	<New State>
MODULE_STATE	SET	MODULE_STATE+1
	IFNE	MODULE_STATE-\1
	FAIL	Error: INCORECT MODULE DESCRIPTION SEQUENCE!
	ENDC
	ENDM

;---------------------------------------------------------------------------
; DEFINITION_PROCEDURES - Procedures Defined in the Definition Part of the
;  module.
;---------------------------------------------------------------------------
DEFINITION_PROCEDURES	MACRO	<Procedures>
MODULE_STATE	SET	0
	NEXT_MODULE_STATE	1

DEF_NEXT_PROC		SET	0
DEF_PROCEDURE_COUNT	EQU	\1+1
	ENDM

;---------------------------------------------------------------------------
; DEF_PROC - Create an equate PROC_<Procedure_Name> and assign it the
;  next procedure number.
;---------------------------------------------------------------------------
DEF_PROC	MACRO	<Procedure_Name>
PROC_\1		EQU	DEF_NEXT_PROC
DEF_NEXT_PROC	SET	DEF_NEXT_PROC+1
	ENDM

;---------------------------------------------------------------------------
; DEFINITION_MODULES - Modules Imported by the Definition Part of the module.
;  After this macro may follow a series of IMPORT macros 
;---------------------------------------------------------------------------
DEFINITION_MODULES	MACRO	<Modules>
	NEXT_MODULE_STATE	2
DEF_NEXT_MODULE		SET	1
DEF_MODULE_COUNT	EQU	\1+1
	ENDM

;---------------------------------------------------------------------------
; IMPORT - Create a module number to refrence an imported module.
;---------------------------------------------------------------------------
IMPORT	MACRO	<Module_Name>
MODULE_\1	EQU	DEF_NEXT_MODULE
DEF_NEXT_MODULE	SET	DEF_NEXT_MODULE+1
	ENDM

;---------------------------------------------------------------------------
; DEFINITION_VARIABLES - After this macro a list of variable follows which
;  corresponds to the variables defined in the definition module.
;---------------------------------------------------------------------------
DEFINITION_VARIABLES	MACRO
	NEXT_MODULE_STATE	3
VAR_OFFSET	SET	0
VAR_MODE	SET	VAR_MODE.VARIABLES
	ENDM

;---------------------------------------------------------------------------
; IMPLEMENTATION_VARIABLES - After this macro a list of variables follows which
;  correspnds to the variables defined in the implementation module.
;---------------------------------------------------------------------------
IMPLEMENTATION_VARIABLES	MACRO
	NEXT_MODULE_STATE	4
DEF_VAR_SIZE	EQU	-VAR_OFFSET
	ENDM

;---------------------------------------------------------------------------
; START_CODE - Start of code for procedures. Create a HEADER_BLOCK, DATA_BLOCK,
;  and CODE_BLOCK.
;---------------------------------------------------------------------------
START_CODE	MACRO
	NEXT_MODULE_STATE	5
IMP_VAR_SIZE	EQU	(-VAR_OFFSET)-DEF_VAR_SIZE

	SECTION	HEADER_BLOCK,DATA
	dc.W	CODE_BLOCK_END-CODE_BLOCK_START
	dc.W	DEF_VAR_SIZE
	dc.W	IMP_VAR_SIZE
	dc.W	DEF_PROCEDURE_COUNT
	dc.W	DEF_MODULE_COUNT

	SECTION	DATA_BLOCK,DATA
PROCEDURE_OFFSET_TABLE_START	ds.W	DEF_PROCEDURE_COUNT

	SECTION	CODE_BLOCK,CODE

MODULE_BASE		EQU	*
CODE_BLOCK_START 	EQU	*
	nop
	nop
	ENDM

;---------------------------------------------------------------------------
; PROCEDURE_CODE - Begining of the implementation of an exported procedure.
;  ALLOC_LOCAL_VAR - can be used as link A6,#ALLOC_LOCAL_VAR to allocate
;  space for local variables. Store offset of procedure into DATA_BLOCK.
;---------------------------------------------------------------------------
PROCEDURE_CODE	MACRO	<Procedure Name>
ALLOC_LOCAL_VAR	SET	(VAR_OFFSET&$FFFFFFFE)
CURRENT_RORG	SET	*
	SECTION	DATA_BLOCK,DATA
	RORG	PROCEDURE_OFFSET_TABLE_START+(PROC_\1*2)
	dc.W	CURRENT_RORG-CODE_BLOCK_START
	SECTION	CODE_BLOCK,CODE
	RORG	CURRENT_RORG
	ENDM

;---------------------------------------------------------------------------
; PARAMETER_LIST - This macro begins a procedure's parameter list.
;  <Base_Offset> is the first offset at which the parameters begin and go
;    up in the stack.
;---------------------------------------------------------------------------
PARAMETER_LIST	MACRO	<Base_Offset>,<Parameter_Size>
VAR_OFFSET		SET	\1+\2
VAR_MODE		SET	VAR_MODE.PARAMETERS
PARAMETER_BASE_OFFSET	SET	\1
POP_PARAMETER_SIZE	SET	\2
RETURN_ADR_OFFSET	SET	VAR_OFFSET-4
	ENDM

;---------------------------------------------------------------------------
; END_PARAMETER_LIST - macro placed after last parameter variable specified
;  this macro is used for error checking purposes!
;---------------------------------------------------------------------------
END_PARAMETER_LIST	MACRO
	IFLT	PARAMETER_BASE_OFFSET-VAR_OFFSET
	FAIL	Error: Parameter_Size Specified is Too Large!
	ENDC

	IFGT	PARAMETER_BASE_OFFSET-VAR_OFFSET
	FAIL	Error: Parameter_Size Specified is Too Small!
	ENDC
	ENDM

;---------------------------------------------------------------------------
; LOCAL_VARIABLES - This macro begins a procedures local variables
;---------------------------------------------------------------------------
LOCAL_VARIABLES	MACRO	
VAR_OFFSET	SET	0
VAR_MODE	SET	VAR_MODE.VARIABLES
	ENDM

;---------------------------------------------------------------------------
; JUMP - this macro is used to setup for a call to a library function in
;  such a way that a return from the library function will cause a return
;  directly to the program rather than the glue routine.
;---------------------------------------------------------------------------
JUMP	MACRO	<Function_Name>
	IFGT	POP_PARAMETER_SIZE
	IFLE	POP_PARAMETER_SIZE-8
	move.L	(SP),RETURN_ADR_OFFSET(SP)
	addq.L	#POP_PARAMETER_SIZE,SP
	ENDC

	IFGT	POP_PARAMETER_SIZE-8
	move.L	(SP),RETURN_ADR_OFFSET(SP)
	lea	POP_PARAMETER_SIZE(SP),SP
	ENDC
	ENDC

	jmp	_LVO\1(A6)
	ENDM

;---------------------------------------------------------------------------
; RETURN - Procedure Return Macro
;---------------------------------------------------------------------------
RETURN	MACRO
	IFEQ	POP_PARAMETER_SIZE
	rts
	MEXIT
	ENDC

	IFLE	POP_PARAMETER_SIZE-8
	move.L	(SP)+,A0
	addq.L	#POP_PARAMETER_SIZE,SP
	jmp	(A0)
	MEXIT
	ENDC

	move.L	(SP)+,A0
	lea	POP_PARAMETER_SIZE(SP),SP
	jmp	(A0)

	ENDM

;---------------------------------------------------------------------------
; END_CODE - End of code. Force to word boundary
;---------------------------------------------------------------------------
END_CODE	MACRO
	NEXT_MODULE_STATE	6
	CNOP	0,2
CODE_BLOCK_END		EQU	*
	ENDM

;---------------------------------------------------------------------------
; EMPTY_MODULE_BODY - Create the shortest possible module body.
;---------------------------------------------------------------------------
EMPTY_MODULE_BODY	MACRO
	rts
	ENDM

;---------------------------------------------------------------------------
; MODULE_BODY_LINK_LIBRARY_BASE - Generate module body code to get the library
;  base from the System Module.
; A4 - assumed to have module base of "System"
;---------------------------------------------------------------------------
MODULE_BODY_LINK_LIBRARY_BASE	MACRO	<Library_Base_Name>
	lea	MODULE_BASE(PC),A0
	move.L	Sys_\1(A4),\1(A0)
	rts
	ENDM

	LIST
