/* tc-a29k.c -- Assemble for the AMD 29000.
- Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 2000
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* John Gilmore has reorganized this module somewhat, to make it easier
to convert it to new machines' assemblers as desired. There was too
{NULL, 0, 0},
};
-int md_short_jump_size = 4;
-int md_long_jump_size = 4;
#if defined(BFD_HEADERS)
#ifdef RELSZ
const int md_reloc_size = RELSZ; /* Coff headers */
.line and .file directives will appear in the pre-processed output */
/* Note that input_file.c hand checks for '#' at the beginning of the
first line of the input file. This is because the compiler outputs
- #NO_APP at the beginning of its output. */
+ #NO_APP at the beginning of its output. */
/* Also note that comments like this one will always work */
const char line_comment_chars[] = "#";
return;
}
/* Literals can't go in the text segment because you can't read from
- instruction memory on some 29k's. So, into initialized data. */
+ instruction memory on some 29k's. So, into initialized data. */
if (strncmp (input_line_pointer, ".lit", 4) == 0)
{
input_line_pointer += 4;
return;
}
- as_bad ("Unknown segment type");
+ as_bad (_("Unknown segment type"));
demand_empty_rest_of_line ();
}
}
/* Hack to avoid multiple opcode entries. We pre-locate all the
- variations (b/i field and P/A field) and handle them. */
+ variations (b/i field and P/A field) and handle them. */
if (!strcmp (name, machine_opcodes[i + 1].name))
{
}
if (lose)
- as_fatal ("Broken assembler. No assembly attempted.");
+ as_fatal (_("Broken assembler. No assembly attempted."));
define_some_regs ();
}
input_line_pointer = s;
expression (operandp);
if (operandp->X_op == O_absent && ! opt)
- as_bad ("missing operand");
+ as_bad (_("missing operand"));
new = input_line_pointer;
input_line_pointer = save;
return new;
break;
default:
- as_bad ("Unknown opcode: `%s'", str);
+ as_bad (_("Unknown opcode: `%s'"), str);
return;
}
if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
{
- as_bad ("Unknown opcode `%s'.", str);
+ as_bad (_("Unknown opcode `%s'."), str);
return;
}
argsStart = s;
/* Build the opcode, checking as we go to make sure that the
operands match.
-
+
If an operand matches, we modify the_insn or opcode appropriately,
and do a "continue". If an operand fails to match, we "break". */
case '\0': /* end of args */
if (*s == '\0')
{
- /* We are truly done. */
+ /* We are truly done. */
the_insn.opcode = opcode;
return;
}
- as_bad ("Too many operands: %s", s);
+ as_bad (_("Too many operands: %s"), s);
break;
case ',': /* Must match a comma */
}
else
{
- as_bad ("Immediate value of %ld is too large",
+ as_bad (_("Immediate value of %ld is too large"),
(long) operand->X_add_number);
continue;
}
}
else
{
- as_bad ("Immediate value of %ld is too large",
+ as_bad (_("Immediate value of %ld is too large"),
(long) operand->X_add_number);
continue;
}
opcode |= reg << 16;
continue;
}
- as_fatal ("failed sanity check.");
+ as_fatal (_("failed sanity check."));
break;
case 'x': /* 16 bit constant, zero-extended */
}
break;
-
case 'f': /* FS bits of CONVERT */
if (operand->X_op == O_constant &&
operand->X_add_number < 4)
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
+ 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 */
fixP->fx_addnumber = val; /* Remember value for emit_reloc */
-
know (fixP->fx_size == 4);
know (fixP->fx_r_type < NO_RELOC);
case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */
if (!fixP->fx_done)
- /* let linker deal */
- ;
+ {
+ /* The linker tries to support both AMD and old GNU style
+ R_IREL relocs. That means that if the addend is exactly
+ the negative of the address within the section, the
+ linker will not handle it correctly. */
+ if (fixP->fx_pcrel
+ && val != 0
+ && val == - (fixP->fx_frag->fr_address + fixP->fx_where))
+ as_bad_where
+ (fixP->fx_file, fixP->fx_line,
+ "the linker will not handle this relocation correctly");
+ }
else if (fixP->fx_pcrel)
{
- long v = val >> 16;
+ long v = val >> 17;
if (v != 0 && v != -1)
as_bad_where (fixP->fx_file, fixP->fx_line,
"call/jmp target out of range");
case NO_RELOC:
default:
- as_bad ("bad relocation type: 0x%02x", fixP->fx_r_type);
+ as_bad (_("bad relocation type: 0x%02x"), fixP->fx_r_type);
break;
}
}
case RELOC_JUMPTARG:
return (R_IREL);
default:
- printf ("need %o3\n", fixP->fx_r_type);
+ printf (_("need %o3\n"), fixP->fx_r_type);
abort ();
} /* switch on type */
#endif /* OBJ_COFF */
-/* should never be called for 29k */
-void
-md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
- char *ptr;
- addressT from_addr, to_addr;
- fragS *frag;
- symbolS *to_symbol;
-{
- as_fatal ("a29k_create_short_jmp\n");
-}
-
/* should never be called for 29k */
void
md_convert_frag (headers, seg, fragP)
segT seg;
register fragS *fragP;
{
- as_fatal ("a29k_convert_frag\n");
-}
-
-/* should never be called for 29k */
-void
-md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
- char *ptr;
- addressT from_addr;
- addressT to_addr;
- fragS *frag;
- symbolS *to_symbol;
-{
- as_fatal ("a29k_create_long_jump\n");
+ as_fatal (_("a29k_convert_frag\n"));
}
/* should never be called for a29k */
register fragS *fragP;
segT segtype;
{
- as_fatal ("a29k_estimate_size_before_relax\n");
+ as_fatal (_("a29k_estimate_size_before_relax\n"));
return 0;
}
On sparc/29k: 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 addend. */
+ five bits as relocation type. Next 4 bytes are long addend. */
/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
#ifdef OBJ_AOUT
struct option md_longopts[] = {
{NULL, no_argument, NULL, 0}
};
-size_t md_longopts_size = sizeof(md_longopts);
+size_t md_longopts_size = sizeof (md_longopts);
int
md_parse_option (c, arg)
{
}
\f
+/* This is called when a line is unrecognized. This is used to handle
+ definitions of a29k style local labels. */
+
+int
+a29k_unrecognized_line (c)
+ int c;
+{
+ int lab;
+ char *s;
+
+ if (c != '$'
+ || ! isdigit ((unsigned char) input_line_pointer[0]))
+ return 0;
+
+ s = input_line_pointer;
+
+ lab = 0;
+ while (isdigit ((unsigned char) *s))
+ {
+ lab = lab * 10 + *s - '0';
+ ++s;
+ }
+
+ if (*s != ':')
+ {
+ /* Not a label definition. */
+ return 0;
+ }
+
+ if (dollar_label_defined (lab))
+ {
+ as_bad (_("label \"$%d\" redefined"), lab);
+ return 0;
+ }
+
+ define_dollar_label (lab);
+ colon (dollar_label_name (lab, 0));
+ input_line_pointer = s + 1;
+
+ return 1;
+}
+
/* Default the values of symbols known that should be "predefined". We
don't bother to predefine them unless you actually use one, since there
are a lot of them. */
long maxreg;
/* Parse the number, make sure it has no extra zeroes or
- trailing chars. */
+ trailing chars. */
regnum = atol (&name[2]);
if (name[0] == 's' || name[0] == 'S')
(void) expression (expressionP);
if (expressionP->X_op != O_constant
|| expressionP->X_add_number > 255)
- as_bad ("Invalid expression after %%%%\n");
+ as_bad (_("Invalid expression after %%%%\n"));
expressionP->X_op = O_register;
}
else if (input_line_pointer[0] == '&')
input_line_pointer++; /* Skip & */
(void) expression (expressionP);
if (expressionP->X_op != O_register)
- as_bad ("Invalid register in & expression");
+ as_bad (_("Invalid register in & expression"));
else
expressionP->X_op = O_constant;
}
+ else if (input_line_pointer[0] == '$'
+ && isdigit ((unsigned char) input_line_pointer[1]))
+ {
+ long lab;
+ char *name;
+ symbolS *sym;
+
+ /* This is a local label. */
+ ++input_line_pointer;
+ lab = (long) get_absolute_expression ();
+ if (dollar_label_defined (lab))
+ {
+ name = dollar_label_name (lab, 0);
+ sym = symbol_find (name);
+ }
+ else
+ {
+ name = dollar_label_name (lab, 1);
+ sym = symbol_find_or_make (name);
+ }
+
+ expressionP->X_op = O_symbol;
+ expressionP->X_add_symbol = sym;
+ expressionP->X_add_number = 0;
+ }
else if (input_line_pointer[0] == '$')
{
char *s;
type = 'x';
fieldlimit = 4;
}
- else
+ else
{
- /* FIXME: We should handle a29k local labels here. */
return;
}
SKIP_WHITESPACE ();
input_line_pointer = s;
- expressionP->X_op = O_constant;
+ expressionP->X_op = O_constant;
expressionP->X_unsigned = 1;
expressionP->X_add_number = ((floatbuf[fieldnum * 2]
<< LITTLENUM_NUMBER_OF_BITS)
{
return fixP->fx_where + fixP->fx_frag->fr_address;
}
-
-/* end of tc-a29k.c */