/* 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.
#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;
}