/* tc-i960.c - All the i80960-specific stuff
- Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2005
- Free Software Foundation, Inc.
+ Copyright (C) 1989-2017 Free Software Foundation, Inc.
This file is part of GAS.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
less than 4096 is specified, in which case we need neither a fixup nor
a relocation directive. */
-#include <stdio.h>
-
#include "as.h"
#include "safe-ctype.h"
-#include "obstack.h"
#include "opcode/i960.h"
extern char *input_line_pointer;
-#if !defined (BFD_ASSEMBLER) && !defined (BFD)
-#ifdef OBJ_COFF
-const int md_reloc_size = sizeof (struct reloc);
-#else /* OBJ_COFF */
-const int md_reloc_size = sizeof (struct relocation_info);
-#endif /* OBJ_COFF */
-#endif
-
/* Local i80960 routines. */
struct memS;
struct regop;
operands. */
static const struct
{
- char *reg_name;
+ const char *reg_name;
int reg_num;
}
regnames[] =
'abase' (indirect addressing) registers. */
static const struct
{
- char *areg_name;
+ const char *areg_name;
int areg_num;
}
aregs[] =
of branches taken/not-taken for later input to a utility that will
set the branch prediction bits of the instructions in accordance with
the behavior observed. (Note that the KX series does not have
- brach-prediction.)
+ branch-prediction.)
The instrumentation consists of:
/* Name of the table of pointers to branches. A local (i.e.,
non-external) symbol. */
-static void ctrl_fmt (char *, long, int);
+static void ctrl_fmt (const char *, long, int);
\f
void
string is not consumed in the evaluation -- tolerate no dangling junk! */
static void
-parse_expr (char *textP, /* Text of expression to be parsed. */
+parse_expr (const char *textP, /* Text of expression to be parsed. */
expressionS *expP) /* Where to put the results of parsing. */
{
char *save_in; /* Save global here. */
else
{
save_in = input_line_pointer; /* Save global. */
- input_line_pointer = textP; /* Make parser work for us. */
+ input_line_pointer = (char *) textP; /* Make parser work for us. */
(void) expression (expP);
if ((size_t) (input_line_pointer - textP) != strlen (textP))
address displacement is greater than 13 bits. */
static void
-get_cdisp (char *dispP, /* Displacement as specified in source instruction. */
- char *ifmtP, /* "COBR" or "CTRL" (for use in error message). */
+get_cdisp (const char *dispP, /* Displacement as specified in source instruction. */
+ const char *ifmtP, /* "COBR" or "CTRL" (for use in error message). */
long instr, /* Instruction needing the displacement. */
int numbits, /* # bits of displacement (13 for COBR, 24 for CTRL). */
int var_frag,/* 1 if varying length code fragment should be emitted;
0 if an address fix should be emitted. */
- int callj) /* 1 if callj relocation should be done; else 0. */
+ int callj) /* 1 if callj relocation should be done; else 0. */
{
expressionS e; /* Parsed expression. */
fixS *fixP; /* Structure describing needed address fix. */
{
case O_illegal:
as_bad (_("expression syntax error"));
+ break;
case O_symbol:
if (S_GET_SEGMENT (e.X_add_symbol) == now_seg
}
/* get_ispec: parse a memory operand for an index specification
-
+
Here, an "index specification" is taken to be anything surrounded
by square brackets and NOT followed by anything else.
static char *
get_ispec (char *textP) /* Pointer to memory operand from source instruction, no white space. */
-
+
{
/* Points to start of index specification. */
char *start;
regnum = *intP;
*p = '\0'; /* Discard register spec. */
if (regnum == IPREL)
- /* We have to specialcase ip-rel mode. */
+ /* We have to special-case ip-rel mode. */
iprel_flag = 1;
else
{
case I_BIT:
/* Treat missing displacement as displacement of 0. */
mode |= D_BIT;
- /* Fall into next case. */
+ /* Fall through. */
case D_BIT | A_BIT | I_BIT:
case D_BIT | I_BIT:
/* Set MEMB bit in mode, and OR in mode bits. */
char opdesc; /* Operand descriptor byte. */
memS instr; /* Description of binary to be output. */
char *outP; /* Where the binary was output to. */
- expressionS expr; /* Parsed expression. */
+ expressionS exp; /* Parsed expression. */
/* ->description of deferred address fixup. */
fixS *fixP;
/* Parse the displacement; this must be done before emitting the
opcode, in case it is an expression using `.'. */
- parse_expr (instr.e, &expr);
+ parse_expr (instr.e, &exp);
/* Output opcode. */
outP = emit (instr.opcode);
return;
/* Process the displacement. */
- switch (expr.X_op)
+ switch (exp.X_op)
{
case O_illegal:
as_bad (_("expression syntax error"));
case O_constant:
if (instr.disp == 32)
- (void) emit (offs (expr)); /* Output displacement. */
+ (void) emit (offs (exp)); /* Output displacement. */
else
{
/* 12-bit displacement. */
- if (offs (expr) & ~0xfff)
+ if (offs (exp) & ~0xfff)
{
/* Won't fit in 12 bits: convert already-output
instruction to MEMB format, output
displacement. */
mema_to_memb (outP);
- (void) emit (offs (expr));
+ (void) emit (offs (exp));
}
else
{
/* WILL fit in 12 bits: OR into opcode and
overwrite the binary we already put out. */
- instr.opcode |= offs (expr);
+ instr.opcode |= offs (exp);
md_number_to_chars (outP, instr.opcode, 4);
}
}
outP = emit ((long) 0);
fixP = fix_new_exp (frag_now,
outP - frag_now->fr_literal,
- 4, & expr, 0, NO_RELOC);
+ 4, &exp, 0, NO_RELOC);
/* Steve's linker relaxing hack. Mark this 32-bit relocation as
being in the instruction stream, specifically as part of a callx
instruction. */
{
default:
/* We're dependent on one or more symbols -- use "lda". */
- arg[0] = "lda";
+ arg[0] = (char *) "lda";
break;
case O_constant:
ldconst 64,<reg> -> shlo 8,3,<reg>
ldconst -1,<reg> -> subo 1,0,<reg>
ldconst -31,<reg> -> subo 31,0,<reg>
-
+
Anything else becomes:
lda xxx,<reg>. */
n = offs (e);
if ((0 <= n) && (n <= 31))
- arg[0] = "mov";
+ arg[0] = (char *) "mov";
else if ((-31 <= n) && (n <= -1))
{
- arg[0] = "subo";
+ arg[0] = (char *) "subo";
arg[3] = arg[2];
sprintf (buf, "%d", -n);
arg[1] = buf;
- arg[2] = "0";
+ arg[2] = (char *) "0";
}
else if ((32 <= n) && (n <= 62))
{
- arg[0] = "addo";
+ arg[0] = (char *) "addo";
arg[3] = arg[2];
- arg[1] = "31";
+ arg[1] = (char *) "31";
sprintf (buf, "%d", n - 31);
arg[2] = buf;
}
else if ((shift = shift_ok (n)) != 0)
{
- arg[0] = "shlo";
+ arg[0] = (char *) "shlo";
arg[3] = arg[2];
sprintf (buf, "%d", shift);
arg[1] = buf;
arg[2] = buf2;
}
else
- arg[0] = "lda";
+ arg[0] = (char *) "lda";
break;
case O_illegal:
n = 1;
args[1] = p;
- /* Squeze blanks out by moving non-blanks toward start of string.
+ /* Squeeze blanks out by moving non-blanks toward start of string.
Isolate operands, whenever comma is found. */
to = p;
while (*p != '\0')
}
static void
-ctrl_fmt (char *targP, /* Pointer to text of lone operand (if any). */
+ctrl_fmt (const char *targP, /* Pointer to text of lone operand (if any). */
long opcode, /* Template of instruction. */
int num_ops) /* Number of operands. */
{
if (!oP || !targ_has_iclass (oP->iclass))
as_bad (_("invalid opcode, \"%s\"."), args[0]);
else if (n_ops != oP->num_ops)
- as_bad (_("improper number of operands. expecting %d, got %d"),
+ as_bad (_("improper number of operands. Expecting %d, got %d"),
oP->num_ops, n_ops);
else
{
break;
case REG:
if (branch_predict)
- as_warn (bp_error_msg);
+ as_warn ("%s", bp_error_msg);
reg_fmt (args, oP);
break;
case MEM1:
if (args[0][0] == 'c' && args[0][1] == 'a')
{
if (branch_predict)
- as_warn (bp_error_msg);
+ as_warn ("%s", bp_error_msg);
mem_fmt (args, oP, 1);
break;
}
+ /* Fall through. */
case MEM2:
case MEM4:
case MEM8:
case MEM12:
case MEM16:
if (branch_predict)
- as_warn (bp_error_msg);
+ as_warn ("%s", bp_error_msg);
mem_fmt (args, oP, 0);
break;
case CALLJ:
if (branch_predict)
- as_warn (bp_error_msg);
+ as_warn ("%s", bp_error_msg);
/* Output opcode & set up "fixup" (relocation); flag
relocation as 'callj' type. */
know (oP->num_ops == 1);
number_to_chars_littleendian (buf, value, n);
}
-#define MAX_LITTLENUMS 6
-#define LNUM_SIZE sizeof (LITTLENUM_TYPE)
-
-/* md_atof: convert ascii to floating point
-
- Turn a string at input_line_pointer into a floating point constant of type
- 'type', and store the appropriate bytes at *litP. The number of LITTLENUMS
- emitted is returned at 'sizeP'. An error message is returned, or a pointer
- to an empty message if OK.
-
- Note we call the i386 floating point routine, rather than complicating
- things with more files or symbolic links. */
-
-char *
+const char *
md_atof (int type, char *litP, int *sizeP)
{
- LITTLENUM_TYPE words[MAX_LITTLENUMS];
- LITTLENUM_TYPE *wordP;
- int prec;
- char *t;
-
- switch (type)
- {
- case 'f':
- case 'F':
- prec = 2;
- break;
-
- case 'd':
- case 'D':
- prec = 4;
- break;
-
- case 't':
- case 'T':
- prec = 5;
- type = 'x'; /* That's what atof_ieee() understands. */
- 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 * LNUM_SIZE;
-
- /* Output the LITTLENUMs in REVERSE order in accord with i80960
- word-order. (Dunno why atof_ieee doesn't do it in the right
- order in the first place -- probably because it's a hack of
- atof_m68k.) */
- for (wordP = words + prec - 1; prec--;)
- {
- md_number_to_chars (litP, (long) (*wordP--), LNUM_SIZE);
- litP += sizeof (LITTLENUM_TYPE);
- }
-
- return 0;
+ return ieee_md_atof (type, litP, sizeP, FALSE);
}
static void
{
/* Put bit field into instruction and write back in target
* byte order. */
- val &= ~(-1 << (int) numbits); /* Clear unused sign bits. */
+ val &= ~(-(1 << (int) numbits)); /* Clear unused sign bits. */
instr |= val;
md_number_to_chars (instrP, instr, 4);
}
struct tabentry
{
- char *flag;
+ const char *flag;
int arch;
};
static const struct tabentry arch_tab[] =
};
int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
{
switch (c)
{
case 'A':
{
const struct tabentry *tp;
- char *p = arg;
+ const char *p = arg;
for (tp = arch_tab; tp->flag != NULL; tp++)
if (!strcmp (p, tp->flag))
If the fragment substate is 2, a 13-bit displacement was not enough.
Replace the cobr with a two instructions (a compare and a branch). */
-#ifndef BFD_ASSEMBLER
-void
-md_convert_frag (object_headers *headers ATTRIBUTE_UNUSED,
- segT seg ATTRIBUTE_UNUSED,
- fragS *fragP)
-#else
void
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
segT sec ATTRIBUTE_UNUSED,
fragS *fragP)
-#endif
{
/* Structure describing needed address fix. */
fixS *fixP;
char buf[20];
/* Where the binary was output to. */
char *p;
- /* Pointer to description of deferred address fixup. */
- fixS *fixP;
if (!instrument_branches)
return;
{
sprintf (buf, "%s%d", BR_LABEL_BASE, i);
p = emit (0);
- fixP = fix_new (frag_now,
- p - frag_now->fr_literal,
- 4, symbol_find (buf), 0, 0, NO_RELOC);
+ fix_new (frag_now,
+ p - frag_now->fr_literal,
+ 4, symbol_find (buf), 0, 0, NO_RELOC);
}
}
passed fixup structure. */
int
-reloc_callj (fixS *fixP) /* Relocation that can be done at assembly time. */
+reloc_callj (fixS *fixP) /* Relocation that can be done at assembly time. */
{
/* Points to the binary for the instruction being relocated. */
char *where;
char *name;
char c;
- name = input_line_pointer;
- c = get_symbol_end ();
+ c = get_symbol_name (&name);
if (strcasecmp (name, "little") == 0)
;
else if (strcasecmp (name, "big") == 0)
else
as_warn (_("ignoring unrecognized .endian type `%s'"), name);
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
demand_empty_rest_of_line ();
}
}
void
-md_apply_fix3 (fixS *fixP,
+md_apply_fix (fixS *fixP,
valueT *valP,
segT seg ATTRIBUTE_UNUSED)
{
if (!fixP->fx_bit_fixP)
{
-#ifndef BFD_ASSEMBLER
- /* For callx, we always want to write out zero, and emit a
- symbolic relocation. */
- if (fixP->fx_bsr)
- val = 0;
-
- fixP->fx_addnumber = val;
-#endif
-
md_number_to_imm (place, val, fixP->fx_size);
}
else if ((int) (size_t) fixP->fx_bit_fixP == 13
#endif /* OBJ_AOUT or OBJ_BOUT */
-#if defined (OBJ_COFF) && defined (BFD)
-short
-tc_coff_fix2rtype (fixS *fixP)
-{
- if (fixP->fx_bsr)
- abort ();
-
- if (fixP->fx_pcrel == 0 && fixP->fx_size == 4)
- return R_RELLONG;
-
- if (fixP->fx_pcrel != 0 && fixP->fx_size == 4)
- return R_IPRMED;
-
- abort ();
- return 0;
-}
-
-int
-tc_coff_sizemachdep (fragS *frag)
-{
- if (frag->fr_next)
- return frag->fr_next->fr_address - frag->fr_address;
- else
- return 0;
-}
-#endif
-
/* Align an address by rounding it up to the specified boundary. */
valueT
{
int align;
-#ifdef BFD_ASSEMBLER
align = bfd_get_section_alignment (stdoutput, seg);
-#else
- align = section_alignment[(int) seg];
-#endif
- return (addr + (1 << align) - 1) & (-1 << align);
+ return (addr + (1 << align) - 1) & -(1 << align);
}
extern int coff_flags;
-#ifdef OBJ_COFF
-void
-tc_headers_hook (object_headers *headers)
-{
- switch (architecture)
- {
- case ARCH_KA:
- coff_flags |= F_I960KA;
- break;
-
- case ARCH_KB:
- coff_flags |= F_I960KB;
- break;
-
- case ARCH_MC:
- coff_flags |= F_I960MC;
- break;
-
- case ARCH_CA:
- coff_flags |= F_I960CA;
- break;
-
- case ARCH_JX:
- coff_flags |= F_I960JX;
- break;
-
- case ARCH_HX:
- coff_flags |= F_I960HX;
- break;
-
- default:
- if (iclasses_seen == I_BASE)
- coff_flags |= F_I960CORE;
- else if (iclasses_seen & I_CX)
- coff_flags |= F_I960CA;
- else if (iclasses_seen & I_HX)
- coff_flags |= F_I960HX;
- else if (iclasses_seen & I_JX)
- coff_flags |= F_I960JX;
- else if (iclasses_seen & I_CX2)
- coff_flags |= F_I960CA;
- else if (iclasses_seen & I_MIL)
- coff_flags |= F_I960MC;
- else if (iclasses_seen & (I_DEC | I_FP))
- coff_flags |= F_I960KB;
- else
- coff_flags |= F_I960KA;
- break;
- }
-
- if (flag_readonly_data_in_text)
- {
- headers->filehdr.f_magic = I960RWMAGIC;
- headers->aouthdr.magic = OMAGIC;
- }
- else
- {
- headers->filehdr.f_magic = I960ROMAGIC;
- headers->aouthdr.magic = NMAGIC;
- } /* set magic numbers */
-}
-
-#endif /* OBJ_COFF */
-
-#ifndef BFD_ASSEMBLER
-
-/* Things going on here:
-
- For bout, We need to assure a couple of simplifying
- assumptions about leafprocs for the linker: the leafproc
- entry symbols will be defined in the same assembly in
- which they're declared with the '.leafproc' directive;
- and if a leafproc has both 'call' and 'bal' entry points
- they are both global or both local.
-
- For coff, the call symbol has a second aux entry that
- contains the bal entry point. The bal symbol becomes a
- label.
-
- For coff representation, the call symbol has a second aux entry that
- contains the bal entry point. The bal symbol becomes a label. */
-
-void
-tc_crawl_symbol_chain (object_headers *headers ATTRIBUTE_UNUSED)
-{
- symbolS *symbolP;
-
- for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
- {
-#ifdef OBJ_COFF
- if (TC_S_IS_SYSPROC (symbolP))
- {
- /* Second aux entry already contains the sysproc number. */
- S_SET_NUMBER_AUXILIARY (symbolP, 2);
- S_SET_STORAGE_CLASS (symbolP, C_SCALL);
- S_SET_DATA_TYPE (symbolP, S_GET_DATA_TYPE (symbolP) | (DT_FCN << N_BTSHFT));
- continue;
- }
-#endif /* OBJ_COFF */
-
- if (!TC_S_IS_BALNAME (symbolP) && !TC_S_IS_CALLNAME (symbolP))
- continue;
-
- if (!S_IS_DEFINED (symbolP))
- as_bad (_("leafproc symbol '%s' undefined"), S_GET_NAME (symbolP));
-
- if (TC_S_IS_CALLNAME (symbolP))
- {
- symbolS *balP = tc_get_bal_of_call (symbolP);
-
- if (S_IS_EXTERNAL (symbolP) != S_IS_EXTERNAL (balP))
- {
- S_SET_EXTERNAL (symbolP);
- S_SET_EXTERNAL (balP);
- as_warn (_("Warning: making leafproc entries %s and %s both global\n"),
- S_GET_NAME (symbolP), S_GET_NAME (balP));
- } /* externality mismatch */
- } /* if callname */
- } /* walk the symbol chain */
-}
-
-#endif /* ! BFD_ASSEMBLER */
-
/* For aout or bout, the bal immediately follows the call.
For coff, we cheat and store a pointer to the bal symbol in the
return 1;
}
-#ifdef BFD_ASSEMBLER
-
/* From cgen.c: */
static short
{
arelent * reloc;
- reloc = xmalloc (sizeof (arelent));
+ reloc = XNEW (arelent);
/* HACK: Is this right? */
fixP->fx_r_type = tc_bfd_fix2rtype (fixP);
if (reloc->howto == NULL)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
- "internal error: can't export reloc type %d (`%s')",
+ _("internal error: can't export reloc type %d (`%s')"),
fixP->fx_r_type,
bfd_get_reloc_code_name (fixP->fx_r_type));
return NULL;
}
- assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
+ gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
reloc->addend = fixP->fx_addnumber;
/* end from cgen.c */
-#endif /* BFD_ASSEMBLER */
-
const pseudo_typeS md_pseudo_table[] =
{
{"bss", s_lcomm, 1},