File:  [Research Unix] / researchv9 / cmd / sun / as / ps.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#ifndef lint
static	char sccsid[] = "@(#)ps.c 1.1 86/02/03 Copyr 1985 Sun Micro";
#endif

/*
 * Copyright (c) 1985 by Sun Microsystems, Inc.
 */

#include "as.h"
#include <a.out.h>

/* a sop here to the cross-assemblers */
#define put_words( x, y ) put_text( x, y )
#define CSECT_MAX       5       /* number of control sections. */
/* Csect descriptor */
struct csect {
    char *name_cs;	/* print name					*/
    long  len_cs;	/* Length in machine addresses,			*/
			/* i.e., highest address referenced		*/
    long  dot_cs;	/* current dot in this cs, in machine addresses */
    short id_cs;	/* UNIX a.out name for this csect		*/
    short which_cs;	/* C_name for csect				*/
};

struct csect csect[CSECT_MAX] = {
  ".text", 0,0,N_TEXT,C_TEXT,	  	/* text csect */
  ".data", 0,0,N_DATA,C_DATA, 		/* data csect */
  ".data1",0,0,N_DATA,C_DATA1,		/* data csect */
  ".data2",0,0,N_DATA,C_DATA2,		/* data csect */
  ".bss",  0,0,N_BSS, C_BSS   		/* uninitialized csect */
} ;

short cur_csect_name      = C_TEXT;

int cansdi = (C_TEXT == C_TEXT) ; /* i.e. yes */


prog_end()
{ 
	register int i;
	register struct csect *p;

	/* pass 2 */
	if (pass > 1) 	       /* On the second pass, */
	   { fix_rel();	       /* patch up object file */
	     return; 
	   }

	/* pass 1 */
	current_file= 0;
	new_csect( C_TEXT );	/* end in text segment */
	/* export these values to sdi_resolve */
	if (even_align_flag == 0)
		{
	dsize  = (csect[C_DATA-1].len_cs  + 3) & ~3;
	d1size = (csect[C_DATA1-1].len_cs + 3) & ~3;
	d2size = (csect[C_DATA2-1].len_cs + 3) & ~3;
	bsize  = (csect[C_BSS-1].len_cs   + 3) & ~3;
	tsize  = (csect[C_TEXT-1].len_cs  + 3) & ~3;	/* make long aligned */
		}
	else
		{
	dsize  = (csect[C_DATA-1].len_cs  + 1) & ~1;
	d1size = (csect[C_DATA1-1].len_cs + 1) & ~1;
	d2size = (csect[C_DATA2-1].len_cs + 1) & ~1;
	bsize  = (csect[C_BSS-1].len_cs   + 1) & ~1;
	tsize  = (csect[C_TEXT-1].len_cs  + 1) & ~1;	/* make word aligned */
		}
	
	sdi_resolve();	       /* resolve span dependent instructions */

	csect[C_TEXT-1].len_cs += sdi_inc( csect[C_TEXT-1].len_cs, NULL);
	/* re-compute values for sym_fix and rel_header */
	if (even_align_flag == 0)
		{
	dsize  = (csect[C_DATA-1].len_cs  + 3) & ~3;
	d1size = (csect[C_DATA1-1].len_cs + 3) & ~3;
	d2size = (csect[C_DATA2-1].len_cs + 3) & ~3;
	bsize  = (csect[C_BSS-1].len_cs   + 3) & ~3;
	tsize  = (csect[C_TEXT-1].len_cs  + 3) & ~3;	/* make long aligned */
		}
	else
		{
	dsize  = (csect[C_DATA-1].len_cs  + 1) & ~1;
	d1size = (csect[C_DATA1-1].len_cs + 1) & ~1;
	d2size = (csect[C_DATA2-1].len_cs + 1) & ~1;
	bsize  = (csect[C_BSS-1].len_cs   + 1) & ~1;
	tsize  = (csect[C_TEXT-1].len_cs  + 1) & ~1;	/* make word aligned */
		}
	sym_fix();	               /* relocate and globalize */
	rel_header();	               /* Initialize output stuff */
	start_pass();	               /* Init per-pass variables */
	return;
} /* end prog_end */

