xref: /csrg-svn/old/as.vax/as.h (revision 13523)
15829Srrh /*
25829Srrh  *	Copyright (c) 1982 Regents of the University of California
3*13523Srrh  *	@(#)as.h 4.17 06/30/83
45829Srrh  */
55829Srrh #define	reg	register
65829Srrh 
7635Shenry #include <sys/types.h>
8*13523Srrh #include <a.out.h>
9*13523Srrh #include <stab.h>
10635Shenry 
11601Sbill #define readonly
12601Sbill #define	NINST		300
13601Sbill 
14601Sbill #define	NEXP		20	/* max number of expr. terms per instruction */
15601Sbill #define	NARG		6	/* max number of args per instruction */
16601Sbill #define	NHASH		1103	/* hash table is dynamically extended */
17626Shenry #define	TNAMESIZE	32	/* maximum length of temporary file names */
18601Sbill #define	NLOC		4	/* number of location ctrs */
1913461Srrh /*
2013461Srrh  *	Sizes for character buffers.
2113461Srrh  *	what			size #define name	comments
2213461Srrh  *
2313461Srrh  *	source file reads	ASINBUFSIZ		integral of BUFSIZ
2413461Srrh  *	string assembly		NCPString		large for .stabs
25*13523Srrh  *	name assembly		NCPName
2613461Srrh  *	string save		STRPOOLDALLOP
2713461Srrh  *
2813461Srrh  *
2913461Srrh  *	-source file reads should be integral of BUFSIZ for efficient reads
3013461Srrh  *	-string saving is a simple first fit
3113461Srrh  */
3213461Srrh #ifndef ASINBUFSIZ
3313461Srrh #	define	ASINBUFSIZ	4096
3413461Srrh #endif not ASINBUFSIZ
3513461Srrh #ifndef STRPOOLDALLOP
3613461Srrh #	define STRPOOLDALLOP	8192
3713461Srrh #endif not STRPOOLDALLOP
3813461Srrh #ifndef NCPString
3913461Srrh #	define	NCPString	4080
4013461Srrh #endif not NCPString
41601Sbill 
4213461Srrh #define	NCPName	NCPS
43*13523Srrh #ifndef NCPS
44*13523Srrh #	undef	NCPName
45*13523Srrh #	define	NCPName	4096
46*13523Srrh #endif not NCPS
47601Sbill /*
4813461Srrh  *	Check sizes, and compiler error if sizes botch
4913461Srrh  */
5013466Srrh #if ((STRPOOLDALLOP < NCPString) || (STRPOOLDALLOP < NCPName))
5113461Srrh 	$$$botch with definition sizes
5213461Srrh #endif test botches
5313461Srrh /*
54601Sbill  * Symbol types
55601Sbill  */
56601Sbill #define	XUNDEF	0x0
57601Sbill #define	XABS	0x2
58601Sbill #define	XTEXT	0x4
59601Sbill #define	XDATA	0x6
60601Sbill #define	XBSS	0x8
61601Sbill 
62601Sbill #define	XXTRN	0x1
63601Sbill #define	XTYPE	0x1E
64601Sbill 
65601Sbill #define	XFORW	0x20	/* Was forward-referenced when undefined */
66601Sbill 
67601Sbill #define	ERR	(-1)
68601Sbill #define	NBPW	32	/* Bits per word */
69601Sbill 
70601Sbill #define	AMASK	017
71601Sbill 
72601Sbill /*
73601Sbill  * Actual argument syntax types
74601Sbill  */
75626Shenry #define	AREG	1	/* %r */
76626Shenry #define	ABASE	2	/* (%r) */
77626Shenry #define	ADECR	3	/* -(%r) */
78626Shenry #define	AINCR	4	/* (%r)+ */
79626Shenry #define	ADISP	5	/* expr(%r) */
80626Shenry #define	AEXP	6	/* expr */
81626Shenry #define	AIMM	7	/* $ expr */
82626Shenry #define	ASTAR	8	/* * */
83626Shenry #define	AINDX	16	/* [%r] */
84601Sbill /*
855829Srrh  *	Definitions for the things found in ``instrs''
86601Sbill  */
875829Srrh #define	INSTTAB 1
885829Srrh #include "instrs.h"
89601Sbill 
90601Sbill /*
915829Srrh  *	Tells outrel what it is relocating
925829Srrh  *	RELOC_PCREL is an implicit argument to outrel; it is or'ed in
935829Srrh  *	with a TYPX
94601Sbill  */
955829Srrh #define	RELOC_PCREL	(1<<TYPLG)
96672Shenry /*
97672Shenry  *	reference types for loader
98672Shenry  */
99626Shenry #define	PCREL	1
100626Shenry #define	LEN1	2
101626Shenry #define	LEN2	4
102626Shenry #define	LEN4	6
103626Shenry #define	LEN8	8
1045829Srrh #define	LEN16	10
105601Sbill 
106672Shenry extern	int	reflen[];	/* {LEN*+PCREL} ==> number of bytes */
107672Shenry extern	int	lgreflen[];	/* {LEN*+PCREL} ==> lg number of bytes */
1085829Srrh extern	int	len124[];	/* {1,2,4,8,16} ==> {LEN1, LEN2, LEN4, LEN8} */
1095829Srrh extern	char	mod124[];	/* {1,2,4,8,16} ==> {bits to construct operands */
1105829Srrh extern	int	type_124[];	/* {1,2,4,8,16} ==> {TYPB,TYPW,TYPL,TYPQ,TYPO} */
1115829Srrh extern	int	ty_NORELOC[];	/* {TYPB..TYPH} ==> {1 if relocation not OK */
1125829Srrh extern	int	ty_float[];	/* {TYPB..TYPH} ==> {1 if floating number */
1135829Srrh extern	int	ty_LEN[];	/* {TYPB..TYPH} ==> {LEN1..LEN16} */
1145829Srrh extern	int	ty_nbyte[];	/* {TYPB..TYPH} ==> {1,2,4,8,16} */
1155829Srrh extern	int	ty_nlg[];	/* {TYPB..TYPH} ==> lg{1,2,4,8,16} */
1165829Srrh extern	char	*ty_string[];	/* {TYPB..TYPH} ==> printable */
117672Shenry 
118601Sbill #define	TMPC	7
1195829Srrh #define	HW	0x1
1205829Srrh #define	FW	0x3
1215829Srrh #define	DW	0x7
1225829Srrh #define	OW	0xF
123601Sbill 
124601Sbill #define	round(x,y)	(((x)+(y)) & ~(y))
125601Sbill 
126601Sbill #define	STABTYPS	0340
127626Shenry #define	STABFLAG	0200
128601Sbill 
129601Sbill /*
130601Sbill  *	Follows are the definitions for the symbol table tags, which are
131601Sbill  *	all unsigned characters..
132601Sbill  *	High value tags are generated by the asembler for internal
133601Sbill  *	use.
134601Sbill  *	Low valued tags are the parser coded tokens the scanner returns.
135601Sbill  *	There are several pertinant bounds in this ordering:
136601Sbill  *		a)	Symbols greater than JXQUESTIONABLE
137601Sbill  *			are used by the jxxx bumper, indicating that
138601Sbill  *			the symbol table entry is a jxxx entry
139601Sbill  *			that has yet to be bumped.
140601Sbill  *		b)	Symbols greater than IGNOREBOUND are not
141601Sbill  *			bequeathed to the loader; they are truly
142601Sbill  *			for assembler internal use only.
143601Sbill  *		c)	Symbols greater than OKTOBUMP represent
144601Sbill  *			indices into the program text that should
145601Sbill  *			be changed in preceeding jumps or aligns
146601Sbill  *			must get turned into their long form.
147601Sbill  */
148601Sbill 
149626Shenry #define	TAGMASK		0xFF
150601Sbill 
151601Sbill #	define	JXACTIVE	0xFF	/*jxxx size unknown*/
152601Sbill #	define	JXNOTYET	0xFE	/*jxxx size known, but not yet expanded*/
153601Sbill #	define	JXALIGN		0xFD	/*align jxxx entry*/
154601Sbill #	define	JXINACTIVE	0xFC	/*jxxx size known and expanded*/
155601Sbill 
156626Shenry #define	JXQUESTIONABLE		0xFB
157601Sbill 
158601Sbill #	define	JXTUNNEL	0xFA	/*jxxx that jumps to another*/
159601Sbill #	define	OBSOLETE	0xF9	/*erroneously entered symbol*/
160601Sbill 
161601Sbill #define	IGNOREBOUND	0xF8		/*symbols greater than this are ignored*/
162601Sbill #	define	STABFLOATING	0xF7
163601Sbill #	define	LABELID		0xF6
164601Sbill 
165601Sbill #define	OKTOBUMP	0xF5
166601Sbill #	define	STABFIXED	0xF4
167601Sbill 
168601Sbill /*
169601Sbill  *	astoks.h contains reserved word codings the parser should
170601Sbill  *	know about
171601Sbill  */
172601Sbill #include "astoks.h"
173601Sbill 
174601Sbill /*
175601Sbill  *	The structure for one symbol table entry.
176601Sbill  *	Symbol table entries are used for both user defined symbols,
177601Sbill  *	and symbol slots generated to create the jxxx jump from
178601Sbill  *	slots.
179635Shenry  *	Caution: the instructions are stored in a shorter version
180635Shenry  *	of the struct symtab, using all fields in sym_nm and
181635Shenry  *	tag.  The fields used in sym_nm are carefully redeclared
182635Shenry  *	in struct Instab and struct instab (see below).
183635Shenry  *	If struct nlist gets changed, then Instab and instab may
184635Shenry  *	have to be changed.
185601Sbill  */
186601Sbill 
187601Sbill struct symtab{
188635Shenry 		struct	nlist	s_nm;
189635Shenry 		u_char	s_tag;		/* assembler tag */
190635Shenry 		u_char	s_ptype;	/* if tag == NAME */
191635Shenry 		u_char	s_jxoveralign;	/* if a JXXX, jumped over align */
192635Shenry 		short	s_index;	/* which segment */
193635Shenry 		struct	symtab *s_dest;	/* if JXXX, where going to */
194601Sbill #ifdef DJXXX
195635Shenry 		short	s_jxline;	/* source line of the jump from */
196601Sbill #endif
197601Sbill };
198635Shenry /*
199635Shenry  *	Redefinitions of the fields in symtab for
200635Shenry  *	use when the symbol table entry marks a jxxx instruction.
201635Shenry  */
202635Shenry #define	s_jxbump	s_ptype		/* tag == JX..., how far to expand */
203635Shenry #define	s_jxfear	s_desc		/* how far needs to be bumped */
204635Shenry /*
205635Shenry  *	Redefinitions of fields in the struct nlist for symbols so that
206635Shenry  *	one saves typing, and so that they conform
207635Shenry  *	with the old naming conventions.
208635Shenry  */
20913515Srrh #define	s_name	s_nm.n_un.n_name
21013515Srrh #define	i_name	s_name
21113515Srrh #define	FETCHNAME(sp)	(((struct strdesc *)(sp)->s_name)->sd_string)
21213515Srrh #define	STRLEN(sp)	(((struct strdesc *)(sp)->s_name)->sd_strlen)
21313515Srrh #define	STROFF(sp)	(((struct strdesc *)(sp)->s_name)->sd_stroff)
214635Shenry #define	s_nmx	s_nm.n_un.n_strx	/* string table index */
215635Shenry #define	s_type	s_nm.n_type		/* type of the symbol */
216635Shenry #define	s_other	s_nm.n_other		/* other information for sdb */
217635Shenry #define	s_desc	s_nm.n_desc		/* type descriptor */
218635Shenry #define	s_value	s_nm.n_value		/* value of the symbol, or sdb delta */
219601Sbill 
220635Shenry struct	instab{
221635Shenry 	struct	nlist	s_nm;		/* instruction name, type (opcode) */
222635Shenry 	u_char	s_tag;
2235829Srrh 	u_char	s_eopcode;
2245829Srrh 	char	s_pad[2];		/* round to 20 bytes */
225601Sbill };
2265829Srrh typedef	struct	instab	*Iptr;
227635Shenry /*
228635Shenry  *	The fields nm.n_desc and nm.n_value total 6 bytes; this is
229635Shenry  *	just enough for the 6 bytes describing the argument types.
230635Shenry  *	We use a macro to define access to these 6 bytes, assuming that
231635Shenry  *	they are allocated adjacently.
232635Shenry  *	IF THE FORMAT OF STRUCT nlist CHANGES, THESE MAY HAVE TO BE CHANGED.
233635Shenry  *
2341745Shenry  *	Instab is cleverly declared to look very much like the combination of
235635Shenry  *	a struct symtab and a struct nlist.
236635Shenry  */
2375829Srrh /*
2385829Srrh  *	With the 1981 VAX architecture reference manual,
2395829Srrh  *	DEC defined and named two byte opcodes.
2405829Srrh  *	In addition, DEC defined four new one byte instructions for
2415829Srrh  *	queue manipulation.
2425829Srrh  *	The assembler was patched in 1982 to reflect this change.
2435829Srrh  *
2445829Srrh  *	The two byte opcodes are preceded with an escape byte
2455829Srrh  *	(usually an ESCD) and an opcode byte.
2465829Srrh  *	For one byte opcodes, the opcode is called the primary opcode.
2475829Srrh  *	For two byte opcodes, the second opcode is called the primary opcode.
2485829Srrh  *
2495829Srrh  *	We store the primary opcode in I_popcode,
2505829Srrh  *	and the escape opcode in I_eopcode.
2515829Srrh  *
2525829Srrh  *	For one byte opcodes in the basic arhitecture,
2535829Srrh  *		I_eopcode is CORE
2545829Srrh  *	For one byte opcodes in the new architecture definition,
2555829Srrh  *		I_eopcode is NEW
2565829Srrh  *	For the two byte opcodes, I_eopcode is the escape byte.
2575829Srrh  *
2585829Srrh  *	The assembler checks if a NEW or two byte opcode is used,
2595829Srrh  *	and issues a warning diagnostic.
2605829Srrh  */
2615829Srrh /*
2625829Srrh  *	For upward compatability reasons, we can't have the two opcodes
2635829Srrh  *	forming an operator specifier byte(s) be physically adjacent
2645829Srrh  *	in the instruction table.
2655829Srrh  *	We define a structure and a constructor that is used in
2665829Srrh  *	the instruction generator.
2675829Srrh  */
2685829Srrh struct Opcode{
2695829Srrh 	u_char	Op_eopcode;
2705829Srrh 	u_char	Op_popcode;
2715829Srrh };
2725829Srrh 
2735829Srrh #define	BADPOINT	0xAAAAAAAA
2745829Srrh /*
2755829Srrh  *	See if a structured opcode is bad
2765829Srrh  */
2775829Srrh #define	ITABCHECK(o)	((itab[o.Op_eopcode] != (Iptr*)BADPOINT) && (itab[o.Op_eopcode][o.Op_popcode] != (Iptr)BADPOINT))
2785829Srrh /*
2795829Srrh  *	Index the itab by a structured opcode
2805829Srrh  */
2815829Srrh #define	ITABFETCH(o)	itab[o.Op_eopcode][o.Op_popcode]
2825829Srrh 
283635Shenry struct	Instab{
284635Shenry 	char	*I_name;
2855829Srrh 	u_char	I_popcode;		/* basic op code */
286635Shenry 	char	I_nargs;
287635Shenry 	char	I_args[6];
288635Shenry 	u_char	I_s_tag;
2895829Srrh 	u_char	I_eopcode;
2905829Srrh 	char	I_pad[2];		/* round to 20 bytes */
291635Shenry };
292635Shenry /*
293635Shenry  *	Redefinitions of fields in the struct nlist for instructions so that
294635Shenry  *	one saves typing, and conforms to the old naming conventions
295635Shenry  */
2965829Srrh #define	i_popcode	s_nm.n_type	/* use the same field as symtab.type */
2975829Srrh #define	i_eopcode	s_eopcode
298635Shenry #define	i_nargs		s_nm.n_other	/* number of arguments */
299635Shenry #define	fetcharg(ptr, n) ((struct Instab *)ptr)->I_args[n]
300601Sbill 
301601Sbill struct	arg {				/*one argument to an instruction*/
302635Shenry 	char	a_atype;
303635Shenry 	char	a_areg1;
304635Shenry 	char	a_areg2;
305635Shenry 	char	a_dispsize;		/*usually d124, unless have B^, etc*/
306635Shenry 	struct	exp *a_xp;
307601Sbill };
3085829Srrh /*
3095829Srrh  *	Definitions for numbers and expressions.
3105829Srrh  */
3115829Srrh #include "asnumber.h"
312601Sbill struct	exp {
3135829Srrh 	Bignum	e_number;	/* 128 bits of #, plus tag */
314635Shenry 	char	e_xtype;
315635Shenry 	char	e_xloc;
3165829Srrh 	struct	symtab		*e_xname;
317601Sbill };
3185829Srrh #define	e_xvalue	e_number.num_num.numIl_int.Il_long
319601Sbill 
3205829Srrh #define		MINLIT		0
3215829Srrh #define		MAXLIT		63
322601Sbill 
3235829Srrh #define		MINBYTE		-128
3245829Srrh #define		MAXBYTE		127
3255829Srrh #define		MINUBYTE	0
3265829Srrh #define		MAXUBYTE	255
327601Sbill 
3285829Srrh #define		MINWORD		-32768
3295829Srrh #define		MAXWORD		32767
3305829Srrh #define		MINUWORD	0
3315829Srrh #define		MAXUWORD	65535
332601Sbill 
3335829Srrh #define		ISLIT(x)	(((x) >= MINLIT) && ((x) <= MAXLIT))
3345829Srrh #define		ISBYTE(x)	(((x) >= MINBYTE) && ((x) <= MAXBYTE))
3355829Srrh #define		ISUBYTE(x)	(((x) >= MINUBYTE) && ((x) <= MAXUBYTE))
3365829Srrh #define		ISWORD(x)	(((x) >= MINWORD) && ((x) <= MAXWORD))
3375829Srrh #define		ISUWORD(x)	(((x) >= MINUWORD) && ((x) <= MAXUWORD))
33813515Srrh /*
33913515Srrh  *	Definitions for strings.
34013515Srrh  *
34113515Srrh  *	Strings are stored in the string pool; see strsave(str, length)
34213515Srrh  *	Strings are known by their length and values.
34313515Srrh  *	A string pointer points to the beginning of the value bytes;
34413515Srrh  *
34513515Srrh  *	If this structure is changed, change insts also.
34613515Srrh  */
34713515Srrh struct	strdesc{
34813515Srrh 	int	sd_stroff;	/* offset into string file */
34913515Srrh 	short	sd_place;	/* where string is */
35013515Srrh 	u_short	sd_strlen;	/* string length */
35113515Srrh 	char	sd_string[1];	/* the string itself, flexible length */
35213515Srrh };
35313515Srrh /*
35413515Srrh  *	Where a string can be.  If these are changed, also change instrs.
35513515Srrh  */
35613515Srrh #define	STR_FILE	0x1
35713515Srrh #define	STR_CORE	0x2
35813515Srrh #define	STR_BOTH	0x3
359601Sbill 
36013515Srrh struct strdesc *savestr();
36113515Srrh 
36213515Srrh /*
36313515Srrh  *	Global variables
36413515Srrh  */
365601Sbill 	extern	struct	arg	arglist[NARG];	/*building operands in instructions*/
366601Sbill 	extern	struct	exp	explist[NEXP];	/*building up a list of expressions*/
367601Sbill 	extern	struct	exp	*xp;		/*current free expression*/
368601Sbill 	/*
369601Sbill 	 *	Communication between the scanner and the jxxx handlers.
370601Sbill 	 *	lastnam:	the last name seen on the input
371601Sbill 	 *	lastjxxx:	pointer to the last symbol table entry for
372601Sbill 	 *			a jump from
373601Sbill 	 */
374601Sbill 	extern	struct	symtab	*lastnam;
375601Sbill 	extern	struct	symtab	*lastjxxx;
376601Sbill 	/*
377601Sbill 	 *	Lgensym is used to make up funny names for local labels.
378601Sbill 	 *	lgensym[i] is the current funny number to put after
379601Sbill 	 *	references to if, lgensym[i]-1 is for ib.
380601Sbill 	 *	genref[i] is set when the label is referenced before
381601Sbill 	 *	it is defined (i.e. 2f) so that we can be sure these
382601Sbill 	 *	labels are always defined to avoid weird diagnostics
383601Sbill 	 *	from the loader later.
384601Sbill 	 */
385601Sbill 	extern	int	lgensym[10];
386601Sbill 	extern	char	genref[10];
387601Sbill 
388601Sbill 	extern	struct	exp	*dotp;		/* the current dot location */
389601Sbill 	extern	int	loctr;
390601Sbill 
391601Sbill 	extern	struct	exec	hdr;		/* a.out header */
392601Sbill 	extern	u_long	tsize;			/* total text size */
393601Sbill 	extern	u_long	dsize;			/* total data size */
394601Sbill 	extern	u_long	trsize;			/* total text relocation size */
395601Sbill 	extern	u_long	drsize;			/* total data relocation size */
396601Sbill 	extern	u_long	datbase;		/* base of the data segment */
397601Sbill 	/*
398601Sbill 	 *	Bitoff and bitfield keep track of the packing into
399601Sbill 	 *	bytes mandated by the expression syntax <expr> ':' <expr>
400601Sbill 	 */
401601Sbill 	extern	int	bitoff;
402601Sbill 	extern	long	bitfield;
403601Sbill 
404601Sbill 	/*
405601Sbill 	 *	The lexical analyzer builds up symbols in yytext.  Lookup
406601Sbill 	 *	expects its argument in this buffer
407601Sbill 	 */
40813461Srrh 	extern	char	yytext[NCPName+2];	/* text buffer for lexical */
409601Sbill 	/*
410601Sbill 	 *	Variables to manage the input assembler source file
411601Sbill 	 */
412601Sbill 	extern	int	lineno;			/*the line number*/
413601Sbill 	extern	char	*dotsname;		/*the name of the as source*/
414601Sbill 
41513515Srrh 	extern	FILE	*tokfile;		/* temp token communication*/
41613515Srrh 	extern	FILE	*strfile;		/* temp string file*/
41713515Srrh 	extern	char	tokfilename[TNAMESIZE];	/* token file name */
41813515Srrh 	extern	char	strfilename[TNAMESIZE];	/* string file name */
41913515Srrh 	extern	int	strfilepos;		/* position in string file */
420601Sbill 
421601Sbill 	extern	int	passno;			/* 1 or 2 */
422601Sbill 
4235829Srrh 	extern	int	anyerrs;		/*errors as'ing arguments*/
4245829Srrh 	extern	int	anywarnings;		/*warnings as'ing arguments*/
425601Sbill 	extern	int	silent;			/*don't mention the errors*/
426601Sbill 	extern	int	savelabels;		/*save labels in a.out*/
427601Sbill 	extern	int	orgwarn;		/* questionable origin ? */
428601Sbill 	extern	int	useVM;			/*use virtual memory temp file*/
429637Shenry 	extern	int	jxxxJUMP;		/*use jmp instead of brw for jxxx */
430639Sbill 	extern	int	readonlydata;		/*initialized data into text space*/
4315829Srrh 	extern	int	nGHnumbers;		/* GH numbers used */
4325829Srrh 	extern	int	nGHopcodes;		/* GH opcodes used */
4335829Srrh 	extern	int	nnewopcodes;		/* new opcodes used */
434601Sbill #ifdef DEBUG
435601Sbill 	extern	int	debug;
436601Sbill 	extern	int	toktrace;
437601Sbill #endif
438601Sbill 	/*
439601Sbill 	 *	Information about the instructions
440601Sbill 	 */
4415829Srrh 	extern	struct	instab	**itab[NINST];	/*maps opcodes to instructions*/
442635Shenry 	extern  readonly struct Instab instab[];
443601Sbill 
444601Sbill 	extern	int	curlen;			/*current literal storage size*/
445601Sbill 	extern	int	d124;			/*current pointer storage size*/
446601Sbill 
447601Sbill 	struct	symtab	**lookup();		/*argument in yytext*/
448601Sbill 	struct 	symtab	*symalloc();
449601Sbill 
4505829Srrh 	char	*Calloc();
4515829Srrh 	char	*ClearCalloc();
4525829Srrh 
453635Shenry #define outb(val) {dotp->e_xvalue++; if (passno==2) bputc((val), (txtfil));}
454601Sbill 
455635Shenry #define outs(cp, lg) dotp->e_xvalue += (lg); if (passno == 2) bwrite((cp), (lg), (txtfil))
456601Sbill 
4575829Srrh #define	Outb(o)	outb(o)
458601Sbill /*
459601Sbill  *	Most of the time, the argument to flushfield is a power of two constant,
460601Sbill  *	the calculations involving it can be optimized to shifts.
461601Sbill  */
462601Sbill #define flushfield(n) if (bitoff != 0)  Flushfield( ( (bitoff+n-1) /n ) * n)
463601Sbill 
464601Sbill /*
465601Sbill  * The biobuf structure and associated routines are used to write
466601Sbill  * into one file at several places concurrently.  Calling bopen
467601Sbill  * with a biobuf structure sets it up to write ``biofd'' starting
468601Sbill  * at the specified offset.  You can then use ``bwrite'' and/or ``bputc''
469601Sbill  * to stuff characters in the stream, much like ``fwrite'' and ``fputc''.
470601Sbill  * Calling bflush drains all the buffers and MUST be done before exit.
471601Sbill  */
472601Sbill struct	biobuf {
473601Sbill 	short	b_nleft;		/* Number free spaces left in b_buf */
474601Sbill /* Initialize to be less than BUFSIZ initially, to boundary align in file */
475601Sbill 	char	*b_ptr;			/* Next place to stuff characters */
476601Sbill 	char	b_buf[BUFSIZ];		/* The buffer itself */
477601Sbill 	off_t	b_off;			/* Current file offset */
478601Sbill 	struct	biobuf *b_link;		/* Link in chain for bflush() */
479601Sbill };
480601Sbill #define	bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \
481601Sbill 		       : bflushc(b, c))
482601Sbill #define BFILE	struct biobuf
483601Sbill 
484601Sbill 	extern	BFILE	*biobufs;	/* head of the block I/O buffer chain */
485601Sbill 	extern	int	biofd;		/* file descriptor for block I/O file */
486601Sbill 	extern	off_t	boffset;	/* physical position in logical file */
487601Sbill 
488601Sbill 	/*
489601Sbill 	 *	For each of the named .text .data segments
490601Sbill 	 *	(introduced by .text <expr>), we maintain
491601Sbill 	 *	the current value of the dot, and the BFILE where
492601Sbill 	 *	the information for each of the segments is placed
493601Sbill 	 *	during the second pass.
494601Sbill 	 */
495601Sbill 	extern	struct	exp	usedot[NLOC + NLOC];
496601Sbill 	extern		BFILE	*usefile[NLOC + NLOC];
497601Sbill 	extern		BFILE	*txtfil;/* file for text and data: into usefile */
498601Sbill 	/*
499601Sbill 	 *	Relocation information for each segment is accumulated
500601Sbill 	 *	seperately from the others.  Writing the relocation
501601Sbill 	 *	information is logically viewed as writing to one
502601Sbill 	 *	relocation saving file for  each segment; physically
503601Sbill 	 *	we have a bunch of buffers allocated internally that
504601Sbill 	 *	contain the relocation information.
505601Sbill 	 */
506601Sbill 	struct	relbufdesc	*rusefile[NLOC + NLOC];
507601Sbill 	struct	relbufdesc	*relfil;
508