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. */
+ Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stdio.h>
#include <string.h>
static void s_dual (int);
static void s_enddual (int);
static void s_atmp (int);
+static void s_align_wrapper (int);
static int i860_get_expression (char *);
static bfd_reloc_code_real_type obtain_reloc_for_imm16 (fixS *, long *);
#ifdef DEBUG_I860
const pseudo_typeS md_pseudo_table[] =
{
-#ifdef OBJ_ELF
- {"align", s_align_bytes, 0},
-#endif
- {"dual", s_dual, 0},
- {"enddual", s_enddual, 0},
- {"atmp", s_atmp, 0},
- {NULL, 0, 0},
+ {"align", s_align_wrapper, 0},
+ {"dual", s_dual, 0},
+ {"enddual", s_enddual, 0},
+ {"atmp", s_atmp, 0},
+ {NULL, 0, 0},
};
/* Dual-instruction mode handling. */
static void
s_dual (int ignore ATTRIBUTE_UNUSED)
{
- dual_mode = DUAL_ON;
+ if (target_intel_syntax)
+ dual_mode = DUAL_ON;
+ else
+ as_bad (_("Directive .dual available only with -mintel-syntax option"));
}
/* Handle ".enddual" directive. */
static void
s_enddual (int ignore ATTRIBUTE_UNUSED)
{
- dual_mode = DUAL_OFF;
+ if (target_intel_syntax)
+ dual_mode = DUAL_OFF;
+ else
+ as_bad (_("Directive .enddual available only with -mintel-syntax option"));
}
/* Temporary register used when expanding assembler pseudo operations. */
static void
s_atmp (int ignore ATTRIBUTE_UNUSED)
{
- register int temp;
+ int temp;
+
+ if (! target_intel_syntax)
+ {
+ as_bad (_("Directive .atmp available only with -mintel-syntax option"));
+ demand_empty_rest_of_line ();
+ return;
+ }
+
if (strncmp (input_line_pointer, "sp", 2) == 0)
{
input_line_pointer += 2;
demand_empty_rest_of_line ();
}
+/* Handle ".align" directive depending on syntax mode.
+ AT&T/SVR4 syntax uses the standard align directive. However,
+ the Intel syntax additionally allows keywords for the alignment
+ parameter: ".align type", where type is one of {.short, .long,
+ .quad, .single, .double} representing alignments of 2, 4,
+ 16, 4, and 8, respectively. */
+static void
+s_align_wrapper (int arg)
+{
+ char *parm = input_line_pointer;
+
+ if (target_intel_syntax)
+ {
+ /* Replace a keyword with the equivalent integer so the
+ standard align routine can parse the directive. */
+ if (strncmp (parm, ".short", 6) == 0)
+ strncpy (parm, " 2", 6);
+ else if (strncmp (parm, ".long", 5) == 0)
+ strncpy (parm, " 4", 5);
+ else if (strncmp (parm, ".quad", 5) == 0)
+ strncpy (parm, " 16", 5);
+ else if (strncmp (parm, ".single", 7) == 0)
+ strncpy (parm, " 4", 7);
+ else if (strncmp (parm, ".double", 7) == 0)
+ strncpy (parm, " 8", 7);
+
+ while (*input_line_pointer == ' ')
+ ++input_line_pointer;
+ }
+
+ s_align_bytes (arg);
+}
+
/* This function is called once, at assembler startup time. It should
set up all the tables and data structures that the MD part of the
assembler will need. */
&& the_insn.fi[0].exp.X_add_number >= -(1 << 15)))
break;
- /* Emit "orh ha%addr_expr,r0,r31". */
- pseudo[0].opcode = 0xec000000 | (atmp << 16);
+ /* Emit "orh ha%addr_expr,ireg_src2,r31". */
+ pseudo[0].opcode = 0xec000000 | (the_insn.opcode & 0x03e00000)
+ | (atmp << 16);
pseudo[0].fi[0].fup = (OP_IMM_S16 | OP_SEL_HA);
/* Emit "l%addr_expr(r31),ireg_dest". We pick up the fixup
case 'g':
opcode |= mask << 16;
- if (dual_mode != DUAL_OFF)
- opcode |= (1 << 9);
- if (dual_mode == DUAL_DDOT)
- dual_mode = DUAL_OFF;
- if (dual_mode == DUAL_ONDDOT)
- dual_mode = DUAL_ON;
if ((opcode & (1 << 10)) && mask != 0
&& (mask == ((opcode >> 11) & 0x1f)))
as_warn (_("Pipelined instruction: fsrc1 = fdest"));
break;
}
+ /* Set the dual bit on this instruction if necessary. */
+ if (dual_mode != DUAL_OFF)
+ {
+ if ((opcode & 0xfc000000) == 0x48000000 || opcode == 0xb0000000)
+ {
+ /* The instruction is a flop or a fnop, so set its dual bit
+ (but check that it is 8-byte aligned). */
+ if (((frag_now->fr_address + frag_now_fix_octets ()) & 7) == 0)
+ opcode |= (1 << 9);
+ else
+ as_bad (_("'d.%s' must be 8-byte aligned"), insn->name);
+
+ if (dual_mode == DUAL_DDOT)
+ dual_mode = DUAL_OFF;
+ else if (dual_mode == DUAL_ONDDOT)
+ dual_mode = DUAL_ON;
+ }
+ else if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT)
+ as_bad (_("Prefix 'd.' invalid for instruction `%s'"), insn->name);
+ }
+
the_insn.opcode = opcode;
/* Only recognize XP instructions when the user has requested it. */
}
/* On the i860, a PC-relative offset is relative to the address of the
- of the offset plus its size. */
+ offset plus its size. */
long
md_pcrel_from (fixS *fixP)
{
we will have to generate a reloc entry. */
void
-md_apply_fix3 (fixS *fix, valueT *valP, segT seg ATTRIBUTE_UNUSED)
+md_apply_fix (fixS *fix, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
char *buf;
long val = *valP;
}
return reloc;
}
+
+/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
+ of an rs_align_code fragment. */
+
+void
+i860_handle_align (fragS *fragp)
+{
+ /* Instructions are always stored little-endian on the i860. */
+ static const unsigned char le_nop[] = { 0x00, 0x00, 0x00, 0xA0 };
+
+ int bytes;
+ char *p;
+
+ if (fragp->fr_type != rs_align_code)
+ return;
+
+ bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
+ p = fragp->fr_literal + fragp->fr_fix;
+
+ /* Make sure we are on a 4-byte boundary, in case someone has been
+ putting data into a text section. */
+ if (bytes & 3)
+ {
+ int fix = bytes & 3;
+ memset (p, 0, fix);
+ p += fix;
+ fragp->fr_fix += fix;
+ }
+
+ memcpy (p, le_nop, 4);
+ fragp->fr_var = 4;
+}
+
+/* This is called after a user-defined label is seen. We check
+ if the label has a double colon (valid in Intel syntax mode only),
+ in which case it should be externalized. */
+
+void
+i860_check_label (symbolS *labelsym)
+{
+ /* At this point, the current line pointer is sitting on the character
+ just after the first colon on the label. */
+ if (target_intel_syntax && *input_line_pointer == ':')
+ {
+ S_SET_EXTERNAL (labelsym);
+ input_line_pointer++;
+ }
+}
+