/* tc-m32r.c -- Assembler for the Mitsubishi M32R.
- Copyright (C) 1996, 1997, 1998, 1999, 2000
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
In order to implement this, we keep track of each unmatched HI
relocation. We then sort them so that they immediately precede the
- corresponding LO relocation. */
+ corresponding LO relocation. */
struct m32r_hi_fixup
{
#define NOP_INSN 0x7000
#define PAR_NOP_INSN 0xf000 /* Can only be used in 2nd slot. */
-/* When we align the .text section, insert the correct NOP pattern.
- N is the power of 2 alignment. LEN is the length of pattern FILL.
- MAX is the maximum number of characters to skip when doing the alignment,
- or 0 if there is no maximum. */
+/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
+ of an rs_align_code fragment. */
-int
-m32r_do_align (n, fill, len, max)
- int n;
- const char *fill;
- int len;
- int max;
+void
+m32r_handle_align (fragp)
+ fragS *fragp;
{
- /* Only do this if the fill pattern wasn't specified. */
- if (fill == NULL
- && subseg_text_p (now_seg)
- /* Only do this special handling if aligning to at least a
- 4 byte boundary. */
- && n > 1
- /* Only do this special handling if we're allowed to emit at
- least two bytes. */
- && (max == 0 || max > 1))
- {
- static const unsigned char nop_pattern[] = { 0xf0, 0x00 };
+ static const unsigned char nop_pattern[] = { 0xf0, 0x00 };
+ static const unsigned char multi_nop_pattern[] = { 0x70, 0x00, 0xf0, 0x00 };
-#if 0
- /* First align to a 2 byte boundary, in case there is an odd .byte. */
- /* FIXME: How much memory will cause gas to use when assembling a big
- program? Perhaps we can avoid the frag_align call? */
- frag_align (1, 0, 0);
-#endif
- /* Next align to a 4 byte boundary (we know n >= 2) using a parallel
- nop. */
- frag_align_pattern (2, nop_pattern, sizeof nop_pattern, 0);
- /* If doing larger alignments use a repeating sequence of appropriate
- nops. */
- if (n > 2)
- {
- static const unsigned char multi_nop_pattern[] =
- { 0x70, 0x00, 0xf0, 0x00 };
- frag_align_pattern (n, multi_nop_pattern, sizeof multi_nop_pattern,
- max ? max - 2 : 0);
- }
+ int bytes, fix;
+ 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;
+ fix = 0;
- prev_insn.insn = NULL;
- return 1;
+ if (bytes & 1)
+ {
+ fix = 1;
+ *p++ = 0;
+ bytes--;
}
- return 0;
+ if (bytes & 2)
+ {
+ memcpy (p, nop_pattern, 2);
+ p += 2;
+ bytes -= 2;
+ fix += 2;
+ }
+
+ memcpy (p, multi_nop_pattern, 4);
+
+ fragp->fr_fix += fix;
+ fragp->fr_var = 4;
}
/* If the last instruction was the first of 2 16 bit insns,
fill_insn (ignore)
int ignore;
{
- (void) m32r_do_align (2, NULL, 0, 0);
+ frag_align_code (2, 0);
prev_insn.insn = NULL;
seen_relaxable_p = 0;
}
if (!syms)
return;
- (void) m32r_do_align (align, NULL, 0, 0);
+ (void) frag_align_code (align, 0);
for (; syms != (sym_linkS *) 0; syms = next_syms)
{
symbolS *symbolP = syms->symbol;
scom_symbol.section = &scom_section;
allow_m32rx (enable_m32rx);
+
+ gas_cgen_initialize_saved_fixups_array ();
}
#define OPERAND_IS_COND_BIT(operand, indices, index) \
/* Preserve any fixups that have been generated and reset the list
to empty. */
- gas_cgen_save_fixups ();
+ gas_cgen_save_fixups (0);
/* Get the indices of the operands of the instruction. */
/* FIXME: CGEN_FIELDS is already recorded, but relying on that fact
|| (errmsg = (char *) can_make_parallel (&first, &second)) == NULL)
{
/* Get the fixups for the first instruction. */
- gas_cgen_swap_fixups ();
+ gas_cgen_swap_fixups (0);
/* Write it out. */
expand_debug_syms (first.debug_sym_link, 1);
make_parallel (second.buffer);
/* Get its fixups. */
- gas_cgen_restore_fixups ();
+ gas_cgen_restore_fixups (0);
/* Write it out. */
expand_debug_syms (second.debug_sym_link, 1);
make_parallel (first.buffer);
/* Get the fixups for the first instruction. */
- gas_cgen_restore_fixups ();
+ gas_cgen_restore_fixups (0);
/* Write out the first instruction. */
expand_debug_syms (first.debug_sym_link, 1);
};
long
-m32r_relax_frag (fragP, stretch)
+m32r_relax_frag (segment, fragP, stretch)
+ segT segment;
fragS *fragP;
long stretch;
{
}
else
{
- growth = relax_frag (fragP, stretch);
+ growth = relax_frag (segment, fragP, stretch);
/* Long jump on odd halfword boundary? */
if (fragP->fr_subtype == 2 && (address & 3) != 0)
fragS *fragP;
segT segment;
{
- int old_fr_fix = fragP->fr_fix;
-
/* The only thing we have to handle here are symbols outside of the
current segment. They may be undefined or in a different segment in
which case linker scripts may place them anywhere.
if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
{
+ int old_fr_fix = fragP->fr_fix;
+
/* The symbol is undefined in this segment.
Change the relaxation subtype to the max allowable and leave
all further handling to md_convert_frag. */
/* Mark this fragment as finished. */
frag_wane (fragP);
+ return fragP->fr_fix - old_fr_fix;
#else
{
const CGEN_INSN *insn;
#endif
}
- return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+ return md_relax_table[fragP->fr_subtype].rlx_length;
}
/* *FRAGP has been relaxed to its final size, and now needs to have
{
/* Address we want to reach in file space. */
target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
- target_address += symbol_get_frag (fragP->fr_symbol)->fr_address;
addend = (target_address - (opcode_address & -4)) >> 2;
}