Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/kcc5/c-asmh.c
There are no other files named c-asmh.c in the archive.
/*
** C-ASMH.C   - KCC Assembler Header file
**
**	Copyright (c) 1986 by Ken Harrenstien, SRI International
**
** This file is run through KCC's preprocessor using the -E switch
** in order to generate the standard C-ASMH file which KCC inserts
** automatically, without parsing, at the beginning of all its assembler
** output files (just after any ENTRY or TITLE statements).
**
** Any independent assembler modules intended for use with KCC programs
** should also .INSERT C-ASMH; however, such modules are very, very strongly
** discouraged in favor of using #asm or asm().
**
** Keep all comments herein in slash-star form (rather than semicolons)
** so the assembler doesn't have to look at them again.
*/

#include "c-env.h"		/* Insert our configuration parameters! */

/* The header for both FAIL and MACRO is identical.
** However, MIDAS requires a radically different syntax, and for this reason
** the following switches exist to produce a MIDAS-suitable header if defined.
*/
#ifndef ASM_FAIL
#define ASM_FAIL 0
#endif
#ifndef ASM_MACRO
#define ASM_MACRO 0
#endif
#ifndef ASM_MIDAS
#define ASM_MIDAS 0
#endif
#if !(ASM_FAIL+ASM_MACRO+ASM_MIDAS)
#undef ASM_FAIL
#define ASM_FAIL 1			/* Default is FAIL (and MACRO) */
#endif

/* Define various preprocessor macros to help compensate for differences
** in the way the assemblers define THEIR macros.
*/
#if ASM_FAIL+ASM_MACRO
#define macdef0(name)		DEFINE name
#define macdef1(name,arg1)	DEFINE name(arg1)
#define macdef2(name,arg1,arg2)	DEFINE name(arg1,arg2)
#define macbeg <
#define macend >
#elif ASM_MIDAS
#define macdef0(name)		DEFINE name
#define macdef1(name,arg1)	DEFINE name arg1
#define macdef2(name,arg1,arg2)	DEFINE name arg1,arg2
#define macbeg
#define macend TERMIN
#endif
/* Define assembler macros to help compensate for CPU differences. */
#if CENV_DMOVX==0
macdef2(DMOVE, AC,MEM)
macbeg	MOVE	AC,MEM
	MOVE	AC+1,1+MEM
macend

macdef2(DMOVEM, AC,MEM)
macbeg	MOVEM	AC,MEM
	MOVEM	AC+1,1+MEM
macend
#endif /* No DMOVx */

#if CENV_ADJSP==0
macdef2(ADJSP, AC,CONST)
macbeg	ADD	AC,[<CONST,,CONST>+<CONST&<-1,,0>>]
macend
#endif /* No ADJSP */

/*
** Byte pointer operations.
**
** ADJBP AC,MEM
**    takes a byte count in AC and a byte pointer of any shape in MEM,
**    and leaves a byte pointer shifted over by the count in the AC.
**
** %CHRBP AC,MEM
**    backs up the byte pointer in MEM by one and leaves it in AC.
**    This is often used in the runtimes to produce an ILDB pointer
**    from an IBP pointer.  The result may not quite be the same as
**    corresponding AC -- it may be a (POINT n,X) pointer i.e. have
**    a P field of 44 -- so only do this once and don't index through
**    the result or compare it to another non-%CHRBP pointer.
*/

#if CENV_ADJBP
#if ASM_FAIL+ASM_MACRO
	OPDEF	ADJBP	[IBP]	/* ADJBP is same as IBP on KS/KL */
#endif
macdef2(%CHRBP, TOAC,FRMBP)	/* Turn LDB pointer into ILDB pointer: */
macbeg	SETO	TOAC,		/* Get -1 */
	ADJBP	TOAC,FRMBP	/* And do ADJBP */
macend

#else	/* No ADJBP */

macdef2(ADJBP, AC,MEM)		/* No ADJBP, simulate: */
macbeg	EXTERN	$ADJBP		/* Declare extern routine to simulate it */
	MOVE	16,MEM		/* Do this before EXCH.  Get byte pointer */
	EXCH	15,AC		/* Put count into expected reg, save AC15 */
	PUSHJ	17,$ADJBP	/* Call $ADJBP to simulate byte ptr add */
	EXCH	15,AC		/* restore AC15 and get adjusted bp in reg */
