This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
code alignment cleanup
- To: binutils at sources dot redhat dot com
- Subject: code alignment cleanup
- From: Richard Henderson <rth at redhat dot com>
- Date: Thu, 28 Dec 2000 02:17:17 -0800
The initial object of this was to get Alpha to pad with nops instead
of zeros at the end of the text section. Instead this has turned into
a general cleanup of alignment within code-bearing sections.
To wit:
* rs_align_code means exactly that, and is created by generic
assembler bits in appropriate places.
* rs_align_test replaces abuse of rs_align_code within the
sh and sparc ports.
* No need to define md_do_align if all you want is control
of nop filling.
Tested on alpha-linux, ia64-elf, sparc-elf, sh-hms, i386-linux.
r~
* as.h (rs_align_test): New.
* frags.c (NOP_OPCODE): Move default from read.c.
(MAX_MEM_FOR_RS_ALIGN_CODE): New default.
(frag_align_code): New.
* frags.h (frag_align_code): Declare.
* read.c (NOP_OPCODE): Remove.
(do_align): Use frag_align_code.
* write.c (NOP_OPCODE): Remove.
(get_recorded_alignment): New.
(cvt_frag_to_fill): Handle rs_align_test.
(relax_segment): Likewise.
(subsegs_finish): Align last subseg in section to the
section alignment. Use frag_align_code.
* write.h (get_recorded_alignment): Declare.
* config/obj-coff.c (size_section): Handle rs_align_test.
(fill_section, fixup_mdeps): Likewise.
(write_object_file): Use frag_align_code.
* config/tc-alpha.c (alpha_align): Use frag_align_code.
(alpha_handle_align): New.
* config/tc-alpha.h (HANDLE_ALIGN): New.
(MAX_MEM_FOR_RS_ALIGN_CODE): New.
* config/tc-i386.h (md_do_align): Use frag_align_code.
(MAX_MEM_FOR_RS_ALIGN_CODE): New.
* config/tc-ia64.c (ia64_md_do_align): Don't do code alignment.
(ia64_handle_align): New.
* config/tc-ia64.h (HANDLE_ALIGN): New.
(MAX_MEM_FOR_RS_ALIGN_CODE): New.
* config/tc-m32r.c (m32r_do_align): Remove.
(m32r_handle_align): New.
(fill_insn): Use frag_align_code.
* config/tc-m32r.h (md_do_align): Remove.
(HANDLE_ALIGN, MAX_MEM_FOR_RS_ALIGN_CODE): New.
* config/tc-m88k.c, config/tc-m88k.h: Similarly.
* config/tc-mips.c, config/tc-mips.h: Similarly.
* config/tc-sh.c (sh_cons_align): Use rs_align_test.
(sh_handle_align): Likewise. Handle rs_align_code.
(sh_do_align): Remove.
* config/tc-sh.h (md_do_align): Remove.
(MAX_MEM_FOR_RS_ALIGN_CODE): New.
* config/tc-sparc.c (sparc_cons_align): Use rs_align_test.
(sparc_handle_align): Likewise. Handle rs_align_code.
* config/tc-sparc.h (md_do_align): Remove.
(MAX_MEM_FOR_RS_ALIGN_CODE): New.
Index: as.h
===================================================================
RCS file: /cvs/src/src/gas/as.h,v
retrieving revision 1.20
diff -c -p -d -r1.20 as.h
*** as.h 2000/12/14 01:12:43 1.20
--- as.h 2000/12/28 10:06:54
*************** enum _relax_state {
*** 364,369 ****
--- 364,373 ----
bytes to skip when aligning, or 0 if there is no maximum. */
rs_align_code,
+ /* Test for alignment. Like rs_align, but used by several targets
+ to warn if data is not properly aligned. */
+ rs_align_test,
+
/* Org: Fr_offset, fr_symbol: address. 1 variable char: fill
character. */
rs_org,
Index: frags.c
===================================================================
RCS file: /cvs/src/src/gas/frags.c,v
retrieving revision 1.7
diff -c -p -d -r1.7 frags.c
*** frags.c 2000/08/31 18:36:18 1.7
--- frags.c 2000/12/28 10:06:54
*************** frag_align_pattern (alignment, fill_patt
*** 322,327 ****
--- 322,360 ----
memcpy (p, fill_pattern, n_fill);
}
+ /* The NOP_OPCODE is for the alignment fill value. Fill it with a nop
+ instruction so that the disassembler does not choke on it. */
+ #ifndef NOP_OPCODE
+ #define NOP_OPCODE 0x00
+ #endif
+
+ /* Use this to restrict the amount of memory allocated for representing
+ the alignment code. Needs to be large enough to hold any fixed sized
+ prologue plus the replicating portion. */
+ #ifndef MAX_MEM_FOR_RS_ALIGN_CODE
+ /* Assume that if HANDLE_ALIGN is not defined then no special action
+ is required to code fill, which means that we get just repeat the
+ one NOP_OPCODE byte. */
+ # ifndef HANDLE_ALIGN
+ # define MAX_MEM_FOR_RS_ALIGN_CODE 1
+ # else
+ # define MAX_MEM_FOR_RS_ALIGN_CODE ((1 << alignment) - 1)
+ # endif
+ #endif
+
+ void
+ frag_align_code (alignment, max)
+ int alignment;
+ int max;
+ {
+ char *p;
+
+ p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, 1,
+ (relax_substateT) max, (symbolS *) 0,
+ (offsetT) alignment, (char *) 0);
+ *p = NOP_OPCODE;
+ }
+
addressT
frag_now_fix_octets ()
{
Index: frags.h
===================================================================
RCS file: /cvs/src/src/gas/frags.h,v
retrieving revision 1.7
diff -c -p -d -r1.7 frags.h
*** frags.h 2000/10/17 20:21:45 1.7
--- frags.h 2000/12/28 10:06:54
*************** void frag_align_pattern PARAMS ((int ali
*** 132,137 ****
--- 132,138 ----
const char *fill_pattern,
int n_fill,
int max));
+ void frag_align_code PARAMS ((int alignment, int max));
void frag_new PARAMS ((int old_frags_var_max_size));
void frag_wane PARAMS ((fragS * fragP));
Index: read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.31
diff -c -p -d -r1.31 read.c
*** read.c 2000/11/17 08:47:51 1.31
--- read.c 2000/12/28 10:06:54
*************** Software Foundation, 59 Temple Place - S
*** 67,79 ****
while (0)
#endif
- /* The NOP_OPCODE is for the alignment fill value.
- Fill it a nop instruction so that the disassembler does not choke
- on it. */
- #ifndef NOP_OPCODE
- #define NOP_OPCODE 0x00
- #endif
-
char *input_line_pointer; /*->next char of source file to parse. */
#if BITS_PER_CHAR != 8
--- 67,72 ----
*************** do_align (n, fill, len, max)
*** 1172,1197 ****
int len;
int max;
{
- char default_fill;
-
#ifdef md_do_align
md_do_align (n, fill, len, max, just_record_alignment);
#endif
- if (fill == NULL)
- {
- if (subseg_text_p (now_seg))
- default_fill = NOP_OPCODE;
- else
- default_fill = 0;
- fill = &default_fill;
- len = 1;
- }
-
/* Only make a frag if we HAVE to... */
if (n != 0 && !need_pass_2)
{
! if (len <= 1)
frag_align (n, *fill, max);
else
frag_align_pattern (n, fill, len, max);
--- 1165,1185 ----
int len;
int max;
{
#ifdef md_do_align
md_do_align (n, fill, len, max, just_record_alignment);
#endif
/* Only make a frag if we HAVE to... */
if (n != 0 && !need_pass_2)
{
! if (fill == NULL)
! {
! if (subseg_text_p (now_seg))
! frag_align_code (n, max);
! else
! frag_align (n, 0, max);
! }
! else if (len <= 1)
frag_align (n, *fill, max);
else
frag_align_pattern (n, fill, len, max);
Index: write.c
===================================================================
RCS file: /cvs/src/src/gas/write.c,v
retrieving revision 1.23
diff -c -p -d -r1.23 write.c
*** write.c 2000/11/29 21:42:41 1.23
--- write.c 2000/12/28 10:06:54
***************
*** 31,42 ****
#undef BFD_FAST_SECTION_FILL
#define BFD_FAST_SECTION_FILL
- /* The NOP_OPCODE is for the alignment fill value. Fill it with a nop
- instruction so that the disassembler does not choke on it. */
- #ifndef NOP_OPCODE
- #define NOP_OPCODE 0x00
- #endif
-
#ifndef TC_ADJUST_RELOC_COUNT
#define TC_ADJUST_RELOC_COUNT(FIXP,COUNT)
#endif
--- 31,36 ----
*************** record_alignment (seg, align)
*** 383,388 ****
--- 377,395 ----
#endif
}
+ int
+ get_recorded_alignment (seg)
+ segT seg;
+ {
+ if (seg == absolute_section)
+ return 0;
+ #ifdef BFD_ASSEMBLER
+ return bfd_get_section_alignment (stdoutput, seg);
+ #else
+ return section_alignment[(int) seg];
+ #endif
+ }
+
#ifdef BFD_ASSEMBLER
/* Reset the section indices after removing the gas created sections. */
*************** cvt_frag_to_fill (headersP, sec, fragP)
*** 494,499 ****
--- 501,507 ----
{
case rs_align:
case rs_align_code:
+ case rs_align_test:
case rs_org:
case rs_space:
#ifdef HANDLE_ALIGN
*************** subsegs_finish ()
*** 1390,1404 ****
for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
{
subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
/* This now gets called even if we had errors. In that case,
any alignment is meaningless, and, moreover, will look weird
if we are generating a listing. */
! frag_align (had_errors () ? 0 : SUB_SEGMENT_ALIGN (now_seg),
! subseg_text_p (now_seg) ? NOP_OPCODE : 0,
! 0);
/* frag_align will have left a new frag.
Use this last frag for an empty ".fill".
--- 1398,1426 ----
for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
{
+ int alignment;
+
subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
/* This now gets called even if we had errors. In that case,
any alignment is meaningless, and, moreover, will look weird
if we are generating a listing. */
! alignment = had_errors () ? 0 : SUB_SEGMENT_ALIGN (now_seg);
!
! /* The last subsegment gets an aligment corresponding to the
! alignment of the section. This allows proper nop-filling
! at the end of code-bearing sections. */
! if (!frchainP->frch_next || frchainP->frch_next->frch_seg != now_seg)
! alignment = get_recorded_alignment (now_seg);
+ if (alignment > 0)
+ {
+ if (subseg_text_p (now_seg))
+ frag_align_code (alignment, 0);
+ else
+ frag_align (alignment, 0, 0);
+ }
+
/* frag_align will have left a new frag.
Use this last frag for an empty ".fill".
*************** relax_segment (segment_frag_root, segmen
*** 2156,2161 ****
--- 2178,2184 ----
case rs_align:
case rs_align_code:
+ case rs_align_test:
{
addressT offset = relax_align (address, (int) fragP->fr_offset);
*************** relax_segment (segment_frag_root, segmen
*** 2305,2310 ****
--- 2328,2334 ----
#endif
case rs_align:
case rs_align_code:
+ case rs_align_test:
{
addressT oldoff, newoff;
Index: write.h
===================================================================
RCS file: /cvs/src/src/gas/write.h,v
retrieving revision 1.2
diff -c -p -d -r1.2 write.h
*** write.h 2000/09/12 20:57:14 1.2
--- write.h 2000/12/28 10:06:54
*************** extern bit_fixS *bit_fix_new
*** 178,183 ****
--- 178,184 ----
long max, long add));
extern void append PARAMS ((char **charPP, char *fromP, unsigned long length));
extern void record_alignment PARAMS ((segT seg, int align));
+ extern int get_recorded_alignment PARAMS ((segT seg));
extern void subsegs_finish PARAMS ((void));
extern void write_object_file PARAMS ((void));
extern long relax_frag PARAMS ((fragS *, long));
Index: config/obj-coff.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-coff.c,v
retrieving revision 1.38
diff -c -p -d -r1.38 obj-coff.c
*** obj-coff.c 2000/12/01 17:11:57 1.38
--- obj-coff.c 2000/12/28 10:06:54
*************** size_section (abfd, idx)
*** 1826,1831 ****
--- 1826,1832 ----
break;
case rs_align:
case rs_align_code:
+ case rs_align_test:
{
addressT off;
*************** fill_section (abfd, h, file_cursor)
*** 2135,2140 ****
--- 2136,2142 ----
case rs_fill:
case rs_align:
case rs_align_code:
+ case rs_align_test:
case rs_org:
if (frag->fr_fix)
{
*************** write_object_file ()
*** 3443,3454 ****
md_do_align (SUB_SEGMENT_ALIGN (now_seg), (char *) NULL, 0, 0,
alignment_done);
#endif
! frag_align (SUB_SEGMENT_ALIGN (now_seg),
! subseg_text_p (now_seg) ? NOP_OPCODE : 0,
! 0);
#ifdef md_do_align
alignment_done:
#endif
frag_wane (frag_now);
frag_now->fr_fix = 0;
know (frag_now->fr_next == NULL);
--- 3445,3459 ----
md_do_align (SUB_SEGMENT_ALIGN (now_seg), (char *) NULL, 0, 0,
alignment_done);
#endif
! if (subseg_text_p (now_seg))
! frag_align_code (SUB_SEGMENT_ALIGN (now_seg), 0);
! else
! frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0);
!
#ifdef md_do_align
alignment_done:
#endif
+
frag_wane (frag_now);
frag_now->fr_fix = 0;
know (frag_now->fr_next == NULL);
*************** fixup_mdeps (frags, h, this_segment)
*** 4092,4097 ****
--- 4097,4103 ----
{
case rs_align:
case rs_align_code:
+ case rs_align_test:
case rs_org:
#ifdef HANDLE_ALIGN
HANDLE_ALIGN (frags);
Index: config/tc-alpha.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.c,v
retrieving revision 1.16
diff -c -p -d -r1.16 tc-alpha.c
*** tc-alpha.c 2000/12/03 06:49:21 1.16
--- tc-alpha.c 2000/12/28 10:06:55
*************** alpha_align (n, pfill, label, force)
*** 5673,5699 ****
if (pfill == NULL)
{
! if (n > 2
! && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
! {
! static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f };
! static char const nopunop[8] = {
! 0x1f, 0x04, 0xff, 0x47,
! 0x00, 0x00, 0xe0, 0x2f
! };
!
! /* First, make sure we're on a four-byte boundary, in case
! someone has been putting .byte values into the text
! section. The DEC assembler silently fills with unaligned
! no-op instructions. This will zero-fill, then nop-fill
! with proper alignment. */
! if (alpha_current_align < 2)
! frag_align (2, 0, 0);
! if (alpha_current_align < 3)
! frag_align_pattern (3, unop, sizeof unop, 0);
! if (n > 3)
! frag_align_pattern (n, nopunop, sizeof nopunop, 0);
! }
else
frag_align (n, 0, 0);
}
--- 5673,5680 ----
if (pfill == NULL)
{
! if (subseg_text_p (now_seg))
! frag_align_code (n, 0);
else
frag_align (n, 0, 0);
}
*************** alpha_align (n, pfill, label, force)
*** 5710,5717 ****
record_alignment (now_seg, n);
! /* ??? if alpha_flag_relax && force && elf, record the requested alignment
in a reloc for the linker to see. */
}
/* The Alpha has support for some VAX floating point types, as well as for
--- 5691,5743 ----
record_alignment (now_seg, n);
! /* ??? If alpha_flag_relax && force && elf, record the requested alignment
in a reloc for the linker to see. */
+ }
+
+ /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
+ of an rs_align_code fragment. */
+
+ void
+ alpha_handle_align (fragp)
+ fragS *fragp;
+ {
+ static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f };
+ static char const nopunop[8] = {
+ 0x1f, 0x04, 0xff, 0x47,
+ 0x00, 0x00, 0xe0, 0x2f
+ };
+
+ 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;
+
+ if (bytes & 3)
+ {
+ fix = bytes & 3;
+ memset (p, 0, fix);
+ p += fix;
+ bytes -= fix;
+ }
+
+ if (bytes & 4)
+ {
+ memcpy (p, unop, 4);
+ p += 4;
+ bytes -= 4;
+ fix += 4;
+ }
+
+ memcpy (p, nopunop, 8);
+
+ fragp->fr_fix += fix;
+ fragp->fr_var = 8;
}
/* The Alpha has support for some VAX floating point types, as well as for
Index: config/tc-alpha.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.h,v
retrieving revision 1.4
diff -c -p -d -r1.4 tc-alpha.h
*** tc-alpha.h 2000/11/17 08:47:51 1.4
--- tc-alpha.h 2000/12/28 10:06:55
*************** extern void alpha_define_label PARAMS ((
*** 90,95 ****
--- 90,100 ----
#define md_cons_align(nbytes) alpha_cons_align (nbytes)
extern void alpha_cons_align PARAMS ((int));
+ #define HANDLE_ALIGN(fragp) alpha_handle_align (fragp)
+ extern void alpha_handle_align PARAMS ((struct frag *));
+
+ #define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4 + 8)
+
#ifdef OBJ_ECOFF
#define tc_frob_file_before_adjust() alpha_frob_file_before_adjust ()
extern void alpha_frob_file_before_adjust PARAMS ((void));
Index: config/tc-i386.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.h,v
retrieving revision 1.19
diff -c -p -d -r1.19 tc-i386.h
*** tc-i386.h 2000/12/20 13:24:12 1.19
--- tc-i386.h 2000/12/28 10:06:55
*************** if ((n) && !need_pass_2 \
*** 505,516 ****
&& (!(fill) || ((char)*(fill) == (char)0x90 && (len) == 1)) \
&& subseg_text_p (now_seg)) \
{ \
! char *p; \
! p = frag_var (rs_align_code, 15, 1, (relax_substateT) max, \
! (symbolS *) 0, (offsetT) (n), (char *) 0); \
! *p = 0x90; \
goto around; \
}
extern void i386_align_code PARAMS ((fragS *, int));
--- 505,515 ----
&& (!(fill) || ((char)*(fill) == (char)0x90 && (len) == 1)) \
&& subseg_text_p (now_seg)) \
{ \
! frag_align_code ((n), (max)); \
goto around; \
}
+
+ #define MAX_MEM_FOR_RS_ALIGN_CODE 15
extern void i386_align_code PARAMS ((fragS *, int));
Index: config/tc-ia64.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.c,v
retrieving revision 1.36
diff -c -p -d -r1.36 tc-ia64.c
*** tc-ia64.c 2000/12/03 06:49:22 1.36
--- tc-ia64.c 2000/12/28 10:06:55
*************** md_section_align (seg, size)
*** 9768,9809 ****
/* Handle ia64 specific semantics of the align directive. */
! int
ia64_md_do_align (n, fill, len, max)
int n;
const char *fill;
int len ATTRIBUTE_UNUSED;
int max;
{
! /* Fill any pending bundle with nops. */
! if (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)
ia64_flush_insns ();
! /* When we align code in a text section, emit a bundle of 3 nops instead of
! zero bytes. We can only do this if a multiple of 16 bytes was requested.
! N is log base 2 of the requested alignment. */
! if (fill == NULL
! && bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE
! && n > 4)
! {
! /* Use mfi bundle of nops with no stop bits. */
! static const unsigned char be_nop[]
! = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
! 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c};
! static const unsigned char le_nop[]
! = { 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
! 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
! /* Make sure we are on a 16-byte boundary, in case someone has been
! putting data into a text section. */
! frag_align (4, 0, 0);
! if (target_big_endian)
! frag_align_pattern (n, be_nop, 16, max);
! else
! frag_align_pattern (n, le_nop, 16, max);
! return 1;
}
! return 0;
}
--- 9768,9819 ----
/* Handle ia64 specific semantics of the align directive. */
! void
ia64_md_do_align (n, fill, len, max)
int n;
const char *fill;
int len ATTRIBUTE_UNUSED;
int max;
{
! if (subseg_text_p (now_seg))
ia64_flush_insns ();
+ }
! /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
! of an rs_align_code fragment. */
! void
! ia64_handle_align (fragp)
! fragS *fragp;
! {
! /* Use mfi bundle of nops with no stop bits. */
! static const unsigned char be_nop[]
! = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
! 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c};
! static const unsigned char le_nop[]
! = { 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
! 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
! 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 16-byte boundary, in case someone has been
! putting data into a text section. */
! if (bytes & 15)
! {
! int fix = bytes & 15;
! memset (p, 0, fix);
! p += fix;
! bytes -= fix;
! fragp->fr_fix += fix;
}
! memcpy (p, (target_big_endian ? be_nop : le_nop), 16);
! fragp->fr_var = 16;
}
Index: config/tc-ia64.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.h,v
retrieving revision 1.5
diff -c -p -d -r1.5 tc-ia64.h
*** tc-ia64.h 2000/12/12 22:56:35 1.5
--- tc-ia64.h 2000/12/28 10:06:55
*************** extern void ia64_validate_fix PARAMS ((s
*** 83,89 ****
extern char * ia64_canonicalize_symbol_name PARAMS ((char *));
extern flagword ia64_elf_section_flags PARAMS ((flagword, int, int));
extern long ia64_pcrel_from_section PARAMS ((struct fix *fix, segT sec));
! extern int ia64_md_do_align PARAMS ((int, const char *, int, int));
#define md_end() ia64_end_of_source ()
#define md_start_line_hook() ia64_start_line ()
--- 83,90 ----
extern char * ia64_canonicalize_symbol_name PARAMS ((char *));
extern flagword ia64_elf_section_flags PARAMS ((flagword, int, int));
extern long ia64_pcrel_from_section PARAMS ((struct fix *fix, segT sec));
! extern void ia64_md_do_align PARAMS ((int, const char *, int, int));
! extern void ia64_handle_align PARAMS ((fragS *f));
#define md_end() ia64_end_of_source ()
#define md_start_line_hook() ia64_start_line ()
*************** extern int ia64_md_do_align PARAMS ((int
*** 108,114 ****
#define TC_CONS_FIX_NEW(f,o,l,e) ia64_cons_fix_new (f, o, l, e)
#define TC_VALIDATE_FIX(fix,seg,skip) ia64_validate_fix (fix)
#define MD_PCREL_FROM_SECTION(fix,sec) ia64_pcrel_from_section (fix, sec)
! #define md_do_align(n,f,l,m,j) if (ia64_md_do_align (n,f,l,m)) goto j
/* Call md_apply_fix3 with segment instead of md_apply_fix. */
#define MD_APPLY_FIX3
--- 109,118 ----
#define TC_CONS_FIX_NEW(f,o,l,e) ia64_cons_fix_new (f, o, l, e)
#define TC_VALIDATE_FIX(fix,seg,skip) ia64_validate_fix (fix)
#define MD_PCREL_FROM_SECTION(fix,sec) ia64_pcrel_from_section (fix, sec)
! #define md_do_align(n,f,l,m,j) ia64_md_do_align (n,f,l,m)
! #define HANDLE_ALIGN(f) ia64_handle_align (f)
!
! #define MAX_MEM_FOR_RS_ALIGN_CODE (15 + 16)
/* Call md_apply_fix3 with segment instead of md_apply_fix. */
#define MD_APPLY_FIX3
Index: config/tc-m32r.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m32r.c,v
retrieving revision 1.13
diff -c -p -d -r1.13 tc-m32r.c
*** tc-m32r.c 2000/09/20 22:05:08 1.13
--- tc-m32r.c 2000/12/28 10:06:55
*************** const pseudo_typeS md_pseudo_table[] =
*** 327,380 ****
#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. */
! int
! m32r_do_align (n, fill, len, max)
! int n;
! const char *fill;
! int len;
! int max;
{
! /* 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 };
! #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);
! }
! prev_insn.insn = NULL;
! return 1;
}
! return 0;
}
/* If the last instruction was the first of 2 16 bit insns,
--- 327,370 ----
#define NOP_INSN 0x7000
#define PAR_NOP_INSN 0xf000 /* Can only be used in 2nd slot. */
! /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
! of an rs_align_code fragment. */
! void
! m32r_handle_align (fragp)
{
! static const unsigned char nop_pattern[] = { 0xf0, 0x00 };
! static const unsigned char multi_nop_pattern[] = { 0x70, 0x00, 0xf0, 0x00 };
! 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;
!
! if (bytes & 1)
! {
! fix = 1;
! *p++ = 0;
! bytes--;
}
! 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,
*************** static void
*** 390,396 ****
fill_insn (ignore)
int ignore;
{
! (void) m32r_do_align (2, NULL, 0, 0);
prev_insn.insn = NULL;
seen_relaxable_p = 0;
}
--- 380,386 ----
fill_insn (ignore)
int ignore;
{
! frag_align_code (2, 0);
prev_insn.insn = NULL;
seen_relaxable_p = 0;
}
Index: config/tc-m32r.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m32r.h,v
retrieving revision 1.2
diff -c -p -d -r1.2 tc-m32r.h
*** tc-m32r.h 2000/09/20 22:05:08 1.2
--- tc-m32r.h 2000/12/28 10:06:55
*************** m32r_relax_frag (fragP, stretch)
*** 61,71 ****
/* Account for nop if 32 bit insn falls on odd halfword boundary. */
#define TC_CGEN_MAX_RELAX(insn, len) (6)
! /* Alignments are used to ensure 32 bit insns live on 32 bit boundaries, so
! we use a special alignment function to insert the correct nop pattern. */
! extern int m32r_do_align PARAMS ((int, const char *, int, int));
! #define md_do_align(n, fill, len, max, l) \
! if (m32r_do_align (n, fill, len, max)) goto l
#define MD_APPLY_FIX3
#define md_apply_fix3 gas_cgen_md_apply_fix3
--- 61,71 ----
/* Account for nop if 32 bit insn falls on odd halfword boundary. */
#define TC_CGEN_MAX_RELAX(insn, len) (6)
! /* Fill in rs_align_code fragments. */
! extern void m32r_handle_align PARAMS ((fragS *));
! #define HANDLE_ALIGN(f) m32r_handle_align (f)
!
! #define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2 + 4)
#define MD_APPLY_FIX3
#define md_apply_fix3 gas_cgen_md_apply_fix3
Index: config/tc-m88k.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m88k.c,v
retrieving revision 1.5
diff -c -p -d -r1.5 tc-m88k.c
*** tc-m88k.c 2000/12/03 06:49:22 1.5
--- tc-m88k.c 2000/12/28 10:06:55
*************** md_pcrel_from (fixp)
*** 1427,1449 ****
/*NOTREACHED*/
}
! /* When we align the .init section, insert the correct NOP pattern. */
! int
! m88k_do_align (n, fill, max, len)
! int n;
! const char *fill;
! int len;
! int max;
{
! if (fill == NULL
! && strcmp (obj_segment_name (now_seg), ".init") == 0)
{
! static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
! frag_align_pattern (n, nop_pattern, sizeof (nop_pattern), max);
! return 1;
}
! return 0;
}
#endif /* M88KCOFF */
--- 1427,1460 ----
/*NOTREACHED*/
}
! /* Fill in rs_align_code fragments. */
! void
! m88k_handle_align (fragp)
! fragS *fragp;
{
! static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };
!
! 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;
!
! if (bytes & 3)
{
! int fix = bytes & 3;
! memset (p, 0, fix);
! p += fix;
! bytes -= fix;
! fragp->fr_fix += fix;
}
!
! memcpy (p, nop_pattern, 4);
! fragp->fr_var = 4;
}
#endif /* M88KCOFF */
Index: config/tc-m88k.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m88k.h,v
retrieving revision 1.2
diff -c -p -d -r1.2 tc-m88k.h
*** tc-m88k.h 2000/02/24 01:56:31 1.2
--- tc-m88k.h 2000/12/28 10:06:55
*************** struct reloc_info_m88k
*** 100,108 ****
#endif
#define SUB_SEGMENT_ALIGN(SEG) max (section_alignment[(int) (SEG)], 4)
! /* We use a special alignment function to insert the correct nop
! pattern in .init. */
! extern int m88k_do_align PARAMS ((int, const char *, int, int));
! #define md_do_align(n,fill,len,max,l) if (m88k_do_align(n,fill,max,len)) goto l
#endif /* M88KCOFF */
--- 100,109 ----
#endif
#define SUB_SEGMENT_ALIGN(SEG) max (section_alignment[(int) (SEG)], 4)
! /* Fill in rs_align_code fragments. */
! extern void m88k_handle_align PARAMS ((fragS *));
! #define HANDLE_ALIGN(frag) m88k_handle_align (frag)
!
! #define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
#endif /* M88KCOFF */
Index: config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.33
diff -c -p -d -r1.33 tc-mips.c
*** tc-mips.c 2000/12/12 19:29:24 1.33
--- tc-mips.c 2000/12/28 10:06:55
*************** static procS cur_proc;
*** 11550,11583 ****
static procS *cur_proc_ptr;
static int numprocs;
! /* When we align code in the .text section of mips16, use the correct two
! byte nop pattern of 0x6500 (move $0,$0) */
! int
! mips_do_align (n, fill, len, max)
! int n;
! const char *fill;
! int len ATTRIBUTE_UNUSED;
! int max;
{
! if (fill == NULL
! && subseg_text_p (now_seg)
! && n > 1
! && mips_opts.mips16)
{
static const unsigned char be_nop[] = { 0x65, 0x00 };
static const unsigned char le_nop[] = { 0x00, 0x65 };
! frag_align (1, 0, 0);
! if (target_big_endian)
! frag_align_pattern (n, be_nop, 2, max);
! else
! frag_align_pattern (n, le_nop, 2, max);
! return 1;
}
! return 0;
}
static void
--- 11550,11586 ----
static procS *cur_proc_ptr;
static int numprocs;
! /* Fill in an rs_align_code fragment. */
! void
! mips_handle_align (fragp)
! fragS *fragp;
{
! if (fragp->fr_type != rs_align_code)
! return;
!
! if (mips_opts.mips16)
{
static const unsigned char be_nop[] = { 0x65, 0x00 };
static const unsigned char le_nop[] = { 0x00, 0x65 };
! int bytes;
! char *p;
! bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
! p = fragp->fr_literal + fragp->fr_fix;
!
! if (bytes & 1)
! {
! *p++ = 0;
! fragp->fr_fix += 1;
! }
!
! memcpy (p, (target_big_endian ? be_nop : le_nop), 2);
! fragp->fr_var = 2;
}
! /* For mips32, a nop is a zero, which we trivially get by doing nothing. */
}
static void
Index: config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.6
diff -c -p -d -r1.6 tc-mips.h
*** tc-mips.h 2000/09/20 22:05:08 1.6
--- tc-mips.h 2000/12/28 10:06:55
*************** extern int mips_relax_frag PARAMS ((stru
*** 55,62 ****
#define md_undefined_symbol(name) (0)
#define md_operand(x)
! extern int mips_do_align PARAMS ((int, const char *, int, int));
! #define md_do_align(n,fill,len,max,l) if (mips_do_align (n,fill,len,max)) goto l
/* We permit PC relative difference expressions when generating
embedded PIC code. */
--- 55,64 ----
#define md_undefined_symbol(name) (0)
#define md_operand(x)
! extern void mips_handle_align PARAMS ((struct frag *));
! #define HANDLE_ALIGN(fragp) mips_handle_align (fragp)
!
! #define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2)
/* We permit PC relative difference expressions when generating
embedded PIC code. */
Index: config/tc-sh.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.c,v
retrieving revision 1.32
diff -c -p -d -r1.32 tc-sh.c
*** tc-sh.c 2000/12/03 06:49:22 1.32
--- tc-sh.c 2000/12/28 10:06:55
*************** sh_cons_align (nbytes)
*** 2582,2588 ****
return;
}
! p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0,
(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
record_alignment (now_seg, nalign);
--- 2582,2588 ----
return;
}
! p = frag_var (rs_align_test, 1, 1, (relax_substateT) 0,
(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
record_alignment (now_seg, nalign);
*************** void
*** 2596,2612 ****
sh_handle_align (frag)
fragS *frag;
{
if (sh_relax
! && frag->fr_type == rs_align
&& frag->fr_address + frag->fr_fix > 0
&& frag->fr_offset > 1
&& now_seg != bss_section)
fix_new (frag, frag->fr_fix, 2, &abs_symbol, frag->fr_offset, 0,
BFD_RELOC_SH_ALIGN);
-
- if (frag->fr_type == rs_align_code
- && frag->fr_next->fr_address - frag->fr_address - frag->fr_fix != 0)
- as_warn_where (frag->fr_file, frag->fr_line, _("misaligned data"));
}
/* This macro decides whether a particular reloc is an entry in a
--- 2596,2642 ----
sh_handle_align (frag)
fragS *frag;
{
+ int bytes = frag->fr_next->fr_address - frag->fr_address - frag->fr_fix;
+
+ if (frag->fr_type == rs_align_code)
+ {
+ static const unsigned char big_nop_pattern[] = { 0x00, 0x09 };
+ static const unsigned char little_nop_pattern[] = { 0x09, 0x00 };
+
+ char *p = frag->fr_literal + frag->fr_fix;
+
+ if (bytes & 1)
+ {
+ *p++ = 0;
+ bytes--;
+ frag->fr_fix += 1;
+ }
+
+ if (target_big_endian)
+ {
+ memcpy (p, big_nop_pattern, sizeof big_nop_pattern);
+ frag->fr_var = sizeof big_nop_pattern;
+ }
+ else
+ {
+ memcpy (p, little_nop_pattern, sizeof little_nop_pattern);
+ frag->fr_var = sizeof little_nop_pattern;
+ }
+ }
+ else if (frag->fr_type == rs_align_test)
+ {
+ if (bytes != 0)
+ as_warn_where (frag->fr_file, frag->fr_line, _("misaligned data"));
+ }
+
if (sh_relax
! && (frag->fr_type == rs_align
! || frag->fr_type == rs_align_code)
&& frag->fr_address + frag->fr_fix > 0
&& frag->fr_offset > 1
&& now_seg != bss_section)
fix_new (frag, frag->fr_fix, 2, &abs_symbol, frag->fr_offset, 0,
BFD_RELOC_SH_ALIGN);
}
/* This macro decides whether a particular reloc is an entry in a
*************** tc_coff_sizemachdep (frag)
*** 3081,3116 ****
}
#endif /* OBJ_COFF */
-
- /* When we align the .text section, insert the correct NOP pattern. */
-
- int
- sh_do_align (n, fill, len, max)
- int n;
- const char *fill;
- int len ATTRIBUTE_UNUSED;
- int max;
- {
- if (fill == NULL
- && subseg_text_p (now_seg)
- && n > 1)
- {
- static const unsigned char big_nop_pattern[] = { 0x00, 0x09 };
- static const unsigned char little_nop_pattern[] = { 0x09, 0x00 };
-
- /* First align to a 2 byte boundary, in case there is an odd
- .byte. */
- frag_align (1, 0, 0);
- if (target_big_endian)
- frag_align_pattern (n, big_nop_pattern, sizeof big_nop_pattern, max);
- else
- frag_align_pattern (n, little_nop_pattern, sizeof little_nop_pattern,
- max);
- return 1;
- }
-
- return 0;
- }
#ifndef BFD_ASSEMBLER
#ifdef OBJ_COFF
--- 3111,3116 ----
Index: config/tc-sh.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.h,v
retrieving revision 1.10
diff -c -p -d -r1.10 tc-sh.h
*** tc-sh.h 2000/11/17 08:47:52 1.10
--- tc-sh.h 2000/12/28 10:06:55
*************** extern void sh_cons_align PARAMS ((int))
*** 53,58 ****
--- 53,60 ----
#define HANDLE_ALIGN(frag) sh_handle_align (frag)
extern void sh_handle_align PARAMS ((fragS *));
+ #define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2)
+
/* We need to force out some relocations when relaxing. */
#define TC_FORCE_RELOCATION(fix) sh_force_relocation (fix)
extern int sh_force_relocation ();
*************** extern boolean sh_fix_adjustable PARAMS
*** 75,85 ****
extern const struct relax_type md_relax_table[];
#define TC_GENERIC_RELAX_TABLE md_relax_table
-
- /* We use a special alignment function to insert the correct nop
- pattern. */
- extern int sh_do_align PARAMS ((int, const char *, int, int));
- #define md_do_align(n,fill,len,max,l) if (sh_do_align (n,fill,len,max)) goto l
/* We record, for each section, whether we have most recently output a
CODE reloc or a DATA reloc. */
--- 77,82 ----
Index: config/tc-sparc.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sparc.c,v
retrieving revision 1.26
diff -c -p -d -r1.26 tc-sparc.c
*** tc-sparc.c 2000/12/03 06:49:23 1.26
--- tc-sparc.c 2000/12/28 10:06:55
*************** sparc_cons_align (nbytes)
*** 4085,4137 ****
return;
}
! p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0,
(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
record_alignment (now_seg, nalign);
}
! /* This is where we do the unexpected alignment check.
! This is called from HANDLE_ALIGN in tc-sparc.h. */
void
sparc_handle_align (fragp)
fragS *fragp;
{
! if (fragp->fr_type == rs_align_code && !fragp->fr_subtype
! && fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix != 0)
! as_bad_where (fragp->fr_file, fragp->fr_line, _("misaligned data"));
! if (fragp->fr_type == rs_align_code && fragp->fr_subtype == 1024)
{
! int count =
! fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
! if (count >= 4
! && !(count & 3)
! && count <= 1024
! && !((long) (fragp->fr_literal + fragp->fr_fix) & 3))
! {
! unsigned *p = (unsigned *) (fragp->fr_literal + fragp->fr_fix);
! int i;
! for (i = 0; i < count; i += 4, p++)
! if (INSN_BIG_ENDIAN)
! /* Emit nops. */
! number_to_chars_bigendian ((char *) p, 0x01000000, 4);
! else
! number_to_chars_littleendian ((char *) p, 0x10000000, 4);
! if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8)
! {
! char *waddr = &fragp->fr_literal[fragp->fr_fix];
! unsigned wval = (0x30680000 | count >> 2); /* ba,a,pt %xcc, 1f */
! if (INSN_BIG_ENDIAN)
! number_to_chars_bigendian (waddr, wval, 4);
! else
! number_to_chars_littleendian (waddr, wval, 4);
! }
! fragp->fr_var = count;
}
}
}
--- 4085,4149 ----
return;
}
! p = frag_var (rs_align_test, 1, 1, (relax_substateT) 0,
(symbolS *) NULL, (offsetT) nalign, (char *) NULL);
record_alignment (now_seg, nalign);
}
! /* This is called from HANDLE_ALIGN in tc-sparc.h. */
void
sparc_handle_align (fragp)
fragS *fragp;
{
! int count, fix;
! char *p;
!
! count = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
!
! switch (fragp->fr_type)
{
! case rs_align_test:
! if (count != 0)
! as_bad_where (fragp->fr_file, fragp->fr_line, _("misaligned data"));
! break;
! case rs_align_code:
! p = fragp->fr_literal + fragp->fr_fix;
! fix = 0;
! if (count & 3)
! {
! fix = count & 3;
! memset (p, 0, fix);
! p += fix;
! count -= fix;
! }
! if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8)
! {
! unsigned wval = (0x30680000 | count >> 2); /* ba,a,pt %xcc, 1f */
! if (INSN_BIG_ENDIAN)
! number_to_chars_bigendian (p, wval, 4);
! else
! number_to_chars_littleendian (p, wval, 4);
! p += 4;
! count -= 4;
! fix += 4;
}
+
+ if (INSN_BIG_ENDIAN)
+ number_to_chars_bigendian (p, 0x01000000, 4);
+ else
+ number_to_chars_littleendian (p, 0x01000000, 4);
+
+ fragp->fr_fix += fix;
+ fragp->fr_var = 4;
+ break;
+
+ default:
+ break;
}
}
Index: config/tc-sparc.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sparc.h,v
retrieving revision 1.10
diff -c -p -d -r1.10 tc-sparc.h
*** tc-sparc.h 2000/11/28 21:29:02 1.10
--- tc-sparc.h 2000/12/28 10:06:55
*************** extern const char *sparc_target_format P
*** 50,79 ****
#define WORKING_DOT_WORD
! #define md_convert_frag(b,s,f) {as_fatal (_("sparc convert_frag\n"));}
#define md_estimate_size_before_relax(f,s) \
! (as_fatal(_("estimate_size_before_relax called")),1)
#define LISTING_HEADER "SPARC GAS "
extern int sparc_pic_code;
- #define md_do_align(n, fill, len, max, around) \
- if ((n) && (n) <= 10 && !need_pass_2 && !(fill) \
- && subseg_text_p (now_seg)) \
- { \
- char *p; \
- p = frag_var (rs_align_code, 1 << n, 1, (relax_substateT) 1024, \
- (symbolS *) 0, (offsetT) (n), (char *) 0); \
- *p = 0x00; \
- goto around; \
- }
-
/* We require .word, et. al., to be aligned correctly. */
#define md_cons_align(nbytes) sparc_cons_align (nbytes)
extern void sparc_cons_align PARAMS ((int));
#define HANDLE_ALIGN(fragp) sparc_handle_align (fragp)
extern void sparc_handle_align PARAMS ((struct frag *));
#if defined (OBJ_ELF) || defined (OBJ_AOUT)
--- 50,72 ----
#define WORKING_DOT_WORD
! #define md_convert_frag(b,s,f) \
! as_fatal (_("sparc convert_frag\n"))
#define md_estimate_size_before_relax(f,s) \
! (as_fatal(_("estimate_size_before_relax called")), 1)
#define LISTING_HEADER "SPARC GAS "
extern int sparc_pic_code;
/* We require .word, et. al., to be aligned correctly. */
#define md_cons_align(nbytes) sparc_cons_align (nbytes)
extern void sparc_cons_align PARAMS ((int));
+
#define HANDLE_ALIGN(fragp) sparc_handle_align (fragp)
extern void sparc_handle_align PARAMS ((struct frag *));
+
+ #define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4 + 4)
#if defined (OBJ_ELF) || defined (OBJ_AOUT)