/* Initialize per-pass variables */
start_pass()
{ 
	register int i;

	last_symbol = dot_bkt;	/* last defined symbol at start of pass */
	line_no = 0;
	errors = 0;
	implicit_cpid = INITIAL_CPID ;
        pass++;
	if (pass == 1) {
		for (i=0; i<CSECT_MAX; i++) 
	        csect[i].dot_cs = 0;
	} else { 
	    csect[C_TEXT-1].dot_cs = 0;
	    csect[C_DATA-1].dot_cs = tsize;
	    csect[C_DATA1-1].dot_cs = tsize + dsize;
	    csect[C_DATA2-1].dot_cs = tsize + dsize + d1size;
	    csect[C_BSS-1].dot_cs = tsize + dsize + d1size + d2size;
	}
	dot = 0;
	new_csect( C_TEXT ); /* start in text segment */
} /* end Start_pass */


/* .even handler */
even_op( ip, nops )
    struct ins_bkt *ip;
{ 
    int align_val, dot_delta;
    if (nops == 0 ){
	/* just plain .even */
	align_val = 2;
    } else {
	/* .align something */
	if (operands[0].sym_o)
	    PROG_ERROR(E_OPERAND);
	align_val = operands[0].value_o;
    }
    switch( align_val ){
    case 1: /* no-op */
	break;
    case 4:
	if (cansdi){
	    PROG_ERROR(E_ALIGN);
	    break;
	}
	/* FALL THROUGH */
    case 2:
	dot_delta = align_val - (dot%align_val);
	if (dot_delta != 0 && dot_delta != align_val){
	    dot += dot_delta;
	    wcode[0] = 0;
	    wcode[1] = 0;
	    put_text(wcode, dot_delta);
	}
	break;
    default:
	PROG_ERROR(E_OPERAND);
    }
} /* end Even */

byteword( ip )
    struct ins_bkt *ip;
{ 
    register int i;
    register struct oper *p;
  
    for (i=0, p=operands; i < numops; i++, p++) { 
	if (p->type_o != T_NORMAL) { 
	     p->sym_o = 0;
  	     p->type_o = T_NORMAL;
  	     p->value_o = 0;
  	     PROG_ERROR(E_OPERAND);
	 } else if (p->sym_o) 
	      put_rel(p, ip->subop_i, dot+bc,(p->flags_o&O_COMPLEX)!=0);
  
  	switch (ip->subop_i){
	case SUBOP_L:	*(unsigned *)code = p->value_o;
			/* if cross-assembling, we die here */
  			put_words(wcode,4);
  			bc += 4;
  			break;
  
	case SUBOP_W:	wcode[0] = p->value_o;
  	  		put_words(wcode,2);
  			bc += 2;
  			break;
  
	case SUBOP_B:	code[0] = p->value_o;
  			put_text(code,1);
  			bc++;
  			break;
  	    } /* end switch */
       } /* end for */
} /* end ByteWord */

/* handle .ascii and .asciz pseudo ops -- zero<>0 indicates that
 * user wants zero byte at end of string.
 */
ascii_op( ip )
    struct ins_bkt *ip;
{
    register char *p;
    char c;
    /*
     * opval_i[0] == 1 => ASCIZ
     *               0 => ASCII
     */

    if (numops!=1 || operands[0].type_o!=T_STRING){
	PROG_ERROR(E_OPERAND);
	return;
    }
    p = operands[0].stringval_o;
    while (*p) {
	    bc++; 
	    if ((c = *p++) != '\\') {
		    put_text(&c,1);
	    } else switch ( c = *p){
		case '\\':
		case '"':
			put_text(&c, 1);
			p++;
			break;
		default:
		{
		    register i;
		    /* \octal number.  Max of 3 octal digits */

		    for(i=0,c=0;i<3;i++) {
			    if ((*p >= '0') && (*p <= '7')) {
				    c = c * 8 + (*p++) - '0';
			    } else
				    break;
		    }
		    put_text(&c,1);
		}
	    }
    }
    if (ip->opval_i[0]) { put_text(p,1); bc++; }
} /* end Ascii */	

/*
 * handle .float and .double pseudo-ops. We distinguish by the opcode in
 * the instruction bucket handed us. We expect >=0 operands of type
 * T_FLOAT or T_DOUBLE.
 */
float_op( ip )
    struct ins_bkt *ip;
{ 
    register int i;
    register struct oper *p;
    double d;
    float f;
  