macend
macdef2(%CHRBP, TOAC,FRMBP)	/* Expand call to $ADJBP for special case: */
macbeg	MOVE	TOAC,FRMBP	/* Get byte pointer */
	ADD	TOAC,[110000,,0] /* Adjust assuming 9-bit bytes */
	TLNN	TOAC,007000	/* Was it 7-bit byte pointer? */
	 SUB	TOAC,[020000,,0] /* Yes, fix up for that case */
macend
#endif /* No ADJBP */
#if CENV_DFL_S		/* Software double-precision instructions */

/*
** KA-10 Double-Precision Floating Point (software format)
**
** Copied from:
**    DEC Assembly Language Handbook, 1st edition, 1972
**    PDP-10 System Reference Manual  DEC-10-HGAC-D
**	3rd printing August 1969
**	Page 2-67, "Programming Examples".
**
** NOTE!  These macros require 3 registers, not just 2!
** We can save things in AC16 and be sure that A+2 is free
** (KCC reserves AC16 as a temporary for just such purposes).
** We never use doublewords beyond 14/15 so A+2 always exists.
**
** Some of these sequences are less than efficient, but they
** have to be sufficiently general to cover all possible abuses
** (e.g. unexpected registers used as indices in addresses).
*/

macdef2(%DSAVE, A,M)		/* Set up A+2/free, M into -2(17)/-1(17): */
macbeg	MOVE	16,1+M		/* Get low word (push here would mess up M) */
	PUSH	17,M		/* Now safe to push high word */
	PUSH	17,16		/* Followed by low word (careful if A+2==16) */
	PUSH	17,A+2		/* Followed by AC to be freed */
macend
macdef0(%DREST)			/* Restore at end of double op after %DSAVE: */
macbeg	POP	17,A+2		/* Get saved register back */
	ADJSP	17,-2		/* Forget about pushed copy of doubleword */
macend
macdef2(DMOVN, A,M)		/* Get double from memory and negate: */
macbeg	DMOVE	A,M		/* Get double using previously defined macro */
	DFN	A,A+1		/* Do double register negate */
macend
macdef2(DMOVNM, A,M)		/* Save negated doubleword into memory: */
macbeg	DFN	A,A+1		/* Negate register doubleword */
	MOVEM	A,M		/* Save high part of negated word into mem */
	MOVEM	A+1,1+M		/* Save low part */
	DFN	A,A+1		/* Negate reg again to leave the way it was */
macend
macdef2(DFAD, A,M)		/* Add two doubles: */
macbeg	%DSAVE	A,M		/* Set up for doubleword op */
	UFA	A+1,-1(17)	/* Sum of low parts to A+2 */
	FADL	A,-2(17)	/* Sum of high parts to A,A+1 */
	UFA	A+1,A+2		/* Add low part of high sum to A+2 */
	FADL	A,A+2		/* Add low sum to high sum */
	%DREST			/* Fix up after doubleword op */
macend
macdef2(DFSB, A,M)		/* Subtract double in mem from one in acs: */
macbeg	DFN	A,A+1		/* Negate double length operand */
	DFAD	A,M		/* Perform normal add */
	DFN	A,A+1		/* -(M - AC) = AC - M */
macend
macdef2(DFMP, A,M)		/* Multiply two doubles: */
macbeg	%DSAVE	A,M		/* Set up for doubleword op */
	MOVEM	A,A+2		/* Copy high AC operand in A+2 */
	FMPR	A+2,-1(17)	/* High reg times low mem to A+2 */
	FMPR	A+1,-2(17)	/* Low reg times high mem to A+1 */
	UFA	A+1,A+2		/* Add cross products into A+2 */
	FMPL	A,-2(17)	/* High product to A,A+1 */
	UFA	A+1,A+2		/* Add low part to cross sum in A+2 */
	FADL	A,A+2		/* Add low sum to high part of product */
	%DREST			/* Fix up after doubleword op */
