Hi Dan,
> The assembler support structure provided by the GNU assembler has worked
> quite well for this circumstance, with only a couple minor changes that
> I would like to propose.
Thanks for sending us this patch. I have decided to apply the changes to
the alignment functions, but not to the LEB128 encoding functions. The
reason for this is that the LEB128 functions currently pack only a single
octet into a byte, which is terribly wasteful for targets such as yours,
but this is how the DWARF spec appears to define the encoding operation.
Changing the functions to pack multiple octets into a single byte (where
possible) would be a much more extensive change, and probably contravene
the DWARF standard.
> Without these changes, the assembler would crash with some strange bugs.
I would be interested to know more about these crashes.
Note - we already support two targets where OCTETS_PER_BYTE_POWER is 2
(tic4x and tic54x), so I would hope that in general we have the octets
vs bytes thing sorted out.
Attached is the patch that I am going to apply.
Cheers
Nick
gas/ChangeLog
2016-02-18 Dan Gisselquist
Nick Clifton
* read.c (finish_bundle): Avoid recording a negative alignment.
(do_align): Use unsigned values for n, len and max. Only create
a frag if the alignment requirement is greater than the minimum
byte alignment. Avoid recording a negative alignment.
(s_align): Use unsigned values where appropriate.
(bss_alloc): Use an unsigned value for the alignment.
(sizeof_sleb128): Add a comment noting that we encode one octet
per byte, regardless of the value of OCTETS_PER_BYTE_POWER.
(emit_leb129_expr): Abort if the emitted encoding was longer than
expected.
* read.h (output_leb128): Update prototype.
(sizeof_leb128): Update prototype.
(bss_alloc): Update prototype.
* write.c (record_alignment): Use an unsigned value for the
alignment. Do not record alignments less than the minimum
alignment for a byte.
* write.h (record_alignment): Update prototype.
diff --git a/gas/read.c b/gas/read.c
index 5c04789..f8fff78 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -238,7 +238,6 @@ static unsigned int bundle_lock_depth;
#endif
static void do_s_func (int end_p, const char *default_prefix);
-static void do_align (int, char *, int, int);
static void s_align (int, int);
static void s_altmacro (int);
static void s_bad_end (int);
@@ -685,7 +685,8 @@ finish_bundle (fragS *frag, unsigned int size)
/* We do this every time rather than just in s_bundle_align_mode
so that we catch any affected section without needing hooks all
over for all paths that do section changes. It's cheap enough. */
- record_alignment (now_seg, bundle_align_p2 - OCTETS_PER_BYTE_POWER);
+ if (bundle_align_p2 > OCTETS_PER_BYTE_POWER)
+record_alignment (now_seg, bundle_align_p2 - OCTETS_PER_BYTE_POWER);
}
/* Assemble one instruction. This takes care of the bundle features
@@ -736,6 +737,75 @@ single instruction is %u bytes long but .bundle_align_mode limit is %u"),
#endif /* HANDLE_BUNDLE */
+static bfd_boolean
+in_bss (void)
+{
+ flagword flags = bfd_get_section_flags (stdoutput, now_seg);
+
+ return (flags & SEC_ALLOC) && !(flags & (SEC_LOAD | SEC_HAS_CONTENTS));
+}
+
+/* Guts of .align directive:
+ N is the power of two to which to align. A value of zero is accepted but
+ignored: the default alignment of the section will be at least this.
+ FILL may be NULL, or it may point to the bytes of the fill pattern.
+ LEN is the length of whatever FILL points to, if anything. If LEN is zero
+but FILL is not NULL then LEN is treated as if it were one.
+ MAX is the maximum number of characters to skip when doing the alignment,
+or 0 if there is no maximum. */
+
+static void
+do_align (unsigned int n, char *fill, unsigned int len, unsigned int max)
+{
+ if (now_seg == absolute_section || in_bss ())
+{
+ if (fill != NULL)
+ while (len-- > 0)
+ if (*fill++ != '\0')
+ {
+ if (now_seg == absolute_section)
+ as_warn (_("ignoring fill value in absolute section"));
+ else
+ as_warn (_("ignoring fill value in section `%s'"),
+ segment_name (now_seg));
+ break;
+ }
+ fill = NULL;
+ len = 0;
+}
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+#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 > OCTETS_PER_BYTE_POWER) && !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);
+}
+
+#ifdef md_do_align
+