/* tc-tic80.c -- Assemble for the TI TMS320C80 (MV)
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#include "opcode/tic80.h"
#define internal_error(what) \
- as_fatal("internal error:%s:%d: %s\n",__FILE__,__LINE__,what)
+ as_fatal(_("internal error:%s:%d: %s\n"),__FILE__,__LINE__,what)
#define internal_error_a(what,arg) \
- as_fatal("internal error:%s:%d: %s %d\n",__FILE__,__LINE__,what,arg)
+ as_fatal(_("internal error:%s:%d: %s %d\n"),__FILE__,__LINE__,what,arg)
\f
/* Generic assembler global variables which must be defined by all targets. */
{
{ "align", s_align_bytes, 4 }, /* Do byte alignment, default is a 4 byte boundary */
{ "word", cons, 4 }, /* FIXME: Should this be machine independent? */
- { "bss", s_lcomm, 1 },
+ { "bss", s_lcomm_bytes, 1 },
{ "sect", obj_coff_section, 0}, /* For compatibility with TI tools */
{ "section", obj_coff_section, 0}, /* Standard COFF .section pseudo-op */
{ NULL, NULL, 0 }
static int get_operands PARAMS ((expressionS exp[]));
static int const_overflow PARAMS ((unsigned long num, int bits, int flags));
+/* Replace short PC relative instructions with long form when necessary. Currently
+ this is off by default or when given the -no-relax option. Turning it on by using
+ the -relax option forces all PC relative instructions to use the long form, which
+ is why it is currently not the default. */
+static int tic80_relax = 0;
+
\f
int
md_estimate_size_before_relax (fragP, segment_type)
fragS *fragP;
segT segment_type;
{
- internal_error ("Relaxation is a luxury we can't afford");
+ internal_error (_("Relaxation is a luxury we can't afford"));
return (-1);
}
default:
*sizeP = 0;
- return "bad call to md_atof ()";
+ return _("bad call to md_atof ()");
}
t = atof_ieee (input_line_pointer, type, words);
}
else
{
- as_bad ("':' not followed by 'm' or 's'");
+ as_bad (_("':' not followed by 'm' or 's'"));
}
numexp++;
continue;
{
if (++parens != 1)
{
- as_bad ("paren nesting");
+ as_bad (_("paren nesting"));
}
p++;
continue;
/* Record that we have left a paren group and continue */
if (--parens < 0)
{
- as_bad ("mismatched parenthesis");
+ as_bad (_("mismatched parenthesis"));
}
p++;
continue;
if (exp[numexp].X_op == O_illegal)
{
- as_bad ("illegal operand");
+ as_bad (_("illegal operand"));
}
else if (exp[numexp].X_op == O_absent)
{
- as_bad ("missing operand");
+ as_bad (_("missing operand"));
}
numexp++;
}
break;
case O_symbol:
- if ((bits < 32) && (flags & TIC80_OPERAND_PCREL))
+ if ((bits < 32) && (flags & TIC80_OPERAND_PCREL) && !tic80_relax)
{
- /* For now we only allow PC relative relocations in the
- short immediate fields, like the TI assembler.
+ /* The default is to prefer the short form of PC relative relocations.
+ This is the only form that the TI assembler supports.
+ If the -relax option is given, we never use the short forms.
FIXME: Should be able to choose "best-fit". */
}
else if ((bits == 32) /* && (flags & TIC80_OPERAND_BASEREL) */)
{
- /* For now we only allow base relative relocations in
- the long immediate fields, like the TI assembler.
+ /* The default is to prefer the long form of base relative relocations.
+ This is the only form that the TI assembler supports.
+ If the -no-relax option is given, we always use the long form of
+ PC relative relocations.
FIXME: Should be able to choose "best-fit". */
}
else
case O_logical_or:
case O_max:
default:
- internal_error_a ("unhandled expression type", X_op);
+ internal_error_a (_("unhandled expression type"), X_op);
}
}
if (!match)
if (!match)
{
- as_bad ("bad opcode or operands");
+ as_bad (_("bad opcode or operands"));
return (0);
}
{
if ((tic80_operands[opcode->operands[i]].flags & TIC80_OPERAND_EVEN) &&
(myops[i].X_add_number & 1))
- as_fatal ("Register number must be EVEN");
+ as_fatal (_("Register number must be EVEN"));
if (myops[i].X_op == O_register)
{
if (!(tic80_operands[opcode->operands[i]].flags & TIC80_OPERAND_REG))
}
break;
case O_symbol:
- if (flags & TIC80_OPERAND_PCREL)
+ if (bits == 32)
+ {
+ fx = frag_more (4);
+ fxfrag = frag_now;
+ insn[1] = 0;
+ if (flags & TIC80_OPERAND_PCREL)
+ {
+ fix_new_exp (fxfrag,
+ fx - (fxfrag -> fr_literal),
+ 4,
+ &opers[expi],
+ 1,
+ R_MPPCR);
+ }
+ else
+ {
+ fix_new_exp (fxfrag,
+ fx - (fxfrag -> fr_literal),
+ 4,
+ &opers[expi],
+ 0,
+ R_RELLONGX);
+ }
+ }
+ else if (flags & TIC80_OPERAND_PCREL)
{
fix_new_exp (ffrag,
f - (ffrag -> fr_literal),
4, /* FIXME! how is this used? */
&opers[expi],
1,
- R_MPPCR);
- }
- else if (bits == 32) /* was (flags & TIC80_OPERAND_BASEREL) */
- {
- fx = frag_more (4);
- fxfrag = frag_now;
- insn[1] = 0;
- fix_new_exp (fxfrag,
- fx - (fxfrag -> fr_literal),
- 4,
- &opers[expi],
- 0,
- R_RELLONGX);
+ R_MPPCR15W);
}
else
{
- internal_error ("symbol reloc that is not PC relative or 32 bits");
+ internal_error (_("symbol reloc that is not PC relative or 32 bits"));
}
break;
case O_absent:
}
else
{
- internal_error_a ("unhandled operand modifier", opers[expi].X_add_number);
+ internal_error_a (_("unhandled operand modifier"), opers[expi].X_add_number);
}
break;
case O_big:
case O_logical_or:
case O_max:
default:
- internal_error_a ("unhandled expression", X_op);
+ internal_error_a (_("unhandled expression"), X_op);
break;
}
}
/* Try to find this mnemonic in the hash table */
if ((opcode = (struct tic80_opcode *) hash_find (tic80_hash, str)) == NULL)
{
- as_bad ("Invalid mnemonic: '%s'", str);
+ as_bad (_("Invalid mnemonic: '%s'"), str);
return;
}
opcode = find_opcode (opcode, myops);
if (opcode == NULL)
{
- as_bad ("Invalid operands: '%s'", input_line_save);
+ as_bad (_("Invalid operands: '%s'"), input_line_save);
}
input_line_pointer = input_line_save;
valu = PDS_VALUE (pdsp) & ~TIC80_OPERAND_MASK;
break;
default:
- internal_error_a ("unhandled predefined symbol bits", symtype);
+ internal_error_a (_("unhandled predefined symbol bits"), symtype);
break;
}
symbol_table_insert (symbol_create (PDS_NAME (pdsp), segment, valu,
that are passed to getopt. */
struct option md_longopts[] = {
+
+#define OPTION_RELAX (OPTION_MD_BASE)
+ {"relax", no_argument, NULL, OPTION_RELAX},
+
+#define OPTION_NO_RELAX (OPTION_RELAX + 1)
+ {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
+
{NULL, no_argument, NULL, 0}
};
int c;
char *arg;
{
- return (0);
+ switch (c)
+ {
+ case OPTION_RELAX:
+ tic80_relax = 1;
+ break;
+ case OPTION_NO_RELAX:
+ tic80_relax = 0;
+ break;
+ default:
+ return (0);
+ }
+ return (1);
}
/* The md_show_usage function will be called whenever a usage message is
md_show_usage (stream)
FILE *stream;
{
+ fprintf (stream, "\
+TIc80 options:\n\
+-relax alter PC relative branch instructions to use long form when needed\n\
+-no-relax always use short PC relative branch instructions, error on overflow\n");
}
\f
md_number_to_chars (dest, (valueT) val, 4);
break;
case R_MPPCR:
- overflow = (val < -65536) || (val > 65532);
+ val >>= 2;
+ val += 1; /* Target address computed from inst start */
+ md_number_to_chars (dest, (valueT) val, 4);
+ break;
+ case R_MPPCR15W:
+ overflow = (val < -65536L) || (val > 65532L);
if (overflow)
{
- as_bad_where (fixP -> fx_file, fixP -> fx_line, "PC relative target out of range");
+ as_bad_where (fixP -> fx_file, fixP -> fx_line,
+ _("PC offset 0x%lx outside range 0x%lx-0x%lx"),
+ val, -65536L, 65532L);
}
else
{
md_number_to_chars (dest, (valueT) val, fixP -> fx_size);
break;
default:
- internal_error_a ("unhandled relocation type in fixup", fixP -> fx_r_type);
+ internal_error_a (_("unhandled relocation type in fixup"), fixP -> fx_r_type);
break;
}
}
segT seg;
fragS *fragP;
{
- internal_error ("md_convert_frag() not implemented yet");
+ internal_error (_("md_convert_frag() not implemented yet"));
abort ();
}