aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2017-10-05 16:17:22 +0100
committerNick Clifton <nickc@redhat.com>2017-10-05 16:17:22 +0100
commit2bfa0cdfadd313f3cc35329a17ba3c62865208a3 (patch)
treed6fc935991b31ebd04dc78a00fc44b870d681d69
parent97953bab05cca82bd3119de4d5cf26103b649597 (diff)
downloadfsf-binutils-gdb-2bfa0cdfadd313f3cc35329a17ba3c62865208a3.zip
fsf-binutils-gdb-2bfa0cdfadd313f3cc35329a17ba3c62865208a3.tar.gz
fsf-binutils-gdb-2bfa0cdfadd313f3cc35329a17ba3c62865208a3.tar.bz2
Fix the MSP430 assembler so that it detects and reports extraneous text at the end of operands.
PR 22133 * config/tc-msp430.c (parse_exp): Skip an 'h' suffix to constant expressions. (msp430_srcoperand): Check that the entire text was parsed by parse_exp. (msp430_operands): Likewise. * testsuite/gas/msp430/pr22133.s: New test file. * testsuite/gas/msp430/pr22133.d: New test driver. * testsuite/gas/msp430/pr22133.s: Expected error output. * testsuite/gas/msp430/msp430.exp: Run the new test.
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/config/tc-msp430.c110
-rw-r--r--gas/testsuite/gas/msp430/msp430.exp1
-rw-r--r--gas/testsuite/gas/msp430/pr22133.d4
-rw-r--r--gas/testsuite/gas/msp430/pr22133.l4
-rw-r--r--gas/testsuite/gas/msp430/pr22133.s9
6 files changed, 114 insertions, 27 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index df8edc1..ed40a79 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2017-10-05 Nick Clifton <nickc@redhat.com>
+
+ PR 22133
+ * config/tc-msp430.c (parse_exp): Skip an 'h' suffix to constant
+ expressions.
+ (msp430_srcoperand): Check that the entire text was parsed by
+ parse_exp.
+ (msp430_operands): Likewise.
+ * testsuite/gas/msp430/pr22133.s: New test file.
+ * testsuite/gas/msp430/pr22133.d: New test driver.
+ * testsuite/gas/msp430/pr22133.s: Expected error output.
+ * testsuite/gas/msp430/msp430.exp: Run the new test.
+
2017-10-04 H.J. Lu <hongjiu.lu@intel.com>
PR gas/21167
diff --git a/gas/config/tc-msp430.c b/gas/config/tc-msp430.c
index 62a34ed..6f3acdf 100644
--- a/gas/config/tc-msp430.c
+++ b/gas/config/tc-msp430.c
@@ -415,6 +415,13 @@ parse_exp (char * s, expressionS * op)
expression (op);
if (op->X_op == O_absent)
as_bad (_("missing operand"));
+ /* Our caller is likely to check that the entire expression was parsed.
+ If we have found a hex constant with an 'h' suffix, ilp will be left
+ pointing at the 'h', so skip it here. */
+ if (input_line_pointer != NULL
+ && op->X_op == O_constant
+ && (*input_line_pointer == 'h' || *input_line_pointer == 'H'))
+ ++ input_line_pointer;
return input_line_pointer;
}
@@ -625,7 +632,7 @@ msp430_profiler (int dummy ATTRIBUTE_UNUSED)
/* Now get profiling info. */
halt = extract_operand (input_line_pointer, str, 1024);
/* Process like ".word xxx" directive. */
- parse_exp (str, & exp);
+ (void) parse_exp (str, & exp);
emit_expr (& exp, 2);
input_line_pointer = halt;
}
@@ -1709,6 +1716,7 @@ msp430_srcoperand (struct msp430_operand_s * op,
bfd_boolean allow_20bit_values,
bfd_boolean constants_allowed)
{
+ char * end;
char *__tl = l;
/* Check if an immediate #VALUE. The hash sign should be only at the beginning! */
@@ -1765,7 +1773,12 @@ msp430_srcoperand (struct msp430_operand_s * op,
op->mode = OP_EXP;
op->vshift = vshift;
- parse_exp (__tl, &(op->exp));
+ end = parse_exp (__tl, &(op->exp));
+ if (end != NULL && *end != 0 && *end != ')' )
+ {
+ as_bad (_("extra characters '%s' at end of immediate expression '%s'"), end, l);
+ return 1;
+ }
if (op->exp.X_op == O_constant)
{
int x = op->exp.X_add_number;
@@ -1962,7 +1975,12 @@ msp430_srcoperand (struct msp430_operand_s * op,
op->am = 1; /* mode As == 01 bin. */
op->ol = 1; /* Immediate value followed by instruction. */
__tl = h + 1;
- parse_exp (__tl, &(op->exp));
+ end = parse_exp (__tl, &(op->exp));
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at the end of absolute operand '%s'"), end, l);
+ return 1;
+ }
op->mode = OP_EXP;
op->vshift = 0;
if (op->exp.X_op == O_constant)
@@ -2073,7 +2091,12 @@ msp430_srcoperand (struct msp430_operand_s * op,
*h = 0;
op->mode = OP_EXP;
op->vshift = 0;
- parse_exp (__tl, &(op->exp));
+ end = parse_exp (__tl, &(op->exp));
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l);
+ return 1;
+ }
if (op->exp.X_op == O_constant)
{
int x = op->exp.X_add_number;
@@ -2135,23 +2158,20 @@ msp430_srcoperand (struct msp430_operand_s * op,
}
/* Symbolic mode 'mov a, b' == 'mov x(pc), y(pc)'. */
- do
+ op->mode = OP_EXP;
+ op->reg = 0; /* PC relative... be careful. */
+ /* An expression starting with a minus sign is a constant, not an address. */
+ op->am = (*l == '-' ? 3 : 1);
+ op->ol = 1;
+ op->vshift = 0;
+ __tl = l;
+ end = parse_exp (__tl, &(op->exp));
+ if (end != NULL && * end != 0)
{
- op->mode = OP_EXP;
- op->reg = 0; /* PC relative... be careful. */
- /* An expression starting with a minus sign is a constant, not an address. */
- op->am = (*l == '-' ? 3 : 1);
- op->ol = 1;
- op->vshift = 0;
- __tl = l;
- parse_exp (__tl, &(op->exp));
- return 0;
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l);
+ return 1;
}
- while (0);
-
- /* Unreachable. */
- as_bad (_("unknown addressing mode for operand %s"), l);
- return 1;
+ return 0;
}
@@ -2178,7 +2198,7 @@ msp430_dstoperand (struct msp430_operand_s * op,
op->am = 1;
op->ol = 1;
op->vshift = 0;
- parse_exp (__tl, &(op->exp));
+ (void) parse_exp (__tl, &(op->exp));
if (op->exp.X_op != O_constant || op->exp.X_add_number != 0)
{
@@ -2475,6 +2495,7 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
int insn_length = 0;
char l1[MAX_OP_LEN], l2[MAX_OP_LEN];
char *frag;
+ char *end;
int where;
struct msp430_operand_s op1, op2;
int res = 0;
@@ -3106,7 +3127,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
as_bad (_("expected #n as first argument of %s"), opcode->name);
break;
}
- parse_exp (l1 + 1, &(op1.exp));
+ end = parse_exp (l1 + 1, &(op1.exp));
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of constant expression '%s'"), end, l1);
+ break;
+ }
if (op1.exp.X_op != O_constant)
{
as_bad (_("expected constant expression as first argument of %s"),
@@ -3177,7 +3203,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
as_bad (_("expected #n as first argument of %s"), opcode->name);
break;
}
- parse_exp (l1 + 1, &(op1.exp));
+ end = parse_exp (l1 + 1, &(op1.exp));
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l1);
+ break;
+ }
if (op1.exp.X_op != O_constant)
{
as_bad (_("expected constant expression as first argument of %s"),
@@ -3240,7 +3271,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
if (*l1 == '#')
{
- parse_exp (l1 + 1, &(op1.exp));
+ end = parse_exp (l1 + 1, &(op1.exp));
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l1);
+ break;
+ }
if (op1.exp.X_op == O_constant)
{
@@ -3352,7 +3388,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
/* The RPT instruction only accepted immediates and registers. */
if (*l1 == '#')
{
- parse_exp (l1 + 1, &(op1.exp));
+ end = parse_exp (l1 + 1, &(op1.exp));
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l1);
+ break;
+ }
if (op1.exp.X_op != O_constant)
{
as_bad (_("expected constant value as argument to RPT"));
@@ -3720,7 +3761,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
if (*m == '$')
m++;
- parse_exp (m, &exp);
+ end = parse_exp (m, &exp);
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l1);
+ break;
+ }
/* In order to handle something like:
@@ -3814,7 +3860,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
if (*m == '#' || *m == '$')
m++;
- parse_exp (m, & exp);
+ end = parse_exp (m, & exp);
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l1);
+ break;
+ }
if (exp.X_op == O_symbol)
{
/* Relaxation required. */
@@ -3860,7 +3911,12 @@ msp430_operands (struct msp430_opcode_s * opcode, char * line)
if (*m == '#' || *m == '$')
m++;
- parse_exp (m, & exp);
+ end = parse_exp (m, & exp);
+ if (end != NULL && *end != 0)
+ {
+ as_bad (_("extra characters '%s' at end of operand '%s'"), end, l1);
+ break;
+ }
if (exp.X_op == O_symbol)
{
/* Relaxation required. */
diff --git a/gas/testsuite/gas/msp430/msp430.exp b/gas/testsuite/gas/msp430/msp430.exp
index 0dfb271..bf6c83d 100644
--- a/gas/testsuite/gas/msp430/msp430.exp
+++ b/gas/testsuite/gas/msp430/msp430.exp
@@ -26,4 +26,5 @@ if [expr [istarget "msp430-*-*"]] then {
run_dump_test "errata_fixes"
run_dump_test "high-data-bss-sym" { { as "-mdata-region=upper" } }
run_dump_test "high-data-bss-sym" { { as "-mdata-region=either" } }
+ run_dump_test "pr22133"
}
diff --git a/gas/testsuite/gas/msp430/pr22133.d b/gas/testsuite/gas/msp430/pr22133.d
new file mode 100644
index 0000000..c8a4b39
--- /dev/null
+++ b/gas/testsuite/gas/msp430/pr22133.d
@@ -0,0 +1,4 @@
+#name: Extraneous extra text at the end of operands
+#source: pr22133.s
+#as:
+#error-output: pr22133.l
diff --git a/gas/testsuite/gas/msp430/pr22133.l b/gas/testsuite/gas/msp430/pr22133.l
new file mode 100644
index 0000000..dce5121
--- /dev/null
+++ b/gas/testsuite/gas/msp430/pr22133.l
@@ -0,0 +1,4 @@
+[^:]*: Assembler messages:
+[^:]*:5: Error: extra characters '\(R13\)' at the end of absolute operand '&SRC\(R13\)'
+[^:]*:5: Error: extra characters '\(R13\)' at the end of absolute operand '&DST\(R13\)'
+
diff --git a/gas/testsuite/gas/msp430/pr22133.s b/gas/testsuite/gas/msp430/pr22133.s
new file mode 100644
index 0000000..45ee867
--- /dev/null
+++ b/gas/testsuite/gas/msp430/pr22133.s
@@ -0,0 +1,9 @@
+
+.equiv SRC, 1800h
+.equiv DST, 1880h
+
+ mov &SRC(R13), &DST(R13)
+# mov &SRC, &DST
+# mov &1800h(R13), &DST(R13)
+# mov &1800h(R13), &1800h(R13)
+