diff --git a/src/asm/parser.y b/src/asm/parser.y index c70cc927..4bcc7798 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -1026,15 +1026,16 @@ align_spec : uconst { $$.alignOfs = 0; } } - | uconst T_COMMA uconst { + | uconst T_COMMA const { if ($1 > 16) { error("Alignment must be between 0 and 16, not %u\n", $1); - } else if ($3 >= 1 << $1) { - error("Alignment offset (%u) must be smaller than alignment size (%u)\n", - $3, 1 << $1); + } else if ($3 <= -(1 << $1) || $3 >= 1 << $1) { + error("The absolute alignment offset (%" PRIu32 + ") must be less than alignment size (%d)\n", + (uint32_t)($3 < 0 ? -$3 : $3), 1 << $1); } else { $$.alignment = $1; - $$.alignOfs = $3; + $$.alignOfs = $3 < 0 ? (1 << $1) + $3 : $3; } } ; diff --git a/test/asm/align-large-ofs.err b/test/asm/align-large-ofs.err index 611d1c81..1cbdb2fd 100644 --- a/test/asm/align-large-ofs.err +++ b/test/asm/align-large-ofs.err @@ -1,3 +1,3 @@ error: align-large-ofs.asm(2): - Alignment offset (2) must be smaller than alignment size (2) + The absolute alignment offset (2) must be less than alignment size (2) error: Assembly aborted (1 error)! diff --git a/test/asm/align-offset.asm b/test/asm/align-offset.asm new file mode 100644 index 00000000..1d9d2343 --- /dev/null +++ b/test/asm/align-offset.asm @@ -0,0 +1,6 @@ +SECTION "good", ROM0, ALIGN[4, -2] +align 4, 14 ; -2 == (1 << 4) - 2 == -2 mod (1 << 4) + +SECTION "bad+", ROM0, ALIGN[4, 18] ; out of range + +SECTION "bad-", ROM0, ALIGN[4, -20] ; out of range negative diff --git a/test/asm/align-offset.err b/test/asm/align-offset.err new file mode 100644 index 00000000..e3e3369a --- /dev/null +++ b/test/asm/align-offset.err @@ -0,0 +1,5 @@ +error: align-offset.asm(4): + The absolute alignment offset (18) must be less than alignment size (16) +error: align-offset.asm(6): + The absolute alignment offset (20) must be less than alignment size (16) +error: Assembly aborted (2 errors)!