    switch (ip->op_i){
    case OP_FLOAT:
	for (i=0, p=operands; i < numops; i++, p++) {
	    switch (p->type_o){
	    default:
		PROG_ERROR( E_OPERAND );
		f = 0.0;
		break;
	    case T_NORMAL:
		if (p->sym_o )
		    PROG_ERROR( E_CONSTANT );
		f = (double) p->value_o;
		break;
	    case T_FLOAT:
		f =  p->fval_o;        break;
	    case T_DOUBLE:
		f = (float) p->dval_o; break;
	    }
	    put_text((char *) &f, sizeof f );
	    bc += sizeof f;
       }
	break;
    case OP_DOUBLE:
	for (i=0, p=operands; i < numops; i++, p++) {
	    switch (p->type_o){
	    default:
		PROG_ERROR( E_OPERAND );
		d = 0.0;
		break;
	    case T_NORMAL:
		if (p->sym_o )
		    PROG_ERROR( E_CONSTANT );
		d = (double) p->value_o;
		break;
	    case T_FLOAT:
		d = (double) p->fval_o; break;
	    case T_DOUBLE:
		d = p->dval_o;          break;
	    }
	    put_text((char *) &d, sizeof d );
	    bc += sizeof d;
	}
	break;
    default:
	sys_error("broken .float\n");
    }
}

csect_op( ip )
    struct ins_bkt *ip;
{ 
    new_csect( (int)(ip->op_i) - (int)OP_TEXT + C_TEXT );
}

new_csect( cname )
    int cname;
{
    register struct sym_bkt *sbp;        /* for defining new symbol */
    register struct csect   *csp;	/* ptr to current csect */
    extern struct sym_bkt  *last_symbol;	/* used for local symbols */
    extern struct sym_bkt  *dot_bkt;	/* sym_bkt for location counter */
	
    /* update current csect */
    csp = &csect[ cur_csect_name -1 ];
    csp->dot_cs = dot;
    if (dot > csp->len_cs) csp->len_cs = dot;
    /* now install new one */
    csp = &csect[cname-1];
    cur_csect_name = csp->which_cs;
    dot = csp->dot_cs;
    dot_bkt->csect_s = cur_csect_name;/* update dot's csect. dot_bkt->value_s */
    dot_bkt->value_s = dot;
                                      /* will be updated in the main loop     */
    sbp = lookup(csp->name_cs);
    sbp->attr_s |= S_DEC | S_DEF | S_LOCAL | S_PERM;
    sbp->csect_s = cur_csect_name;
    cansdi = !Jflag && (cur_csect_name==C_TEXT);
    sbp->value_s = 0;
} /* end New_csect */


proc_op( ip )
    struct ins_bkt *ip;
{
    if (pass == 1) makesdi( NULL, 0, 0 ); 
}

globl_op( ip )
    struct ins_bkt *ip;
{ 
    register int i;
    register struct sym_bkt *sbp;
  
    if (pass == 1) 
	for (i=0; i<numops; i++) {
	     sbp = operands[i].sym_o;
	     if (sbp == NULL) {
		PROG_ERROR(E_SYMBOL);
	     } else { 
		  sbp->attr_s |= S_DEC | S_EXT;	/* declared and external */
		  if (!(sbp->attr_s & S_DEF)){
		      sbp->csect_s = C_UNDEF;   /* don't know which */
		  }
	     }
	}
    return;
} /* end Globl */


comm_op( ip )
    struct ins_bkt *ip;
{ 
	register struct sym_bkt *sbp;

	sbp = operands[0].sym_o;
	if (sbp == NULL) {
	    PROG_ERROR(E_OPERAND);
	    return;
	}
	if (ip->op_i == OP_COMM ){
	    /* .comm */
	    if (pass == 1){
		sbp->csect_s = C_UNDEF;	/* make it undefined */
		sbp->attr_s |= S_DEC | S_EXT | S_COMM;
		sbp->value_s = operands[1].value_o;
	    }
	} else {
	    /* .lcomm */
	    /*
	     * switch to bss segment;
	     * bump dot and plant label;
	     * switch back
	     */
	    auto save_csect = cur_csect_name;
	    new_csect( C_BSS );
	    if (pass == 1) {
		    sbp->attr_s |=S_LABEL|S_DEC|S_DEF;
		    sbp->csect_s = C_BSS;
		    sbp->value_s = dot;
	    } else {
		if (sbp->csect_s != C_BSS || sbp->value_s != dot)
		    prog_error(E_MULTSYM);
	    }
	    dot += operands[1].value_o;
	    new_csect( save_csect );
    }
}

skip_op( ip )
    struct ins_bkt *ip;
{
	register i;
	static int zed[1024] = {0};
	bc += i = operands[0].value_o;
	if (cur_csect_name != C_BSS){
		while (i>sizeof zed){
			put_text(zed, sizeof zed);
			i -= sizeof zed;
		}
		if (i) {
			put_text(zed,i);
		}
	}
}
 
cpid_op( ip )
     struct ins_bkt *ip ;
{
implicit_cpid = operands[0].value_o ;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.