File:  [DragonFly] / src / gnu / usr.bin / as / config / Attic / tc-sparc.c
Revision 1.3: download - view: text, annotated - select for diffs
Sat Nov 22 19:30:55 2003 UTC (10 years, 9 months ago) by asmodai
Branches: MAIN
CVS tags: HEAD, DragonFly_Snap29Sep2004, DragonFly_Snap13Sep2004, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Properly spell compatible and compatibility.

    1: /* tc-sparc.c -- Assemble for the SPARC
    2:    Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
    3: 
    4:    This file is part of GAS, the GNU Assembler.
    5: 
    6:    GAS is free software; you can redistribute it and/or modify
    7:    it under the terms of the GNU General Public License as published by
    8:    the Free Software Foundation; either version 2, or (at your option)
    9:    any later version.
   10: 
   11:    GAS is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14:    GNU General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU General Public License
   17:    along with GAS; see the file COPYING.  If not, write to
   18:    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
   19: 
   20: /*
   21:  * $FreeBSD: src/gnu/usr.bin/as/config/tc-sparc.c,v 1.8 1999/08/27 23:34:30 peter Exp $
   22:  * $DragonFly: src/gnu/usr.bin/as/config/tc-sparc.c,v 1.3 2003/11/22 19:30:55 asmodai Exp $
   23:  */
   24: #define cypress 1234
   25: 
   26: #include <stdio.h>
   27: #include <ctype.h>
   28: 
   29: #include "as.h"
   30: 
   31: /* careful, this file includes data *declarations* */
   32: #include "opcode/sparc.h"
   33: 
   34: #define DEBUG_SPARC 1
   35: void md_begin();
   36: void md_end();
   37: void md_number_to_chars();
   38: void md_assemble();
   39: char *md_atof();
   40: void md_convert_frag();
   41: void md_create_short_jump();
   42: void md_create_long_jump();
   43: int md_estimate_size_before_relax();
   44: void md_ri_to_chars();
   45: symbolS *md_undefined_symbol();
   46: static void sparc_ip();
   47: 
   48: static enum sparc_architecture current_architecture = v6;
   49: static int architecture_requested = 0;
   50: static int warn_on_bump = 0;
   51: 
   52: const relax_typeS md_relax_table[] = {
   53: 	0 };
   54: 
   55: /* handle of the OPCODE hash table */
   56: static struct hash_control *op_hash = NULL;
   57: 
   58: static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common(), s_empty();
   59: extern void s_globl(), s_long(), s_short(), s_space(), cons();
   60: extern void s_align_bytes(), s_ignore();
   61: 
   62: const pseudo_typeS md_pseudo_table[] = {
   63: 	{ "align",	s_align_bytes,	0 },    /* Defaulting is invalid (0) */
   64: 	{ "empty",	s_empty,	0 },
   65: 	{ "common",	s_common,	0 },
   66: 	{ "global",	s_globl,	0 },
   67: 	{ "half",	cons,		2 },
   68: 	{ "optim",	s_ignore,	0 },
   69: 	{ "proc",	s_proc,		0 },
   70: 	{ "reserve",	s_reserve,	0 },
   71: 	{ "seg",	s_seg,		0 },
   72: 	{ "skip",	s_space,	0 },
   73: 	{ "word",	cons,		4 },
   74: 	{ NULL,		0,		0 },
   75: };
   76: 
   77: const int md_short_jump_size = 4;
   78: const int md_long_jump_size = 4;
   79: const int md_reloc_size = 12;			/* Size of relocation record */
   80: 
   81: /* This array holds the chars that always start a comment.  If the
   82:    pre-processor is disabled, these aren't very useful */
   83: const char comment_chars[] = "!";	/* JF removed '|' from comment_chars */
   84: 
   85: /* This array holds the chars that only start a comment at the beginning of
   86:    a line.  If the line seems to have the form '# 123 filename'
   87:    .line and .file directives will appear in the pre-processed output */
   88: /* Note that input_file.c hand checks for '#' at the beginning of the
   89:    first line of the input file.  This is because the compiler outputs
   90:    #NO_APP at the beginning of its output. */
   91: /* Also note that comments started like this one will always
   92:    work if '/' isn't otherwise defined. */
   93: const char line_comment_chars[] = "#";
   94: 
   95: /* Chars that can be used to separate mant from exp in floating point nums */
   96: const char EXP_CHARS[] = "eE";
   97: 
   98: /* Chars that mean this number is a floating point constant */
   99: /* As in 0f12.456 */
  100: /* or    0d1.2345e12 */
  101: const char FLT_CHARS[] = "rRsSfFdDxXpP";
  102: 
  103: /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
  104:    changed in read.c. Ideally it shouldn't have to know about it at all,
  105:    but nothing is ideal around here.
  106:    */
  107: 
  108: static unsigned char octal[256];
  109: #define isoctal(c)  octal[c]
  110:     static unsigned char toHex[256];
  111: 
  112: struct sparc_it {
  113: 	char *error;
  114: 	unsigned long opcode;
  115: 	struct nlist *nlistp;
  116: 	expressionS exp;
  117: 	int pcrel;
  118: 	enum reloc_type reloc;
  119: } the_insn, set_insn;
  120: 
  121: #if __STDC__ == 1
  122: #if DEBUG_SPARC
  123: static void print_insn(struct sparc_it *insn);
  124: #endif
  125: static int getExpression(char *str);
  126: #else /* not __STDC__ */
  127: #if DEBUG_SPARC
  128: static void print_insn();
  129: #endif
  130: static int getExpression();
  131: #endif /* not __STDC__ */
  132: 
  133: static char *Reloc[] = {
  134: 	"RELOC_8",
  135: 	"RELOC_16",
  136: 	"RELOC_32",
  137: 	"RELOC_DISP8",
  138: 	"RELOC_DISP16",
  139: 	"RELOC_DISP32",
  140: 	"RELOC_WDISP30",
  141: 	"RELOC_WDISP22",
  142: 	"RELOC_HI22",
  143: 	"RELOC_22",
  144: 	"RELOC_13",
  145: 	"RELOC_LO10",
  146: 	"RELOC_SFA_BASE",
  147: 	"RELOC_SFA_OFF13",
  148: 	"RELOC_BASE10",
  149: 	"RELOC_BASE13",
  150: 	"RELOC_BASE22",
  151: 	"RELOC_PC10",
  152: 	"RELOC_PC22",
  153: 	"RELOC_JMP_TBL",
  154: 	"RELOC_SEGOFF16",
  155: 	"RELOC_GLOB_DAT",
  156: 	"RELOC_JMP_SLOT",
  157: 	"RELOC_RELATIVE",
  158: 	"NO_RELOC"
  159: };
  160: 
  161: static char *expr_end;
  162: static int special_case;
  163: 
  164: /*
  165:  * Instructions that require wierd handling because they're longer than
  166:  * 4 bytes.
  167:  */
  168: #define	SPECIAL_CASE_SET	1
  169: #define	SPECIAL_CASE_FDIV	2
  170: 
  171: /*
  172:  * sort of like s_lcomm
  173:  *
  174:  */
  175: static int max_alignment = 15;
  176: 
  177: static void s_reserve() {
  178: 	char *name;
  179: 	char *p;
  180: 	char c;
  181: 	int align;
  182: 	int size;
  183: 	int temp;
  184: 	symbolS *symbolP;
  185: 
  186: 	name = input_line_pointer;
  187: 	c = get_symbol_end();
  188: 	p = input_line_pointer;
  189: 	*p = c;
  190: 	SKIP_WHITESPACE();
  191: 
  192: 	if (*input_line_pointer != ',') {
  193: 		as_bad("Expected comma after name");
  194: 		ignore_rest_of_line();
  195: 		return;
  196: 	}
  197: 
  198: 	++input_line_pointer;
  199: 
  200: 	if ((size = get_absolute_expression()) < 0) {
  201: 		as_bad("BSS length (%d.) <0! Ignored.", size);
  202: 		ignore_rest_of_line();
  203: 		return;
  204: 	} /* bad length */
  205: 
  206: 	*p = 0;
  207: 	symbolP = symbol_find_or_make(name);
  208: 	*p = c;
  209: 
  210: 	if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
  211: 		as_bad("bad .reserve segment: `%s'", input_line_pointer);
  212: 		return;
  213: 	} /* if not bss */
  214: 
  215: 	input_line_pointer += 6;
  216: 	SKIP_WHITESPACE();
  217: 
  218: 	if (*input_line_pointer == ',') {
  219: 		++input_line_pointer;
  220: 
  221: 		SKIP_WHITESPACE();
  222: 		if (*input_line_pointer == '\n') {
  223: 			as_bad("Missing alignment");
  224: 			return;
  225: 		}
  226: 
  227: 		align = get_absolute_expression();
  228: 		if (align > max_alignment){
  229: 			align = max_alignment;
  230: 			as_warn("Alignment too large: %d. assumed.", align);
  231: 		} else if (align < 0) {
  232: 			align = 0;
  233: 			as_warn("Alignment negative. 0 assumed.");
  234: 		}
  235: #ifdef MANY_SEGMENTS
  236: #define SEG_BSS SEG_E2
  237: 		record_alignment(SEG_E2, align);
  238: #else
  239: 		record_alignment(SEG_BSS, align);
  240: #endif
  241: 
  242: 		/* convert to a power of 2 alignment */
  243: 		for (temp = 0; (align & 1) == 0; align >>= 1, ++temp) ;;
  244: 
  245: 		if (align != 1) {
  246: 			as_bad("Alignment not a power of 2");
  247: 			ignore_rest_of_line();
  248: 			return;
  249: 		} /* not a power of two */
  250: 
  251: 		align = temp;
  252: 
  253: 		/* Align */
  254: 		align = ~((~0) << align);	/* Convert to a mask */
  255: 		local_bss_counter = (local_bss_counter + align) & (~align);
  256: 	} /* if has optional alignment */
  257: 
  258: 	if (S_GET_OTHER(symbolP) == 0
  259: 	    && S_GET_DESC(symbolP) == 0
  260: 	    && ((S_GET_SEGMENT(symbolP) == SEG_BSS
  261: 		 && S_GET_VALUE(symbolP) == local_bss_counter)
  262: 		|| !S_IS_DEFINED(symbolP))) {
  263: 		S_SET_VALUE(symbolP, local_bss_counter);
  264: 		S_SET_SEGMENT(symbolP, SEG_BSS);
  265: 		symbolP->sy_frag  = &bss_address_frag;
  266: 		local_bss_counter += size;
  267: 	} else {
  268: 		as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
  269: 			S_GET_VALUE(symbolP), local_bss_counter);
  270: 	} /* if not redefining */
  271: 
  272: 	demand_empty_rest_of_line();
  273: 	return;
  274: } /* s_reserve() */
  275: 
  276: static void s_common() {
  277: 	register char *name;
  278: 	register char c;
  279: 	register char *p;
  280: 	register int temp;
  281: 	register symbolS *	symbolP;
  282: 
  283: 	name = input_line_pointer;
  284: 	c = get_symbol_end();
  285: 	/* just after name is now '\0' */
  286: 	p = input_line_pointer;
  287: 	*p = c;
  288: 	SKIP_WHITESPACE();
  289: 	if (* input_line_pointer != ',') {
  290: 		as_bad("Expected comma after symbol-name");
  291: 		ignore_rest_of_line();
  292: 		return;
  293: 	}
  294: 	input_line_pointer ++; /* skip ',' */
  295: 	if ((temp = get_absolute_expression ()) < 0) {
  296: 		as_bad(".COMMon length (%d.) <0! Ignored.", temp);
  297: 		ignore_rest_of_line();
  298: 		return;
  299: 	}
  300: 	*p = 0;
  301: 	symbolP = symbol_find_or_make(name);
  302: 	*p = c;
  303: 	if (S_IS_DEFINED(symbolP)) {
  304: 		as_bad("Ignoring attempt to re-define symbol");
  305: 		ignore_rest_of_line();
  306: 		return;
  307: 	}
  308: 	if (S_GET_VALUE(symbolP) != 0) {
  309: 		if (S_GET_VALUE(symbolP) != temp) {
  310: 			as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
  311: 				S_GET_NAME(symbolP), S_GET_VALUE(symbolP), temp);
  312: 		}
  313: 	} else {
  314: 		S_SET_VALUE(symbolP, temp);
  315: 		S_SET_EXTERNAL(symbolP);
  316: 	}
  317: 	know(symbolP->sy_frag == &zero_address_frag);
  318: 	if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0
  319: 	    && strncmp(input_line_pointer, ",\"data\"", 7) != 0) {
  320: 		p=input_line_pointer;
  321: 		while (*p && *p != '\n')
  322: 		    p++;
  323: 		c= *p;
  324: 		*p='\0';
  325: 		as_bad("bad .common segment: `%s'", input_line_pointer);
  326: 		*p=c;
  327: 		return;
  328: 	}
  329: 	input_line_pointer += 6 + (input_line_pointer[2] == 'd'); /* Skip either */
  330: 	demand_empty_rest_of_line();
  331: 	return;
  332: } /* s_common() */
  333: 
  334: static void s_seg() {
  335: 
  336: 	if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
  337: 		input_line_pointer += 6;
  338: 		s_text();
  339: 		return;
  340: 	}
  341: 	if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
  342: 		input_line_pointer += 6;
  343: 		s_data();
  344: 		return;
  345: 	}
  346: 	if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
  347: 		input_line_pointer += 7;
  348: 		s_data1();
  349: 		return;
  350: 	}
  351: 	if (strncmp(input_line_pointer, "\"bss\"", 5) == 0) {
  352: 		input_line_pointer += 5;
  353: 		/* We only support 2 segments -- text and data -- for now, so
  354: 		   things in the "bss segment" will have to go into data for now.
  355: 		   You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
  356: 		subseg_new(SEG_DATA, 255);	/* FIXME-SOMEDAY */
  357: 		return;
  358: 	}
  359: 	as_bad("Unknown segment type");
  360: 	demand_empty_rest_of_line();
  361: 	return;
  362: } /* s_seg() */
  363: 
  364: static void s_data1() {
  365: 	subseg_new(SEG_DATA, 1);
  366: 	demand_empty_rest_of_line();
  367: 	return;
  368: } /* s_data1() */
  369: 
  370: static void s_proc() {
  371: 	extern char is_end_of_line[];
  372: 
  373: 	while (!is_end_of_line[*input_line_pointer]) {
  374: 		++input_line_pointer;
  375: 	}
  376: 	++input_line_pointer;
  377: 	return;
  378: } /* s_proc() */
  379: 
  380: /*
  381:  * GI: This is needed for compatibility with Sun's assembler - which
  382:  * otherwise generates a warning when certain "suspect" instructions
  383:  * appear in the delay slot of a branch.  And more seriously without
  384:  * this directive in certain cases Sun's assembler will rearrange
  385:  * code thinking it knows how to alter things when it doesn't.
  386:  */
  387: static void
  388: s_empty()
  389: {
  390: 	demand_empty_rest_of_line();
  391: 	return;
  392: } /* s_empty() */
  393: 
  394: /* This function is called once, at assembler startup time.  It should
  395:    set up all the tables, etc. that the MD part of the assembler will need. */
  396: void md_begin() {
  397: 	register char *retval = NULL;
  398: 	int lose = 0;
  399: 	register unsigned int i = 0;
  400: 
  401: 	op_hash = hash_new();
  402: 	if (op_hash == NULL)
  403: 	    as_fatal("Virtual memory exhausted");
  404: 
  405: 	while (i < NUMOPCODES) {
  406: 		const char *name = sparc_opcodes[i].name;
  407: 		retval = hash_insert(op_hash, name, &sparc_opcodes[i]);
  408: 		if (retval != NULL && *retval != '\0') {
  409: 			fprintf (stderr, "internal error: can't hash `%s': %s\n",
  410: 				 sparc_opcodes[i].name, retval);
  411: 			lose = 1;
  412: 		}
  413: 		do
  414: 		    {
  415: 			    if (sparc_opcodes[i].match & sparc_opcodes[i].lose) {
  416: 				    fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
  417: 					     sparc_opcodes[i].name, sparc_opcodes[i].args);
  418: 				    lose = 1;
  419: 			    }
  420: 			    ++i;
  421: 		    } while (i < NUMOPCODES
  422: 			     && !strcmp(sparc_opcodes[i].name, name));
  423: 	}
  424: 
  425: 	if (lose)
  426: 	    as_fatal("Broken assembler.  No assembly attempted.");
  427: 
  428: 	for (i = '0'; i < '8'; ++i)
  429: 	    octal[i] = 1;
  430: 	for (i = '0'; i <= '9'; ++i)
  431: 	    toHex[i] = i - '0';
  432: 	for (i = 'a'; i <= 'f'; ++i)
  433: 	    toHex[i] = i + 10 - 'a';
  434: 	for (i = 'A'; i <= 'F'; ++i)
  435: 	    toHex[i] = i + 10 - 'A';
  436: 
  437: #if 0
  438: 	if (picmode)
  439: 		GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
  440: #endif
  441: } /* md_begin() */
  442: 
  443: void md_end() {
  444: 	return;
  445: } /* md_end() */
  446: 
  447: void md_assemble(str)
  448: char *str;
  449: {
  450: 	char *toP;
  451: 	int rsd;
  452: 
  453: 	know(str);
  454: 	sparc_ip(str);
  455: 
  456: 	/* See if "set" operand is absolute and small; skip sethi if so. */
  457: 	if (special_case == SPECIAL_CASE_SET && the_insn.exp.X_seg == SEG_ABSOLUTE) {
  458: 		if (the_insn.exp.X_add_number >= -(1<<12)
  459: 		    && the_insn.exp.X_add_number <   (1<<12)) {
  460: 			the_insn.opcode = 0x80102000 		/* or %g0,imm,... */
  461: 			    | (the_insn.opcode & 0x3E000000)	/* dest reg */
  462: 				| (the_insn.exp.X_add_number & 0x1FFF); /* imm */
  463: 			special_case = 0;		/* No longer special */
  464: 			the_insn.reloc = NO_RELOC;	/* No longer relocated */
  465: 		}
  466: 	}
  467: 
  468: 	toP = frag_more(4);
  469: 	/* put out the opcode */
  470: 	md_number_to_chars(toP, the_insn.opcode, 4);
  471: 
  472: 	/* put out the symbol-dependent stuff */
  473: 	if (the_insn.reloc != NO_RELOC) {
  474: 		fix_new(frag_now,              /* which frag */
  475: 			(toP - frag_now->fr_literal), /* where */
  476: 			4,                            /* size */
  477: 			the_insn.exp.X_add_symbol,
  478: 			the_insn.exp.X_subtract_symbol,
  479: 			the_insn.exp.X_add_number,
  480: 			the_insn.pcrel,
  481: 			the_insn.reloc,
  482: 			the_insn.exp.X_got_symbol);
  483: 	}
  484: 	switch (special_case) {
  485: 
  486: 	case SPECIAL_CASE_SET:
  487: 		special_case = 0;
  488: 		know(the_insn.reloc == RELOC_HI22 ||
  489: 				the_insn.reloc == RELOC_BASE22);
  490: 		/* See if "set" operand has no low-order bits; skip OR if so. */
  491: 		if (the_insn.exp.X_seg == SEG_ABSOLUTE
  492: 		    && ((the_insn.exp.X_add_number & 0x3FF) == 0))
  493: 		    return;
  494: 		toP = frag_more(4);
  495: 		rsd = (the_insn.opcode >> 25) & 0x1f;
  496: 		the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14);
  497: 		md_number_to_chars(toP, the_insn.opcode, 4);
  498: 		fix_new(frag_now,                           /* which frag */
  499: 			(toP - frag_now->fr_literal),       /* where */
  500: 			4,                                  /* size */
  501: 			the_insn.exp.X_add_symbol,
  502: 			the_insn.exp.X_subtract_symbol,
  503: 			the_insn.exp.X_add_number,
  504: 			the_insn.pcrel,
  505: 			the_insn.reloc==RELOC_BASE22?RELOC_BASE10:RELOC_LO10,
  506: 			the_insn.exp.X_got_symbol);
  507: 		return;
  508: 
  509: 	case SPECIAL_CASE_FDIV:
  510: 		/* According to information leaked from Sun, the "fdiv" instructions
  511: 		   on early SPARC machines would produce incorrect results sometimes.
  512: 		   The workaround is to add an fmovs of the destination register to
  513: 		   itself just after the instruction.  This was true on machines
  514: 		   with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
  515: 		special_case = 0;
  516: 		assert(the_insn.reloc == NO_RELOC);
  517: 		toP = frag_more(4);
  518: 		rsd = (the_insn.opcode >> 25) & 0x1f;
  519: 		the_insn.opcode = 0x81A00020 | (rsd << 25) | rsd;  /* fmovs dest,dest */
  520: 		md_number_to_chars(toP, the_insn.opcode, 4);
  521: 		return;
  522: 
  523: 	case 0:
  524: 		return;
  525: 
  526: 	default:
  527: 		as_fatal("md_assemble: failed sanity check.");
  528: 	}
  529: } /* md_assemble() */
  530: 
  531: static void sparc_ip(str)
  532: char *str;
  533: {
  534: 	char *error_message = "";
  535: 	char *s;
  536: 	const char *args;
  537: 	char c;
  538: 	struct sparc_opcode *insn;
  539: 	char *argsStart;
  540: 	unsigned long opcode;
  541: 	unsigned int mask = 0;
  542: 	int match = 0;
  543: 	int comma = 0;
  544: 
  545: 	for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s)
  546: 	    ;
  547: 	switch (*s) {
  548: 
  549: 	case '\0':
  550: 		break;
  551: 
  552: 	case ',':
  553: 		comma = 1;
  554: 
  555: 		/*FALLTHROUGH */
  556: 
  557: 	case ' ':
  558: 		*s++ = '\0';
  559: 		break;
  560: 
  561: 	default:
  562: 		as_bad("Unknown opcode: `%s'", str);
  563: 		exit(1);
  564: 	}
  565: 	if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) {
  566: 		as_bad("Unknown opcode: `%s'", str);
  567: 		return;
  568: 	}
  569: 	if (comma) {
  570: 		*--s = ',';
  571: 	}
  572: 	argsStart = s;
  573: 	for (;;) {
  574: 		opcode = insn->match;
  575: 		memset(&the_insn, '\0', sizeof(the_insn));
  576: 		the_insn.reloc = NO_RELOC;
  577: 
  578: 		/*
  579: 		 * Build the opcode, checking as we go to make
  580: 		 * sure that the operands match
  581: 		 */
  582: 		for (args = insn->args; ; ++args) {
  583: 			switch (*args) {
  584: 
  585: 			case 'M':
  586: 			case 'm':
  587: 				if (strncmp(s, "%asr", 4) == 0) {
  588: 					s += 4;
  589: 
  590: 					if (isdigit(*s)) {
  591: 						long num = 0;
  592: 
  593: 						while (isdigit(*s)) {
  594: 							num = num*10 + *s-'0';
  595: 							++s;
  596: 						}
  597: 
  598: 						if (num < 16 || 31 < num) {
  599: 							error_message = ": asr number must be between 15 and 31";
  600: 							goto error;
  601: 						} /* out of range */
  602: 
  603: 						opcode |= (*args == 'M' ? RS1(num) : RD(num));
  604: 						continue;
  605: 					} else {
  606: 						error_message = ": expecting %asrN";
  607: 						goto error;
  608: 					} /* if %asr followed by a number. */
  609: 
  610: 				} /* if %asr */
  611: 				break;
  612: 
  613: 
  614: 			case '\0':  /* end of args */
  615: 				if (*s == '\0') {
  616: 					match = 1;
  617: 				}
  618: 				break;
  619: 
  620: 			case '+':
  621: 				if (*s == '+') {
  622: 					++s;
  623: 					continue;
  624: 				}
  625: 				if (*s == '-') {
  626: 					continue;
  627: 				}
  628: 				break;
  629: 
  630: 			case '[':   /* these must match exactly */
  631: 			case ']':
  632: 			case ',':
  633: 			case ' ':
  634: 				if (*s++ == *args)
  635: 				    continue;
  636: 				break;
  637: 
  638: 			case '#':   /* must be at least one digit */
  639: 				if (isdigit(*s++)) {
  640: 					while (isdigit(*s)) {
  641: 						++s;
  642: 					}
  643: 					continue;
  644: 				}
  645: 				break;
  646: 
  647: 			case 'C':   /* coprocessor state register */
  648: 				if (strncmp(s, "%csr", 4) == 0) {
  649: 					s += 4;
  650: 					continue;
  651: 				}
  652: 				break;
  653: 
  654: 			case 'b':    /* next operand is a coprocessor register */
  655: 			case 'c':
  656: 			case 'D':
  657: 				if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) {
  658: 					mask = *s++;
  659: 					if (isdigit(*s)) {
  660: 						mask = 10 * (mask - '0') + (*s++ - '0');
  661: 						if (mask >= 32) {
  662: 							break;
  663: 						}
  664: 					} else {
  665: 						mask -= '0';
  666: 					}
  667: 					switch (*args) {
  668: 
  669: 					case 'b':
  670: 						opcode |= mask << 14;
  671: 						continue;
  672: 
  673: 					case 'c':
  674: 						opcode |= mask;
  675: 						continue;
  676: 
  677: 					case 'D':
  678: 						opcode |= mask << 25;
  679: 						continue;
  680: 					}
  681: 				}
  682: 				break;
  683: 
  684: 			case 'r':   /* next operand must be a register */
  685: 			case 's':
  686: 			case '1':
  687: 			case '2':
  688: 			case 'd':
  689: 			case 'x':
  690: 				if (*s++ == '%') {
  691: 					switch (c = *s++) {
  692: 
  693: 					case 'f':   /* frame pointer */
  694: 						if (*s++ == 'p') {
  695: 							mask = 0x1e;
  696: 							break;
  697: 						}
  698: 						goto error;
  699: 
  700: 					case 'g':   /* global register */
  701: 						if (isoctal(c = *s++)) {
  702: 							mask = c - '0';
  703: 							break;
  704: 						}
  705: 						goto error;
  706: 
  707: 					case 'i':   /* in register */
  708: 						if (isoctal(c = *s++)) {
  709: 							mask = c - '0' + 24;
  710: 							break;
  711: 						}
  712: 						goto error;
  713: 
  714: 					case 'l':   /* local register */
  715: 						if (isoctal(c = *s++)) {
  716: 							mask= (c - '0' + 16) ;
  717: 							break;
  718: 						}
  719: 						goto error;
  720: 
  721: 					case 'o':   /* out register */
  722: 						if (isoctal(c = *s++)) {
  723: 							mask= (c - '0' + 8) ;
  724: 							break;
  725: 						}
  726: 						goto error;
  727: 
  728: 					case 's':   /* stack pointer */
  729: 						if (*s++ == 'p') {
  730: 							mask= 0xe;
  731: 							break;
  732: 						}
  733: 						goto error;
  734: 
  735: 					case 'r': /* any register */
  736: 						if (!isdigit(c = *s++)) {
  737: 							goto error;
  738: 						}
  739: 						/* FALLTHROUGH */
  740: 					case '0': case '1': case '2': case '3': case '4':
  741: 					case '5': case '6': case '7': case '8': case '9':
  742: 						if (isdigit(*s)) {
  743: 							if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
  744: 								goto error;
  745: 							}
  746: 						} else {
  747: 							c -= '0';
  748: 						}
  749: 						mask= c;
  750: 						break;
  751: 
  752: 					case 'x':
  753: 						opcode |= (mask << 25) | mask;
  754: 						continue;
  755: 
  756: 					default:
  757: 						goto error;
  758: 					}
  759: 					/*
  760: 					 * Got the register, now figure out where
  761: 					 * it goes in the opcode.
  762: 					 */
  763: 					switch (*args) {
  764: 
  765: 					case '1':
  766: 						opcode |= mask << 14;
  767: 						continue;
  768: 
  769: 					case '2':
  770: 						opcode |= mask;
  771: 						continue;
  772: 
  773: 					case 'd':
  774: 						opcode |= mask << 25;
  775: 						continue;
  776: 
  777: 					case 'r':
  778: 						opcode |= (mask << 25) | (mask << 14);
  779: 						continue;
  780: 					case 'x':
  781: 						opcode |= (mask << 25) | mask;
  782: 						continue;
  783: 					}
  784: 				}
  785: 				break;
  786: 
  787: 			case 'e': /* next operand is a floating point register */
  788: 			case 'v':
  789: 			case 'V':
  790: 
  791: 			case 'f':
  792: 			case 'B':
  793: 			case 'R':
  794: 
  795: 			case 'g':
  796: 			case 'H':
  797: 			case 'J': {
  798: 				char format;
  799: 
  800: 				if (*s++ == '%'
  801: 
  802: 				    && ((format = *s) == 'f')
  803: 
  804: 				    && isdigit(*++s)) {
  805: 
  806: 
  807: 
  808: 					for (mask = 0; isdigit(*s); ++s) {
  809: 						mask = 10 * mask + (*s - '0');
  810: 					} /* read the number */
  811: 
  812: 					if ((*args == 'u'
  813: 					     || *args == 'v'
  814: 					     || *args == 'B'
  815: 					     || *args == 'H')
  816: 					    && (mask & 1)) {
  817: 						break;
  818: 					} /* register must be even numbered */
  819: 
  820: 					if ((*args == 'U'
  821: 					     || *args == 'V'
  822: 					     || *args == 'R'
  823: 					     || *args == 'J')
  824: 					    && (mask & 3)) {
  825: 						break;
  826: 					} /* register must be multiple of 4 */
  827: 
  828: 					if (format == 'f') {
  829: 						if (mask >= 32) {
  830: 							error_message = ": There are only 32 f registers; [0-31]";
  831: 							goto error;
  832: 						} /* on error */
  833: 					} /* if not an 'f' register. */
  834: 				} /* on error */
  835: 
  836: 				switch (*args) {
  837: 
  838: 				case 'v':
  839: 				case 'V':
  840: 				case 'e':
  841: 					opcode |= RS1(mask);
  842: 					continue;
  843: 
  844: 
  845: 				case 'f':
  846: 				case 'B':
  847: 				case 'R':
  848: 					opcode |= RS2(mask);
  849: 					continue;
  850: 
  851: 				case 'g':
  852: 				case 'H':
  853: 				case 'J':
  854: 					opcode |= RD(mask);
  855: 					continue;
  856: 				} /* pack it in. */
  857: 
  858: 				know(0);
  859: 				break;
  860: 			} /* float arg */
  861: 
  862: 			case 'F':
  863: 				if (strncmp(s, "%fsr", 4) == 0) {
  864: 					s += 4;
  865: 					continue;
  866: 				}
  867: 				break;
  868: 
  869: 			case 'h': /* high 22 bits */
  870: 				/*
  871: 				 * In the case of a `set' pseudo instruction
  872: 				 * we have an implied `%hi' operator.
  873: 				 */
  874: 				if (special_case == SPECIAL_CASE_SET)
  875: 					the_insn.reloc = RELOC_HI22;
  876: 				else
  877: 					the_insn.reloc = RELOC_22;
  878: 				goto immediate;
  879: 
  880: 			case 'l': /* 22 bit PC relative immediate */
  881: 				the_insn.reloc = RELOC_WDISP22;
  882: 				the_insn.pcrel = 1;
  883: 				goto immediate;
  884: 
  885: 			case 'L': /* 30 bit immediate */
  886: 				the_insn.reloc =
  887: #ifdef PIC
  888: 					picmode?RELOC_JMP_TBL:
  889: #endif
  890: 					RELOC_WDISP30;
  891: 				the_insn.pcrel = 1;
  892: 				goto immediate;
  893: 
  894: 			case 'n': /* 22 bit immediate */
  895: 				the_insn.reloc = RELOC_22;
  896: 				goto immediate;
  897: 
  898: 			case 'i':   /* 13 bit immediate */
  899: 				the_insn.reloc = RELOC_13;
  900: 
  901: 				/*FALLTHROUGH */
  902: 
  903: 			immediate:
  904: 				if (*s == ' ')
  905: 				    s++;
  906: 				if (*s == '%') {
  907: 					if ((c = s[1]) == 'h' && s[2] == 'i') {
  908: 						if (the_insn.reloc != RELOC_22)
  909: 							as_bad(
  910: 						"`%hi' in improper context");
  911: 						the_insn.reloc = RELOC_HI22;
  912: 						s+=3;
  913: 					} else if (c == 'l' && s[2] == 'o') {
  914: 						the_insn.reloc = RELOC_LO10;
  915: 						s+=3;
  916: 					} else
  917: 					    break;
  918: 				}
  919: 				/* Note that if the getExpression() fails, we
  920: 				   will still have created U entries in the
  921: 				   symbol table for the 'symbols' in the input
  922: 				   string.  Try not to create U symbols for
  923: 				   registers, etc. */
  924: 				{
  925: 					/* This stuff checks to see if the
  926: 					   expression ends in +%reg If it does,
  927: 					   it removes the register from the
  928: 					   expression, and re-sets 's' to point
  929: 					   to the right place */
  930: 
  931: 					char *s1;
  932: 
  933: 					for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ;;
  934: 
  935: 					if (s1 != s && isdigit(s1[-1])) {
  936: 						if (s1[-2] == '%' && s1[-3] == '+') {
  937: 							s1 -= 3;
  938: 							*s1 = '\0';
  939: 							(void) getExpression(s);
  940: 							*s1 = '+';
  941: 							s = s1;
  942: 							continue;
  943: 						} else if (strchr("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+') {
  944: 							s1 -= 4;
  945: 							*s1 = '\0';
  946: 							(void) getExpression(s);
  947: 							*s1 = '+';
  948: 							s = s1;
  949: 							continue;
  950: 						}
  951: 					}
  952: 				}
  953: 				(void)getExpression(s);
  954: #ifdef PIC
  955: 				/*
  956: 				 * Handle refs to __GLOBAL_OFFSET_TABLE_
  957: 				 */
  958: 				if (the_insn.exp.X_got_symbol) {
  959: 					switch(the_insn.reloc) {
  960: 					case RELOC_22:
  961: 					case RELOC_HI22:
  962: 						the_insn.reloc = RELOC_PC22;
  963: 						the_insn.pcrel = 1;
  964: 						break;
  965: 					case RELOC_LO10:
  966: 						the_insn.reloc = RELOC_PC10;
  967: 						the_insn.pcrel = 1;
  968: 						break;
  969: 					default:
  970: 						break;
  971: 					}
  972: 				}
  973: 
  974: 				if (picmode && the_insn.exp.X_add_symbol) {
  975: 					switch (the_insn.reloc) {
  976: 					case RELOC_LO10:
  977: 						the_insn.reloc = RELOC_BASE10;
  978: 						the_insn.exp.X_add_symbol->sy_forceout = 1;
  979: 						break;
  980: 					case RELOC_HI22:
  981: 						the_insn.reloc = RELOC_BASE22;
  982: 						the_insn.exp.X_add_symbol->sy_forceout = 1;
  983: 						break;
  984: 					case RELOC_13:
  985: 						the_insn.reloc = RELOC_BASE13;
  986: 						the_insn.exp.X_add_symbol->sy_forceout = 1;
  987: 						break;
  988: 					}
  989: 				}
  990: #endif
  991: 				s = expr_end;
  992: 				continue;
  993: 
  994: 			case 'a':
  995: 				if (*s++ == 'a') {
  996: 					opcode |= ANNUL;
  997: 					continue;
  998: 				}
  999: 				break;
 1000: 
 1001: 			case 'A': {
 1002: 				char *push = input_line_pointer;
 1003: 				expressionS e;
 1004: 
 1005: 				input_line_pointer = s;
 1006: 
 1007: 				if (expression(&e) == SEG_ABSOLUTE) {
 1008: 					opcode |= e.X_add_number << 5;
 1009: 					s = input_line_pointer;
 1010: 					input_line_pointer = push;
 1011: 					continue;
 1012: 				} /* if absolute */
 1013: 
 1014: 				break;
 1015: 			} /* alternate space */
 1016: 
 1017: 			case 'p':
 1018: 				if (strncmp(s, "%psr", 4) == 0) {
 1019: 					s += 4;
 1020: 					continue;
 1021: 				}
 1022: 				break;
 1023: 
 1024: 			case 'q':   /* floating point queue */
 1025: 				if (strncmp(s, "%fq", 3) == 0) {
 1026: 					s += 3;
 1027: 					continue;
 1028: 				}
 1029: 				break;
 1030: 
 1031: 			case 'Q':   /* coprocessor queue */
 1032: 				if (strncmp(s, "%cq", 3) == 0) {
 1033: 					s += 3;
 1034: 					continue;
 1035: 				}
 1036: 				break;
 1037: 
 1038: 			case 'S':
 1039: 				if (strcmp(str, "set") == 0) {
 1040: 					special_case = SPECIAL_CASE_SET;
 1041: 					continue;
 1042: 				} else if (strncmp(str, "fdiv", 4) == 0) {
 1043: 					special_case = SPECIAL_CASE_FDIV;
 1044: 					continue;
 1045: 				}
 1046: 				break;
 1047: 
 1048: 			case 't':
 1049: 				if (strncmp(s, "%tbr", 4) != 0)
 1050: 				    break;
 1051: 				s += 4;
 1052: 				continue;
 1053: 
 1054: 			case 'w':
 1055: 				if (strncmp(s, "%wim", 4) != 0)
 1056: 				    break;
 1057: 				s += 4;
 1058: 				continue;
 1059: 
 1060: 			case 'y':
 1061: 				if (strncmp(s, "%y", 2) != 0)
 1062: 				    break;
 1063: 				s += 2;
 1064: 				continue;
 1065: 
 1066: 			default:
 1067: 				as_fatal("sparc_ip: failed sanity check.");
 1068: 			} /* switch on arg code */
 1069: 			break;
 1070: 		} /* for each arg that we expect */
 1071: 	error:
 1072: 		if (match == 0) {
 1073: 			/* Args don't match. */
 1074: 			if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
 1075: 			    && !strcmp(insn->name, insn[1].name)) {
 1076: 				++insn;
 1077: 				s = argsStart;
 1078: 				continue;
 1079: 			} else {
 1080: 				as_bad("Illegal operands%s", error_message);
 1081: 				return;
 1082: 			}
 1083: 		} else {
 1084: 			if (insn->architecture > current_architecture) {
 1085: 				if (!architecture_requested || warn_on_bump) {
 1086: 
 1087: 					if (warn_on_bump) {
 1088: 						as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
 1089: 							architecture_pname[current_architecture],
 1090: 							architecture_pname[insn->architecture],
 1091: 							str);
 1092: 					} /* if warning */
 1093: 
 1094: 					current_architecture = insn->architecture;
 1095: 				} else {
 1096: 					as_bad("architecture mismatch on \"%s\" (\"%s\").  current architecture is \"%s\"",
 1097: 					       str,
 1098: 					       architecture_pname[insn->architecture],
 1099: 					       architecture_pname[current_architecture]);
 1100: 					return;
 1101: 				} /* if bump ok else error */
 1102: 			} /* if architecture higher */
 1103: 		} /* if no match */
 1104: 
 1105: 		break;
 1106: 	} /* forever looking for a match */
 1107: 
 1108: 	the_insn.opcode = opcode;
 1109: #if DEBUG_SPARC
 1110: 	if (flagseen['D'])
 1111: 		print_insn(&the_insn);
 1112: #endif
 1113: 	return;
 1114: } /* sparc_ip() */
 1115: 
 1116: static int getExpression(str)
 1117: char *str;
 1118: {
 1119: 	char *save_in;
 1120: 	segT seg;
 1121: 
 1122: 	save_in = input_line_pointer;
 1123: 	input_line_pointer = str;
 1124: 	switch (seg = expression(&the_insn.exp)) {
 1125: 
 1126: 	case SEG_ABSOLUTE:
 1127: 	case SEG_TEXT:
 1128: 	case SEG_DATA:
 1129: 	case SEG_BSS:
 1130: 	case SEG_UNKNOWN:
 1131: 	case SEG_DIFFERENCE:
 1132: 	case SEG_BIG:
 1133: 	case SEG_ABSENT:
 1134: 		break;
 1135: 
 1136: 	default:
 1137: 		the_insn.error = "bad segment";
 1138: 		expr_end = input_line_pointer;
 1139: 		input_line_pointer=save_in;
 1140: 		return 1;
 1141: 	}
 1142: 
 1143: 	expr_end = input_line_pointer;
 1144: 	input_line_pointer = save_in;
 1145: 	return 0;
 1146: } /* getExpression() */
 1147: 
 1148: 
 1149: /*
 1150:   This is identical to the md_atof in m68k.c.  I think this is right,
 1151:   but I'm not sure.
 1152: 
 1153:   Turn a string in input_line_pointer into a floating point constant of type
 1154:   type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
 1155:   emitted is stored in *sizeP. An error message is returned, or NULL on OK.
 1156:   */
 1157: 
 1158: /* Equal to MAX_PRECISION in atof-ieee.c */
 1159: #define MAX_LITTLENUMS 6
 1160: 
 1161: char *md_atof(type,litP,sizeP)
 1162: char type;
 1163: char *litP;
 1164: int *sizeP;
 1165: {
 1166: 	int prec;
 1167: 	LITTLENUM_TYPE words[MAX_LITTLENUMS];
 1168: 	LITTLENUM_TYPE *wordP;
 1169: 	char *t;
 1170: 	char *atof_ieee();
 1171: 
 1172: 	switch (type) {
 1173: 
 1174: 	case 'f':
 1175: 	case 'F':
 1176: 	case 's':
 1177: 	case 'S':
 1178: 		prec = 2;
 1179: 		break;
 1180: 
 1181: 	case 'd':
 1182: 	case 'D':
 1183: 	case 'r':
 1184: 	case 'R':
 1185: 		prec = 4;
 1186: 		break;
 1187: 
 1188: 	case 'x':
 1189: 	case 'X':
 1190: 		prec = 6;
 1191: 		break;
 1192: 
 1193: 	case 'p':
 1194: 	case 'P':
 1195: 		prec = 6;
 1196: 		break;
 1197: 
 1198: 	default:
 1199: 		*sizeP=0;
 1200: 		return "Bad call to MD_ATOF()";
 1201: 	}
 1202: 	t=atof_ieee(input_line_pointer,type,words);
 1203: 	if (t)
 1204: 	    input_line_pointer=t;
 1205: 	*sizeP=prec * sizeof(LITTLENUM_TYPE);
 1206: 	for (wordP=words;prec--;) {
 1207: 		md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
 1208: 		litP+=sizeof(LITTLENUM_TYPE);
 1209: 	}
 1210: 	return "";	/* Someone should teach Dean about null pointers */
 1211: } /* md_atof() */
 1212: 
 1213: /*
 1214:  * Write out big-endian.
 1215:  */
 1216: void md_number_to_chars(buf,val,n)
 1217: char *buf;
 1218: long val;
 1219: int n;
 1220: {
 1221: 
 1222: 	switch (n) {
 1223: 
 1224: 	case 4:
 1225: 		*buf++ = val >> 24;
 1226: 		*buf++ = val >> 16;
 1227: 	case 2:
 1228: 		*buf++ = val >> 8;
 1229: 	case 1:
 1230: 		*buf = val;
 1231: 		break;
 1232: 
 1233: 	default:
 1234: 		as_fatal("md_number_to_chars: failed sanity check.");
 1235: 	}
 1236: 	return;
 1237: } /* md_number_to_chars() */
 1238: 
 1239: static int reloc_check(val, bits, fixP)
 1240: long val;
 1241: int bits;
 1242: fixS *fixP	/* For reporting errors */;
 1243: {
 1244: 	if (((val & (-1 << bits)) != 0)
 1245: 	    && ((val & (-1 << bits)) != (-1 << (bits - 0)))) {
 1246: 
 1247: 		long addr = fixP->fx_where + fixP->fx_frag->fr_address;
 1248: 		int ln;
 1249: 		char *fname;
 1250: 
 1251: 		if (fixP->fx_frag->line) {
 1252: 			fname = fixP->fx_frag->line->file->filename;
 1253: 			ln = fixP->fx_frag->line->line;
 1254: 		} else {
 1255: 			fname = "";
 1256: 			ln = -1;
 1257: 		}
 1258: 
 1259: 		as_warn_where(fname, ln,
 1260: 			"Relocation (%s) overflow at %#x, value truncated.",
 1261: 			Reloc[fixP->fx_r_type], addr);
 1262: 	} /* on overflow */
 1263: 
 1264: } /* reloc_check() */
 1265: 
 1266: 
 1267: /* Apply a fixS to the frags, now that we know the value it ought to
 1268:    hold. */
 1269: 
 1270: void md_apply_fix(fixP, val)
 1271: fixS *fixP;
 1272: long val;
 1273: {
 1274: 	char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
 1275: 	long addr = fixP->fx_where + fixP->fx_frag->fr_address;
 1276: 
 1277: #if DEBUG_SPARC
 1278: 	if (flagseen['D'])
 1279: 		fprintf(stderr, "md_apply_fix: \"%s\" \"%s\", val %d -- %s\n",
 1280: 				((fixP->fx_addsy != NULL)
 1281: 				 ? ((S_GET_NAME(fixP->fx_addsy) != NULL)
 1282: 				    ? S_GET_NAME(fixP->fx_addsy)
 1283: 				    : "???")
 1284: 				 : "0"),
 1285: 				((fixP->fx_subsy != NULL)
 1286: 				 ? ((S_GET_NAME(fixP->fx_subsy) != NULL)
 1287: 				    ? S_GET_NAME(fixP->fx_subsy)
 1288: 				    : "???")
 1289: 				 : "0"),
 1290: 			val, Reloc[fixP->fx_r_type]);
 1291: #endif
 1292: 
 1293: 	assert(fixP->fx_size == 4);
 1294: 	assert(fixP->fx_r_type < NO_RELOC);
 1295: 
 1296: 	fixP->fx_addnumber = val;	/* Remember value for emit_reloc */
 1297: 
 1298: 	/*
 1299: 	 * This is a hack.  There should be a better way to
 1300: 	 * handle this.
 1301: 	 */
 1302: 	if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {
 1303: 		val += fixP->fx_where + fixP->fx_frag->fr_address;
 1304: 	}
 1305: 
 1306: 	switch (fixP->fx_r_type) {
 1307: 
 1308: 		/* Michael Bloom <mb@ttidca.tti.com> says...  [This] change was
 1309: 		   made to match the behavior of Sun's assembler.  Some broken
 1310: 		   loaders depend on that. At least one such loader actually
 1311: 		   adds the section data to what it finds in the addend. (It
 1312: 		   should only be using the addend like Sun's loader seems to).
 1313: 		   This caused incorrect relocation: (addend + adjustment)
 1314: 		   became  ( ( 2 * addend ) + adjustment ).  [and there should
 1315: 		   be no cases that reach here anyway.  */
 1316: 	case RELOC_32:
 1317: 		if (fixP->fx_addsy == NULL) {
 1318: 			/*
 1319: 			 * Ok, the remarks above do not hold if the
 1320: 			 * expression has been reduced to a number.
 1321: 			 */
 1322: 			buf[0] = val >> 24;
 1323: 			buf[1] = val >> 16;
 1324: 			buf[2] = val >> 8;
 1325: 			buf[3] = val;
 1326: 		} else {
 1327: 			buf[0] = 0;
 1328: 			buf[1] = 0;
 1329: 			buf[2] = 0;
 1330: 			buf[3] = 0;
 1331: 		}
 1332: 		break;
 1333: 
 1334: 	case RELOC_JMP_TBL:
 1335: 		if (!fixP->fx_addsy) {
 1336: 			val = (val >>= 2) + 1;
 1337: 			reloc_check(val, 30, fixP);
 1338: 
 1339: 			buf[0] |= (val >> 24) & 0x3f;
 1340: 			buf[1]= (val >> 16);
 1341: 			buf[2] = val >> 8;
 1342: 			buf[3] = val;
 1343: 		}
 1344: 		break;
 1345: 
 1346: 	case RELOC_WDISP30:
 1347: 		val = (val >>= 2) + 1;
 1348: 		reloc_check(val, 30, fixP);
 1349: 
 1350: 		buf[0] |= (val >> 24) & 0x3f;
 1351: 		buf[1]= (val >> 16);
 1352: 		buf[2] = val >> 8;
 1353: 		buf[3] = val;
 1354: 		break;
 1355: 
 1356: 	case RELOC_WDISP22:
 1357: 		val = (val >>= 2) + 1;
 1358: 		reloc_check(val, 22, fixP);
 1359: 
 1360: 		buf[1] |= (val >> 16) & 0x3f;
 1361: 		buf[2] = val >> 8;
 1362: 		buf[3] = val;
 1363: 		break;
 1364: 
 1365: 	/*
 1366: 	 * We should only use the RELOC_HI22 type as a result of the %hi
 1367: 	 * operator (which is implicit in the case of the `set' pseudo op),
 1368: 	 * This is NOT the same as using the `sethi' instruction, which merely
 1369: 	 * puts the 22 bit operand into the high 22 bits of the destination
 1370: 	 * register.
 1371: 	 */
 1372: 	case RELOC_22:
 1373: 		if (!fixP->fx_addsy) {
 1374: 			reloc_check(val, 22, fixP);
 1375: 
 1376: 			buf[1] |= (val >> 16) & 0x3f;
 1377: 			buf[2] = val >> 8;
 1378: 			buf[3] = val;
 1379: 		}
 1380: 		break;
 1381: 
 1382: 	case RELOC_HI22:
 1383: 	case RELOC_BASE22:
 1384: 		if (!fixP->fx_addsy) {
 1385: 			buf[1] |= (val >> 26) & 0x3f;
 1386: 			buf[2] = val >> 18;
 1387: 			buf[3] = val >> 10;
 1388: 		} else {
 1389: 			if (picmode && fixP->fx_r_type == RELOC_HI22)
 1390: 				as_warn("non-PIC access to %s",
 1391: 						S_GET_NAME(fixP->fx_addsy));
 1392: 			buf[2]=0;
 1393: 			buf[3]=0;
 1394: 		}
 1395: 		break;
 1396: 
 1397: 	case RELOC_13:
 1398: 	case RELOC_BASE13:
 1399: 		if (!fixP->fx_addsy) {
 1400: 			reloc_check(val, 13, fixP);
 1401: 			buf[2] |= (val >> 8) & 0x1f;
 1402: 			buf[3] = val;
 1403: 		} else {
 1404: 			buf[3]=0;
 1405: 		}
 1406: 		break;
 1407: 
 1408: 	case RELOC_LO10:
 1409: 	case RELOC_BASE10:
 1410: 		if (!fixP->fx_addsy) {
 1411: 			buf[2] |= (val >> 8) & 0x03;
 1412: 			buf[3] = val & 0xff;
 1413: 		} else {
 1414: 			if (picmode && fixP->fx_r_type == RELOC_LO10)
 1415: 				as_warn("non-PIC access to %s",
 1416: 						S_GET_NAME(fixP->fx_addsy));
 1417: 			buf[3]=0;
 1418: 		}
 1419: 		break;
 1420: 
 1421: 	case RELOC_PC10:
 1422: 	case RELOC_PC22:
 1423: 		if (fixP->fx_addsy != GOT_symbol) {
 1424: 			as_fatal("GOT");
 1425: 		}
 1426: 		break;
 1427: 
 1428: #if 0
 1429: 	case RELOC_8:         /* These don't seem to ever be needed. */
 1430: 	case RELOC_16:
 1431: 	case RELOC_DISP8:
 1432: 	case RELOC_DISP16:
 1433: 	case RELOC_DISP32:
 1434: 	case RELOC_SEGOFF16:
 1435: 	case RELOC_SFA_BASE:
 1436: 	case RELOC_SFA_OFF13:
 1437: 
 1438: 	case RELOC_GLOB_DAT: /* These are output by linker only */
 1439: 	case RELOC_JMP_SLOT:
 1440: 	case RELOC_RELATIVE:
 1441: #endif
 1442: 
 1443: 	case NO_RELOC:
 1444: 	default:
 1445: 		as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
 1446: 		break;
 1447: 	}
 1448: } /* md_apply_fix() */
 1449: 
 1450: /* should never be called for sparc */
 1451: void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
 1452: char *ptr;
 1453: long from_addr;
 1454: long to_addr;
 1455: fragS *frag;
 1456: symbolS *to_symbol;
 1457: {
 1458: 	as_fatal("sparc_create_short_jmp\n");
 1459: } /* md_create_short_jump() */
 1460: 
 1461: /* Translate internal representation of relocation info to target format.
 1462: 
 1463:    On sparc: first 4 bytes are normal unsigned long address, next three
 1464:    bytes are index, most sig. byte first.  Byte 7 is broken up with
 1465:    bit 7 as external, bits 6 & 5 unused, and the lower
 1466:    five bits as relocation type.  Next 4 bytes are long addend. */
 1467: /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
 1468: void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
 1469: char *where;
 1470: fixS *fixP;
 1471: relax_addressT segment_address_in_file;
 1472: {
 1473: 	long r_index;
 1474: 	long r_extern;
 1475: 	long r_addend = 0;
 1476: 	long r_address;
 1477: #ifdef PIC
 1478: 	int kflag = 0;
 1479: #endif
 1480: 
 1481: 	know(fixP->fx_addsy);
 1482: 
 1483: 	if (!S_IS_DEFINED(fixP->fx_addsy)) {
 1484: 		r_extern = 1;
 1485: 		r_index = fixP->fx_addsy->sy_number;
 1486: 	} else {
 1487: 		r_extern = 0;
 1488: 		r_index = S_GET_TYPE(fixP->fx_addsy);
 1489: #ifdef PIC
 1490: 		if (picmode) {
 1491: 			switch (fixP->fx_r_type) {
 1492: 			case RELOC_BASE10:
 1493: 			case RELOC_BASE13:
 1494: 			case RELOC_BASE22:
 1495: 				r_index = fixP->fx_addsy->sy_number;
 1496: 				if (S_IS_EXTERNAL(fixP->fx_addsy))
 1497: 					r_extern = 1;
 1498: 				kflag = 1;
 1499: 				break;
 1500: 
 1501: 			case RELOC_32:
 1502: 				if (!S_IS_EXTERNAL(fixP->fx_addsy))
 1503: 					break;
 1504: 				r_extern = 1;
 1505: 				r_index = fixP->fx_addsy->sy_number;
 1506: 				break;
 1507: 
 1508: 			default:
 1509: 				break;
 1510: 			}
 1511: 		}
 1512: #endif
 1513: 	}
 1514: 
 1515: 	/* this is easy */
 1516: 	md_number_to_chars(where,
 1517: 			   r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
 1518: 			   4);
 1519: 
 1520: 	/* now the fun stuff */
 1521: 	where[4] = (r_index >> 16) & 0x0ff;
 1522: 	where[5] = (r_index >> 8) & 0x0ff;
 1523: 	where[6] = r_index & 0x0ff;
 1524: 	where[7] = ((r_extern << 7)  & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
 1525: 
 1526: 	/* Also easy */
 1527: 	if (fixP->fx_addsy->sy_frag) {
 1528: 		r_addend = fixP->fx_addsy->sy_frag->fr_address;
 1529: 	}
 1530: 
 1531: 	if (fixP->fx_pcrel) {
 1532: #ifdef PIC
 1533: 		if (fixP->fx_gotsy) {
 1534: 			r_addend = r_address;
 1535: 			r_addend += fixP->fx_addnumber;
 1536: 		} else
 1537: #endif
 1538: 			r_addend -= r_address;
 1539: 	} else {
 1540: #ifdef PIC
 1541: 		if (kflag)
 1542: 			r_addend = 0;
 1543: 		else
 1544: #endif
 1545: 			r_addend = fixP->fx_addnumber;
 1546: 	}
 1547: 
 1548: 	md_number_to_chars(&where[8], r_addend, 4);
 1549: 
 1550: 	return;
 1551: } /* tc_aout_fix_to_chars() */
 1552: 
 1553: /* should never be called for sparc */
 1554: void md_convert_frag(headers, fragP)
 1555: object_headers *headers;
 1556: register fragS *fragP;
 1557: {
 1558: 	as_fatal("sparc_convert_frag\n");
 1559: } /* md_convert_frag() */
 1560: 
 1561: /* should never be called for sparc */
 1562: void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
 1563: char *ptr;
 1564: long from_addr, to_addr;
 1565: fragS	*frag;
 1566: symbolS	*to_symbol;
 1567: {
 1568: 	as_fatal("sparc_create_long_jump\n");
 1569: } /* md_create_long_jump() */
 1570: 
 1571: /* should never be called for sparc */
 1572: int md_estimate_size_before_relax(fragP, segtype)
 1573: fragS *fragP;
 1574: segT segtype;
 1575: {
 1576: 	as_fatal("sparc_estimate_size_before_relax\n");
 1577: 	return(1);
 1578: } /* md_estimate_size_before_relax() */
 1579: 
 1580: #if DEBUG_SPARC
 1581: /* for debugging only */
 1582: static void print_insn(insn)
 1583: struct sparc_it *insn;
 1584: {
 1585: 
 1586: 	if (insn->error) {
 1587: 		fprintf(stderr, "ERROR: %s\n", insn->error);
 1588: 	}
 1589: 	fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
 1590: 	fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
 1591: 	fprintf(stderr, "exp = {\n");
 1592: 	fprintf(stderr, "\t\tX_add_symbol = %s\n",
 1593: 		((insn->exp.X_add_symbol != NULL)
 1594: 		 ? ((S_GET_NAME(insn->exp.X_add_symbol) != NULL)
 1595: 		    ? S_GET_NAME(insn->exp.X_add_symbol)
 1596: 		    : "???")
 1597: 		 : "0"));
 1598: 	fprintf(stderr, "\t\tX_sub_symbol = %s\n",
 1599: 		((insn->exp.X_subtract_symbol != NULL)
 1600: 		 ? (S_GET_NAME(insn->exp.X_subtract_symbol)
 1601: 		    ? S_GET_NAME(insn->exp.X_subtract_symbol)
 1602: 		    : "???")
 1603: 		 : "0"));
 1604: 	fprintf(stderr, "\t\tX_got_symbol = %s\n",
 1605: 		((insn->exp.X_got_symbol != NULL)
 1606: 		 ? (S_GET_NAME(insn->exp.X_got_symbol)
 1607: 		    ? S_GET_NAME(insn->exp.X_got_symbol)
 1608: 		    : "???")
 1609: 		 : "0"));
 1610: 	fprintf(stderr, "\t\tX_add_number = %d\n",
 1611: 		insn->exp.X_add_number);
 1612: 	fprintf(stderr, "}\n");
 1613: 	return;
 1614: } /* print_insn() */
 1615: #endif
 1616: 
 1617: /* Set the hook... */
 1618: 
 1619: /* void emit_sparc_reloc();
 1620:    void (*md_emit_relocations)() = emit_sparc_reloc; */
 1621: 
 1622: #ifdef comment
 1623: 
 1624: /*
 1625:  * Sparc/AM29K relocations are completely different, so it needs
 1626:  * this machine dependent routine to emit them.
 1627:  */
 1628: #if defined(OBJ_AOUT) || defined(OBJ_BOUT)
 1629: void emit_sparc_reloc(fixP, segment_address_in_file)
 1630: register fixS *fixP;
 1631: relax_addressT segment_address_in_file;
 1632: {
 1633: 	struct reloc_info_generic ri;
 1634: 	register symbolS *symbolP;
 1635: 	extern char *next_object_file_charP;
 1636: 	/*    long add_number; */
 1637: 
 1638: 	memset((char *) &ri, '\0', sizeof(ri));
 1639: 	for (; fixP; fixP = fixP->fx_next) {
 1640: 
 1641: 		if (fixP->fx_r_type >= NO_RELOC) {
 1642: 			as_fatal("fixP->fx_r_type = %d\n", fixP->fx_r_type);
 1643: 		}
 1644: 
 1645: 		if ((symbolP = fixP->fx_addsy) != NULL) {
 1646: 			ri.r_address = fixP->fx_frag->fr_address +
 1647: 			    fixP->fx_where - segment_address_in_file;
 1648: 			if ((S_GET_TYPE(symbolP)) == N_UNDF) {
 1649: 				ri.r_extern = 1;
 1650: 				ri.r_index = symbolP->sy_number;
 1651: 			} else {
 1652: 				ri.r_extern = 0;
 1653: 				ri.r_index = S_GET_TYPE(symbolP);
 1654: 			}
 1655: 			if (symbolP && symbolP->sy_frag) {
 1656: 				ri.r_addend = symbolP->sy_frag->fr_address;
 1657: 			}
 1658: 			ri.r_type = fixP->fx_r_type;
 1659: 			if (fixP->fx_pcrel) {
 1660: 				/*		ri.r_addend -= fixP->fx_where; */
 1661: 				ri.r_addend -= ri.r_address;
 1662: 			} else {
 1663: 				ri.r_addend = fixP->fx_addnumber;
 1664: 			}
 1665: 
 1666: 			md_ri_to_chars(next_object_file_charP, &ri);
 1667: 			next_object_file_charP += md_reloc_size;
 1668: 		}
 1669: 	}
 1670: 	return;
 1671: } /* emit_sparc_reloc() */
 1672: #endif /* aout or bout */
 1673: #endif /* comment */
 1674: 
 1675: /*
 1676:  * md_parse_option
 1677:  *	Invocation line includes a switch not recognized by the base assembler.
 1678:  *	See if it's a processor-specific option.  These are:
 1679:  *
 1680:  *	-bump
 1681:  *		Warn on architecture bumps.  See also -A.
 1682:  *
 1683:  *	-Av6, -Av7, -Av8
 1684:  *		Select the architecture.  Instructions or features not
 1685:  *		supported by the selected architecture cause fatal errors.
 1686:  *
 1687:  *		The default is to start at v6, and bump the architecture up
 1688:  *		whenever an instruction is seen at a higher level.
 1689:  *
 1690:  *		If -bump is specified, a warning is printing when bumping to
 1691:  *		higher levels.
 1692:  *
 1693:  *		If an architecture is specified, all instructions must match
 1694:  *		that architecture.  Any higher level instructions are flagged
 1695:  *		as errors.
 1696:  *
 1697:  *		if both an architecture and -bump are specified, the
 1698:  *		architecture starts at the specified level, but bumps are
 1699:  *		warnings.
 1700:  *
 1701:  */
 1702: int md_parse_option(argP, cntP, vecP)
 1703: char **argP;
 1704: int *cntP;
 1705: char ***vecP;
 1706: {
 1707: 	char *p;
 1708: 	const char **arch;
 1709: 
 1710: 	if (!strcmp(*argP,"bump")){
 1711: 		warn_on_bump = 1;
 1712: 
 1713: 	} else if (**argP == 'A'){
 1714: 		p = (*argP) + 1;
 1715: 
 1716: 		for (arch = architecture_pname; *arch != NULL; ++arch){
 1717: 			if (strcmp(p, *arch) == 0){
 1718: 				break;
 1719: 			} /* found a match */
 1720: 		} /* walk the pname table */
 1721: 
 1722: 		if (*arch == NULL){
 1723: 			as_bad("unknown architecture: %s", p);
 1724: 		} else {
 1725: 			current_architecture = (enum sparc_architecture) (arch - architecture_pname);
 1726: 			architecture_requested = 1;
 1727: 		}
 1728: #ifdef PIC
 1729: 	} else if (**argP == 'k' || **argP == 'K') {
 1730: 		/* Predefine GOT symbol */
 1731: 		GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
 1732: #endif
 1733: 	} else {
 1734: 		/* Unknown option */
 1735: 		(*argP)++;
 1736: 		return 0;
 1737: 	}
 1738: 	**argP = '\0';	/* Done parsing this switch */
 1739: 	return 1;
 1740: } /* md_parse_option() */
 1741: 
 1742: /* We have no need to default values of symbols. */
 1743: 
 1744: /* ARGSUSED */
 1745: symbolS *md_undefined_symbol(name)
 1746: char *name;
 1747: {
 1748: 	return 0;
 1749: } /* md_undefined_symbol() */
 1750: 
 1751: /* Parse an operand that is machine-specific.
 1752:    We just return without modifying the expression if we have nothing
 1753:    to do. */
 1754: 
 1755: /* ARGSUSED */
 1756: void md_operand(expressionP)
 1757: expressionS *expressionP;
 1758: {
 1759: } /* md_operand() */
 1760: 
 1761: /* Round up a section size to the appropriate boundary. */
 1762: long md_section_align(segment, size)
 1763: segT segment;
 1764: long size;
 1765: {
 1766: 	return((size + 7) & ~7); /* Round all sects to multiple of 8 */
 1767: } /* md_section_align() */
 1768: 
 1769: /* Exactly what point is a PC-relative offset relative TO?
 1770:    On the sparc, they're relative to the address of the offset, plus
 1771:    its size.  This gets us to the following instruction.
 1772:    (??? Is this right?  FIXME-SOON) */
 1773: long md_pcrel_from(fixP)
 1774: fixS *fixP;
 1775: {
 1776: #ifdef PIC
 1777: 	/*
 1778: 	 * _GLOBAL_OFFSET_TABLE_ refs are relative to the offset of the
 1779: 	 * current instruction. We omit fx_size from the computation (which
 1780: 	 * is always 4 anyway).
 1781: 	 */
 1782: 	if (fixP->fx_gotsy)
 1783: 		return fixP->fx_where + fixP->fx_frag->fr_address;
 1784: 	else
 1785: #endif
 1786: 	return(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address);
 1787: } /* md_pcrel_from() */
 1788: 
 1789: void tc_aout_pre_write_hook(headers)
 1790: object_headers *headers;
 1791: {
 1792: 	H_SET_VERSION(headers, 1);
 1793: 	return;
 1794: } /* tc_aout_pre_write_hook() */
 1795: 
 1796: /*
 1797:  * Local Variables:
 1798:  * comment-column: 0
 1799:  * fill-column: 131
 1800:  * End:
 1801:  */
 1802: 
 1803: /* end of tc-sparc.c */