macend
macdef2(DFDV, A,M)		/* Divide double in acs by one in mem: */
macbeg	%DSAVE	A,M		/* Set up for complicated double op */
	FDVL	A,-2(17)	/* Get high part of quotient */
	MOVN	A+2,A		/* Copy negative of quotient in A+2 */
	FMPR	A+2,-1(17)	/* Multiply by low part of divisor */
	UFA	A+1,A+2		/* Add remainder */
	FDVR	A+2,-2(17)	/* Divide sum by high part of divisor */
	FADL	A,A+2		/* Add result to original quotient */
	%DREST			/* Fix up after doubleword op */
macend
#endif /* CENV_DFL_S */
/*
** Some more opcode definitions.
**
** ERJMP and ERJMPA are for TOPS-20 and TENEX sites only.
** ERJMPA should be used instead of ERJMP when the JSYS normally skips.
**
** XMOVEI, and IFIW are for KL-10B extended addressing.
** We might also define XHLLI here but I've yet to see a correct use.
*/

#if ASM_FAIL+ASM_MACRO
#if SYS_T20+SYS_10X
	IFNDEF	ERJMP,< OPDEF ERJMP [JUMP 16,] >
#if SYS_T20
	OPDEF	ERJMPA	[ERJMP]
#else
	OPDEF	ERJMPA	[JUMPA 16,]
#endif
#endif
	OPDEF	XMOVEI	[SETMI]
	DEFINE	IFIW	<SETZ >

#elif ASM_MIDAS

#if SYS_T20
	ERJMPA==<ERJMP>
#else
	ERJMPA==<JUMPA 16,>
#endif
	IFIW==<SETZ>
#endif

/*
** Data segmentation.
**
** KCC emits code in two sections: code and data.  This file sets things up
** so that code and data are in the high and low segments, which typically
** correspond to the high and low halves of their section but which can be
** rearranged by the appropriate LINK directives.
**
** Code and data are separated in the assembly output by the %%CODE and %%DATA
** macros.  %%CODE will never be called from any context other than the data
** segment, and vice versa.  KCC expects the header to initially be in code.
*/
#if ASM_FAIL+ASM_MACRO
	TWOSEG	400000	    	/* Set up for pure and impure segments */
	RELOC	0
	RELOC	400000		/* Begin in the pure segment */
	DEFINE %%CODE <RELOC>
	DEFINE %%DATA <RELOC>
#elif ASM_MIDAS
	.DECTWO 400000
	$$RLO==.
	.=.+400000	/* Go into code seg */
	$$RHI==.
DEFINE %%CODE
$$RLO==. ? .=$$RHI	/* Remember current lowseg loc, switch to hiseg */
TERMIN
DEFINE %%DATA
$$RHI==. ? .=$$RLO	/* Remember current hiseg loc, switch to lowseg */
TERMIN
#endif

/*
** Finally, we try to purge symbols which may conflict with user-defined syms.
** However, there is a bug in FAIL which causes SEARCH MONSYM to barf
** ("FAIL BUG IN SEARCH") if the SEARCH comes after the IF's are purged!
** But if we put the SEARCH here, before the PURGE, we are including it in ALL
** KCC output, which is not a good idea; there is more overhead, and
** otherwise undefined symbols might be unexpectedly satisfied from MONSYM!
** For the time being, since FAIL will output a .REL file anyway even after
** barfing about the SEARCH, we will continue doing this, and include a
** note in the doc to ignore those barfs, and hope someone fixes FAIL someday.
**
** Note that MACRO will not complain, and consequently MACRO is preferred
** when compiling modules with #asm code (such as the C library!)
*/
#if ASM_FAIL+ASM_MACRO
	PURGE	IFE,IFN,IFG,IFGE,IFL,IFLE,IFDEF,IFNDEF,IFIDN,IFDIF
#elif ASM_MIDAS
	EXPUNGE	IFE,IFN,IFG,IFGE,IFL,IFLE,IFDEF,IFNDEF,IFIDN,IFDIF
#endif

/* End of C-ASMH.C */