This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Patch: Add a stop bit in alignment for alloc.
On Tue, Mar 02, 2004 at 10:12:16PM -0800, David Mosberger wrote:
> >>>>> On Tue, 2 Mar 2004 20:41:29 -0800, "H. J. Lu" <hjl@lucon.org> said:
>
> HJ> I checked in the patch. But it is not complete. If the alignment
> HJ> directive is a no-op, the stop bit will be missing.
>
> Yeah, I guess that's counter-intuitive given that gas would normally
> insert a stop-bit in front of the "alloc". Having said that, putting
> an explicit stop-bit in front of the .align seems to do the right
> thing so hand-crafted assembly would probably be OK. Also, for the
> first time, the Linux kernel built and worked with -falign-loops=32!
> Very nice!
>
We only want to set align_frag for ".align N". If we can look back
a bundle, we can add a stop bit when needed. This patch seems to
work OK. When we can't look back and we need to, it will abort.
H.J.
---
2004-03-02 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-ia64.c (dot_align): New.
(ia64_do_align): Make it static.
(md_pseudo_table): Use "dot_align" for "align".
(ia64_md_do_align): Don't set align_frag here.
(ia64_handle_align): Add a stop bit to the previous bundle if
needed.
* config/tc-ia64.h (ia64_do_align): Removed.
--- gas/config/tc-ia64.c.noop 2004-03-02 18:52:25.000000000 -0800
+++ gas/config/tc-ia64.c 2004-03-02 23:21:02.000000000 -0800
@@ -705,6 +705,7 @@ static int ar_is_in_integer_unit PARAMS
static void set_section PARAMS ((char *name));
static unsigned int set_regstack PARAMS ((unsigned int, unsigned int,
unsigned int, unsigned int));
+static void dot_align (int);
static void dot_radix PARAMS ((int));
static void dot_special_section PARAMS ((int));
static void dot_proc PARAMS ((int));
@@ -1135,9 +1136,8 @@ ia64_flush_insns ()
as_bad ("qualifying predicate not followed by instruction");
}
-void
-ia64_do_align (nbytes)
- int nbytes;
+static void
+ia64_do_align (int nbytes)
{
char *saved_input_line_pointer = input_line_pointer;
@@ -3034,6 +3034,14 @@ convert_expr_to_xy_reg (e, xy, regp)
}
static void
+dot_align (int arg)
+{
+ /* The current frag is an alignment frag. */
+ align_frag = frag_now;
+ s_align_bytes (arg);
+}
+
+static void
dot_radix (dummy)
int dummy ATTRIBUTE_UNUSED;
{
@@ -4960,7 +4968,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "lb", dot_scope, 0 },
{ "le", dot_scope, 1 },
#endif
- { "align", s_align_bytes, 0 },
+ { "align", dot_align, 0 },
{ "regstk", dot_regstk, 0 },
{ "rotr", dot_rot, DYNREG_GR },
{ "rotf", dot_rot, DYNREG_FR },
@@ -10828,8 +10836,6 @@ ia64_md_do_align (n, fill, len, max)
int len ATTRIBUTE_UNUSED;
int max ATTRIBUTE_UNUSED;
{
- /* The current frag is an alignment frag. */
- align_frag = frag_now;
if (subseg_text_p (now_seg))
ia64_flush_insns ();
}
@@ -10862,6 +10868,23 @@ ia64_handle_align (fragp)
bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
p = fragp->fr_literal + fragp->fr_fix;
+ /* If no paddings are needed, we check if we need a stop bit. */
+ if (!bytes && fragp->tc_frag_data)
+ {
+ if (fragp->fr_fix < 16)
+ as_bad ("Can't add stop bit to mark end of instruction group");
+ else
+ {
+ bfd_vma t0;
+
+ /* Bundles are always in little-endian byte order. */
+ t0 = bfd_getl64 (p - 16);
+ /* Add the stop bit to the previous bundle. */
+ t0 |= 1;
+ bfd_putl64 (t0, p - 16);
+ }
+ }
+
/* Make sure we are on a 16-byte boundary, in case someone has been
putting data into a text section. */
if (bytes & 15)
--- gas/config/tc-ia64.h.noop 2004-03-02 22:27:05.000000000 -0800
+++ gas/config/tc-ia64.h 2004-03-02 23:14:53.000000000 -0800
@@ -90,7 +90,6 @@ struct ia64_fix
enum ia64_opnd opnd;
};
-extern void ia64_do_align PARAMS((int n));
extern void ia64_end_of_source PARAMS((void));
extern void ia64_start_line PARAMS((void));
extern int ia64_unrecognized_line PARAMS((int ch));