diff options
Diffstat (limited to 'gas/config/bfin-parse.y')
-rw-r--r-- | gas/config/bfin-parse.y | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/gas/config/bfin-parse.y b/gas/config/bfin-parse.y index b320c72..6a36863 100644 --- a/gas/config/bfin-parse.y +++ b/gas/config/bfin-parse.y @@ -264,6 +264,35 @@ check_multiply_halfregs (Macfunc *aa, Macfunc *ab) } +/* Check mac option. */ + +static int +check_macfunc_option (Macfunc *a, Opt_mode *opt) +{ + /* Default option is always valid. */ + if (opt->mod == 0) + return 0; + + if ((a->op == 3 && a->w == 1 && a->P == 1 + && opt->mod != M_FU && opt->mod != M_S2RND && opt->mod != M_ISS2) + || (a->op == 3 && a->w == 1 && a->P == 0 + && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU + && opt->mod != M_T && opt->mod != M_S2RND && opt->mod != M_ISS2 + && opt->mod != M_IH) + || (a->w == 0 && a->P == 0 + && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_W32) + || (a->w == 1 && a->P == 1 + && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_S2RND + && opt->mod != M_ISS2) + || (a->w == 1 && a->P == 0 + && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU + && opt->mod != M_T && opt->mod != M_TFU && opt->mod != M_S2RND + && opt->mod != M_ISS2 && opt->mod != M_IH)) + return -1; + + return 0; +} + /* Check (vector) mac funcs and ops. */ static int @@ -274,6 +303,11 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa, Macfunc mtmp; Opt_mode otmp; + /* The option mode should be put at the end of the second instruction + of the vector except M, which should follow MAC1 instruction. */ + if (opa->mod != 0) + return yyerror ("Bad opt mode"); + /* If a0macfunc comes before a1macfunc, swap them. */ if (aa->n == 0) @@ -291,16 +325,14 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa, { if (opb->MM != 0) return yyerror ("(M) not allowed with A0MAC"); - if (opa->mod != 0) - return yyerror ("Bad opt mode"); if (ab->n != 0) return yyerror ("Vector AxMACs can't be same"); } /* If both ops are one of 0, 1, or 2, we have multiply_halfregs in both assignment_or_macfuncs. */ - if (aa->op < 3 && aa->op >=0 - && ab->op < 3 && ab->op >= 0) + if ((aa->op == 0 || aa->op == 1 || aa->op == 2) + && (ab->op == 0 || ab->op == 1 || ab->op == 2)) { if (check_multiply_halfregs (aa, ab) < 0) return -1; @@ -330,11 +362,17 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa, || (ab->w && !aa->P && IS_H (ab->dst))) return yyerror ("High/Low register assignment mismatch"); + /* Make sure mod flags get ORed, too. */ + opb->mod |= opa->mod; + + /* Check option. */ + if (check_macfunc_option (aa, opb) < 0 + && check_macfunc_option (ab, opb) < 0) + return yyerror ("bad option"); + /* Make sure first macfunc has got both P flags ORed. */ aa->P |= ab->P; - /* Make sure mod flags get ORed, too. */ - opb->mod |= opa->mod; return 0; } @@ -660,6 +698,9 @@ asm_1: int w0 = 0, w1 = 0; int h00, h10, h01, h11; + if (check_macfunc_option (&$1, &$2) < 0) + return yyerror ("bad option"); + if ($1.n == 0) { if ($2.MM) |