201 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Header$ */
 | |
| /* EM CODE OUTPUT ROUTINES */
 | |
| 
 | |
| #define CMODE 0644
 | |
| #define MAX_ARG_CNT 32
 | |
| 
 | |
| #include	"em.h"
 | |
| #include	<system.h>
 | |
| #include	"arith.h"
 | |
| #include	"label.h"
 | |
| 
 | |
| /*
 | |
| 	putbyte(), C_open() and C_close() are the basic routines for
 | |
| 	respectively write on, open and close the output file.
 | |
| 	The put_*() functions serve as formatting functions of the
 | |
| 	various EM language constructs.
 | |
| 	See "Description of a Machine Architecture for use with
 | |
| 	Block Structured Languages" par. 11.2 for the meaning of these
 | |
| 	names.
 | |
| */
 | |
| 
 | |
| /* supply a kind of buffered output */
 | |
| #define	flush(x)	sys_write(ofp, &obuf[0], x)
 | |
| 
 | |
| static char obuf[BUFSIZ];
 | |
| static char *opp = &obuf[0];
 | |
| File *ofp = 0;
 | |
| 
 | |
| putbyte(b)	/* shouldn't putbyte() be a macro ??? (EB)	*/
 | |
| 	int b;
 | |
| {
 | |
| 	if (opp >= &obuf[BUFSIZ]) { /* flush if buffer overflows */
 | |
| 		if (flush(BUFSIZ) == 0)
 | |
| 			sys_stop(S_ABORT);
 | |
| 		opp = &obuf[0];
 | |
| 	}
 | |
| 	*opp++ = (char) b;
 | |
| }
 | |
| 
 | |
| C_init(wsize, psize)
 | |
| 	arith wsize, psize;
 | |
| {}
 | |
| 
 | |
| C_open(nm)	/* open file for compact code output	*/
 | |
| 	char *nm;
 | |
| {
 | |
| 	if (nm == 0)
 | |
| 		ofp = STDOUT;	/* standard output	*/
 | |
| 	else
 | |
| 	if (sys_open(nm, OP_WRITE, &ofp) == 0)
 | |
| 		return 0;
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| C_close()
 | |
| {
 | |
| 	if (flush(opp - &obuf[0]) == 0)
 | |
| 		sys_stop(S_ABORT);
 | |
| 	opp = obuf;	/* reset opp	*/
 | |
| 	if (ofp != STDOUT)
 | |
| 		sys_close(ofp);
 | |
| 	ofp = 0;
 | |
| }
 | |
| 
 | |
| C_busy()
 | |
| {
 | |
| 	return ofp != 0; /* true if code is being generated */
 | |
| }
 | |
| 
 | |
| /***    the compact code generating routines	***/
 | |
| #define	fit16i(x)	((x) >= (long)0xFFFF8000 && (x) <= (long)0x00007FFF)
 | |
| #define	fit8u(x)	((x) <= 0xFF)		/* x is already unsigned */
 | |
| 
 | |
| put_ilb(l)
 | |
| 	label l;
 | |
| {
 | |
| 	if (fit8u(l))	{
 | |
| 		put8(sp_ilb1);
 | |
| 		put8((int)l);
 | |
| 	}
 | |
| 	else	{
 | |
| 		put8(sp_ilb2);
 | |
| 		put16(l);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| put_dlb(l)
 | |
| 	label l;
 | |
| {
 | |
| 	if (fit8u(l))	{
 | |
| 		put8(sp_dlb1);
 | |
| 		put8((int)l);
 | |
| 	}
 | |
| 	else	{
 | |
| 		put8(sp_dlb2);
 | |
| 		put16(l);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| put_cst(l)
 | |
| 	arith l;
 | |
| {
 | |
| 	if (l >= (arith) -sp_zcst0 && l < (arith) (sp_ncst0 - sp_zcst0)) {
 | |
| 		/*	we can convert 'l' to an int because its value
 | |
| 			can be stored in a byte.
 | |
| 		*/
 | |
| 		put8((int) l + (sp_zcst0 + sp_fcst0));
 | |
| 	}
 | |
| 	else
 | |
| 	if (fit16i(l)) { /* the cast from long to int causes no trouble here */
 | |
| 		put8(sp_cst2);
 | |
| 		put16((int) l);
 | |
| 	}
 | |
| 	else	{
 | |
| 		put8(sp_cst4);
 | |
| 		put32(l);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| put_doff(l, v)
 | |
| 	label l;
 | |
| 	arith v;
 | |
| {
 | |
| 	if (v == 0)
 | |
| 		put_dlb(l);
 | |
| 	else	{
 | |
| 		put8(sp_doff);
 | |
| 		put_dlb(l);
 | |
| 		put_cst(v);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| put_noff(s, v)
 | |
| 	char *s;
 | |
| 	arith v;
 | |
| {
 | |
| 	if (v == 0)
 | |
| 		put_dnam(s);
 | |
| 	else	{
 | |
| 		put8(sp_doff);
 | |
| 		put_dnam(s);
 | |
| 		put_cst(v);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| put_dnam(s)
 | |
| 	char *s;
 | |
| {
 | |
| 	put8(sp_dnam);
 | |
| 	put_str(s);
 | |
| }
 | |
| 
 | |
| put_pnam(s)
 | |
| 	char *s;
 | |
| {
 | |
| 	put8(sp_pnam);
 | |
| 	put_str(s);
 | |
| }
 | |
| 
 | |
| #ifdef	____
 | |
| put_fcon(s, sz)
 | |
| 	char *s;
 | |
| 	arith sz;
 | |
| {
 | |
| 	put8(sp_fcon);
 | |
| 	put_cst(sz);
 | |
| 	put_str(s);
 | |
| }
 | |
| #endif	____
 | |
| 
 | |
| put_wcon(sp, v, sz)	/* sp_icon, sp_ucon or sp_fcon with int repr	*/
 | |
| 	int sp;
 | |
| 	char *v;
 | |
| 	arith sz;
 | |
| {
 | |
| 	/* how 'bout signextension int --> long ???	*/
 | |
| 	put8(sp);
 | |
| 	put_cst(sz);
 | |
| 	put_str(v);
 | |
| }
 | |
| 
 | |
| put_str(s)
 | |
| 	char *s;
 | |
| {
 | |
| 	register int len;
 | |
| 
 | |
| 	put_cst((arith) (len = strlen(s)));
 | |
| 	while (--len >= 0)
 | |
| 		put8(*s++);
 | |
| }
 | |
| 
 | |
| put_cstr(s)
 | |
| 	char *s;
 | |
| {
 | |
| 	register int len = prepare_string(s);
 | |
| 
 | |
| 	put8(sp_scon);
 | |
| 	put_cst((arith) len);
 | |
| 	while (--len >= 0)
 | |
| 		put8(*s++);
 | |
| }
 |