⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sparc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (mask >= 32) {			    break;			}		    } else {			mask -= '0';		    }		    switch (*args) {		    case 'e':			opcode |= mask << 14;			continue;		    case 'f':			opcode |= mask;			continue;		    case 'g':			opcode |= mask << 25;			continue;		    }		}		break;	    case 'F':		if (strncmp(s, "%fsr", 4) == 0) {		    s += 4;		    continue;		}		break;	    case 'h':       /* high 22 bits */	        the_insn.reloc = RELOC_HI22;		goto immediate;	    case 'l':   /* 22 bit PC relative immediate */	        the_insn.reloc = RELOC_WDISP22;		the_insn.pcrel = 1;		goto immediate;	    case 'L':   /* 30 bit immediate */	        the_insn.reloc = RELOC_WDISP30;		the_insn.pcrel = 1;		goto immediate;	    case 'i':   /* 13 bit immediate */	        the_insn.reloc = RELOC_BASE13;		/*FALLTHROUGH*/	    immediate:		if(*s==' ')		  s++;		if (*s == '%') {		    if ((c = s[1]) == 'h' && s[2] == 'i') {			the_insn.reloc = RELOC_HI22;			s+=3;		    } else if (c == 'l' && s[2] == 'o') {			the_insn.reloc = RELOC_LO10;			s+=3;		    } else		    	break;		}		/* Note that if the getExpression() fails, we will still have		   created U entries in the symbol table for the 'symbols'		   in the input string.  Try not to create U symbols for		   registers, etc. */		{			/* This stuff checks to see if the expression ends			   in +%reg If it does, it removes the register from			   the expression, and re-sets 's' to point to the			   right place */			char *s1;			for(s1=s;*s1 && *s1!=','&& *s1!=']';s1++)				;			if(s1!=s && isdigit(s1[-1])) {				if(s1[-2]=='%' && s1[-3]=='+') {					s1-=3;					*s1='\0';					(void)getExpression(s);					*s1='+';					s=s1;					continue;				} else if(index("goli0123456789",s1[-2]) && s1[-3]=='%' && s1[-4]=='+') {					s1-=4;					*s1='\0';					(void)getExpression(s);					*s1='+';					s=s1;					continue;				}			}		}		(void)getExpression(s);		s = expr_end;		continue;	    case 'a':		if (*s++ == 'a') {		    opcode |= ANNUL;		    continue;		}		break;	    case 'A':       /* alternate space */		if (isdigit(*s)) {		    long num;		    num=0;		    while (isdigit(*s)) {			num= num*10 + *s-'0';			++s;		    }		    opcode |= num<<5;		    continue;		}		break;		/* abort(); */	    case 'p':		if (strncmp(s, "%psr", 4) == 0) {		    s += 4;		    continue;		}		break;	    case 'q':   /* floating point queue */		if (strncmp(s, "%fq", 3) == 0) {		    s += 3;		    continue;		}		break;	    case 'Q':   /* coprocessor queue */		if (strncmp(s, "%cq", 3) == 0) {		    s += 3;		    continue;		}		break;	    case 'S':		if (strcmp(str, "set") == 0) {		    special_case = SPECIAL_CASE_SET;		    continue;		}		break;	    case 't':		if (strncmp(s, "%tbr", 4) != 0)		    break;		s += 4;		continue;	    case 'w':		if (strncmp(s, "%wim", 4) != 0)		    break;		s += 4;		continue;	    case 'y':		if (strncmp(s, "%y", 2) != 0)		    break;		s += 2;		continue;	    default:		abort();	    }	    break;	}	error:	if (match == FALSE)	  {	    /* Args don't match.  */	    if (&insn[1] - sparc_opcodes < NUMOPCODES		&& !strcmp(insn->name, insn[1].name))	      {		++insn;		s = argsStart;		continue;	      }	    else	      {		as_warn("Illegal operands");		return;	      }	  }	break;    }    the_insn.opcode = opcode;    return;}static intgetExpression(str)    char *str;{    char *save_in;    segT seg;    save_in = input_line_pointer;    input_line_pointer = str;    switch (seg = expression(&the_insn.exp)) {    case SEG_ABSOLUTE:    case SEG_TEXT:    case SEG_DATA:    case SEG_BSS:    case SEG_UNKNOWN:    case SEG_DIFFERENCE:    case SEG_BIG:    case SEG_NONE:	break;    default:	the_insn.error = "bad segment";	expr_end = input_line_pointer;	input_line_pointer=save_in;	return 1;    }    expr_end = input_line_pointer;    input_line_pointer = save_in;    return 0;}/*    This is identical to the md_atof in m68k.c.  I think this is right,    but I'm not sure.   Turn a string in input_line_pointer into a floating point constant of type   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS   emitted is stored in *sizeP .  An error message is returned, or NULL on OK. *//* Equal to MAX_PRECISION in atof-ieee.c */#define MAX_LITTLENUMS 6char *md_atof(type,litP,sizeP)    char type;    char *litP;    int *sizeP;{    int	prec;    LITTLENUM_TYPE words[MAX_LITTLENUMS];    LITTLENUM_TYPE *wordP;    char	*t;    char	*atof_ieee();    switch(type) {    case 'f':    case 'F':    case 's':    case 'S':	prec = 2;	break;    case 'd':    case 'D':    case 'r':    case 'R':	prec = 4;	break;    case 'x':    case 'X':	prec = 6;	break;    case 'p':    case 'P':	prec = 6;	break;    default:	*sizeP=0;	return "Bad call to MD_ATOF()";    }    t=atof_ieee(input_line_pointer,type,words);    if(t)	input_line_pointer=t;    *sizeP=prec * sizeof(LITTLENUM_TYPE);    for(wordP=words;prec--;) {	md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));	litP+=sizeof(LITTLENUM_TYPE);    }    return "";	/* Someone should teach Dean about null pointers */}/* * Write out big-endian. */voidmd_number_to_chars(buf,val,n)    char *buf;    long val;    int n;{    switch(n) {    case 4:	*buf++ = val >> 24;	*buf++ = val >> 16;    case 2:	*buf++ = val >> 8;    case 1:	*buf = val;	break;    default:	abort();    }    return;}voidmd_number_to_imm(buf,val,n, fixP, seg_type)    char *buf;    long val;    int n;    fixS *fixP;    int seg_type;{    if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC) {	switch (n) {	case 1:		*buf = val;		break;	case 2:		*buf++ = (val>>8);		*buf = val;		break;	case 4:		*buf++ = (val>>24);		*buf++ = (val>>16);		*buf++ = (val>>8);		*buf = val;		break;	default:		abort();	}	return;    }    assert(n == 4);    assert(fixP->fx_r_type < NO_RELOC);    /*     * This is a hack.  There should be a better way to     * handle this.     */    if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {	    val += fixP->fx_where + fixP->fx_frag->fr_address;    }    switch (fixP->fx_r_type) {    case RELOC_32:	buf[0] = val >> 24;	buf[1] = val >> 16;	buf[2] = val >> 8;	buf[3] = val;	break;#if 0    case RELOC_8:         /* These don't seem to ever be needed. */    case RELOC_16:    case RELOC_DISP8:    case RELOC_DISP16:    case RELOC_DISP32:#endif    case RELOC_WDISP30:	val = (val >>= 2) + 1;	buf[0] |= (val >> 24) & 0x3f;	buf[1]= (val >> 16);	buf[2] = val >> 8;	buf[3] = val;	break;    case RELOC_HI22:	if(!fixP->fx_addsy) {	  buf[1] |= (val >> 26) & 0x3f;	  buf[2] = val >> 18;	  buf[3] = val >> 10;	} else {	  buf[2]=0;	  buf[3]=0;	}	break;#if 0    case RELOC_22:    case RELOC_13:#endif    case RELOC_LO10:	if(!fixP->fx_addsy) {	  buf[2] |= (val >> 8) & 0x03;	  buf[3] = val;	} else	  buf[3]=0;	break;#if 0    case RELOC_SFA_BASE:    case RELOC_SFA_OFF13:    case RELOC_BASE10:#endif    case RELOC_BASE13:	buf[2] |= (val >> 8) & 0x1f;	buf[3] = val;	break;    case RELOC_WDISP22:	val = (val >>= 2) + 1;	/* FALLTHROUGH */    case RELOC_BASE22:	buf[1] |= (val >> 16) & 0x3f;	buf[2] = val >> 8;	buf[3] = val;	break;#if 0    case RELOC_PC10:     case RELOC_PC22:     case RELOC_JMP_TBL:    case RELOC_SEGOFF16:    case RELOC_GLOB_DAT:    case RELOC_JMP_SLOT:     case RELOC_RELATIVE:#endif    case NO_RELOC:    default:	as_warn("bad relocation type: 0x%02x", fixP->fx_r_type);	break;    }    return;}/* should never be called for sparc */voidmd_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)    char *ptr;    long from_addr, to_addr;{    fprintf(stderr, "sparc_create_short_jmp\n");    abort();}/* should never be called for sparc */voidmd_number_to_disp(buf,val,n)    char	*buf;    long	val;{    fprintf(stderr, "md_number_to_disp\n");    abort();}/* should never be called for sparc */voidmd_number_to_field(buf,val,fix)    char *buf;    long val;    void *fix;{    fprintf(stderr, "sparc_number_to_field\n");    abort();}/* the bit-field entries in the relocation_info struct plays hell    with the byte-order problems of cross-assembly.  So as a hack,   I added this mach. dependent ri twiddler.  Ugly, but it gets   you there. -KWK *//* on sparc: first 4 bytes are normal unsigned long address, next three   bytes are index, most sig. byte first.  Byte 7 is broken up with   bit 7 as external, bits 6 & 5 unused, and the lower   five bits as relocation type.  Next 4 bytes are long int addend. *//* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */voidmd_ri_to_chars(ri_p, ri)     struct reloc_info_sparc *ri_p, ri;{  unsigned char the_bytes[sizeof(*ri_p)];    /* this is easy */  md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address));  /* now the fun stuff */  the_bytes[4] = (ri.r_index >> 16) & 0x0ff;  the_bytes[5] = (ri.r_index >> 8) & 0x0ff;  the_bytes[6] = ri.r_index & 0x0ff;  the_bytes[7] = ((ri.r_extern << 7)  & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F);  /* Also easy */  md_number_to_chars(&the_bytes[8], ri.r_addend, sizeof(ri.r_addend));  /* now put it back where you found it, Junior... */  bcopy (the_bytes, (char *)ri_p, sizeof(*ri_p));}/* should never be called for sparc */voidmd_convert_frag(fragP)    register fragS *fragP;{    fprintf(stderr, "sparc_convert_frag\n");    abort();}/* should never be called for sparc */voidmd_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)    char	*ptr;    long	from_addr,	        to_addr;    fragS	*frag;    symbolS	*to_symbol;{    fprintf(stderr, "sparc_create_long_jump\n");    abort();}/* should never be called for sparc */intmd_estimate_size_before_relax(fragP, segtype)    register fragS *fragP;{    fprintf(stderr, "sparc_estimate_size_before_relax\n");    abort();    return 0;}#if 0/* for debugging only */static voidprint_insn(insn)    struct sparc_it *insn;{    char *Reloc[] = {    "RELOC_8",    "RELOC_16",    "RELOC_32",    "RELOC_DISP8",    "RELOC_DISP16",    "RELOC_DISP32",    "RELOC_WDISP30",    "RELOC_WDISP22",    "RELOC_HI22",    "RELOC_22",    "RELOC_13",    "RELOC_LO10",    "RELOC_SFA_BASE",    "RELOC_SFA_OFF13",    "RELOC_BASE10",    "RELOC_BASE13",    "RELOC_BASE22",    "RELOC_PC10",    "RELOC_PC22",    "RELOC_JMP_TBL",    "RELOC_SEGOFF16",    "RELOC_GLOB_DAT",    "RELOC_JMP_SLOT",    "RELOC_RELATIVE",    "NO_RELOC"    };    if (insn->error) {	fprintf(stderr, "ERROR: %s\n");    }    fprintf(stderr, "opcode=0x%08x\n", insn->opcode);    fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);    fprintf(stderr, "exp =  {\n");    fprintf(stderr, "\t\tX_add_symbol = %s\n",	insn->exp.X_add_symbol ?	(insn->exp.X_add_symbol->sy_name ? 	insn->exp.X_add_symbol->sy_name : "???") : "0");    fprintf(stderr, "\t\tX_sub_symbol = %s\n",	insn->exp.X_subtract_symbol ?	    (insn->exp.X_subtract_symbol->sy_name ? 	        insn->exp.X_subtract_symbol->sy_name : "???") : "0");    fprintf(stderr, "\t\tX_add_number = %d\n",	insn->exp.X_add_number);    fprintf(stderr, "}\n");    return;}#endif/* * Sparc relocations are completely different, so it needs * this machine dependent routine to emit them. */voidemit_relocations(fixP, segment_address_in_file)    register fixS *fixP;    relax_addressT segment_address_in_file;{    struct reloc_info_sparc ri;    register symbolS *symbolP;    extern char *next_object_file_charP;    long add_number;    bzero((char *) &ri, sizeof(ri));    for (; fixP; fixP = fixP->fx_next) {	if (fixP->fx_r_type >= NO_RELOC) {	    fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);	    abort();	}	if ((symbolP = fixP->fx_addsy) != NULL) {	    ri.r_address = fixP->fx_frag->fr_address +	        fixP->fx_where - segment_address_in_file;	    if ((symbolP->sy_type & N_TYPE) == N_UNDF) {		ri.r_extern = 1;		ri.r_index = symbolP->sy_number;	    } else {		ri.r_extern = 0;		ri.r_index = symbolP->sy_type & N_TYPE;	    }	    if (symbolP && symbolP->sy_frag) {		ri.r_addend = symbolP->sy_frag->fr_address;	    }	    ri.r_type = fixP->fx_r_type;	    if (fixP->fx_pcrel) {/*		ri.r_addend -= fixP->fx_where;          */		ri.r_addend -= ri.r_address;            	    } else {		ri.r_addend = fixP->fx_addnumber;	    }/*	    md_ri_to_chars((char *) &ri, ri);        */	    append(&next_object_file_charP, (char *)& ri, sizeof(ri));	}    }    return;}intmd_parse_option(argP,cntP,vecP)    char **argP;    int *cntP;    char ***vecP;{    return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -