gas: blackfin: fix DBG/DBGCMPLX insn encoding
[external/binutils.git] / gas / config / bfin-parse.y
1 /* bfin-parse.y  ADI Blackfin parser
2    Copyright 2005, 2006, 2007, 2008, 2009, 2010
3    Free Software Foundation, Inc.
4
5    This file is part of GAS, the GNU Assembler.
6
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to the Free
19    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20    02110-1301, USA.  */
21 %{
22
23 #include "as.h"
24 #include <obstack.h>
25
26 #include "bfin-aux.h"  /* Opcode generating auxiliaries.  */
27 #include "libbfd.h"
28 #include "elf/common.h"
29 #include "elf/bfin.h"
30
31 #define DSP32ALU(aopcde, HL, dst1, dst0, src0, src1, s, x, aop) \
32         bfin_gen_dsp32alu (HL, aopcde, aop, s, x, dst0, dst1, src0, src1)
33
34 #define DSP32MAC(op1, MM, mmod, w1, P, h01, h11, h00, h10, dst, op0, src0, src1, w0) \
35         bfin_gen_dsp32mac (op1, MM, mmod, w1, P, h01, h11, h00, h10, op0, \
36                            dst, src0, src1, w0)
37
38 #define DSP32MULT(op1, MM, mmod, w1, P, h01, h11, h00, h10, dst, op0, src0, src1, w0) \
39         bfin_gen_dsp32mult (op1, MM, mmod, w1, P, h01, h11, h00, h10, op0, \
40                             dst, src0, src1, w0)
41
42 #define DSP32SHIFT(sopcde, dst0, src0, src1, sop, hls)  \
43         bfin_gen_dsp32shift (sopcde, dst0, src0, src1, sop, hls)
44
45 #define DSP32SHIFTIMM(sopcde, dst0, immag, src1, sop, hls)  \
46         bfin_gen_dsp32shiftimm (sopcde, dst0, immag, src1, sop, hls)
47
48 #define LDIMMHALF_R(reg, h, s, z, hword) \
49         bfin_gen_ldimmhalf (reg, h, s, z, hword, 1)
50
51 #define LDIMMHALF_R5(reg, h, s, z, hword) \
52         bfin_gen_ldimmhalf (reg, h, s, z, hword, 2)
53
54 #define LDSTIDXI(ptr, reg, w, sz, z, offset)  \
55         bfin_gen_ldstidxi (ptr, reg, w, sz, z, offset)
56
57 #define LDST(ptr, reg, aop, sz, z, w)  \
58         bfin_gen_ldst (ptr, reg, aop, sz, z, w)
59
60 #define LDSTII(ptr, reg, offset, w, op)  \
61         bfin_gen_ldstii (ptr, reg, offset, w, op)
62
63 #define DSPLDST(i, m, reg, aop, w) \
64         bfin_gen_dspldst (i, reg, aop, w, m)
65
66 #define LDSTPMOD(ptr, reg, idx, aop, w) \
67         bfin_gen_ldstpmod (ptr, reg, aop, w, idx)
68
69 #define LDSTIIFP(offset, reg, w)  \
70         bfin_gen_ldstiifp (reg, offset, w)
71
72 #define LOGI2OP(dst, src, opc) \
73         bfin_gen_logi2op (opc, src, dst.regno & CODE_MASK)
74
75 #define ALU2OP(dst, src, opc)  \
76         bfin_gen_alu2op (dst, src, opc)
77
78 #define BRCC(t, b, offset) \
79         bfin_gen_brcc (t, b, offset)
80
81 #define UJUMP(offset) \
82         bfin_gen_ujump (offset)
83
84 #define PROGCTRL(prgfunc, poprnd) \
85         bfin_gen_progctrl (prgfunc, poprnd)
86
87 #define PUSHPOPMULTIPLE(dr, pr, d, p, w) \
88         bfin_gen_pushpopmultiple (dr, pr, d, p, w)
89
90 #define PUSHPOPREG(reg, w) \
91         bfin_gen_pushpopreg (reg, w)
92
93 #define CALLA(addr, s)  \
94         bfin_gen_calla (addr, s)
95
96 #define LINKAGE(r, framesize) \
97         bfin_gen_linkage (r, framesize)
98
99 #define COMPI2OPD(dst, src, op)  \
100         bfin_gen_compi2opd (dst, src, op)
101
102 #define COMPI2OPP(dst, src, op)  \
103         bfin_gen_compi2opp (dst, src, op)
104
105 #define DAGMODIK(i, op)  \
106         bfin_gen_dagmodik (i, op)
107
108 #define DAGMODIM(i, m, op, br)  \
109         bfin_gen_dagmodim (i, m, op, br)
110
111 #define COMP3OP(dst, src0, src1, opc)   \
112         bfin_gen_comp3op (src0, src1, dst, opc)
113
114 #define PTR2OP(dst, src, opc)   \
115         bfin_gen_ptr2op (dst, src, opc)
116
117 #define CCFLAG(x, y, opc, i, g)  \
118         bfin_gen_ccflag (x, y, opc, i, g)
119
120 #define CCMV(src, dst, t) \
121         bfin_gen_ccmv (src, dst, t)
122
123 #define CACTRL(reg, a, op) \
124         bfin_gen_cactrl (reg, a, op)
125
126 #define LOOPSETUP(soffset, c, rop, eoffset, reg) \
127         bfin_gen_loopsetup (soffset, c, rop, eoffset, reg)
128
129 #define HL2(r1, r0)  (IS_H (r1) << 1 | IS_H (r0))
130 #define IS_RANGE(bits, expr, sign, mul)    \
131         value_match(expr, bits, sign, mul, 1)
132 #define IS_URANGE(bits, expr, sign, mul)    \
133         value_match(expr, bits, sign, mul, 0)
134 #define IS_CONST(expr) (expr->type == Expr_Node_Constant)
135 #define IS_RELOC(expr) (expr->type != Expr_Node_Constant)
136 #define IS_IMM(expr, bits)  value_match (expr, bits, 0, 1, 1)
137 #define IS_UIMM(expr, bits)  value_match (expr, bits, 0, 1, 0)
138
139 #define IS_PCREL4(expr) \
140         (value_match (expr, 4, 0, 2, 0))
141
142 #define IS_LPPCREL10(expr) \
143         (value_match (expr, 10, 0, 2, 0))
144
145 #define IS_PCREL10(expr) \
146         (value_match (expr, 10, 0, 2, 1))
147
148 #define IS_PCREL12(expr) \
149         (value_match (expr, 12, 0, 2, 1))
150
151 #define IS_PCREL24(expr) \
152         (value_match (expr, 24, 0, 2, 1))
153
154
155 static int value_match (Expr_Node *, int, int, int, int);
156
157 extern FILE *errorf;
158 extern INSTR_T insn;
159
160 static Expr_Node *binary (Expr_Op_Type, Expr_Node *, Expr_Node *);
161 static Expr_Node *unary  (Expr_Op_Type, Expr_Node *);
162
163 static void notethat (char *, ...);
164
165 char *current_inputline;
166 extern char *yytext;
167 int yyerror (char *);
168
169 void error (char *format, ...)
170 {
171     va_list ap;
172     static char buffer[2000];
173
174     va_start (ap, format);
175     vsprintf (buffer, format, ap);
176     va_end (ap);
177
178     as_bad ("%s", buffer);
179 }
180
181 int
182 yyerror (char *msg)
183 {
184   if (msg[0] == '\0')
185     error ("%s", msg);
186
187   else if (yytext[0] != ';')
188     error ("%s. Input text was %s.", msg, yytext);
189   else
190     error ("%s.", msg);
191
192   return -1;
193 }
194
195 static int
196 in_range_p (Expr_Node *exp, int from, int to, unsigned int mask)
197 {
198   int val = EXPR_VALUE (exp);
199   if (exp->type != Expr_Node_Constant)
200     return 0;
201   if (val < from || val > to)
202     return 0;
203   return (val & mask) == 0;
204 }
205
206 extern int yylex (void);
207
208 #define imm3(x) EXPR_VALUE (x)
209 #define imm4(x) EXPR_VALUE (x)
210 #define uimm4(x) EXPR_VALUE (x)
211 #define imm5(x) EXPR_VALUE (x)
212 #define uimm5(x) EXPR_VALUE (x)
213 #define imm6(x) EXPR_VALUE (x)
214 #define imm7(x) EXPR_VALUE (x)
215 #define uimm8(x) EXPR_VALUE (x)
216 #define imm16(x) EXPR_VALUE (x)
217 #define uimm16s4(x) ((EXPR_VALUE (x)) >> 2)
218 #define uimm16(x) EXPR_VALUE (x)
219
220 /* Return true if a value is inside a range.  */
221 #define IN_RANGE(x, low, high) \
222   (((EXPR_VALUE(x)) >= (low)) && (EXPR_VALUE(x)) <= ((high)))
223
224 /* Auxiliary functions.  */
225
226 static int
227 valid_dreg_pair (Register *reg1, Expr_Node *reg2)
228 {
229   if (!IS_DREG (*reg1))
230     {
231       yyerror ("Dregs expected");
232       return 0;
233     }
234
235   if (reg1->regno != 1 && reg1->regno != 3)
236     {
237       yyerror ("Bad register pair");
238       return 0;
239     }
240
241   if (imm7 (reg2) != reg1->regno - 1)
242     {
243       yyerror ("Bad register pair");
244       return 0;
245     }
246
247   reg1->regno--;
248   return 1;
249 }
250
251 static int
252 check_multiply_halfregs (Macfunc *aa, Macfunc *ab)
253 {
254   if ((!REG_EQUAL (aa->s0, ab->s0) && !REG_EQUAL (aa->s0, ab->s1))
255       || (!REG_EQUAL (aa->s1, ab->s1) && !REG_EQUAL (aa->s1, ab->s0)))
256     return yyerror ("Source multiplication register mismatch");
257
258   return 0;
259 }
260
261
262 /* Check mac option.  */
263
264 static int
265 check_macfunc_option (Macfunc *a, Opt_mode *opt)
266 {
267   /* Default option is always valid.  */
268   if (opt->mod == 0)
269     return 0;
270
271   if ((a->w == 1 && a->P == 1
272        && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
273        && opt->mod != M_S2RND && opt->mod != M_ISS2)
274       || (a->w == 1 && a->P == 0
275           && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
276           && opt->mod != M_T && opt->mod != M_TFU && opt->mod != M_S2RND
277           && opt->mod != M_ISS2 && opt->mod != M_IH)
278       || (a->w == 0 && a->P == 0
279           && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_W32))
280     return -1;
281
282   return 0;
283 }
284
285 /* Check (vector) mac funcs and ops.  */
286
287 static int
288 check_macfuncs (Macfunc *aa, Opt_mode *opa,
289                 Macfunc *ab, Opt_mode *opb)
290 {
291   /* Variables for swapping.  */
292   Macfunc mtmp;
293   Opt_mode otmp;
294
295   /* The option mode should be put at the end of the second instruction
296      of the vector except M, which should follow MAC1 instruction.  */
297   if (opa->mod != 0)
298     return yyerror ("Bad opt mode");
299
300   /* If a0macfunc comes before a1macfunc, swap them.  */
301
302   if (aa->n == 0)
303     {
304       /*  (M) is not allowed here.  */
305       if (opa->MM != 0)
306         return yyerror ("(M) not allowed with A0MAC");
307       if (ab->n != 1)
308         return yyerror ("Vector AxMACs can't be same");
309
310       mtmp = *aa; *aa = *ab; *ab = mtmp;
311       otmp = *opa; *opa = *opb; *opb = otmp;
312     }
313   else
314     {
315       if (opb->MM != 0)
316         return yyerror ("(M) not allowed with A0MAC");
317       if (ab->n != 0)
318         return yyerror ("Vector AxMACs can't be same");
319     }
320
321   /*  If both ops are one of 0, 1, or 2, we have multiply_halfregs in both
322   assignment_or_macfuncs.  */
323   if ((aa->op == 0 || aa->op == 1 || aa->op == 2)
324       && (ab->op == 0 || ab->op == 1 || ab->op == 2))
325     {
326       if (check_multiply_halfregs (aa, ab) < 0)
327         return -1;
328     }
329   else
330     {
331       /*  Only one of the assign_macfuncs has a half reg multiply
332       Evil trick: Just 'OR' their source register codes:
333       We can do that, because we know they were initialized to 0
334       in the rules that don't use multiply_halfregs.  */
335       aa->s0.regno |= (ab->s0.regno & CODE_MASK);
336       aa->s1.regno |= (ab->s1.regno & CODE_MASK);
337     }
338
339   if (aa->w == ab->w  && aa->P != ab->P)
340     {
341       return yyerror ("macfuncs must differ");
342       if (aa->w && (aa->dst.regno - ab->dst.regno != 1))
343         return yyerror ("Destination Dregs must differ by one");
344     }
345
346   /* Make sure mod flags get ORed, too.  */
347   opb->mod |= opa->mod;
348
349   /* Check option.  */
350   if (check_macfunc_option (aa, opb) < 0
351       && check_macfunc_option (ab, opb) < 0)
352     return yyerror ("bad option");
353
354   /* Make sure first macfunc has got both P flags ORed.  */
355   aa->P |= ab->P;
356
357   return 0;
358 }
359
360
361 static int
362 is_group1 (INSTR_T x)
363 {
364   /* Group1 is dpsLDST, LDSTpmod, LDST, LDSTiiFP, LDSTii.  */
365   if ((x->value & 0xc000) == 0x8000 || (x->value == 0x0000))
366     return 1;
367
368   return 0;
369 }
370
371 static int
372 is_group2 (INSTR_T x)
373 {
374   if ((((x->value & 0xfc00) == 0x9c00)  /* dspLDST.  */
375        && !((x->value & 0xfde0) == 0x9c60)  /* dagMODim.  */
376        && !((x->value & 0xfde0) == 0x9ce0)  /* dagMODim with bit rev.  */
377        && !((x->value & 0xfde0) == 0x9d60)) /* pick dagMODik.  */
378       || (x->value == 0x0000))
379     return 1;
380   return 0;
381 }
382
383 static INSTR_T
384 gen_multi_instr_1 (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
385 {
386   int mask1 = dsp32 ? insn_regmask (dsp32->value, dsp32->next->value) : 0;
387   int mask2 = dsp16_grp1 ? insn_regmask (dsp16_grp1->value, 0) : 0;
388   int mask3 = dsp16_grp2 ? insn_regmask (dsp16_grp2->value, 0) : 0;
389
390   if ((mask1 & mask2) || (mask1 & mask3) || (mask2 & mask3))
391     yyerror ("resource conflict in multi-issue instruction");
392
393   /* Anomaly 05000074 */
394   if (ENABLE_AC_05000074
395       && dsp32 != NULL && dsp16_grp1 != NULL
396       && (dsp32->value & 0xf780) == 0xc680
397       && ((dsp16_grp1->value & 0xfe40) == 0x9240
398           || (dsp16_grp1->value & 0xfe08) == 0xba08
399           || (dsp16_grp1->value & 0xfc00) == 0xbc00))
400     yyerror ("anomaly 05000074 - Multi-Issue Instruction with \
401 dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported");
402
403   return bfin_gen_multi_instr (dsp32, dsp16_grp1, dsp16_grp2);
404 }
405
406 %}
407
408 %union {
409   INSTR_T instr;
410   Expr_Node *expr;
411   SYMBOL_T symbol;
412   long value;
413   Register reg;
414   Macfunc macfunc;
415   struct { int r0; int s0; int x0; int aop; } modcodes;
416   struct { int r0; } r0;
417   Opt_mode mod;
418 }
419
420
421 /* Tokens.  */
422
423 /* Vector Specific.  */
424 %token BYTEOP16P BYTEOP16M
425 %token BYTEOP1P BYTEOP2P BYTEOP2M BYTEOP3P
426 %token BYTEUNPACK BYTEPACK
427 %token PACK
428 %token SAA
429 %token ALIGN8 ALIGN16 ALIGN24
430 %token VIT_MAX
431 %token EXTRACT DEPOSIT EXPADJ SEARCH
432 %token ONES SIGN SIGNBITS
433
434 /* Stack.  */
435 %token LINK UNLINK
436
437 /* Registers.  */
438 %token REG
439 %token PC
440 %token CCREG BYTE_DREG
441 %token REG_A_DOUBLE_ZERO REG_A_DOUBLE_ONE
442 %token A_ZERO_DOT_L A_ZERO_DOT_H A_ONE_DOT_L A_ONE_DOT_H
443 %token HALF_REG
444
445 /* Progctrl.  */
446 %token NOP
447 %token RTI RTS RTX RTN RTE
448 %token HLT IDLE
449 %token STI CLI
450 %token CSYNC SSYNC
451 %token EMUEXCPT
452 %token RAISE EXCPT
453 %token LSETUP
454 %token LOOP
455 %token LOOP_BEGIN
456 %token LOOP_END
457 %token DISALGNEXCPT
458 %token JUMP JUMP_DOT_S JUMP_DOT_L
459 %token CALL
460
461 /* Emulator only.  */
462 %token ABORT
463
464 /* Operators.  */
465 %token NOT TILDA BANG
466 %token AMPERSAND BAR
467 %token PERCENT
468 %token CARET
469 %token BXOR
470
471 %token MINUS PLUS STAR SLASH
472 %token NEG
473 %token MIN MAX ABS
474 %token DOUBLE_BAR
475 %token _PLUS_BAR_PLUS _PLUS_BAR_MINUS _MINUS_BAR_PLUS _MINUS_BAR_MINUS
476 %token _MINUS_MINUS _PLUS_PLUS
477
478 /* Shift/rotate ops.  */
479 %token SHIFT LSHIFT ASHIFT BXORSHIFT
480 %token _GREATER_GREATER_GREATER_THAN_ASSIGN
481 %token ROT
482 %token LESS_LESS GREATER_GREATER
483 %token _GREATER_GREATER_GREATER
484 %token _LESS_LESS_ASSIGN _GREATER_GREATER_ASSIGN
485 %token DIVS DIVQ
486
487 /* In place operators.  */
488 %token ASSIGN _STAR_ASSIGN
489 %token _BAR_ASSIGN _CARET_ASSIGN _AMPERSAND_ASSIGN
490 %token _MINUS_ASSIGN _PLUS_ASSIGN
491
492 /* Assignments, comparisons.  */
493 %token _ASSIGN_BANG _LESS_THAN_ASSIGN _ASSIGN_ASSIGN
494 %token GE LT LE GT
495 %token LESS_THAN
496
497 /* Cache.  */
498 %token FLUSHINV FLUSH
499 %token IFLUSH PREFETCH
500
501 /* Misc.  */
502 %token PRNT
503 %token OUTC
504 %token WHATREG
505 %token TESTSET
506
507 /* Modifiers.  */
508 %token ASL ASR
509 %token B W
510 %token NS S CO SCO
511 %token TH TL
512 %token BP
513 %token BREV
514 %token X Z
515 %token M MMOD
516 %token R RND RNDL RNDH RND12 RND20
517 %token V
518 %token LO HI
519
520 /* Bit ops.  */
521 %token BITTGL BITCLR BITSET BITTST BITMUX
522
523 /* Debug.  */
524 %token DBGAL DBGAH DBGHALT DBG DBGA DBGCMPLX
525
526 /* Semantic auxiliaries.  */
527
528 %token IF COMMA BY
529 %token COLON SEMICOLON
530 %token RPAREN LPAREN LBRACK RBRACK
531 %token STATUS_REG
532 %token MNOP
533 %token SYMBOL NUMBER
534 %token GOT GOT17M4 FUNCDESC_GOT17M4
535 %token AT PLTPC
536
537 /* Types.  */
538 %type <instr> asm
539 %type <value> MMOD
540 %type <mod> opt_mode
541
542 %type <value> NUMBER
543 %type <r0> aligndir
544 %type <modcodes> byteop_mod
545 %type <reg> a_assign
546 %type <reg> a_plusassign
547 %type <reg> a_minusassign
548 %type <macfunc> multiply_halfregs
549 %type <macfunc> assign_macfunc
550 %type <macfunc> a_macfunc
551 %type <expr> expr_1
552 %type <instr> asm_1
553 %type <r0> vmod
554 %type <modcodes> vsmod
555 %type <modcodes> ccstat
556 %type <r0> cc_op
557 %type <reg> CCREG
558 %type <reg> reg_with_postinc
559 %type <reg> reg_with_predec
560
561 %type <r0> searchmod
562 %type <expr> symbol
563 %type <symbol> SYMBOL
564 %type <expr> eterm
565 %type <reg> REG
566 %type <reg> BYTE_DREG
567 %type <reg> REG_A_DOUBLE_ZERO
568 %type <reg> REG_A_DOUBLE_ONE
569 %type <reg> REG_A
570 %type <reg> STATUS_REG
571 %type <expr> expr
572 %type <r0> xpmod
573 %type <r0> xpmod1
574 %type <modcodes> smod
575 %type <modcodes> b3_op
576 %type <modcodes> rnd_op
577 %type <modcodes> post_op
578 %type <reg> HALF_REG
579 %type <r0> iu_or_nothing
580 %type <r0> plus_minus
581 %type <r0> asr_asl
582 %type <r0> asr_asl_0
583 %type <modcodes> sco
584 %type <modcodes> amod0
585 %type <modcodes> amod1
586 %type <modcodes> amod2
587 %type <r0> op_bar_op
588 %type <r0> w32_or_nothing
589 %type <r0> c_align
590 %type <r0> min_max
591 %type <expr> got
592 %type <expr> got_or_expr
593 %type <expr> pltpc
594 %type <value> any_gotrel GOT GOT17M4 FUNCDESC_GOT17M4
595
596 /* Precedence rules.  */
597 %left BAR
598 %left CARET
599 %left AMPERSAND
600 %left LESS_LESS GREATER_GREATER
601 %left PLUS MINUS
602 %left STAR SLASH PERCENT
603
604 %right ASSIGN
605
606 %right TILDA BANG
607 %start statement
608 %%
609 statement:
610         | asm
611         {
612           insn = $1;
613           if (insn == (INSTR_T) 0)
614             return NO_INSN_GENERATED;
615           else if (insn == (INSTR_T) - 1)
616             return SEMANTIC_ERROR;
617           else
618             return INSN_GENERATED;
619         }
620         ;
621
622 asm: asm_1 SEMICOLON
623         /* Parallel instructions.  */
624         | asm_1 DOUBLE_BAR asm_1 DOUBLE_BAR asm_1 SEMICOLON
625         {
626           if (($1->value & 0xf800) == 0xc000)
627             {
628               if (is_group1 ($3) && is_group2 ($5))
629                 $$ = gen_multi_instr_1 ($1, $3, $5);
630               else if (is_group2 ($3) && is_group1 ($5))
631                 $$ = gen_multi_instr_1 ($1, $5, $3);
632               else
633                 return yyerror ("Wrong 16 bit instructions groups, slot 2 and slot 3 must be 16-bit instrution group");
634             }
635           else if (($3->value & 0xf800) == 0xc000)
636             {
637               if (is_group1 ($1) && is_group2 ($5))
638                 $$ = gen_multi_instr_1 ($3, $1, $5);
639               else if (is_group2 ($1) && is_group1 ($5))
640                 $$ = gen_multi_instr_1 ($3, $5, $1);
641               else
642                 return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 3 must be 16-bit instrution group");
643             }
644           else if (($5->value & 0xf800) == 0xc000)
645             {
646               if (is_group1 ($1) && is_group2 ($3))
647                 $$ = gen_multi_instr_1 ($5, $1, $3);
648               else if (is_group2 ($1) && is_group1 ($3))
649                 $$ = gen_multi_instr_1 ($5, $3, $1);
650               else
651                 return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be 16-bit instrution group");
652             }
653           else
654             error ("\nIllegal Multi Issue Construct, at least any one of the slot must be DSP32 instruction group\n");
655         }
656
657         | asm_1 DOUBLE_BAR asm_1 SEMICOLON
658         {
659           if (($1->value & 0xf800) == 0xc000)
660             {
661               if (is_group1 ($3))
662                 $$ = gen_multi_instr_1 ($1, $3, 0);
663               else if (is_group2 ($3))
664                 $$ = gen_multi_instr_1 ($1, 0, $3);
665               else
666                 return yyerror ("Wrong 16 bit instructions groups, slot 2 must be the 16-bit instruction group");
667             }
668           else if (($3->value & 0xf800) == 0xc000)
669             {
670               if (is_group1 ($1))
671                 $$ = gen_multi_instr_1 ($3, $1, 0);
672               else if (is_group2 ($1))
673                 $$ = gen_multi_instr_1 ($3, 0, $1);
674               else
675                 return yyerror ("Wrong 16 bit instructions groups, slot 1 must be the 16-bit instruction group");
676             }
677           else if (is_group1 ($1) && is_group2 ($3))
678               $$ = gen_multi_instr_1 (0, $1, $3);
679           else if (is_group2 ($1) && is_group1 ($3))
680             $$ = gen_multi_instr_1 (0, $3, $1);
681           else
682             return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be the 16-bit instruction group");
683         }
684         | error
685         {
686         $$ = 0;
687         yyerror ("");
688         yyerrok;
689         }
690         ;
691
692 /* DSPMAC.  */
693
694 asm_1:
695         MNOP
696         {
697           $$ = DSP32MAC (3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
698         }
699         | assign_macfunc opt_mode
700         {
701           int op0, op1;
702           int w0 = 0, w1 = 0;
703           int h00, h10, h01, h11;
704
705           if (check_macfunc_option (&$1, &$2) < 0)
706             return yyerror ("bad option");
707
708           if ($1.n == 0)
709             {
710               if ($2.MM)
711                 return yyerror ("(m) not allowed with a0 unit");
712               op1 = 3;
713               op0 = $1.op;
714               w1 = 0;
715               w0 = $1.w;
716               h00 = IS_H ($1.s0);
717               h10 = IS_H ($1.s1);
718               h01 = h11 = 0;
719             }
720           else
721             {
722               op1 = $1.op;
723               op0 = 3;
724               w1 = $1.w;
725               w0 = 0;
726               h00 = h10 = 0;
727               h01 = IS_H ($1.s0);
728               h11 = IS_H ($1.s1);
729             }
730           $$ = DSP32MAC (op1, $2.MM, $2.mod, w1, $1.P, h01, h11, h00, h10,
731                          &$1.dst, op0, &$1.s0, &$1.s1, w0);
732         }
733
734
735 /* VECTOR MACs.  */
736
737         | assign_macfunc opt_mode COMMA assign_macfunc opt_mode
738         {
739           Register *dst;
740
741           if (check_macfuncs (&$1, &$2, &$4, &$5) < 0)
742             return -1;
743           notethat ("assign_macfunc (.), assign_macfunc (.)\n");
744
745           if ($1.w)
746             dst = &$1.dst;
747           else
748             dst = &$4.dst;
749
750           $$ = DSP32MAC ($1.op, $2.MM, $5.mod, $1.w, $1.P,
751                          IS_H ($1.s0),  IS_H ($1.s1), IS_H ($4.s0), IS_H ($4.s1),
752                          dst, $4.op, &$1.s0, &$1.s1, $4.w);
753         }
754
755 /* DSPALU.  */
756
757         | DISALGNEXCPT
758         {
759           notethat ("dsp32alu: DISALGNEXCPT\n");
760           $$ = DSP32ALU (18, 0, 0, 0, 0, 0, 0, 0, 3);
761         }
762         | REG ASSIGN LPAREN a_plusassign REG_A RPAREN
763         {
764           if (IS_DREG ($1) && !IS_A1 ($4) && IS_A1 ($5))
765             {
766               notethat ("dsp32alu: dregs = ( A0 += A1 )\n");
767               $$ = DSP32ALU (11, 0, 0, &$1, 0, 0, 0, 0, 0);
768             }
769           else
770             return yyerror ("Register mismatch");
771         }
772         | HALF_REG ASSIGN LPAREN a_plusassign REG_A RPAREN
773         {
774           if (!IS_A1 ($4) && IS_A1 ($5))
775             {
776               notethat ("dsp32alu: dregs_half = ( A0 += A1 )\n");
777               $$ = DSP32ALU (11, IS_H ($1), 0, &$1, 0, 0, 0, 0, 1);
778             }
779           else
780             return yyerror ("Register mismatch");
781         }
782         | A_ZERO_DOT_H ASSIGN HALF_REG
783         {
784           notethat ("dsp32alu: A_ZERO_DOT_H = dregs_hi\n");
785           $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 0);
786         }
787         | A_ONE_DOT_H ASSIGN HALF_REG
788         {
789           notethat ("dsp32alu: A_ZERO_DOT_H = dregs_hi\n");
790           $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 2);
791         }
792         | LPAREN REG COMMA REG RPAREN ASSIGN BYTEOP16P LPAREN REG
793           COLON expr COMMA REG COLON expr RPAREN aligndir
794         {
795           if (!IS_DREG ($2) || !IS_DREG ($4))
796             return yyerror ("Dregs expected");
797           else if (!valid_dreg_pair (&$9, $11))
798             return yyerror ("Bad dreg pair");
799           else if (!valid_dreg_pair (&$13, $15))
800             return yyerror ("Bad dreg pair");
801           else
802             {
803               notethat ("dsp32alu: (dregs , dregs ) = BYTEOP16P (dregs_pair , dregs_pair ) (half)\n");
804               $$ = DSP32ALU (21, 0, &$2, &$4, &$9, &$13, $17.r0, 0, 0);
805             }
806         }
807
808         | LPAREN REG COMMA REG RPAREN ASSIGN BYTEOP16M LPAREN REG COLON expr COMMA
809           REG COLON expr RPAREN aligndir
810         {
811           if (!IS_DREG ($2) || !IS_DREG ($4))
812             return yyerror ("Dregs expected");
813           else if (!valid_dreg_pair (&$9, $11))
814             return yyerror ("Bad dreg pair");
815           else if (!valid_dreg_pair (&$13, $15))
816             return yyerror ("Bad dreg pair");
817           else
818             {
819               notethat ("dsp32alu: (dregs , dregs ) = BYTEOP16M (dregs_pair , dregs_pair ) (aligndir)\n");
820               $$ = DSP32ALU (21, 0, &$2, &$4, &$9, &$13, $17.r0, 0, 1);
821             }
822         }
823
824         | LPAREN REG COMMA REG RPAREN ASSIGN BYTEUNPACK REG COLON expr aligndir
825         {
826           if (!IS_DREG ($2) || !IS_DREG ($4))
827             return yyerror ("Dregs expected");
828           else if (!valid_dreg_pair (&$8, $10))
829             return yyerror ("Bad dreg pair");
830           else
831             {
832               notethat ("dsp32alu: (dregs , dregs ) = BYTEUNPACK dregs_pair (aligndir)\n");
833               $$ = DSP32ALU (24, 0, &$2, &$4, &$8, 0, $11.r0, 0, 1);
834             }
835         }
836         | LPAREN REG COMMA REG RPAREN ASSIGN SEARCH REG LPAREN searchmod RPAREN
837         {
838           if (IS_DREG ($2) && IS_DREG ($4) && IS_DREG ($8))
839             {
840               notethat ("dsp32alu: (dregs , dregs ) = SEARCH dregs (searchmod)\n");
841               $$ = DSP32ALU (13, 0, &$2, &$4, &$8, 0, 0, 0, $10.r0);
842             }
843           else
844             return yyerror ("Register mismatch");
845         }
846         | REG ASSIGN A_ONE_DOT_L PLUS A_ONE_DOT_H COMMA
847           REG ASSIGN A_ZERO_DOT_L PLUS A_ZERO_DOT_H
848         {
849           if (IS_DREG ($1) && IS_DREG ($7))
850             {
851               notethat ("dsp32alu: dregs = A1.l + A1.h, dregs = A0.l + A0.h  \n");
852               $$ = DSP32ALU (12, 0, &$1, &$7, 0, 0, 0, 0, 1);
853             }
854           else
855             return yyerror ("Register mismatch");
856         }
857
858
859         | REG ASSIGN REG_A PLUS REG_A COMMA REG ASSIGN REG_A MINUS REG_A amod1
860         {
861           if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
862               && IS_A1 ($9) && !IS_A1 ($11))
863             {
864               notethat ("dsp32alu: dregs = A1 + A0 , dregs = A1 - A0 (amod1)\n");
865               $$ = DSP32ALU (17, 0, &$1, &$7, 0, 0, $12.s0, $12.x0, 0);
866
867             }
868           else if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
869                    && !IS_A1 ($9) && IS_A1 ($11))
870             {
871               notethat ("dsp32alu: dregs = A0 + A1 , dregs = A0 - A1 (amod1)\n");
872               $$ = DSP32ALU (17, 0, &$1, &$7, 0, 0, $12.s0, $12.x0, 1);
873             }
874           else
875             return yyerror ("Register mismatch");
876         }
877
878         | REG ASSIGN REG plus_minus REG COMMA REG ASSIGN REG plus_minus REG amod1
879         {
880           if ($4.r0 == $10.r0)
881             return yyerror ("Operators must differ");
882
883           if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5)
884               && REG_SAME ($3, $9) && REG_SAME ($5, $11))
885             {
886               notethat ("dsp32alu: dregs = dregs + dregs,"
887                        "dregs = dregs - dregs (amod1)\n");
888               $$ = DSP32ALU (4, 0, &$1, &$7, &$3, &$5, $12.s0, $12.x0, 2);
889             }
890           else
891             return yyerror ("Register mismatch");
892         }
893
894 /*  Bar Operations.  */
895
896         | REG ASSIGN REG op_bar_op REG COMMA REG ASSIGN REG op_bar_op REG amod2
897         {
898           if (!REG_SAME ($3, $9) || !REG_SAME ($5, $11))
899             return yyerror ("Differing source registers");
900
901           if (!IS_DREG ($1) || !IS_DREG ($3) || !IS_DREG ($5) || !IS_DREG ($7))
902             return yyerror ("Dregs expected");
903
904
905           if ($4.r0 == 1 && $10.r0 == 2)
906             {
907               notethat ("dsp32alu:  dregs = dregs .|. dregs , dregs = dregs .|. dregs (amod2)\n");
908               $$ = DSP32ALU (1, 1, &$1, &$7, &$3, &$5, $12.s0, $12.x0, $12.r0);
909             }
910           else if ($4.r0 == 0 && $10.r0 == 3)
911             {
912               notethat ("dsp32alu:  dregs = dregs .|. dregs , dregs = dregs .|. dregs (amod2)\n");
913               $$ = DSP32ALU (1, 0, &$1, &$7, &$3, &$5, $12.s0, $12.x0, $12.r0);
914             }
915           else
916             return yyerror ("Bar operand mismatch");
917         }
918
919         | REG ASSIGN ABS REG vmod
920         {
921           int op;
922
923           if (IS_DREG ($1) && IS_DREG ($4))
924             {
925               if ($5.r0)
926                 {
927                   notethat ("dsp32alu: dregs = ABS dregs (v)\n");
928                   op = 6;
929                 }
930               else
931                 {
932                   /* Vector version of ABS.  */
933                   notethat ("dsp32alu: dregs = ABS dregs\n");
934                   op = 7;
935                 }
936               $$ = DSP32ALU (op, 0, 0, &$1, &$4, 0, 0, 0, 2);
937             }
938           else
939             return yyerror ("Dregs expected");
940         }
941         | a_assign ABS REG_A
942         {
943           notethat ("dsp32alu: Ax = ABS Ax\n");
944           $$ = DSP32ALU (16, IS_A1 ($1), 0, 0, 0, 0, 0, 0, IS_A1 ($3));
945         }
946         | A_ZERO_DOT_L ASSIGN HALF_REG
947         {
948           if (IS_DREG_L ($3))
949             {
950               notethat ("dsp32alu: A0.l = reg_half\n");
951               $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 0);
952             }
953           else
954             return yyerror ("A0.l = Rx.l expected");
955         }
956         | A_ONE_DOT_L ASSIGN HALF_REG
957         {
958           if (IS_DREG_L ($3))
959             {
960               notethat ("dsp32alu: A1.l = reg_half\n");
961               $$ = DSP32ALU (9, IS_H ($3), 0, 0, &$3, 0, 0, 0, 2);
962             }
963           else
964             return yyerror ("A1.l = Rx.l expected");
965         }
966
967         | REG ASSIGN c_align LPAREN REG COMMA REG RPAREN
968         {
969           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
970             {
971               notethat ("dsp32shift: dregs = ALIGN8 (dregs , dregs )\n");
972               $$ = DSP32SHIFT (13, &$1, &$7, &$5, $3.r0, 0);
973             }
974           else
975             return yyerror ("Dregs expected");
976         }
977
978         | REG ASSIGN BYTEOP1P LPAREN REG COLON expr COMMA REG COLON expr RPAREN byteop_mod
979         {
980           if (!IS_DREG ($1))
981             return yyerror ("Dregs expected");
982           else if (!valid_dreg_pair (&$5, $7))
983             return yyerror ("Bad dreg pair");
984           else if (!valid_dreg_pair (&$9, $11))
985             return yyerror ("Bad dreg pair");
986           else
987             {
988               notethat ("dsp32alu: dregs = BYTEOP1P (dregs_pair , dregs_pair ) (T)\n");
989               $$ = DSP32ALU (20, 0, 0, &$1, &$5, &$9, $13.s0, 0, $13.r0);
990             }
991         }
992         | REG ASSIGN BYTEOP1P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
993         {
994           if (!IS_DREG ($1))
995             return yyerror ("Dregs expected");
996           else if (!valid_dreg_pair (&$5, $7))
997             return yyerror ("Bad dreg pair");
998           else if (!valid_dreg_pair (&$9, $11))
999             return yyerror ("Bad dreg pair");
1000           else
1001             {
1002               notethat ("dsp32alu: dregs = BYTEOP1P (dregs_pair , dregs_pair ) (T)\n");
1003               $$ = DSP32ALU (20, 0, 0, &$1, &$5, &$9, 0, 0, 0);
1004             }
1005         }
1006
1007         | REG ASSIGN BYTEOP2P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
1008           rnd_op
1009         {
1010           if (!IS_DREG ($1))
1011             return yyerror ("Dregs expected");
1012           else if (!valid_dreg_pair (&$5, $7))
1013             return yyerror ("Bad dreg pair");
1014           else if (!valid_dreg_pair (&$9, $11))
1015             return yyerror ("Bad dreg pair");
1016           else
1017             {
1018               notethat ("dsp32alu: dregs = BYTEOP2P (dregs_pair , dregs_pair ) (rnd_op)\n");
1019               $$ = DSP32ALU (22, $13.r0, 0, &$1, &$5, &$9, $13.s0, $13.x0, $13.aop);
1020             }
1021         }
1022
1023         | REG ASSIGN BYTEOP2M LPAREN REG COLON expr COMMA REG COLON expr RPAREN
1024           rnd_op
1025         {
1026           if (!IS_DREG ($1))
1027             return yyerror ("Dregs expected");
1028           else if (!valid_dreg_pair (&$5, $7))
1029             return yyerror ("Bad dreg pair");
1030           else if (!valid_dreg_pair (&$9, $11))
1031             return yyerror ("Bad dreg pair");
1032           else
1033             {
1034               notethat ("dsp32alu: dregs = BYTEOP2P (dregs_pair , dregs_pair ) (rnd_op)\n");
1035               $$ = DSP32ALU (22, $13.r0, 0, &$1, &$5, &$9, $13.s0, 0, $13.x0);
1036             }
1037         }
1038
1039         | REG ASSIGN BYTEOP3P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
1040           b3_op
1041         {
1042           if (!IS_DREG ($1))
1043             return yyerror ("Dregs expected");
1044           else if (!valid_dreg_pair (&$5, $7))
1045             return yyerror ("Bad dreg pair");
1046           else if (!valid_dreg_pair (&$9, $11))
1047             return yyerror ("Bad dreg pair");
1048           else
1049             {
1050               notethat ("dsp32alu: dregs = BYTEOP3P (dregs_pair , dregs_pair ) (b3_op)\n");
1051               $$ = DSP32ALU (23, $13.x0, 0, &$1, &$5, &$9, $13.s0, 0, 0);
1052             }
1053         }
1054
1055         | REG ASSIGN BYTEPACK LPAREN REG COMMA REG RPAREN
1056         {
1057           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
1058             {
1059               notethat ("dsp32alu: dregs = BYTEPACK (dregs , dregs )\n");
1060               $$ = DSP32ALU (24, 0, 0, &$1, &$5, &$7, 0, 0, 0);
1061             }
1062           else
1063             return yyerror ("Dregs expected");
1064         }
1065
1066         | HALF_REG ASSIGN HALF_REG ASSIGN SIGN LPAREN HALF_REG RPAREN STAR
1067           HALF_REG PLUS SIGN LPAREN HALF_REG RPAREN STAR HALF_REG
1068         {
1069           if (IS_HCOMPL ($1, $3) && IS_HCOMPL ($7, $14) && IS_HCOMPL ($10, $17))
1070             {
1071               notethat ("dsp32alu:      dregs_hi = dregs_lo ="
1072                        "SIGN (dregs_hi) * dregs_hi + "
1073                        "SIGN (dregs_lo) * dregs_lo \n");
1074
1075                 $$ = DSP32ALU (12, 0, 0, &$1, &$7, &$10, 0, 0, 0);
1076             }
1077           else
1078             return yyerror ("Dregs expected");
1079         }
1080         | REG ASSIGN REG plus_minus REG amod1
1081         {
1082           if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
1083             {
1084               if ($6.aop == 0)
1085                 {
1086                   /* No saturation flag specified, generate the 16 bit variant.  */
1087                   notethat ("COMP3op: dregs = dregs +- dregs\n");
1088                   $$ = COMP3OP (&$1, &$3, &$5, $4.r0);
1089                 }
1090               else
1091                 {
1092                  /* Saturation flag specified, generate the 32 bit variant.  */
1093                  notethat ("dsp32alu: dregs = dregs +- dregs (amod1)\n");
1094                  $$ = DSP32ALU (4, 0, 0, &$1, &$3, &$5, $6.s0, $6.x0, $4.r0);
1095                 }
1096             }
1097           else
1098             if (IS_PREG ($1) && IS_PREG ($3) && IS_PREG ($5) && $4.r0 == 0)
1099               {
1100                 notethat ("COMP3op: pregs = pregs + pregs\n");
1101                 $$ = COMP3OP (&$1, &$3, &$5, 5);
1102               }
1103             else
1104               return yyerror ("Dregs expected");
1105         }
1106         | REG ASSIGN min_max LPAREN REG COMMA REG RPAREN vmod
1107         {
1108           int op;
1109
1110           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
1111             {
1112               if ($9.r0)
1113                 op = 6;
1114               else
1115                 op = 7;
1116
1117               notethat ("dsp32alu: dregs = {MIN|MAX} (dregs, dregs)\n");
1118               $$ = DSP32ALU (op, 0, 0, &$1, &$5, &$7, 0, 0, $3.r0);
1119             }
1120           else
1121             return yyerror ("Dregs expected");
1122         }
1123
1124         | a_assign MINUS REG_A
1125         {
1126           notethat ("dsp32alu: Ax = - Ax\n");
1127           $$ = DSP32ALU (14, IS_A1 ($1), 0, 0, 0, 0, 0, 0, IS_A1 ($3));
1128         }
1129         | HALF_REG ASSIGN HALF_REG plus_minus HALF_REG amod1
1130         {
1131           notethat ("dsp32alu: dregs_lo = dregs_lo +- dregs_lo (amod1)\n");
1132           $$ = DSP32ALU (2 | $4.r0, IS_H ($1), 0, &$1, &$3, &$5,
1133                          $6.s0, $6.x0, HL2 ($3, $5));
1134         }
1135         | a_assign a_assign expr
1136         {
1137           if (EXPR_VALUE ($3) == 0 && !REG_SAME ($1, $2))
1138             {
1139               notethat ("dsp32alu: A1 = A0 = 0\n");
1140               $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 0, 0, 2);
1141             }
1142           else
1143             return yyerror ("Bad value, 0 expected");
1144         }
1145
1146         /* Saturating.  */
1147         | a_assign REG_A LPAREN S RPAREN
1148         {
1149           if (REG_SAME ($1, $2))
1150             {
1151               notethat ("dsp32alu: Ax = Ax (S)\n");
1152               $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 1, 0, IS_A1 ($1));
1153             }
1154           else
1155             return yyerror ("Registers must be equal");
1156         }
1157
1158         | HALF_REG ASSIGN REG LPAREN RND RPAREN
1159         {
1160           if (IS_DREG ($3))
1161             {
1162               notethat ("dsp32alu: dregs_half = dregs (RND)\n");
1163               $$ = DSP32ALU (12, IS_H ($1), 0, &$1, &$3, 0, 0, 0, 3);
1164             }
1165           else
1166             return yyerror ("Dregs expected");
1167         }
1168
1169         | HALF_REG ASSIGN REG plus_minus REG LPAREN RND12 RPAREN
1170         {
1171           if (IS_DREG ($3) && IS_DREG ($5))
1172             {
1173               notethat ("dsp32alu: dregs_half = dregs (+-) dregs (RND12)\n");
1174               $$ = DSP32ALU (5, IS_H ($1), 0, &$1, &$3, &$5, 0, 0, $4.r0);
1175             }
1176           else
1177             return yyerror ("Dregs expected");
1178         }
1179
1180         | HALF_REG ASSIGN REG plus_minus REG LPAREN RND20 RPAREN
1181         {
1182           if (IS_DREG ($3) && IS_DREG ($5))
1183             {
1184               notethat ("dsp32alu: dregs_half = dregs -+ dregs (RND20)\n");
1185               $$ = DSP32ALU (5, IS_H ($1), 0, &$1, &$3, &$5, 0, 1, $4.r0 | 2);
1186             }
1187           else
1188             return yyerror ("Dregs expected");
1189         }
1190
1191         | a_assign REG_A
1192         {
1193           if (!REG_SAME ($1, $2))
1194             {
1195               notethat ("dsp32alu: An = Am\n");
1196               $$ = DSP32ALU (8, 0, 0, 0, 0, 0, IS_A1 ($1), 0, 3);
1197             }
1198           else
1199             return yyerror ("Accu reg arguments must differ");
1200         }
1201
1202         | a_assign REG
1203         {
1204           if (IS_DREG ($2))
1205             {
1206               notethat ("dsp32alu: An = dregs\n");
1207               $$ = DSP32ALU (9, 0, 0, 0, &$2, 0, 1, 0, IS_A1 ($1) << 1);
1208             }
1209           else
1210             return yyerror ("Dregs expected");
1211         }
1212
1213         | REG ASSIGN HALF_REG xpmod
1214         {
1215           if (!IS_H ($3))
1216             {
1217               if ($1.regno == REG_A0x && IS_DREG ($3))
1218                 {
1219                   notethat ("dsp32alu: A0.x = dregs_lo\n");
1220                   $$ = DSP32ALU (9, 0, 0, 0, &$3, 0, 0, 0, 1);
1221                 }
1222               else if ($1.regno == REG_A1x && IS_DREG ($3))
1223                 {
1224                   notethat ("dsp32alu: A1.x = dregs_lo\n");
1225                   $$ = DSP32ALU (9, 0, 0, 0, &$3, 0, 0, 0, 3);
1226                 }
1227               else if (IS_DREG ($1) && IS_DREG ($3))
1228                 {
1229                   notethat ("ALU2op: dregs = dregs_lo\n");
1230                   $$ = ALU2OP (&$1, &$3, 10 | ($4.r0 ? 0: 1));
1231                 }
1232               else
1233                 return yyerror ("Register mismatch");
1234             }
1235           else
1236             return yyerror ("Low reg expected");
1237         }
1238
1239         | HALF_REG ASSIGN expr
1240         {
1241           notethat ("LDIMMhalf: pregs_half = imm16\n");
1242
1243           if (!IS_DREG ($1) && !IS_PREG ($1) && !IS_IREG ($1)
1244               && !IS_MREG ($1) && !IS_BREG ($1) && !IS_LREG ($1))
1245             return yyerror ("Wrong register for load immediate");
1246
1247           if (!IS_IMM ($3, 16) && !IS_UIMM ($3, 16))
1248             return yyerror ("Constant out of range");
1249
1250           $$ = LDIMMHALF_R (&$1, IS_H ($1), 0, 0, $3);
1251         }
1252
1253         | a_assign expr
1254         {
1255           notethat ("dsp32alu: An = 0\n");
1256
1257           if (imm7 ($2) != 0)
1258             return yyerror ("0 expected");
1259
1260           $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 0, 0, IS_A1 ($1));
1261         }
1262
1263         | REG ASSIGN expr xpmod1
1264         {
1265           if (!IS_DREG ($1) && !IS_PREG ($1) && !IS_IREG ($1)
1266               && !IS_MREG ($1) && !IS_BREG ($1) && !IS_LREG ($1))
1267             return yyerror ("Wrong register for load immediate");
1268
1269           if ($4.r0 == 0)
1270             {
1271               /* 7 bit immediate value if possible.
1272                  We will check for that constant value for efficiency
1273                  If it goes to reloc, it will be 16 bit.  */
1274               if (IS_CONST ($3) && IS_IMM ($3, 7) && IS_DREG ($1))
1275                 {
1276                   notethat ("COMPI2opD: dregs = imm7 (x) \n");
1277                   $$ = COMPI2OPD (&$1, imm7 ($3), 0);
1278                 }
1279               else if (IS_CONST ($3) && IS_IMM ($3, 7) && IS_PREG ($1))
1280                 {
1281                   notethat ("COMPI2opP: pregs = imm7 (x)\n");
1282                   $$ = COMPI2OPP (&$1, imm7 ($3), 0);
1283                 }
1284               else
1285                 {
1286                   if (IS_CONST ($3) && !IS_IMM ($3, 16))
1287                     return yyerror ("Immediate value out of range");
1288
1289                   notethat ("LDIMMhalf: regs = luimm16 (x)\n");
1290                   /* reg, H, S, Z.   */
1291                   $$ = LDIMMHALF_R5 (&$1, 0, 1, 0, $3);
1292                 }
1293             }
1294           else
1295             {
1296               /* (z) There is no 7 bit zero extended instruction.
1297               If the expr is a relocation, generate it.   */
1298
1299               if (IS_CONST ($3) && !IS_UIMM ($3, 16))
1300                 return yyerror ("Immediate value out of range");
1301
1302               notethat ("LDIMMhalf: regs = luimm16 (x)\n");
1303               /* reg, H, S, Z.  */
1304               $$ = LDIMMHALF_R5 (&$1, 0, 0, 1, $3);
1305             }
1306         }
1307
1308         | HALF_REG ASSIGN REG
1309         {
1310           if (IS_H ($1))
1311             return yyerror ("Low reg expected");
1312
1313           if (IS_DREG ($1) && $3.regno == REG_A0x)
1314             {
1315               notethat ("dsp32alu: dregs_lo = A0.x\n");
1316               $$ = DSP32ALU (10, 0, 0, &$1, 0, 0, 0, 0, 0);
1317             }
1318           else if (IS_DREG ($1) && $3.regno == REG_A1x)
1319             {
1320               notethat ("dsp32alu: dregs_lo = A1.x\n");
1321               $$ = DSP32ALU (10, 0, 0, &$1, 0, 0, 0, 0, 1);
1322             }
1323           else
1324             return yyerror ("Register mismatch");
1325         }
1326
1327         | REG ASSIGN REG op_bar_op REG amod0
1328         {
1329           if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
1330             {
1331               notethat ("dsp32alu: dregs = dregs .|. dregs (amod0)\n");
1332               $$ = DSP32ALU (0, 0, 0, &$1, &$3, &$5, $6.s0, $6.x0, $4.r0);
1333             }
1334           else
1335             return yyerror ("Register mismatch");
1336         }
1337
1338         | REG ASSIGN BYTE_DREG xpmod
1339         {
1340           if (IS_DREG ($1) && IS_DREG ($3))
1341             {
1342               notethat ("ALU2op: dregs = dregs_byte\n");
1343               $$ = ALU2OP (&$1, &$3, 12 | ($4.r0 ? 0: 1));
1344             }
1345           else
1346             return yyerror ("Register mismatch");
1347         }
1348
1349         | a_assign ABS REG_A COMMA a_assign ABS REG_A
1350         {
1351           if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
1352             {
1353               notethat ("dsp32alu: A1 = ABS A1 , A0 = ABS A0\n");
1354               $$ = DSP32ALU (16, 0, 0, 0, 0, 0, 0, 0, 3);
1355             }
1356           else
1357             return yyerror ("Register mismatch");
1358         }
1359
1360         | a_assign MINUS REG_A COMMA a_assign MINUS REG_A
1361         {
1362           if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
1363             {
1364               notethat ("dsp32alu: A1 = - A1 , A0 = - A0\n");
1365               $$ = DSP32ALU (14, 0, 0, 0, 0, 0, 0, 0, 3);
1366             }
1367           else
1368             return yyerror ("Register mismatch");
1369         }
1370
1371         | a_minusassign REG_A w32_or_nothing
1372         {
1373           if (!IS_A1 ($1) && IS_A1 ($2))
1374             {
1375               notethat ("dsp32alu: A0 -= A1\n");
1376               $$ = DSP32ALU (11, 0, 0, 0, 0, 0, $3.r0, 0, 3);
1377             }
1378           else
1379             return yyerror ("Register mismatch");
1380         }
1381
1382         | REG _MINUS_ASSIGN expr
1383         {
1384           if (IS_IREG ($1) && EXPR_VALUE ($3) == 4)
1385             {
1386               notethat ("dagMODik: iregs -= 4\n");
1387               $$ = DAGMODIK (&$1, 3);
1388             }
1389           else if (IS_IREG ($1) && EXPR_VALUE ($3) == 2)
1390             {
1391               notethat ("dagMODik: iregs -= 2\n");
1392               $$ = DAGMODIK (&$1, 1);
1393             }
1394           else
1395             return yyerror ("Register or value mismatch");
1396         }
1397
1398         | REG _PLUS_ASSIGN REG LPAREN BREV RPAREN
1399         {
1400           if (IS_IREG ($1) && IS_MREG ($3))
1401             {
1402               notethat ("dagMODim: iregs += mregs (opt_brev)\n");
1403               /* i, m, op, br.  */
1404               $$ = DAGMODIM (&$1, &$3, 0, 1);
1405             }
1406           else if (IS_PREG ($1) && IS_PREG ($3))
1407             {
1408               notethat ("PTR2op: pregs += pregs (BREV )\n");
1409               $$ = PTR2OP (&$1, &$3, 5);
1410             }
1411           else
1412             return yyerror ("Register mismatch");
1413         }
1414
1415         | REG _MINUS_ASSIGN REG
1416         {
1417           if (IS_IREG ($1) && IS_MREG ($3))
1418             {
1419               notethat ("dagMODim: iregs -= mregs\n");
1420               $$ = DAGMODIM (&$1, &$3, 1, 0);
1421             }
1422           else if (IS_PREG ($1) && IS_PREG ($3))
1423             {
1424               notethat ("PTR2op: pregs -= pregs\n");
1425               $$ = PTR2OP (&$1, &$3, 0);
1426             }
1427           else
1428             return yyerror ("Register mismatch");
1429         }
1430
1431         | REG_A _PLUS_ASSIGN REG_A w32_or_nothing
1432         {
1433           if (!IS_A1 ($1) && IS_A1 ($3))
1434             {
1435               notethat ("dsp32alu: A0 += A1 (W32)\n");
1436               $$ = DSP32ALU (11, 0, 0, 0, 0, 0, $4.r0, 0, 2);
1437             }
1438           else
1439             return yyerror ("Register mismatch");
1440         }
1441
1442         | REG _PLUS_ASSIGN REG
1443         {
1444           if (IS_IREG ($1) && IS_MREG ($3))
1445             {
1446               notethat ("dagMODim: iregs += mregs\n");
1447               $$ = DAGMODIM (&$1, &$3, 0, 0);
1448             }
1449           else
1450             return yyerror ("iregs += mregs expected");
1451         }
1452
1453         | REG _PLUS_ASSIGN expr
1454         {
1455           if (IS_IREG ($1))
1456             {
1457               if (EXPR_VALUE ($3) == 4)
1458                 {
1459                   notethat ("dagMODik: iregs += 4\n");
1460                   $$ = DAGMODIK (&$1, 2);
1461                 }
1462               else if (EXPR_VALUE ($3) == 2)
1463                 {
1464                   notethat ("dagMODik: iregs += 2\n");
1465                   $$ = DAGMODIK (&$1, 0);
1466                 }
1467               else
1468                 return yyerror ("iregs += [ 2 | 4 ");
1469             }
1470           else if (IS_PREG ($1) && IS_IMM ($3, 7))
1471             {
1472               notethat ("COMPI2opP: pregs += imm7\n");
1473               $$ = COMPI2OPP (&$1, imm7 ($3), 1);
1474             }
1475           else if (IS_DREG ($1) && IS_IMM ($3, 7))
1476             {
1477               notethat ("COMPI2opD: dregs += imm7\n");
1478               $$ = COMPI2OPD (&$1, imm7 ($3), 1);
1479             }
1480           else if ((IS_DREG ($1) || IS_PREG ($1)) && IS_CONST ($3))
1481             return yyerror ("Immediate value out of range");
1482           else
1483             return yyerror ("Register mismatch");
1484         }
1485
1486         | REG _STAR_ASSIGN REG
1487         {
1488           if (IS_DREG ($1) && IS_DREG ($3))
1489             {
1490               notethat ("ALU2op: dregs *= dregs\n");
1491               $$ = ALU2OP (&$1, &$3, 3);
1492             }
1493           else
1494             return yyerror ("Register mismatch");
1495         }
1496
1497         | SAA LPAREN REG COLON expr COMMA REG COLON expr RPAREN aligndir
1498         {
1499           if (!valid_dreg_pair (&$3, $5))
1500             return yyerror ("Bad dreg pair");
1501           else if (!valid_dreg_pair (&$7, $9))
1502             return yyerror ("Bad dreg pair");
1503           else
1504             {
1505               notethat ("dsp32alu: SAA (dregs_pair , dregs_pair ) (aligndir)\n");
1506               $$ = DSP32ALU (18, 0, 0, 0, &$3, &$7, $11.r0, 0, 0);
1507             }
1508         }
1509
1510         | a_assign REG_A LPAREN S RPAREN COMMA a_assign REG_A LPAREN S RPAREN
1511         {
1512           if (REG_SAME ($1, $2) && REG_SAME ($7, $8) && !REG_SAME ($1, $7))
1513             {
1514               notethat ("dsp32alu: A1 = A1 (S) , A0 = A0 (S)\n");
1515               $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 1, 0, 2);
1516             }
1517           else
1518             return yyerror ("Register mismatch");
1519         }
1520
1521         | REG ASSIGN LPAREN REG PLUS REG RPAREN LESS_LESS expr
1522         {
1523           if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG ($6)
1524               && REG_SAME ($1, $4))
1525             {
1526               if (EXPR_VALUE ($9) == 1)
1527                 {
1528                   notethat ("ALU2op: dregs = (dregs + dregs) << 1\n");
1529                   $$ = ALU2OP (&$1, &$6, 4);
1530                 }
1531               else if (EXPR_VALUE ($9) == 2)
1532                 {
1533                   notethat ("ALU2op: dregs = (dregs + dregs) << 2\n");
1534                   $$ = ALU2OP (&$1, &$6, 5);
1535                 }
1536               else
1537                 return yyerror ("Bad shift value");
1538             }
1539           else if (IS_PREG ($1) && IS_PREG ($4) && IS_PREG ($6)
1540                    && REG_SAME ($1, $4))
1541             {
1542               if (EXPR_VALUE ($9) == 1)
1543                 {
1544                   notethat ("PTR2op: pregs = (pregs + pregs) << 1\n");
1545                   $$ = PTR2OP (&$1, &$6, 6);
1546                 }
1547               else if (EXPR_VALUE ($9) == 2)
1548                 {
1549                   notethat ("PTR2op: pregs = (pregs + pregs) << 2\n");
1550                   $$ = PTR2OP (&$1, &$6, 7);
1551                 }
1552               else
1553                 return yyerror ("Bad shift value");
1554             }
1555           else
1556             return yyerror ("Register mismatch");
1557         }
1558
1559 /*  COMP3 CCFLAG.  */
1560         | REG ASSIGN REG BAR REG
1561         {
1562           if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
1563             {
1564               notethat ("COMP3op: dregs = dregs | dregs\n");
1565               $$ = COMP3OP (&$1, &$3, &$5, 3);
1566             }
1567           else
1568             return yyerror ("Dregs expected");
1569         }
1570         | REG ASSIGN REG CARET REG
1571         {
1572           if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
1573             {
1574               notethat ("COMP3op: dregs = dregs ^ dregs\n");
1575               $$ = COMP3OP (&$1, &$3, &$5, 4);
1576             }
1577           else
1578             return yyerror ("Dregs expected");
1579         }
1580         | REG ASSIGN REG PLUS LPAREN REG LESS_LESS expr RPAREN
1581         {
1582           if (IS_PREG ($1) && IS_PREG ($3) && IS_PREG ($6))
1583             {
1584               if (EXPR_VALUE ($8) == 1)
1585                 {
1586                   notethat ("COMP3op: pregs = pregs + (pregs << 1)\n");
1587                   $$ = COMP3OP (&$1, &$3, &$6, 6);
1588                 }
1589               else if (EXPR_VALUE ($8) == 2)
1590                 {
1591                   notethat ("COMP3op: pregs = pregs + (pregs << 2)\n");
1592                   $$ = COMP3OP (&$1, &$3, &$6, 7);
1593                 }
1594               else
1595                   return yyerror ("Bad shift value");
1596             }
1597           else
1598             return yyerror ("Dregs expected");
1599         }
1600         | CCREG ASSIGN REG_A _ASSIGN_ASSIGN REG_A
1601         {
1602           if ($3.regno == REG_A0 && $5.regno == REG_A1)
1603             {
1604               notethat ("CCflag: CC = A0 == A1\n");
1605               $$ = CCFLAG (0, 0, 5, 0, 0);
1606             }
1607           else
1608             return yyerror ("AREGs are in bad order or same");
1609         }
1610         | CCREG ASSIGN REG_A LESS_THAN REG_A
1611         {
1612           if ($3.regno == REG_A0 && $5.regno == REG_A1)
1613             {
1614               notethat ("CCflag: CC = A0 < A1\n");
1615               $$ = CCFLAG (0, 0, 6, 0, 0);
1616             }
1617           else
1618             return yyerror ("AREGs are in bad order or same");
1619         }
1620         | CCREG ASSIGN REG LESS_THAN REG iu_or_nothing
1621         {
1622           if ((IS_DREG ($3) && IS_DREG ($5))
1623               || (IS_PREG ($3) && IS_PREG ($5)))
1624             {
1625               notethat ("CCflag: CC = dpregs < dpregs\n");
1626               $$ = CCFLAG (&$3, $5.regno & CODE_MASK, $6.r0, 0, IS_PREG ($3) ? 1 : 0);
1627             }
1628           else
1629             return yyerror ("Bad register in comparison");
1630         }
1631         | CCREG ASSIGN REG LESS_THAN expr iu_or_nothing
1632         {
1633           if (!IS_DREG ($3) && !IS_PREG ($3))
1634             return yyerror ("Bad register in comparison");
1635
1636           if (($6.r0 == 1 && IS_IMM ($5, 3))
1637               || ($6.r0 == 3 && IS_UIMM ($5, 3)))
1638             {
1639               notethat ("CCflag: CC = dpregs < (u)imm3\n");
1640               $$ = CCFLAG (&$3, imm3 ($5), $6.r0, 1, IS_PREG ($3) ? 1 : 0);
1641             }
1642           else
1643             return yyerror ("Bad constant value");
1644         }
1645         | CCREG ASSIGN REG _ASSIGN_ASSIGN REG
1646         {
1647           if ((IS_DREG ($3) && IS_DREG ($5))
1648               || (IS_PREG ($3) && IS_PREG ($5)))
1649             {
1650               notethat ("CCflag: CC = dpregs == dpregs\n");
1651               $$ = CCFLAG (&$3, $5.regno & CODE_MASK, 0, 0, IS_PREG ($3) ? 1 : 0);
1652             }
1653           else
1654             return yyerror ("Bad register in comparison");
1655         }
1656         | CCREG ASSIGN REG _ASSIGN_ASSIGN expr
1657         {
1658           if (!IS_DREG ($3) && !IS_PREG ($3))
1659             return yyerror ("Bad register in comparison");
1660
1661           if (IS_IMM ($5, 3))
1662             {
1663               notethat ("CCflag: CC = dpregs == imm3\n");
1664               $$ = CCFLAG (&$3, imm3 ($5), 0, 1, IS_PREG ($3) ? 1 : 0);
1665             }
1666           else
1667             return yyerror ("Bad constant range");
1668         }
1669         | CCREG ASSIGN REG_A _LESS_THAN_ASSIGN REG_A
1670         {
1671           if ($3.regno == REG_A0 && $5.regno == REG_A1)
1672             {
1673               notethat ("CCflag: CC = A0 <= A1\n");
1674               $$ = CCFLAG (0, 0, 7, 0, 0);
1675             }
1676           else
1677             return yyerror ("AREGs are in bad order or same");
1678         }
1679         | CCREG ASSIGN REG _LESS_THAN_ASSIGN REG iu_or_nothing
1680         {
1681           if ((IS_DREG ($3) && IS_DREG ($5))
1682               || (IS_PREG ($3) && IS_PREG ($5)))
1683             {
1684               notethat ("CCflag: CC = dpregs <= dpregs (..)\n");
1685               $$ = CCFLAG (&$3, $5.regno & CODE_MASK,
1686                            1 + $6.r0, 0, IS_PREG ($3) ? 1 : 0);
1687             }
1688           else
1689             return yyerror ("Bad register in comparison");
1690         }
1691         | CCREG ASSIGN REG _LESS_THAN_ASSIGN expr iu_or_nothing
1692         {
1693           if (!IS_DREG ($3) && !IS_PREG ($3))
1694             return yyerror ("Bad register in comparison");
1695
1696           if (($6.r0 == 1 && IS_IMM ($5, 3))
1697               || ($6.r0 == 3 && IS_UIMM ($5, 3)))
1698             {
1699               notethat ("CCflag: CC = dpregs <= (u)imm3\n");
1700               $$ = CCFLAG (&$3, imm3 ($5), 1 + $6.r0, 1, IS_PREG ($3) ? 1 : 0);
1701             }
1702           else
1703             return yyerror ("Bad constant value");
1704         }
1705
1706         | REG ASSIGN REG AMPERSAND REG
1707         {
1708           if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
1709             {
1710               notethat ("COMP3op: dregs = dregs & dregs\n");
1711               $$ = COMP3OP (&$1, &$3, &$5, 2);
1712             }
1713           else
1714             return yyerror ("Dregs expected");
1715         }
1716
1717         | ccstat
1718         {
1719           notethat ("CC2stat operation\n");
1720           $$ = bfin_gen_cc2stat ($1.r0, $1.x0, $1.s0);
1721         }
1722
1723         | REG ASSIGN REG
1724         {
1725           if ((IS_GENREG ($1) && IS_GENREG ($3))
1726               || (IS_GENREG ($1) && IS_DAGREG ($3))
1727               || (IS_DAGREG ($1) && IS_GENREG ($3))
1728               || (IS_DAGREG ($1) && IS_DAGREG ($3))
1729               || (IS_GENREG ($1) && $3.regno == REG_USP)
1730               || ($1.regno == REG_USP && IS_GENREG ($3))
1731               || (IS_DREG ($1) && IS_SYSREG ($3))
1732               || (IS_PREG ($1) && IS_SYSREG ($3))
1733               || (IS_SYSREG ($1) && IS_DREG ($3))
1734               || (IS_SYSREG ($1) && IS_PREG ($3))
1735               || (IS_SYSREG ($1) && $3.regno == REG_USP))
1736             {
1737               $$ = bfin_gen_regmv (&$3, &$1);
1738             }
1739           else
1740             return yyerror ("Register mismatch");
1741         }
1742
1743         | CCREG ASSIGN REG
1744         {
1745           if (IS_DREG ($3))
1746             {
1747               notethat ("CC2dreg: CC = dregs\n");
1748               $$ = bfin_gen_cc2dreg (1, &$3);
1749             }
1750           else
1751             return yyerror ("Register mismatch");
1752         }
1753
1754         | REG ASSIGN CCREG
1755         {
1756           if (IS_DREG ($1))
1757             {
1758               notethat ("CC2dreg: dregs = CC\n");
1759               $$ = bfin_gen_cc2dreg (0, &$1);
1760             }
1761           else
1762             return yyerror ("Register mismatch");
1763         }
1764
1765         | CCREG _ASSIGN_BANG CCREG
1766         {
1767           notethat ("CC2dreg: CC =! CC\n");
1768           $$ = bfin_gen_cc2dreg (3, 0);
1769         }
1770
1771 /* DSPMULT.  */
1772
1773         | HALF_REG ASSIGN multiply_halfregs opt_mode
1774         {
1775           notethat ("dsp32mult: dregs_half = multiply_halfregs (opt_mode)\n");
1776
1777           if (!IS_H ($1) && $4.MM)
1778             return yyerror ("(M) not allowed with MAC0");
1779
1780           if ($4.mod != 0 && $4.mod != M_FU && $4.mod != M_IS
1781               && $4.mod != M_IU && $4.mod != M_T && $4.mod != M_TFU
1782               && $4.mod != M_S2RND && $4.mod != M_ISS2 && $4.mod != M_IH)
1783             return yyerror ("bad option.");
1784
1785           if (IS_H ($1))
1786             {
1787               $$ = DSP32MULT (0, $4.MM, $4.mod, 1, 0,
1788                               IS_H ($3.s0), IS_H ($3.s1), 0, 0,
1789                               &$1, 0, &$3.s0, &$3.s1, 0);
1790             }
1791           else
1792             {
1793               $$ = DSP32MULT (0, 0, $4.mod, 0, 0,
1794                               0, 0, IS_H ($3.s0), IS_H ($3.s1),
1795                               &$1, 0, &$3.s0, &$3.s1, 1);
1796             }
1797         }
1798
1799         | REG ASSIGN multiply_halfregs opt_mode
1800         {
1801           /* Odd registers can use (M).  */
1802           if (!IS_DREG ($1))
1803             return yyerror ("Dreg expected");
1804
1805           if (IS_EVEN ($1) && $4.MM)
1806             return yyerror ("(M) not allowed with MAC0");
1807
1808           if ($4.mod != 0 && $4.mod != M_FU && $4.mod != M_IS
1809               && $4.mod != M_S2RND && $4.mod != M_ISS2)
1810             return yyerror ("bad option");
1811
1812           if (!IS_EVEN ($1))
1813             {
1814               notethat ("dsp32mult: dregs = multiply_halfregs (opt_mode)\n");
1815
1816               $$ = DSP32MULT (0, $4.MM, $4.mod, 1, 1,
1817                               IS_H ($3.s0), IS_H ($3.s1), 0, 0,
1818                               &$1, 0, &$3.s0, &$3.s1, 0);
1819             }
1820           else
1821             {
1822               notethat ("dsp32mult: dregs = multiply_halfregs opt_mode\n");
1823               $$ = DSP32MULT (0, 0, $4.mod, 0, 1,
1824                               0, 0, IS_H ($3.s0), IS_H ($3.s1),
1825                               &$1,  0, &$3.s0, &$3.s1, 1);
1826             }
1827         }
1828
1829         | HALF_REG ASSIGN multiply_halfregs opt_mode COMMA
1830           HALF_REG ASSIGN multiply_halfregs opt_mode
1831         {
1832           if (!IS_DREG ($1) || !IS_DREG ($6))
1833             return yyerror ("Dregs expected");
1834
1835           if (!IS_HCOMPL($1, $6))
1836             return yyerror ("Dest registers mismatch");
1837
1838           if (check_multiply_halfregs (&$3, &$8) < 0)
1839             return -1;
1840
1841           if ((!IS_H ($1) && $4.MM)
1842               || (!IS_H ($6) && $9.MM))
1843             return yyerror ("(M) not allowed with MAC0");
1844
1845           notethat ("dsp32mult: dregs_hi = multiply_halfregs mxd_mod, "
1846                     "dregs_lo = multiply_halfregs opt_mode\n");
1847
1848           if (IS_H ($1))
1849             $$ = DSP32MULT (0, $4.MM, $9.mod, 1, 0,
1850                             IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
1851                             &$1, 0, &$3.s0, &$3.s1, 1);
1852           else
1853             $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 0,
1854                             IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
1855                             &$1, 0, &$3.s0, &$3.s1, 1);
1856         }
1857
1858         | REG ASSIGN multiply_halfregs opt_mode COMMA REG ASSIGN multiply_halfregs opt_mode
1859         {
1860           if (!IS_DREG ($1) || !IS_DREG ($6))
1861             return yyerror ("Dregs expected");
1862
1863           if ((IS_EVEN ($1) && $6.regno - $1.regno != 1)
1864               || (IS_EVEN ($6) && $1.regno - $6.regno != 1))
1865             return yyerror ("Dest registers mismatch");
1866
1867           if (check_multiply_halfregs (&$3, &$8) < 0)
1868             return -1;
1869
1870           if ((IS_EVEN ($1) && $4.MM)
1871               || (IS_EVEN ($6) && $9.MM))
1872             return yyerror ("(M) not allowed with MAC0");
1873
1874           notethat ("dsp32mult: dregs = multiply_halfregs mxd_mod, "
1875                    "dregs = multiply_halfregs opt_mode\n");
1876
1877           if (IS_EVEN ($1))
1878             $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 1,
1879                             IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
1880                             &$1, 0, &$3.s0, &$3.s1, 1);
1881           else
1882             $$ = DSP32MULT (0, $4.MM, $9.mod, 1, 1,
1883                             IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
1884                             &$1, 0, &$3.s0, &$3.s1, 1);
1885         }
1886
1887 \f
1888 /* SHIFTs.  */
1889         | a_assign ASHIFT REG_A BY HALF_REG
1890         {
1891           if (!REG_SAME ($1, $3))
1892             return yyerror ("Aregs must be same");
1893
1894           if (IS_DREG ($5) && !IS_H ($5))
1895             {
1896               notethat ("dsp32shift: A0 = ASHIFT A0 BY dregs_lo\n");
1897               $$ = DSP32SHIFT (3, 0, &$5, 0, 0, IS_A1 ($1));
1898             }
1899           else
1900             return yyerror ("Dregs expected");
1901         }
1902
1903         | HALF_REG ASSIGN ASHIFT HALF_REG BY HALF_REG smod
1904         {
1905           if (IS_DREG ($6) && !IS_H ($6))
1906             {
1907               notethat ("dsp32shift: dregs_half = ASHIFT dregs_half BY dregs_lo\n");
1908               $$ = DSP32SHIFT (0, &$1, &$6, &$4, $7.s0, HL2 ($1, $4));
1909             }
1910           else
1911             return yyerror ("Dregs expected");
1912         }
1913
1914         | a_assign REG_A LESS_LESS expr
1915         {
1916           if (!REG_SAME ($1, $2))
1917             return yyerror ("Aregs must be same");
1918
1919           if (IS_UIMM ($4, 5))
1920             {
1921               notethat ("dsp32shiftimm: A0 = A0 << uimm5\n");
1922               $$ = DSP32SHIFTIMM (3, 0, imm5 ($4), 0, 0, IS_A1 ($1));
1923             }
1924           else
1925             return yyerror ("Bad shift value");
1926         }
1927
1928         | REG ASSIGN REG LESS_LESS expr vsmod
1929         {
1930           if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
1931             {
1932               if ($6.r0)
1933                 {
1934                   /*  Vector?  */
1935                   notethat ("dsp32shiftimm: dregs = dregs << expr (V, .)\n");
1936                   $$ = DSP32SHIFTIMM (1, &$1, imm4 ($5), &$3, $6.s0 ? 1 : 2, 0);
1937                 }
1938               else
1939                 {
1940                   notethat ("dsp32shiftimm: dregs =  dregs << uimm5 (.)\n");
1941                   $$ = DSP32SHIFTIMM (2, &$1, imm6 ($5), &$3, $6.s0 ? 1 : 2, 0);
1942                 }
1943             }
1944           else if ($6.s0 == 0 && IS_PREG ($1) && IS_PREG ($3))
1945             {
1946               if (EXPR_VALUE ($5) == 2)
1947                 {
1948                   notethat ("PTR2op: pregs = pregs << 2\n");
1949                   $$ = PTR2OP (&$1, &$3, 1);
1950                 }
1951               else if (EXPR_VALUE ($5) == 1)
1952                 {
1953                   notethat ("COMP3op: pregs = pregs << 1\n");
1954                   $$ = COMP3OP (&$1, &$3, &$3, 5);
1955                 }
1956               else
1957                 return yyerror ("Bad shift value");
1958             }
1959           else
1960             return yyerror ("Bad shift value or register");
1961         }
1962         | HALF_REG ASSIGN HALF_REG LESS_LESS expr smod
1963         {
1964           if (IS_UIMM ($5, 4))
1965             {
1966               if ($6.s0)
1967                 {
1968                   notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4 (S)\n");
1969                   $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, $6.s0, HL2 ($1, $3));
1970                 }
1971               else
1972                 {
1973                   notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4\n");
1974                   $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, 2, HL2 ($1, $3));
1975                 }
1976             }
1977           else
1978             return yyerror ("Bad shift value");
1979         }
1980         | REG ASSIGN ASHIFT REG BY HALF_REG vsmod
1981         {
1982           int op;
1983
1984           if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG ($6) && !IS_H ($6))
1985             {
1986               if ($7.r0)
1987                 {
1988                   op = 1;
1989                   notethat ("dsp32shift: dregs = ASHIFT dregs BY "
1990                            "dregs_lo (V, .)\n");
1991                 }
1992               else
1993                 {
1994
1995                   op = 2;
1996                   notethat ("dsp32shift: dregs = ASHIFT dregs BY dregs_lo (.)\n");
1997                 }
1998               $$ = DSP32SHIFT (op, &$1, &$6, &$4, $7.s0, 0);
1999             }
2000           else
2001             return yyerror ("Dregs expected");
2002         }
2003
2004 /*  EXPADJ.  */
2005         | HALF_REG ASSIGN EXPADJ LPAREN REG COMMA HALF_REG RPAREN vmod
2006         {
2007           if (IS_DREG_L ($1) && IS_DREG_L ($5) && IS_DREG_L ($7))
2008             {
2009               notethat ("dsp32shift: dregs_lo = EXPADJ (dregs , dregs_lo )\n");
2010               $$ = DSP32SHIFT (7, &$1, &$7, &$5, $9.r0, 0);
2011             }
2012           else
2013             return yyerror ("Bad shift value or register");
2014         }
2015
2016
2017         | HALF_REG ASSIGN EXPADJ LPAREN HALF_REG COMMA HALF_REG RPAREN
2018         {
2019           if (IS_DREG_L ($1) && IS_DREG_L ($5) && IS_DREG_L ($7))
2020             {
2021               notethat ("dsp32shift: dregs_lo = EXPADJ (dregs_lo, dregs_lo)\n");
2022               $$ = DSP32SHIFT (7, &$1, &$7, &$5, 2, 0);
2023             }
2024           else if (IS_DREG_L ($1) && IS_DREG_H ($5) && IS_DREG_L ($7))
2025             {
2026               notethat ("dsp32shift: dregs_lo = EXPADJ (dregs_hi, dregs_lo)\n");
2027               $$ = DSP32SHIFT (7, &$1, &$7, &$5, 3, 0);
2028             }
2029           else
2030             return yyerror ("Bad shift value or register");
2031         }
2032
2033 /* DEPOSIT.  */
2034
2035         | REG ASSIGN DEPOSIT LPAREN REG COMMA REG RPAREN
2036         {
2037           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
2038             {
2039               notethat ("dsp32shift: dregs = DEPOSIT (dregs , dregs )\n");
2040               $$ = DSP32SHIFT (10, &$1, &$7, &$5, 2, 0);
2041             }
2042           else
2043             return yyerror ("Register mismatch");
2044         }
2045
2046         | REG ASSIGN DEPOSIT LPAREN REG COMMA REG RPAREN LPAREN X RPAREN
2047         {
2048           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
2049             {
2050               notethat ("dsp32shift: dregs = DEPOSIT (dregs , dregs ) (X)\n");
2051               $$ = DSP32SHIFT (10, &$1, &$7, &$5, 3, 0);
2052             }
2053           else
2054             return yyerror ("Register mismatch");
2055         }
2056
2057         | REG ASSIGN EXTRACT LPAREN REG COMMA HALF_REG RPAREN xpmod
2058         {
2059           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG_L ($7))
2060             {
2061               notethat ("dsp32shift: dregs = EXTRACT (dregs, dregs_lo ) (.)\n");
2062               $$ = DSP32SHIFT (10, &$1, &$7, &$5, $9.r0, 0);
2063             }
2064           else
2065             return yyerror ("Register mismatch");
2066         }
2067
2068         | a_assign REG_A _GREATER_GREATER_GREATER expr
2069         {
2070           if (!REG_SAME ($1, $2))
2071             return yyerror ("Aregs must be same");
2072
2073           if (IS_UIMM ($4, 5))
2074             {
2075               notethat ("dsp32shiftimm: Ax = Ax >>> uimm5\n");
2076               $$ = DSP32SHIFTIMM (3, 0, -imm6 ($4), 0, 0, IS_A1 ($1));
2077             }
2078           else
2079             return yyerror ("Shift value range error");
2080         }
2081         | a_assign LSHIFT REG_A BY HALF_REG
2082         {
2083           if (REG_SAME ($1, $3) && IS_DREG_L ($5))
2084             {
2085               notethat ("dsp32shift: Ax = LSHIFT Ax BY dregs_lo\n");
2086               $$ = DSP32SHIFT (3, 0, &$5, 0, 1, IS_A1 ($1));
2087             }
2088           else
2089             return yyerror ("Register mismatch");
2090         }
2091
2092         | HALF_REG ASSIGN LSHIFT HALF_REG BY HALF_REG
2093         {
2094           if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
2095             {
2096               notethat ("dsp32shift: dregs_lo = LSHIFT dregs_hi BY dregs_lo\n");
2097               $$ = DSP32SHIFT (0, &$1, &$6, &$4, 2, HL2 ($1, $4));
2098             }
2099           else
2100             return yyerror ("Register mismatch");
2101         }
2102
2103         | REG ASSIGN LSHIFT REG BY HALF_REG vmod
2104         {
2105           if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
2106             {
2107               notethat ("dsp32shift: dregs = LSHIFT dregs BY dregs_lo (V )\n");
2108               $$ = DSP32SHIFT ($7.r0 ? 1: 2, &$1, &$6, &$4, 2, 0);
2109             }
2110           else
2111             return yyerror ("Register mismatch");
2112         }
2113
2114         | REG ASSIGN SHIFT REG BY HALF_REG
2115         {
2116           if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
2117             {
2118               notethat ("dsp32shift: dregs = SHIFT dregs BY dregs_lo\n");
2119               $$ = DSP32SHIFT (2, &$1, &$6, &$4, 2, 0);
2120             }
2121           else
2122             return yyerror ("Register mismatch");
2123         }
2124
2125         | a_assign REG_A GREATER_GREATER expr
2126         {
2127           if (REG_SAME ($1, $2) && IS_IMM ($4, 6) >= 0)
2128             {
2129               notethat ("dsp32shiftimm: Ax = Ax >> imm6\n");
2130               $$ = DSP32SHIFTIMM (3, 0, -imm6 ($4), 0, 1, IS_A1 ($1));
2131             }
2132           else
2133             return yyerror ("Accu register expected");
2134         }
2135
2136         | REG ASSIGN REG GREATER_GREATER expr vmod
2137         {
2138           if ($6.r0 == 1)
2139             {
2140               if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
2141                 {
2142                   notethat ("dsp32shiftimm: dregs = dregs >> uimm5 (V)\n");
2143                   $$ = DSP32SHIFTIMM (1, &$1, -uimm5 ($5), &$3, 2, 0);
2144                 }
2145               else
2146                 return yyerror ("Register mismatch");
2147             }
2148           else
2149             {
2150               if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
2151                 {
2152                   notethat ("dsp32shiftimm: dregs = dregs >> uimm5\n");
2153                   $$ = DSP32SHIFTIMM (2, &$1, -imm6 ($5), &$3, 2, 0);
2154                 }
2155               else if (IS_PREG ($1) && IS_PREG ($3) && EXPR_VALUE ($5) == 2)
2156                 {
2157                   notethat ("PTR2op: pregs = pregs >> 2\n");
2158                   $$ = PTR2OP (&$1, &$3, 3);
2159                 }
2160               else if (IS_PREG ($1) && IS_PREG ($3) && EXPR_VALUE ($5) == 1)
2161                 {
2162                   notethat ("PTR2op: pregs = pregs >> 1\n");
2163                   $$ = PTR2OP (&$1, &$3, 4);
2164                 }
2165               else
2166                 return yyerror ("Register mismatch");
2167             }
2168         }
2169         | HALF_REG ASSIGN HALF_REG GREATER_GREATER expr
2170         {
2171           if (IS_UIMM ($5, 5))
2172             {
2173               notethat ("dsp32shiftimm:  dregs_half =  dregs_half >> uimm5\n");
2174               $$ = DSP32SHIFTIMM (0, &$1, -uimm5 ($5), &$3, 2, HL2 ($1, $3));
2175             }
2176           else
2177             return yyerror ("Register mismatch");
2178         }
2179         | HALF_REG ASSIGN HALF_REG _GREATER_GREATER_GREATER expr smod
2180         {
2181           if (IS_UIMM ($5, 5))
2182             {
2183               notethat ("dsp32shiftimm: dregs_half = dregs_half >>> uimm5\n");
2184               $$ = DSP32SHIFTIMM (0, &$1, -uimm5 ($5), &$3,
2185                                   $6.s0, HL2 ($1, $3));
2186             }
2187           else
2188             return yyerror ("Register or modifier mismatch");
2189         }
2190
2191
2192         | REG ASSIGN REG _GREATER_GREATER_GREATER expr vsmod
2193         {
2194           if (IS_DREG ($1) && IS_DREG ($3) && IS_UIMM ($5, 5))
2195             {
2196               if ($6.r0)
2197                 {
2198                   /* Vector?  */
2199                   notethat ("dsp32shiftimm: dregs  =  dregs >>> uimm5 (V, .)\n");
2200                   $$ = DSP32SHIFTIMM (1, &$1, -uimm5 ($5), &$3, $6.s0, 0);
2201                 }
2202               else
2203                 {
2204                   notethat ("dsp32shiftimm: dregs  =  dregs >>> uimm5 (.)\n");
2205                   $$ = DSP32SHIFTIMM (2, &$1, -uimm5 ($5), &$3, $6.s0, 0);
2206                 }
2207             }
2208           else
2209             return yyerror ("Register mismatch");
2210         }
2211
2212         | HALF_REG ASSIGN ONES REG
2213         {
2214           if (IS_DREG_L ($1) && IS_DREG ($4))
2215             {
2216               notethat ("dsp32shift: dregs_lo = ONES dregs\n");
2217               $$ = DSP32SHIFT (6, &$1, 0, &$4, 3, 0);
2218             }
2219           else
2220             return yyerror ("Register mismatch");
2221         }
2222
2223         | REG ASSIGN PACK LPAREN HALF_REG COMMA HALF_REG RPAREN
2224         {
2225           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
2226             {
2227               notethat ("dsp32shift: dregs = PACK (dregs_hi , dregs_hi )\n");
2228               $$ = DSP32SHIFT (4, &$1, &$7, &$5, HL2 ($5, $7), 0);
2229             }
2230           else
2231             return yyerror ("Register mismatch");
2232         }
2233
2234         | HALF_REG ASSIGN CCREG ASSIGN BXORSHIFT LPAREN REG_A COMMA REG RPAREN
2235         {
2236           if (IS_DREG ($1)
2237               && $7.regno == REG_A0
2238               && IS_DREG ($9) && !IS_H ($1) && !IS_A1 ($7))
2239             {
2240               notethat ("dsp32shift: dregs_lo = CC = BXORSHIFT (A0 , dregs )\n");
2241               $$ = DSP32SHIFT (11, &$1, &$9, 0, 0, 0);
2242             }
2243           else
2244             return yyerror ("Register mismatch");
2245         }
2246
2247         | HALF_REG ASSIGN CCREG ASSIGN BXOR LPAREN REG_A COMMA REG RPAREN
2248         {
2249           if (IS_DREG ($1)
2250               && $7.regno == REG_A0
2251               && IS_DREG ($9) && !IS_H ($1) && !IS_A1 ($7))
2252             {
2253               notethat ("dsp32shift: dregs_lo = CC = BXOR (A0 , dregs)\n");
2254               $$ = DSP32SHIFT (11, &$1, &$9, 0, 1, 0);
2255             }
2256           else
2257             return yyerror ("Register mismatch");
2258         }
2259
2260         | HALF_REG ASSIGN CCREG ASSIGN BXOR LPAREN REG_A COMMA REG_A COMMA CCREG RPAREN
2261         {
2262           if (IS_DREG ($1) && !IS_H ($1) && !REG_SAME ($7, $9))
2263             {
2264               notethat ("dsp32shift: dregs_lo = CC = BXOR (A0 , A1 , CC)\n");
2265               $$ = DSP32SHIFT (12, &$1, 0, 0, 1, 0);
2266             }
2267           else
2268             return yyerror ("Register mismatch");
2269         }
2270
2271         | a_assign ROT REG_A BY HALF_REG
2272         {
2273           if (REG_SAME ($1, $3) && IS_DREG_L ($5))
2274             {
2275               notethat ("dsp32shift: Ax = ROT Ax BY dregs_lo\n");
2276               $$ = DSP32SHIFT (3, 0, &$5, 0, 2, IS_A1 ($1));
2277             }
2278           else
2279             return yyerror ("Register mismatch");
2280         }
2281
2282         | REG ASSIGN ROT REG BY HALF_REG
2283         {
2284           if (IS_DREG ($1) && IS_DREG ($4) && IS_DREG_L ($6))
2285             {
2286               notethat ("dsp32shift: dregs = ROT dregs BY dregs_lo\n");
2287               $$ = DSP32SHIFT (2, &$1, &$6, &$4, 3, 0);
2288             }
2289           else
2290             return yyerror ("Register mismatch");
2291         }
2292
2293         | a_assign ROT REG_A BY expr
2294         {
2295           if (IS_IMM ($5, 6))
2296             {
2297               notethat ("dsp32shiftimm: An = ROT An BY imm6\n");
2298               $$ = DSP32SHIFTIMM (3, 0, imm6 ($5), 0, 2, IS_A1 ($1));
2299             }
2300           else
2301             return yyerror ("Register mismatch");
2302         }
2303
2304         | REG ASSIGN ROT REG BY expr
2305         {
2306           if (IS_DREG ($1) && IS_DREG ($4) && IS_IMM ($6, 6))
2307             {
2308               $$ = DSP32SHIFTIMM (2, &$1, imm6 ($6), &$4, 3, IS_A1 ($1));
2309             }
2310           else
2311             return yyerror ("Register mismatch");
2312         }
2313
2314         | HALF_REG ASSIGN SIGNBITS REG_A
2315         {
2316           if (IS_DREG_L ($1))
2317             {
2318               notethat ("dsp32shift: dregs_lo = SIGNBITS An\n");
2319               $$ = DSP32SHIFT (6, &$1, 0, 0, IS_A1 ($4), 0);
2320             }
2321           else
2322             return yyerror ("Register mismatch");
2323         }
2324
2325         | HALF_REG ASSIGN SIGNBITS REG
2326         {
2327           if (IS_DREG_L ($1) && IS_DREG ($4))
2328             {
2329               notethat ("dsp32shift: dregs_lo = SIGNBITS dregs\n");
2330               $$ = DSP32SHIFT (5, &$1, 0, &$4, 0, 0);
2331             }
2332           else
2333             return yyerror ("Register mismatch");
2334         }
2335
2336         | HALF_REG ASSIGN SIGNBITS HALF_REG
2337         {
2338           if (IS_DREG_L ($1))
2339             {
2340               notethat ("dsp32shift: dregs_lo = SIGNBITS dregs_lo\n");
2341               $$ = DSP32SHIFT (5, &$1, 0, &$4, 1 + IS_H ($4), 0);
2342             }
2343           else
2344             return yyerror ("Register mismatch");
2345         }
2346
2347         /* The ASR bit is just inverted here. */
2348         | HALF_REG ASSIGN VIT_MAX LPAREN REG RPAREN asr_asl
2349         {
2350           if (IS_DREG_L ($1) && IS_DREG ($5))
2351             {
2352               notethat ("dsp32shift: dregs_lo = VIT_MAX (dregs) (..)\n");
2353               $$ = DSP32SHIFT (9, &$1, 0, &$5, ($7.r0 ? 0 : 1), 0);
2354             }
2355           else
2356             return yyerror ("Register mismatch");
2357         }
2358
2359         | REG ASSIGN VIT_MAX LPAREN REG COMMA REG RPAREN asr_asl
2360         {
2361           if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
2362             {
2363               notethat ("dsp32shift: dregs = VIT_MAX (dregs, dregs) (ASR)\n");
2364               $$ = DSP32SHIFT (9, &$1, &$7, &$5, 2 | ($9.r0 ? 0 : 1), 0);
2365             }
2366           else
2367             return yyerror ("Register mismatch");
2368         }
2369
2370         | BITMUX LPAREN REG COMMA REG COMMA REG_A RPAREN asr_asl
2371         {
2372           if (IS_DREG ($3) && IS_DREG ($5) && !IS_A1 ($7))
2373             {
2374               notethat ("dsp32shift: BITMUX (dregs , dregs , A0) (ASR)\n");
2375               $$ = DSP32SHIFT (8, 0, &$3, &$5, $9.r0, 0);
2376             }
2377           else
2378             return yyerror ("Register mismatch");
2379         }
2380
2381         | a_assign BXORSHIFT LPAREN REG_A COMMA REG_A COMMA CCREG RPAREN
2382         {
2383           if (!IS_A1 ($1) && !IS_A1 ($4) && IS_A1 ($6))
2384             {
2385               notethat ("dsp32shift: A0 = BXORSHIFT (A0 , A1 , CC )\n");
2386               $$ = DSP32SHIFT (12, 0, 0, 0, 0, 0);
2387             }
2388           else
2389             return yyerror ("Dregs expected");
2390         }
2391
2392
2393 /* LOGI2op:     BITCLR (dregs, uimm5).  */
2394         | BITCLR LPAREN REG COMMA expr RPAREN
2395         {
2396           if (IS_DREG ($3) && IS_UIMM ($5, 5))
2397             {
2398               notethat ("LOGI2op: BITCLR (dregs , uimm5 )\n");
2399               $$ = LOGI2OP ($3, uimm5 ($5), 4);
2400             }
2401           else
2402             return yyerror ("Register mismatch");
2403         }
2404
2405 /* LOGI2op:     BITSET (dregs, uimm5).  */
2406         | BITSET LPAREN REG COMMA expr RPAREN
2407         {
2408           if (IS_DREG ($3) && IS_UIMM ($5, 5))
2409             {
2410               notethat ("LOGI2op: BITCLR (dregs , uimm5 )\n");
2411               $$ = LOGI2OP ($3, uimm5 ($5), 2);
2412             }
2413           else
2414             return yyerror ("Register mismatch");
2415         }
2416
2417 /* LOGI2op:     BITTGL (dregs, uimm5).  */
2418         | BITTGL LPAREN REG COMMA expr RPAREN
2419         {
2420           if (IS_DREG ($3) && IS_UIMM ($5, 5))
2421             {
2422               notethat ("LOGI2op: BITCLR (dregs , uimm5 )\n");
2423               $$ = LOGI2OP ($3, uimm5 ($5), 3);
2424             }
2425           else
2426             return yyerror ("Register mismatch");
2427         }
2428
2429         | CCREG _ASSIGN_BANG BITTST LPAREN REG COMMA expr RPAREN
2430         {
2431           if (IS_DREG ($5) && IS_UIMM ($7, 5))
2432             {
2433               notethat ("LOGI2op: CC =! BITTST (dregs , uimm5 )\n");
2434               $$ = LOGI2OP ($5, uimm5 ($7), 0);
2435             }
2436           else
2437             return yyerror ("Register mismatch or value error");
2438         }
2439
2440         | CCREG ASSIGN BITTST LPAREN REG COMMA expr RPAREN
2441         {
2442           if (IS_DREG ($5) && IS_UIMM ($7, 5))
2443             {
2444               notethat ("LOGI2op: CC = BITTST (dregs , uimm5 )\n");
2445               $$ = LOGI2OP ($5, uimm5 ($7), 1);
2446             }
2447           else
2448             return yyerror ("Register mismatch or value error");
2449         }
2450
2451         | IF BANG CCREG REG ASSIGN REG
2452         {
2453           if ((IS_DREG ($4) || IS_PREG ($4))
2454               && (IS_DREG ($6) || IS_PREG ($6)))
2455             {
2456               notethat ("ccMV: IF ! CC gregs = gregs\n");
2457               $$ = CCMV (&$6, &$4, 0);
2458             }
2459           else
2460             return yyerror ("Register mismatch");
2461         }
2462
2463         | IF CCREG REG ASSIGN REG
2464         {
2465           if ((IS_DREG ($5) || IS_PREG ($5))
2466               && (IS_DREG ($3) || IS_PREG ($3)))
2467             {
2468               notethat ("ccMV: IF CC gregs = gregs\n");
2469               $$ = CCMV (&$5, &$3, 1);
2470             }
2471           else
2472             return yyerror ("Register mismatch");
2473         }
2474
2475         | IF BANG CCREG JUMP expr
2476         {
2477           if (IS_PCREL10 ($5))
2478             {
2479               notethat ("BRCC: IF !CC JUMP  pcrel11m2\n");
2480               $$ = BRCC (0, 0, $5);
2481             }
2482           else
2483             return yyerror ("Bad jump offset");
2484         }
2485
2486         | IF BANG CCREG JUMP expr LPAREN BP RPAREN
2487         {
2488           if (IS_PCREL10 ($5))
2489             {
2490               notethat ("BRCC: IF !CC JUMP  pcrel11m2\n");
2491               $$ = BRCC (0, 1, $5);
2492             }
2493           else
2494             return yyerror ("Bad jump offset");
2495         }
2496
2497         | IF CCREG JUMP expr
2498         {
2499           if (IS_PCREL10 ($4))
2500             {
2501               notethat ("BRCC: IF CC JUMP  pcrel11m2\n");
2502               $$ = BRCC (1, 0, $4);
2503             }
2504           else
2505             return yyerror ("Bad jump offset");
2506         }
2507
2508         | IF CCREG JUMP expr LPAREN BP RPAREN
2509         {
2510           if (IS_PCREL10 ($4))
2511             {
2512               notethat ("BRCC: IF !CC JUMP  pcrel11m2\n");
2513               $$ = BRCC (1, 1, $4);
2514             }
2515           else
2516             return yyerror ("Bad jump offset");
2517         }
2518         | NOP
2519         {
2520           notethat ("ProgCtrl: NOP\n");
2521           $$ = PROGCTRL (0, 0);
2522         }
2523
2524         | RTS
2525         {
2526           notethat ("ProgCtrl: RTS\n");
2527           $$ = PROGCTRL (1, 0);
2528         }
2529
2530         | RTI
2531         {
2532           notethat ("ProgCtrl: RTI\n");
2533           $$ = PROGCTRL (1, 1);
2534         }
2535
2536         | RTX
2537         {
2538           notethat ("ProgCtrl: RTX\n");
2539           $$ = PROGCTRL (1, 2);
2540         }
2541
2542         | RTN
2543         {
2544           notethat ("ProgCtrl: RTN\n");
2545           $$ = PROGCTRL (1, 3);
2546         }
2547
2548         | RTE
2549         {
2550           notethat ("ProgCtrl: RTE\n");
2551           $$ = PROGCTRL (1, 4);
2552         }
2553
2554         | IDLE
2555         {
2556           notethat ("ProgCtrl: IDLE\n");
2557           $$ = PROGCTRL (2, 0);
2558         }
2559
2560         | CSYNC
2561         {
2562           notethat ("ProgCtrl: CSYNC\n");
2563           $$ = PROGCTRL (2, 3);
2564         }
2565
2566         | SSYNC
2567         {
2568           notethat ("ProgCtrl: SSYNC\n");
2569           $$ = PROGCTRL (2, 4);
2570         }
2571
2572         | EMUEXCPT
2573         {
2574           notethat ("ProgCtrl: EMUEXCPT\n");
2575           $$ = PROGCTRL (2, 5);
2576         }
2577
2578         | CLI REG
2579         {
2580           if (IS_DREG ($2))
2581             {
2582               notethat ("ProgCtrl: CLI dregs\n");
2583               $$ = PROGCTRL (3, $2.regno & CODE_MASK);
2584             }
2585           else
2586             return yyerror ("Dreg expected for CLI");
2587         }
2588
2589         | STI REG
2590         {
2591           if (IS_DREG ($2))
2592             {
2593               notethat ("ProgCtrl: STI dregs\n");
2594               $$ = PROGCTRL (4, $2.regno & CODE_MASK);
2595             }
2596           else
2597             return yyerror ("Dreg expected for STI");
2598         }
2599
2600         | JUMP LPAREN REG RPAREN
2601         {
2602           if (IS_PREG ($3))
2603             {
2604               notethat ("ProgCtrl: JUMP (pregs )\n");
2605               $$ = PROGCTRL (5, $3.regno & CODE_MASK);
2606             }
2607           else
2608             return yyerror ("Bad register for indirect jump");
2609         }
2610
2611         | CALL LPAREN REG RPAREN
2612         {
2613           if (IS_PREG ($3))
2614             {
2615               notethat ("ProgCtrl: CALL (pregs )\n");
2616               $$ = PROGCTRL (6, $3.regno & CODE_MASK);
2617             }
2618           else
2619             return yyerror ("Bad register for indirect call");
2620         }
2621
2622         | CALL LPAREN PC PLUS REG RPAREN
2623         {
2624           if (IS_PREG ($5))
2625             {
2626               notethat ("ProgCtrl: CALL (PC + pregs )\n");
2627               $$ = PROGCTRL (7, $5.regno & CODE_MASK);
2628             }
2629           else
2630             return yyerror ("Bad register for indirect call");
2631         }
2632
2633         | JUMP LPAREN PC PLUS REG RPAREN
2634         {
2635           if (IS_PREG ($5))
2636             {
2637               notethat ("ProgCtrl: JUMP (PC + pregs )\n");
2638               $$ = PROGCTRL (8, $5.regno & CODE_MASK);
2639             }
2640           else
2641             return yyerror ("Bad register for indirect jump");
2642         }
2643
2644         | RAISE expr
2645         {
2646           if (IS_UIMM ($2, 4))
2647             {
2648               notethat ("ProgCtrl: RAISE uimm4\n");
2649               $$ = PROGCTRL (9, uimm4 ($2));
2650             }
2651           else
2652             return yyerror ("Bad value for RAISE");
2653         }
2654
2655         | EXCPT expr
2656         {
2657                 notethat ("ProgCtrl: EMUEXCPT\n");
2658                 $$ = PROGCTRL (10, uimm4 ($2));
2659         }
2660
2661         | TESTSET LPAREN REG RPAREN
2662         {
2663           if (IS_PREG ($3))
2664             {
2665               notethat ("ProgCtrl: TESTSET (pregs )\n");
2666               $$ = PROGCTRL (11, $3.regno & CODE_MASK);
2667             }
2668           else
2669             return yyerror ("Preg expected");
2670         }
2671
2672         | JUMP expr
2673         {
2674           if (IS_PCREL12 ($2))
2675             {
2676               notethat ("UJUMP: JUMP pcrel12\n");
2677               $$ = UJUMP ($2);
2678             }
2679           else
2680             return yyerror ("Bad value for relative jump");
2681         }
2682
2683         | JUMP_DOT_S expr
2684         {
2685           if (IS_PCREL12 ($2))
2686             {
2687               notethat ("UJUMP: JUMP_DOT_S pcrel12\n");
2688               $$ = UJUMP($2);
2689             }
2690           else
2691             return yyerror ("Bad value for relative jump");
2692         }
2693
2694         | JUMP_DOT_L expr
2695         {
2696           if (IS_PCREL24 ($2))
2697             {
2698               notethat ("CALLa: jump.l pcrel24\n");
2699               $$ = CALLA ($2, 0);
2700             }
2701           else
2702             return yyerror ("Bad value for long jump");
2703         }
2704
2705         | JUMP_DOT_L pltpc
2706         {
2707           if (IS_PCREL24 ($2))
2708             {
2709               notethat ("CALLa: jump.l pcrel24\n");
2710               $$ = CALLA ($2, 2);
2711             }
2712           else
2713             return yyerror ("Bad value for long jump");
2714         }
2715
2716         | CALL expr
2717         {
2718           if (IS_PCREL24 ($2))
2719             {
2720               notethat ("CALLa: CALL pcrel25m2\n");
2721               $$ = CALLA ($2, 1);
2722             }
2723           else
2724             return yyerror ("Bad call address");
2725         }
2726         | CALL pltpc
2727         {
2728           if (IS_PCREL24 ($2))
2729             {
2730               notethat ("CALLa: CALL pcrel25m2\n");
2731               $$ = CALLA ($2, 2);
2732             }
2733           else
2734             return yyerror ("Bad call address");
2735         }
2736
2737 /* ALU2ops.  */
2738 /* ALU2op:      DIVQ (dregs, dregs).  */
2739         | DIVQ LPAREN REG COMMA REG RPAREN
2740         {
2741           if (IS_DREG ($3) && IS_DREG ($5))
2742             $$ = ALU2OP (&$3, &$5, 8);
2743           else
2744             return yyerror ("Bad registers for DIVQ");
2745         }
2746
2747         | DIVS LPAREN REG COMMA REG RPAREN
2748         {
2749           if (IS_DREG ($3) && IS_DREG ($5))
2750             $$ = ALU2OP (&$3, &$5, 9);
2751           else
2752             return yyerror ("Bad registers for DIVS");
2753         }
2754
2755         | REG ASSIGN MINUS REG vsmod
2756         {
2757           if (IS_DREG ($1) && IS_DREG ($4))
2758             {
2759               if ($5.r0 == 0 && $5.s0 == 0 && $5.aop == 0)
2760                 {
2761                   notethat ("ALU2op: dregs = - dregs\n");
2762                   $$ = ALU2OP (&$1, &$4, 14);
2763                 }
2764               else if ($5.r0 == 1 && $5.s0 == 0 && $5.aop == 3)
2765                 {
2766                   notethat ("dsp32alu: dregs = - dregs (.)\n");
2767                   $$ = DSP32ALU (15, 0, 0, &$1, &$4, 0, $5.s0, 0, 3);
2768                 }
2769               else
2770                 {
2771                   notethat ("dsp32alu: dregs = - dregs (.)\n");
2772                   $$ = DSP32ALU (7, 0, 0, &$1, &$4, 0, $5.s0, 0, 3);
2773                 }
2774             }
2775           else
2776             return yyerror ("Dregs expected");
2777         }
2778
2779         | REG ASSIGN TILDA REG
2780         {
2781           if (IS_DREG ($1) && IS_DREG ($4))
2782             {
2783               notethat ("ALU2op: dregs = ~dregs\n");
2784               $$ = ALU2OP (&$1, &$4, 15);
2785             }
2786           else
2787             return yyerror ("Dregs expected");
2788         }
2789
2790         | REG _GREATER_GREATER_ASSIGN REG
2791         {
2792           if (IS_DREG ($1) && IS_DREG ($3))
2793             {
2794               notethat ("ALU2op: dregs >>= dregs\n");
2795               $$ = ALU2OP (&$1, &$3, 1);
2796             }
2797           else
2798             return yyerror ("Dregs expected");
2799         }
2800
2801         | REG _GREATER_GREATER_ASSIGN expr
2802         {
2803           if (IS_DREG ($1) && IS_UIMM ($3, 5))
2804             {
2805               notethat ("LOGI2op: dregs >>= uimm5\n");
2806               $$ = LOGI2OP ($1, uimm5 ($3), 6);
2807             }
2808           else
2809             return yyerror ("Dregs expected or value error");
2810         }
2811
2812         | REG _GREATER_GREATER_GREATER_THAN_ASSIGN REG
2813         {
2814           if (IS_DREG ($1) && IS_DREG ($3))
2815             {
2816               notethat ("ALU2op: dregs >>>= dregs\n");
2817               $$ = ALU2OP (&$1, &$3, 0);
2818             }
2819           else
2820             return yyerror ("Dregs expected");
2821         }
2822
2823         | REG _LESS_LESS_ASSIGN REG
2824         {
2825           if (IS_DREG ($1) && IS_DREG ($3))
2826             {
2827               notethat ("ALU2op: dregs <<= dregs\n");
2828               $$ = ALU2OP (&$1, &$3, 2);
2829             }
2830           else
2831             return yyerror ("Dregs expected");
2832         }
2833
2834         | REG _LESS_LESS_ASSIGN expr
2835         {
2836           if (IS_DREG ($1) && IS_UIMM ($3, 5))
2837             {
2838               notethat ("LOGI2op: dregs <<= uimm5\n");
2839               $$ = LOGI2OP ($1, uimm5 ($3), 7);
2840             }
2841           else
2842             return yyerror ("Dregs expected or const value error");
2843         }
2844
2845
2846         | REG _GREATER_GREATER_GREATER_THAN_ASSIGN expr
2847         {
2848           if (IS_DREG ($1) && IS_UIMM ($3, 5))
2849             {
2850               notethat ("LOGI2op: dregs >>>= uimm5\n");
2851               $$ = LOGI2OP ($1, uimm5 ($3), 5);
2852             }
2853           else
2854             return yyerror ("Dregs expected");
2855         }
2856
2857 /* Cache Control.  */
2858
2859         | FLUSH LBRACK REG RBRACK
2860         {
2861           notethat ("CaCTRL: FLUSH [ pregs ]\n");
2862           if (IS_PREG ($3))
2863             $$ = CACTRL (&$3, 0, 2);
2864           else
2865             return yyerror ("Bad register(s) for FLUSH");
2866         }
2867
2868         | FLUSH reg_with_postinc
2869         {
2870           if (IS_PREG ($2))
2871             {
2872               notethat ("CaCTRL: FLUSH [ pregs ++ ]\n");
2873               $$ = CACTRL (&$2, 1, 2);
2874             }
2875           else
2876             return yyerror ("Bad register(s) for FLUSH");
2877         }
2878
2879         | FLUSHINV LBRACK REG RBRACK
2880         {
2881           if (IS_PREG ($3))
2882             {
2883               notethat ("CaCTRL: FLUSHINV [ pregs ]\n");
2884               $$ = CACTRL (&$3, 0, 1);
2885             }
2886           else
2887             return yyerror ("Bad register(s) for FLUSH");
2888         }
2889
2890         | FLUSHINV reg_with_postinc
2891         {
2892           if (IS_PREG ($2))
2893             {
2894               notethat ("CaCTRL: FLUSHINV [ pregs ++ ]\n");
2895               $$ = CACTRL (&$2, 1, 1);
2896             }
2897           else
2898             return yyerror ("Bad register(s) for FLUSH");
2899         }
2900
2901 /* CaCTRL:      IFLUSH [pregs].  */
2902         | IFLUSH LBRACK REG RBRACK
2903         {
2904           if (IS_PREG ($3))
2905             {
2906               notethat ("CaCTRL: IFLUSH [ pregs ]\n");
2907               $$ = CACTRL (&$3, 0, 3);
2908             }
2909           else
2910             return yyerror ("Bad register(s) for FLUSH");
2911         }
2912
2913         | IFLUSH reg_with_postinc
2914         {
2915           if (IS_PREG ($2))
2916             {
2917               notethat ("CaCTRL: IFLUSH [ pregs ++ ]\n");
2918               $$ = CACTRL (&$2, 1, 3);
2919             }
2920           else
2921             return yyerror ("Bad register(s) for FLUSH");
2922         }
2923
2924         | PREFETCH LBRACK REG RBRACK
2925         {
2926           if (IS_PREG ($3))
2927             {
2928               notethat ("CaCTRL: PREFETCH [ pregs ]\n");
2929               $$ = CACTRL (&$3, 0, 0);
2930             }
2931           else
2932             return yyerror ("Bad register(s) for PREFETCH");
2933         }
2934
2935         | PREFETCH reg_with_postinc
2936         {
2937           if (IS_PREG ($2))
2938             {
2939               notethat ("CaCTRL: PREFETCH [ pregs ++ ]\n");
2940               $$ = CACTRL (&$2, 1, 0);
2941             }
2942           else
2943             return yyerror ("Bad register(s) for PREFETCH");
2944         }
2945
2946 /* LOAD/STORE.  */
2947 /* LDST:        B [ pregs <post_op> ] = dregs.  */
2948
2949         | B LBRACK REG post_op RBRACK ASSIGN REG
2950         {
2951           if (!IS_DREG ($7))
2952             return yyerror ("Dreg expected for source operand");
2953           if (!IS_PREG ($3))
2954             return yyerror ("Preg expected in address");
2955
2956           notethat ("LDST: B [ pregs <post_op> ] = dregs\n");
2957           $$ = LDST (&$3, &$7, $4.x0, 2, 0, 1);
2958         }
2959
2960 /* LDSTidxI:    B [ pregs + imm16 ] = dregs.  */
2961         | B LBRACK REG plus_minus expr RBRACK ASSIGN REG
2962         {
2963           Expr_Node *tmp = $5;
2964
2965           if (!IS_DREG ($8))
2966             return yyerror ("Dreg expected for source operand");
2967           if (!IS_PREG ($3))
2968             return yyerror ("Preg expected in address");
2969
2970           if (IS_RELOC ($5))
2971             return yyerror ("Plain symbol used as offset");
2972
2973           if ($4.r0)
2974             tmp = unary (Expr_Op_Type_NEG, tmp);
2975
2976           if (in_range_p (tmp, -32768, 32767, 0))
2977             {
2978               notethat ("LDST: B [ pregs + imm16 ] = dregs\n");
2979               $$ = LDSTIDXI (&$3, &$8, 1, 2, 0, $5);
2980             }
2981           else
2982             return yyerror ("Displacement out of range");
2983         }
2984
2985
2986 /* LDSTii:      W [ pregs + uimm4s2 ] = dregs.  */
2987         | W LBRACK REG plus_minus expr RBRACK ASSIGN REG
2988         {
2989           Expr_Node *tmp = $5;
2990
2991           if (!IS_DREG ($8))
2992             return yyerror ("Dreg expected for source operand");
2993           if (!IS_PREG ($3))
2994             return yyerror ("Preg expected in address");
2995
2996           if ($4.r0)
2997             tmp = unary (Expr_Op_Type_NEG, tmp);
2998
2999           if (IS_RELOC ($5))
3000             return yyerror ("Plain symbol used as offset");
3001
3002           if (in_range_p (tmp, 0, 30, 1))
3003             {
3004               notethat ("LDSTii: W [ pregs +- uimm5m2 ] = dregs\n");
3005               $$ = LDSTII (&$3, &$8, tmp, 1, 1);
3006             }
3007           else if (in_range_p (tmp, -65536, 65535, 1))
3008             {
3009               notethat ("LDSTidxI: W [ pregs + imm17m2 ] = dregs\n");
3010               $$ = LDSTIDXI (&$3, &$8, 1, 1, 0, tmp);
3011             }
3012           else
3013             return yyerror ("Displacement out of range");
3014         }
3015
3016 /* LDST:        W [ pregs <post_op> ] = dregs.  */
3017         | W LBRACK REG post_op RBRACK ASSIGN REG
3018         {
3019           if (!IS_DREG ($7))
3020             return yyerror ("Dreg expected for source operand");
3021           if (!IS_PREG ($3))
3022             return yyerror ("Preg expected in address");
3023
3024           notethat ("LDST: W [ pregs <post_op> ] = dregs\n");
3025           $$ = LDST (&$3, &$7, $4.x0, 1, 0, 1);
3026         }
3027
3028         | W LBRACK REG post_op RBRACK ASSIGN HALF_REG
3029         {
3030           if (!IS_DREG ($7))
3031             return yyerror ("Dreg expected for source operand");
3032           if ($4.x0 == 2)
3033             {
3034               if (!IS_IREG ($3) && !IS_PREG ($3))
3035                 return yyerror ("Ireg or Preg expected in address");
3036             }
3037           else if (!IS_IREG ($3))
3038             return yyerror ("Ireg expected in address");
3039
3040           if (IS_IREG ($3))
3041             {
3042               notethat ("dspLDST: W [ iregs <post_op> ] = dregs_half\n");
3043               $$ = DSPLDST (&$3, 1 + IS_H ($7), &$7, $4.x0, 1);
3044             }
3045           else
3046             {
3047               notethat ("LDSTpmod: W [ pregs ] = dregs_half\n");
3048               $$ = LDSTPMOD (&$3, &$7, &$3, 1 + IS_H ($7), 1);
3049             }
3050         }
3051
3052 /* LDSTiiFP:    [ FP - const ] = dpregs.  */
3053         | LBRACK REG plus_minus expr RBRACK ASSIGN REG
3054         {
3055           Expr_Node *tmp = $4;
3056           int ispreg = IS_PREG ($7);
3057
3058           if (!IS_PREG ($2))
3059             return yyerror ("Preg expected in address");
3060
3061           if (!IS_DREG ($7) && !ispreg)
3062             return yyerror ("Preg expected for source operand");
3063
3064           if ($3.r0)
3065             tmp = unary (Expr_Op_Type_NEG, tmp);
3066
3067           if (IS_RELOC ($4))
3068             return yyerror ("Plain symbol used as offset");
3069
3070           if (in_range_p (tmp, 0, 63, 3))
3071             {
3072               notethat ("LDSTii: dpregs = [ pregs + uimm6m4 ]\n");
3073               $$ = LDSTII (&$2, &$7, tmp, 1, ispreg ? 3 : 0);
3074             }
3075           else if ($2.regno == REG_FP && in_range_p (tmp, -128, 0, 3))
3076             {
3077               notethat ("LDSTiiFP: dpregs = [ FP - uimm7m4 ]\n");
3078               tmp = unary (Expr_Op_Type_NEG, tmp);
3079               $$ = LDSTIIFP (tmp, &$7, 1);
3080             }
3081           else if (in_range_p (tmp, -131072, 131071, 3))
3082             {
3083               notethat ("LDSTidxI: [ pregs + imm18m4 ] = dpregs\n");
3084               $$ = LDSTIDXI (&$2, &$7, 1, 0, ispreg ? 1 : 0, tmp);
3085             }
3086           else
3087             return yyerror ("Displacement out of range");
3088         }
3089
3090         | REG ASSIGN W LBRACK REG plus_minus expr RBRACK xpmod
3091         {
3092           Expr_Node *tmp = $7;
3093           if (!IS_DREG ($1))
3094             return yyerror ("Dreg expected for destination operand");
3095           if (!IS_PREG ($5))
3096             return yyerror ("Preg expected in address");
3097
3098           if ($6.r0)
3099             tmp = unary (Expr_Op_Type_NEG, tmp);
3100
3101           if (IS_RELOC ($7))
3102             return yyerror ("Plain symbol used as offset");
3103
3104           if (in_range_p (tmp, 0, 30, 1))
3105             {
3106               notethat ("LDSTii: dregs = W [ pregs + uimm5m2 ] (.)\n");
3107               $$ = LDSTII (&$5, &$1, tmp, 0, 1 << $9.r0);
3108             }
3109           else if (in_range_p (tmp, -65536, 65535, 1))
3110             {
3111               notethat ("LDSTidxI: dregs = W [ pregs + imm17m2 ] (.)\n");
3112               $$ = LDSTIDXI (&$5, &$1, 0, 1, $9.r0, tmp);
3113             }
3114           else
3115             return yyerror ("Displacement out of range");
3116         }
3117
3118         | HALF_REG ASSIGN W LBRACK REG post_op RBRACK
3119         {
3120           if (!IS_DREG ($1))
3121             return yyerror ("Dreg expected for source operand");
3122           if ($6.x0 == 2)
3123             {
3124               if (!IS_IREG ($5) && !IS_PREG ($5))
3125                 return yyerror ("Ireg or Preg expected in address");
3126             }
3127           else if (!IS_IREG ($5))
3128             return yyerror ("Ireg expected in address");
3129
3130           if (IS_IREG ($5))
3131             {
3132               notethat ("dspLDST: dregs_half = W [ iregs <post_op> ]\n");
3133               $$ = DSPLDST(&$5, 1 + IS_H ($1), &$1, $6.x0, 0);
3134             }
3135           else
3136             {
3137               notethat ("LDSTpmod: dregs_half = W [ pregs <post_op> ]\n");
3138               $$ = LDSTPMOD (&$5, &$1, &$5, 1 + IS_H ($1), 0);
3139             }
3140         }
3141
3142
3143         | REG ASSIGN W LBRACK REG post_op RBRACK xpmod
3144         {
3145           if (!IS_DREG ($1))
3146             return yyerror ("Dreg expected for destination operand");
3147           if (!IS_PREG ($5))
3148             return yyerror ("Preg expected in address");
3149
3150           notethat ("LDST: dregs = W [ pregs <post_op> ] (.)\n");
3151           $$ = LDST (&$5, &$1, $6.x0, 1, $8.r0, 0);
3152         }
3153
3154         | REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK xpmod
3155         {
3156           if (!IS_DREG ($1))
3157             return yyerror ("Dreg expected for destination operand");
3158           if (!IS_PREG ($5) || !IS_PREG ($7))
3159             return yyerror ("Preg expected in address");
3160
3161           notethat ("LDSTpmod: dregs = W [ pregs ++ pregs ] (.)\n");
3162           $$ = LDSTPMOD (&$5, &$1, &$7, 3, $9.r0);
3163         }
3164
3165         | HALF_REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK
3166         {
3167           if (!IS_DREG ($1))
3168             return yyerror ("Dreg expected for destination operand");
3169           if (!IS_PREG ($5) || !IS_PREG ($7))
3170             return yyerror ("Preg expected in address");
3171
3172           notethat ("LDSTpmod: dregs_half = W [ pregs ++ pregs ]\n");
3173           $$ = LDSTPMOD (&$5, &$1, &$7, 1 + IS_H ($1), 0);
3174         }
3175
3176         | LBRACK REG post_op RBRACK ASSIGN REG
3177         {
3178           if (!IS_IREG ($2) && !IS_PREG ($2))
3179             return yyerror ("Ireg or Preg expected in address");
3180           else if (IS_IREG ($2) && !IS_DREG ($6))
3181             return yyerror ("Dreg expected for source operand");
3182           else if (IS_PREG ($2) && !IS_DREG ($6) && !IS_PREG ($6))
3183             return yyerror ("Dreg or Preg expected for source operand");
3184
3185           if (IS_IREG ($2))
3186             {
3187               notethat ("dspLDST: [ iregs <post_op> ] = dregs\n");
3188               $$ = DSPLDST(&$2, 0, &$6, $3.x0, 1);
3189             }
3190           else if (IS_DREG ($6))
3191             {
3192               notethat ("LDST: [ pregs <post_op> ] = dregs\n");
3193               $$ = LDST (&$2, &$6, $3.x0, 0, 0, 1);
3194             }
3195           else
3196             {
3197               notethat ("LDST: [ pregs <post_op> ] = pregs\n");
3198               $$ = LDST (&$2, &$6, $3.x0, 0, 1, 1);
3199             }
3200         }
3201
3202         | LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN REG
3203         {
3204           if (!IS_DREG ($7))
3205             return yyerror ("Dreg expected for source operand");
3206
3207           if (IS_IREG ($2) && IS_MREG ($4))
3208             {
3209               notethat ("dspLDST: [ iregs ++ mregs ] = dregs\n");
3210               $$ = DSPLDST(&$2, $4.regno & CODE_MASK, &$7, 3, 1);
3211             }
3212           else if (IS_PREG ($2) && IS_PREG ($4))
3213             {
3214               notethat ("LDSTpmod: [ pregs ++ pregs ] = dregs\n");
3215               $$ = LDSTPMOD (&$2, &$7, &$4, 0, 1);
3216             }
3217           else
3218             return yyerror ("Preg ++ Preg or Ireg ++ Mreg expected in address");
3219         }
3220
3221         | W LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN HALF_REG
3222         {
3223           if (!IS_DREG ($8))
3224             return yyerror ("Dreg expected for source operand");
3225
3226           if (IS_PREG ($3) && IS_PREG ($5))
3227             {
3228               notethat ("LDSTpmod: W [ pregs ++ pregs ] = dregs_half\n");
3229               $$ = LDSTPMOD (&$3, &$8, &$5, 1 + IS_H ($8), 1);
3230             }
3231           else
3232             return yyerror ("Preg ++ Preg expected in address");
3233         }
3234
3235         | REG ASSIGN B LBRACK REG plus_minus expr RBRACK xpmod
3236         {
3237           Expr_Node *tmp = $7;
3238           if (!IS_DREG ($1))
3239             return yyerror ("Dreg expected for destination operand");
3240           if (!IS_PREG ($5))
3241             return yyerror ("Preg expected in address");
3242
3243           if ($6.r0)
3244             tmp = unary (Expr_Op_Type_NEG, tmp);
3245
3246           if (IS_RELOC ($7))
3247             return yyerror ("Plain symbol used as offset");
3248
3249           if (in_range_p (tmp, -32768, 32767, 0))
3250             {
3251               notethat ("LDSTidxI: dregs = B [ pregs + imm16 ] (%c)\n",
3252                        $9.r0 ? 'X' : 'Z');
3253               $$ = LDSTIDXI (&$5, &$1, 0, 2, $9.r0, tmp);
3254             }
3255           else
3256             return yyerror ("Displacement out of range");
3257         }
3258
3259         | REG ASSIGN B LBRACK REG post_op RBRACK xpmod
3260         {
3261           if (!IS_DREG ($1))
3262             return yyerror ("Dreg expected for destination operand");
3263           if (!IS_PREG ($5))
3264             return yyerror ("Preg expected in address");
3265
3266           notethat ("LDST: dregs = B [ pregs <post_op> ] (%c)\n",
3267                     $8.r0 ? 'X' : 'Z');
3268           $$ = LDST (&$5, &$1, $6.x0, 2, $8.r0, 0);
3269         }
3270
3271         | REG ASSIGN LBRACK REG _PLUS_PLUS REG RBRACK
3272         {
3273           if (!IS_DREG ($1))
3274             return yyerror ("Dreg expected for destination operand");
3275
3276           if (IS_IREG ($4) && IS_MREG ($6))
3277             {
3278               notethat ("dspLDST: dregs = [ iregs ++ mregs ]\n");
3279               $$ = DSPLDST(&$4, $6.regno & CODE_MASK, &$1, 3, 0);
3280             }
3281           else if (IS_PREG ($4) && IS_PREG ($6))
3282             {
3283               notethat ("LDSTpmod: dregs = [ pregs ++ pregs ]\n");
3284               $$ = LDSTPMOD (&$4, &$1, &$6, 0, 0);
3285             }
3286           else
3287             return yyerror ("Preg ++ Preg or Ireg ++ Mreg expected in address");
3288         }
3289
3290         | REG ASSIGN LBRACK REG plus_minus got_or_expr RBRACK
3291         {
3292           Expr_Node *tmp = $6;
3293           int ispreg = IS_PREG ($1);
3294           int isgot = IS_RELOC($6);
3295
3296           if (!IS_PREG ($4))
3297             return yyerror ("Preg expected in address");
3298
3299           if (!IS_DREG ($1) && !ispreg)
3300             return yyerror ("Dreg or Preg expected for destination operand");
3301
3302           if (tmp->type == Expr_Node_Reloc
3303               && strcmp (tmp->value.s_value,
3304                          "_current_shared_library_p5_offset_") != 0)
3305             return yyerror ("Plain symbol used as offset");
3306
3307           if ($5.r0)
3308             tmp = unary (Expr_Op_Type_NEG, tmp);
3309
3310           if (isgot)
3311             {
3312               notethat ("LDSTidxI: dpregs = [ pregs + sym@got ]\n");
3313               $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1 : 0, tmp);
3314             }
3315           else if (in_range_p (tmp, 0, 63, 3))
3316             {
3317               notethat ("LDSTii: dpregs = [ pregs + uimm7m4 ]\n");
3318               $$ = LDSTII (&$4, &$1, tmp, 0, ispreg ? 3 : 0);
3319             }
3320           else if ($4.regno == REG_FP && in_range_p (tmp, -128, 0, 3))
3321             {
3322               notethat ("LDSTiiFP: dpregs = [ FP - uimm7m4 ]\n");
3323               tmp = unary (Expr_Op_Type_NEG, tmp);
3324               $$ = LDSTIIFP (tmp, &$1, 0);
3325             }
3326           else if (in_range_p (tmp, -131072, 131071, 3))
3327             {
3328               notethat ("LDSTidxI: dpregs = [ pregs + imm18m4 ]\n");
3329               $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1 : 0, tmp);
3330
3331             }
3332           else
3333             return yyerror ("Displacement out of range");
3334         }
3335
3336         | REG ASSIGN LBRACK REG post_op RBRACK
3337         {
3338           if (!IS_IREG ($4) && !IS_PREG ($4))
3339             return yyerror ("Ireg or Preg expected in address");
3340           else if (IS_IREG ($4) && !IS_DREG ($1))
3341             return yyerror ("Dreg expected in destination operand");
3342           else if (IS_PREG ($4) && !IS_DREG ($1) && !IS_PREG ($1)
3343                    && ($4.regno != REG_SP || !IS_ALLREG ($1) || $5.x0 != 0))
3344             return yyerror ("Dreg or Preg expected in destination operand");
3345
3346           if (IS_IREG ($4))
3347             {
3348               notethat ("dspLDST: dregs = [ iregs <post_op> ]\n");
3349               $$ = DSPLDST (&$4, 0, &$1, $5.x0, 0);
3350             }
3351           else if (IS_DREG ($1))
3352             {
3353               notethat ("LDST: dregs = [ pregs <post_op> ]\n");
3354               $$ = LDST (&$4, &$1, $5.x0, 0, 0, 0);
3355             }
3356           else if (IS_PREG ($1))
3357             {
3358               if (REG_SAME ($1, $4) && $5.x0 != 2)
3359                 return yyerror ("Pregs can't be same");
3360
3361               notethat ("LDST: pregs = [ pregs <post_op> ]\n");
3362               $$ = LDST (&$4, &$1, $5.x0, 0, 1, 0);
3363             }
3364           else
3365             {
3366               notethat ("PushPopReg: allregs = [ SP ++ ]\n");
3367               $$ = PUSHPOPREG (&$1, 0);
3368             }
3369         }
3370
3371
3372 /*  PushPopMultiple.  */
3373         | reg_with_predec ASSIGN LPAREN REG COLON expr COMMA REG COLON expr RPAREN
3374         {
3375           if ($1.regno != REG_SP)
3376             yyerror ("Stack Pointer expected");
3377           if ($4.regno == REG_R7
3378               && IN_RANGE ($6, 0, 7)
3379               && $8.regno == REG_P5
3380               && IN_RANGE ($10, 0, 5))
3381             {
3382               notethat ("PushPopMultiple: [ -- SP ] = (R7 : reglim , P5 : reglim )\n");
3383               $$ = PUSHPOPMULTIPLE (imm5 ($6), imm5 ($10), 1, 1, 1);
3384             }
3385           else
3386             return yyerror ("Bad register for PushPopMultiple");
3387         }
3388
3389         | reg_with_predec ASSIGN LPAREN REG COLON expr RPAREN
3390         {
3391           if ($1.regno != REG_SP)
3392             yyerror ("Stack Pointer expected");
3393
3394           if ($4.regno == REG_R7 && IN_RANGE ($6, 0, 7))
3395             {
3396               notethat ("PushPopMultiple: [ -- SP ] = (R7 : reglim )\n");
3397               $$ = PUSHPOPMULTIPLE (imm5 ($6), 0, 1, 0, 1);
3398             }
3399           else if ($4.regno == REG_P5 && IN_RANGE ($6, 0, 6))
3400             {
3401               notethat ("PushPopMultiple: [ -- SP ] = (P5 : reglim )\n");
3402               $$ = PUSHPOPMULTIPLE (0, imm5 ($6), 0, 1, 1);
3403             }
3404           else
3405             return yyerror ("Bad register for PushPopMultiple");
3406         }
3407
3408         | LPAREN REG COLON expr COMMA REG COLON expr RPAREN ASSIGN reg_with_postinc
3409         {
3410           if ($11.regno != REG_SP)
3411             yyerror ("Stack Pointer expected");
3412           if ($2.regno == REG_R7 && (IN_RANGE ($4, 0, 7))
3413               && $6.regno == REG_P5 && (IN_RANGE ($8, 0, 6)))
3414             {
3415               notethat ("PushPopMultiple: (R7 : reglim , P5 : reglim ) = [ SP ++ ]\n");
3416               $$ = PUSHPOPMULTIPLE (imm5 ($4), imm5 ($8), 1, 1, 0);
3417             }
3418           else
3419             return yyerror ("Bad register range for PushPopMultiple");
3420         }
3421
3422         | LPAREN REG COLON expr RPAREN ASSIGN reg_with_postinc
3423         {
3424           if ($7.regno != REG_SP)
3425             yyerror ("Stack Pointer expected");
3426
3427           if ($2.regno == REG_R7 && IN_RANGE ($4, 0, 7))
3428             {
3429               notethat ("PushPopMultiple: (R7 : reglim ) = [ SP ++ ]\n");
3430               $$ = PUSHPOPMULTIPLE (imm5 ($4), 0, 1, 0, 0);
3431             }
3432           else if ($2.regno == REG_P5 && IN_RANGE ($4, 0, 6))
3433             {
3434               notethat ("PushPopMultiple: (P5 : reglim ) = [ SP ++ ]\n");
3435               $$ = PUSHPOPMULTIPLE (0, imm5 ($4), 0, 1, 0);
3436             }
3437           else
3438             return yyerror ("Bad register range for PushPopMultiple");
3439         }
3440
3441         | reg_with_predec ASSIGN REG
3442         {
3443           if ($1.regno != REG_SP)
3444             yyerror ("Stack Pointer expected");
3445
3446           if (IS_ALLREG ($3))
3447             {
3448               notethat ("PushPopReg: [ -- SP ] = allregs\n");
3449               $$ = PUSHPOPREG (&$3, 1);
3450             }
3451           else
3452             return yyerror ("Bad register for PushPopReg");
3453         }
3454
3455 /* Linkage.  */
3456
3457         | LINK expr
3458         {
3459           if (IS_URANGE (16, $2, 0, 4))
3460             $$ = LINKAGE (0, uimm16s4 ($2));
3461           else
3462             return yyerror ("Bad constant for LINK");
3463         }
3464
3465         | UNLINK
3466         {
3467                 notethat ("linkage: UNLINK\n");
3468                 $$ = LINKAGE (1, 0);
3469         }
3470
3471
3472 /* LSETUP.  */
3473
3474         | LSETUP LPAREN expr COMMA expr RPAREN REG
3475         {
3476           if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5) && IS_CREG ($7))
3477             {
3478               notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters\n");
3479               $$ = LOOPSETUP ($3, &$7, 0, $5, 0);
3480             }
3481           else
3482             return yyerror ("Bad register or values for LSETUP");
3483
3484         }
3485         | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG
3486         {
3487           if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5)
3488               && IS_PREG ($9) && IS_CREG ($7))
3489             {
3490               notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters = pregs\n");
3491               $$ = LOOPSETUP ($3, &$7, 1, $5, &$9);
3492             }
3493           else
3494             return yyerror ("Bad register or values for LSETUP");
3495         }
3496
3497         | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG GREATER_GREATER expr
3498         {
3499           if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5)
3500               && IS_PREG ($9) && IS_CREG ($7)
3501               && EXPR_VALUE ($11) == 1)
3502             {
3503               notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters = pregs >> 1\n");
3504               $$ = LOOPSETUP ($3, &$7, 3, $5, &$9);
3505             }
3506           else
3507             return yyerror ("Bad register or values for LSETUP");
3508         }
3509
3510 /* LOOP.  */
3511         | LOOP expr REG
3512         {
3513           if (!IS_RELOC ($2))
3514             return yyerror ("Invalid expression in loop statement");
3515           if (!IS_CREG ($3))
3516             return yyerror ("Invalid loop counter register");
3517         $$ = bfin_gen_loop ($2, &$3, 0, 0);
3518         }
3519         | LOOP expr REG ASSIGN REG
3520         {
3521           if (IS_RELOC ($2) && IS_PREG ($5) && IS_CREG ($3))
3522             {
3523               notethat ("Loop: LOOP expr counters = pregs\n");
3524               $$ = bfin_gen_loop ($2, &$3, 1, &$5);
3525             }
3526           else
3527             return yyerror ("Bad register or values for LOOP");
3528         }
3529         | LOOP expr REG ASSIGN REG GREATER_GREATER expr
3530         {
3531           if (IS_RELOC ($2) && IS_PREG ($5) && IS_CREG ($3) && EXPR_VALUE ($7) == 1)
3532             {
3533               notethat ("Loop: LOOP expr counters = pregs >> 1\n");
3534               $$ = bfin_gen_loop ($2, &$3, 3, &$5);
3535             }
3536           else
3537             return yyerror ("Bad register or values for LOOP");
3538         }
3539
3540 /* LOOP_BEGIN.  */
3541         | LOOP_BEGIN expr
3542         {
3543           if (!IS_RELOC ($2))
3544             return yyerror ("Invalid expression in LOOP_BEGIN statement");
3545
3546           bfin_loop_beginend ($2, 1);
3547           $$ = 0;
3548         }
3549
3550 /* LOOP_END.  */
3551         | LOOP_END expr
3552         {
3553           if (!IS_RELOC ($2))
3554             return yyerror ("Invalid expression in LOOP_END statement");
3555
3556           bfin_loop_beginend ($2, 0);
3557           $$ = 0;
3558         }
3559
3560 /* pseudoDEBUG.  */
3561
3562         | ABORT
3563         {
3564           notethat ("psedoDEBUG: ABORT\n");
3565           $$ = bfin_gen_pseudodbg (3, 3, 0);
3566         }
3567
3568         | DBG
3569         {
3570           notethat ("pseudoDEBUG: DBG\n");
3571           $$ = bfin_gen_pseudodbg (3, 7, 0);
3572         }
3573         | DBG REG_A
3574         {
3575           notethat ("pseudoDEBUG: DBG REG_A\n");
3576           $$ = bfin_gen_pseudodbg (3, IS_A1 ($2), 0);
3577         }
3578         | DBG REG
3579         {
3580           notethat ("pseudoDEBUG: DBG allregs\n");
3581           $$ = bfin_gen_pseudodbg (0, $2.regno & CODE_MASK, ($2.regno & CLASS_MASK) >> 4);
3582         }
3583
3584         | DBGCMPLX LPAREN REG RPAREN
3585         {
3586           if (!IS_DREG ($3))
3587             return yyerror ("Dregs expected");
3588           notethat ("pseudoDEBUG: DBGCMPLX (dregs )\n");
3589           $$ = bfin_gen_pseudodbg (3, 6, ($3.regno & CODE_MASK) >> 4);
3590         }
3591
3592         | DBGHALT
3593         {
3594           notethat ("psedoDEBUG: DBGHALT\n");
3595           $$ = bfin_gen_pseudodbg (3, 5, 0);
3596         }
3597
3598         | HLT
3599         {
3600           notethat ("psedoDEBUG: HLT\n");
3601           $$ = bfin_gen_pseudodbg (3, 4, 0);
3602         }
3603
3604         | DBGA LPAREN HALF_REG COMMA expr RPAREN
3605         {
3606           notethat ("pseudodbg_assert: DBGA (regs_lo/hi , uimm16 )\n");
3607           $$ = bfin_gen_pseudodbg_assert (IS_H ($3), &$3, uimm16 ($5));
3608         }
3609
3610         | DBGAH LPAREN REG COMMA expr RPAREN
3611         {
3612           notethat ("pseudodbg_assert: DBGAH (regs , uimm16 )\n");
3613           $$ = bfin_gen_pseudodbg_assert (3, &$3, uimm16 ($5));
3614         }
3615
3616         | DBGAL LPAREN REG COMMA expr RPAREN
3617         {
3618           notethat ("psedodbg_assert: DBGAL (regs , uimm16 )\n");
3619           $$ = bfin_gen_pseudodbg_assert (2, &$3, uimm16 ($5));
3620         }
3621
3622         | OUTC expr
3623         {
3624           if (!IS_UIMM ($2, 8))
3625             return yyerror ("Constant out of range");
3626           notethat ("psedodbg_assert: OUTC uimm8\n");
3627           $$ = bfin_gen_pseudochr (uimm8 ($2));
3628         }
3629
3630         | OUTC REG
3631         {
3632           if (!IS_DREG ($2))
3633             return yyerror ("Dregs expected");
3634           notethat ("psedodbg_assert: OUTC dreg\n");
3635           $$ = bfin_gen_pseudodbg (2, $2.regno & CODE_MASK, 0);
3636         }
3637
3638 ;
3639
3640 /*  AUX RULES.  */
3641
3642 /*  Register rules.  */
3643
3644 REG_A:  REG_A_DOUBLE_ZERO
3645         {
3646         $$ = $1;
3647         }
3648         | REG_A_DOUBLE_ONE
3649         {
3650         $$ = $1;
3651         }
3652         ;
3653
3654
3655 /*  Modifiers. */
3656
3657 opt_mode:
3658         {
3659         $$.MM = 0;
3660         $$.mod = 0;
3661         }
3662         | LPAREN M COMMA MMOD RPAREN
3663         {
3664         $$.MM = 1;
3665         $$.mod = $4;
3666         }
3667         | LPAREN MMOD COMMA M RPAREN
3668         {
3669         $$.MM = 1;
3670         $$.mod = $2;
3671         }
3672         | LPAREN MMOD RPAREN
3673         {
3674         $$.MM = 0;
3675         $$.mod = $2;
3676         }
3677         | LPAREN M RPAREN
3678         {
3679         $$.MM = 1;
3680         $$.mod = 0;
3681         }
3682         ;
3683
3684 asr_asl: LPAREN ASL RPAREN
3685         {
3686         $$.r0 = 1;
3687         }
3688         | LPAREN ASR RPAREN
3689         {
3690         $$.r0 = 0;
3691         }
3692         ;
3693
3694 sco:
3695         {
3696         $$.s0 = 0;
3697         $$.x0 = 0;
3698         }
3699         | S
3700         {
3701         $$.s0 = 1;
3702         $$.x0 = 0;
3703         }
3704         | CO
3705         {
3706         $$.s0 = 0;
3707         $$.x0 = 1;
3708         }
3709         | SCO
3710         {
3711         $$.s0 = 1;
3712         $$.x0 = 1;
3713         }
3714         ;
3715
3716 asr_asl_0:
3717         ASL
3718         {
3719         $$.r0 = 1;
3720         }
3721         | ASR
3722         {
3723         $$.r0 = 0;
3724         }
3725         ;
3726
3727 amod0:
3728         {
3729         $$.s0 = 0;
3730         $$.x0 = 0;
3731         }
3732         | LPAREN sco RPAREN
3733         {
3734         $$.s0 = $2.s0;
3735         $$.x0 = $2.x0;
3736         }
3737         ;
3738
3739 amod1:
3740         {
3741         $$.s0 = 0;
3742         $$.x0 = 0;
3743         $$.aop = 0;
3744         }
3745         | LPAREN NS RPAREN
3746         {
3747         $$.s0 = 0;
3748         $$.x0 = 0;
3749         $$.aop = 1;
3750         }
3751         | LPAREN S RPAREN
3752         {
3753         $$.s0 = 1;
3754         $$.x0 = 0;
3755         $$.aop = 1;
3756         }
3757         ;
3758
3759 amod2:
3760         {
3761         $$.r0 = 0;
3762         $$.s0 = 0;
3763         $$.x0 = 0;
3764         }
3765         | LPAREN asr_asl_0 RPAREN
3766         {
3767         $$.r0 = 2 + $2.r0;
3768         $$.s0 = 0;
3769         $$.x0 = 0;
3770         }
3771         | LPAREN sco RPAREN
3772         {
3773         $$.r0 = 0;
3774         $$.s0 = $2.s0;
3775         $$.x0 = $2.x0;
3776         }
3777         | LPAREN asr_asl_0 COMMA sco RPAREN
3778         {
3779         $$.r0 = 2 + $2.r0;
3780         $$.s0 = $4.s0;
3781         $$.x0 = $4.x0;
3782         }
3783         | LPAREN sco COMMA asr_asl_0 RPAREN
3784         {
3785         $$.r0 = 2 + $4.r0;
3786         $$.s0 = $2.s0;
3787         $$.x0 = $2.x0;
3788         }
3789         ;
3790
3791 xpmod:
3792         {
3793         $$.r0 = 0;
3794         }
3795         | LPAREN Z RPAREN
3796         {
3797         $$.r0 = 0;
3798         }
3799         | LPAREN X RPAREN
3800         {
3801         $$.r0 = 1;
3802         }
3803         ;
3804
3805 xpmod1:
3806         {
3807         $$.r0 = 0;
3808         }
3809         | LPAREN X RPAREN
3810         {
3811         $$.r0 = 0;
3812         }
3813         | LPAREN Z RPAREN
3814         {
3815         $$.r0 = 1;
3816         }
3817         ;
3818
3819 vsmod:
3820         {
3821         $$.r0 = 0;
3822         $$.s0 = 0;
3823         $$.aop = 0;
3824         }
3825         | LPAREN NS RPAREN
3826         {
3827         $$.r0 = 0;
3828         $$.s0 = 0;
3829         $$.aop = 3;
3830         }
3831         | LPAREN S RPAREN
3832         {
3833         $$.r0 = 0;
3834         $$.s0 = 1;
3835         $$.aop = 3;
3836         }
3837         | LPAREN V RPAREN
3838         {
3839         $$.r0 = 1;
3840         $$.s0 = 0;
3841         $$.aop = 3;
3842         }
3843         | LPAREN V COMMA S RPAREN
3844         {
3845         $$.r0 = 1;
3846         $$.s0 = 1;
3847         }
3848         | LPAREN S COMMA V RPAREN
3849         {
3850         $$.r0 = 1;
3851         $$.s0 = 1;
3852         }
3853         ;
3854
3855 vmod:
3856         {
3857         $$.r0 = 0;
3858         }
3859         | LPAREN V RPAREN
3860         {
3861         $$.r0 = 1;
3862         }
3863         ;
3864
3865 smod:
3866         {
3867         $$.s0 = 0;
3868         }
3869         | LPAREN S RPAREN
3870         {
3871         $$.s0 = 1;
3872         }
3873         ;
3874
3875 searchmod:
3876           GE
3877         {
3878         $$.r0 = 1;
3879         }
3880         | GT
3881         {
3882         $$.r0 = 0;
3883         }
3884         | LE
3885         {
3886         $$.r0 = 3;
3887         }
3888         | LT
3889         {
3890         $$.r0 = 2;
3891         }
3892         ;
3893
3894 aligndir:
3895         {
3896         $$.r0 = 0;
3897         }
3898         | LPAREN R RPAREN
3899         {
3900         $$.r0 = 1;
3901         }
3902         ;
3903
3904 byteop_mod:
3905         LPAREN R RPAREN
3906         {
3907         $$.r0 = 0;
3908         $$.s0 = 1;
3909         }
3910         | LPAREN MMOD RPAREN
3911         {
3912         if ($2 != M_T)
3913           return yyerror ("Bad modifier");
3914         $$.r0 = 1;
3915         $$.s0 = 0;
3916         }
3917         | LPAREN MMOD COMMA R RPAREN
3918         {
3919         if ($2 != M_T)
3920           return yyerror ("Bad modifier");
3921         $$.r0 = 1;
3922         $$.s0 = 1;
3923         }
3924         | LPAREN R COMMA MMOD RPAREN
3925         {
3926         if ($4 != M_T)
3927           return yyerror ("Bad modifier");
3928         $$.r0 = 1;
3929         $$.s0 = 1;
3930         }
3931         ;
3932
3933
3934
3935 c_align:
3936         ALIGN8
3937         {
3938         $$.r0 = 0;
3939         }
3940         | ALIGN16
3941         {
3942         $$.r0 = 1;
3943         }
3944         | ALIGN24
3945         {
3946         $$.r0 = 2;
3947         }
3948         ;
3949
3950 w32_or_nothing:
3951         {
3952         $$.r0 = 0;
3953         }
3954         | LPAREN MMOD RPAREN
3955         {
3956           if ($2 == M_W32)
3957             $$.r0 = 1;
3958           else
3959             return yyerror ("Only (W32) allowed");
3960         }
3961         ;
3962
3963 iu_or_nothing:
3964         {
3965         $$.r0 = 1;
3966         }
3967         | LPAREN MMOD RPAREN
3968         {
3969           if ($2 == M_IU)
3970             $$.r0 = 3;
3971           else
3972             return yyerror ("(IU) expected");
3973         }
3974         ;
3975
3976 reg_with_predec: LBRACK _MINUS_MINUS REG RBRACK
3977         {
3978         $$ = $3;
3979         }
3980         ;
3981
3982 reg_with_postinc: LBRACK REG _PLUS_PLUS RBRACK
3983         {
3984         $$ = $2;
3985         }
3986         ;
3987
3988 /* Operators.  */
3989
3990 min_max:
3991         MIN
3992         {
3993         $$.r0 = 1;
3994         }
3995         | MAX
3996         {
3997         $$.r0 = 0;
3998         }
3999         ;
4000
4001 op_bar_op:
4002         _PLUS_BAR_PLUS
4003         {
4004         $$.r0 = 0;
4005         }
4006         | _PLUS_BAR_MINUS
4007         {
4008         $$.r0 = 1;
4009         }
4010         | _MINUS_BAR_PLUS
4011         {
4012         $$.r0 = 2;
4013         }
4014         | _MINUS_BAR_MINUS
4015         {
4016         $$.r0 = 3;
4017         }
4018         ;
4019
4020 plus_minus:
4021         PLUS
4022         {
4023         $$.r0 = 0;
4024         }
4025         | MINUS
4026         {
4027         $$.r0 = 1;
4028         }
4029         ;
4030
4031 rnd_op:
4032         LPAREN RNDH RPAREN
4033         {
4034           $$.r0 = 1;    /* HL.  */
4035           $$.s0 = 0;    /* s.  */
4036           $$.x0 = 0;    /* x.  */
4037           $$.aop = 0;   /* aop.  */
4038         }
4039
4040         | LPAREN TH RPAREN
4041         {
4042           $$.r0 = 1;    /* HL.  */
4043           $$.s0 = 0;    /* s.  */
4044           $$.x0 = 0;    /* x.  */
4045           $$.aop = 1;   /* aop.  */
4046         }
4047
4048         | LPAREN RNDL RPAREN
4049         {
4050           $$.r0 = 0;    /* HL.  */
4051           $$.s0 = 0;    /* s.  */
4052           $$.x0 = 0;    /* x.  */
4053           $$.aop = 0;   /* aop.  */
4054         }
4055
4056         | LPAREN TL RPAREN
4057         {
4058           $$.r0 = 0;    /* HL.  */
4059           $$.s0 = 0;    /* s.  */
4060           $$.x0 = 0;    /* x.  */
4061           $$.aop = 1;
4062         }
4063
4064         | LPAREN RNDH COMMA R RPAREN
4065         {
4066           $$.r0 = 1;    /* HL.  */
4067           $$.s0 = 1;    /* s.  */
4068           $$.x0 = 0;    /* x.  */
4069           $$.aop = 0;   /* aop.  */
4070         }
4071         | LPAREN TH COMMA R RPAREN
4072         {
4073           $$.r0 = 1;    /* HL.  */
4074           $$.s0 = 1;    /* s.  */
4075           $$.x0 = 0;    /* x.  */
4076           $$.aop = 1;   /* aop.  */
4077         }
4078         | LPAREN RNDL COMMA R RPAREN
4079         {
4080           $$.r0 = 0;    /* HL.  */
4081           $$.s0 = 1;    /* s.  */
4082           $$.x0 = 0;    /* x.  */
4083           $$.aop = 0;   /* aop.  */
4084         }
4085
4086         | LPAREN TL COMMA R RPAREN
4087         {
4088           $$.r0 = 0;    /* HL.  */
4089           $$.s0 = 1;    /* s.  */
4090           $$.x0 = 0;    /* x.  */
4091           $$.aop = 1;   /* aop.  */
4092         }
4093         ;
4094
4095 b3_op:
4096         LPAREN LO RPAREN
4097         {
4098           $$.s0 = 0;    /* s.  */
4099           $$.x0 = 0;    /* HL.  */
4100         }
4101         | LPAREN HI RPAREN
4102         {
4103           $$.s0 = 0;    /* s.  */
4104           $$.x0 = 1;    /* HL.  */
4105         }
4106         | LPAREN LO COMMA R RPAREN
4107         {
4108           $$.s0 = 1;    /* s.  */
4109           $$.x0 = 0;    /* HL.  */
4110         }
4111         | LPAREN HI COMMA R RPAREN
4112         {
4113           $$.s0 = 1;    /* s.  */
4114           $$.x0 = 1;    /* HL.  */
4115         }
4116         ;
4117
4118 post_op:
4119         {
4120         $$.x0 = 2;
4121         }
4122         | _PLUS_PLUS
4123         {
4124         $$.x0 = 0;
4125         }
4126         | _MINUS_MINUS
4127         {
4128         $$.x0 = 1;
4129         }
4130         ;
4131
4132 /* Assignments, Macfuncs.  */
4133
4134 a_assign:
4135         REG_A ASSIGN
4136         {
4137         $$ = $1;
4138         }
4139         ;
4140
4141 a_minusassign:
4142         REG_A _MINUS_ASSIGN
4143         {
4144         $$ = $1;
4145         }
4146         ;
4147
4148 a_plusassign:
4149         REG_A _PLUS_ASSIGN
4150         {
4151         $$ = $1;
4152         }
4153         ;
4154
4155 assign_macfunc:
4156         REG ASSIGN REG_A
4157         {
4158           if (IS_A1 ($3) && IS_EVEN ($1))
4159             return yyerror ("Cannot move A1 to even register");
4160           else if (!IS_A1 ($3) && !IS_EVEN ($1))
4161             return yyerror ("Cannot move A0 to odd register");
4162
4163           $$.w = 1;
4164           $$.P = 1;
4165           $$.n = IS_A1 ($3);
4166           $$.op = 3;
4167           $$.dst = $1;
4168           $$.s0.regno = 0;
4169           $$.s1.regno = 0;
4170         }
4171         | a_macfunc
4172         {
4173           $$ = $1;
4174           $$.w = 0; $$.P = 0;
4175           $$.dst.regno = 0;
4176         }
4177         | REG ASSIGN LPAREN a_macfunc RPAREN
4178         {
4179           if ($4.n && IS_EVEN ($1))
4180             return yyerror ("Cannot move A1 to even register");
4181           else if (!$4.n && !IS_EVEN ($1))
4182             return yyerror ("Cannot move A0 to odd register");
4183
4184           $$ = $4;
4185           $$.w = 1;
4186           $$.P = 1;
4187           $$.dst = $1;
4188         }
4189
4190         | HALF_REG ASSIGN LPAREN a_macfunc RPAREN
4191         {
4192           if ($4.n && !IS_H ($1))
4193             return yyerror ("Cannot move A1 to low half of register");
4194           else if (!$4.n && IS_H ($1))
4195             return yyerror ("Cannot move A0 to high half of register");
4196
4197           $$ = $4;
4198           $$.w = 1;
4199           $$.P = 0;
4200           $$.dst = $1;
4201         }
4202
4203         | HALF_REG ASSIGN REG_A
4204         {
4205           if (IS_A1 ($3) && !IS_H ($1))
4206             return yyerror ("Cannot move A1 to low half of register");
4207           else if (!IS_A1 ($3) && IS_H ($1))
4208             return yyerror ("Cannot move A0 to high half of register");
4209
4210           $$.w = 1;
4211           $$.P = 0;
4212           $$.n = IS_A1 ($3);
4213           $$.op = 3;
4214           $$.dst = $1;
4215           $$.s0.regno = 0;
4216           $$.s1.regno = 0;
4217         }
4218         ;
4219
4220 a_macfunc:
4221         a_assign multiply_halfregs
4222         {
4223           $$.n = IS_A1 ($1);
4224           $$.op = 0;
4225           $$.s0 = $2.s0;
4226           $$.s1 = $2.s1;
4227         }
4228         | a_plusassign multiply_halfregs
4229         {
4230           $$.n = IS_A1 ($1);
4231           $$.op = 1;
4232           $$.s0 = $2.s0;
4233           $$.s1 = $2.s1;
4234         }
4235         | a_minusassign multiply_halfregs
4236         {
4237           $$.n = IS_A1 ($1);
4238           $$.op = 2;
4239           $$.s0 = $2.s0;
4240           $$.s1 = $2.s1;
4241         }
4242         ;
4243
4244 multiply_halfregs:
4245         HALF_REG STAR HALF_REG
4246         {
4247           if (IS_DREG ($1) && IS_DREG ($3))
4248             {
4249               $$.s0 = $1;
4250               $$.s1 = $3;
4251             }
4252           else
4253             return yyerror ("Dregs expected");
4254         }
4255         ;
4256
4257 cc_op:
4258         ASSIGN
4259         {
4260         $$.r0 = 0;
4261         }
4262         | _BAR_ASSIGN
4263         {
4264         $$.r0 = 1;
4265         }
4266         | _AMPERSAND_ASSIGN
4267         {
4268         $$.r0 = 2;
4269         }
4270         | _CARET_ASSIGN
4271         {
4272         $$.r0 = 3;
4273         }
4274         ;
4275
4276 ccstat:
4277         CCREG cc_op STATUS_REG
4278         {
4279           $$.r0 = $3.regno;
4280           $$.x0 = $2.r0;
4281           $$.s0 = 0;
4282         }
4283         | CCREG cc_op V
4284         {
4285           $$.r0 = 0x18;
4286           $$.x0 = $2.r0;
4287           $$.s0 = 0;
4288         }
4289         | STATUS_REG cc_op CCREG
4290         {
4291           $$.r0 = $1.regno;
4292           $$.x0 = $2.r0;
4293           $$.s0 = 1;
4294         }
4295         | V cc_op CCREG
4296         {
4297           $$.r0 = 0x18;
4298           $$.x0 = $2.r0;
4299           $$.s0 = 1;
4300         }
4301         ;
4302
4303 /* Expressions and Symbols.  */
4304
4305 symbol: SYMBOL
4306         {
4307         Expr_Node_Value val;
4308         val.s_value = S_GET_NAME($1);
4309         $$ = Expr_Node_Create (Expr_Node_Reloc, val, NULL, NULL);
4310         }
4311         ;
4312
4313 any_gotrel:
4314         GOT
4315         { $$ = BFD_RELOC_BFIN_GOT; }
4316         | GOT17M4
4317         { $$ = BFD_RELOC_BFIN_GOT17M4; }
4318         | FUNCDESC_GOT17M4
4319         { $$ = BFD_RELOC_BFIN_FUNCDESC_GOT17M4; }
4320         ;
4321
4322 got:    symbol AT any_gotrel
4323         {
4324         Expr_Node_Value val;
4325         val.i_value = $3;
4326         $$ = Expr_Node_Create (Expr_Node_GOT_Reloc, val, $1, NULL);
4327         }
4328         ;
4329
4330 got_or_expr:    got
4331         {
4332         $$ = $1;
4333         }
4334         | expr
4335         {
4336         $$ = $1;
4337         }
4338         ;
4339
4340 pltpc :
4341         symbol AT PLTPC
4342         {
4343         $$ = $1;
4344         }
4345         ;
4346
4347 eterm: NUMBER
4348         {
4349         Expr_Node_Value val;
4350         val.i_value = $1;
4351         $$ = Expr_Node_Create (Expr_Node_Constant, val, NULL, NULL);
4352         }
4353         | symbol
4354         {
4355         $$ = $1;
4356         }
4357         | LPAREN expr_1 RPAREN
4358         {
4359         $$ = $2;
4360         }
4361         | TILDA expr_1
4362         {
4363         $$ = unary (Expr_Op_Type_COMP, $2);
4364         }
4365         | MINUS expr_1 %prec TILDA
4366         {
4367         $$ = unary (Expr_Op_Type_NEG, $2);
4368         }
4369         ;
4370
4371 expr: expr_1
4372         {
4373         $$ = $1;
4374         }
4375         ;
4376
4377 expr_1: expr_1 STAR expr_1
4378         {
4379         $$ = binary (Expr_Op_Type_Mult, $1, $3);
4380         }
4381         | expr_1 SLASH expr_1
4382         {
4383         $$ = binary (Expr_Op_Type_Div, $1, $3);
4384         }
4385         | expr_1 PERCENT expr_1
4386         {
4387         $$ = binary (Expr_Op_Type_Mod, $1, $3);
4388         }
4389         | expr_1 PLUS expr_1
4390         {
4391         $$ = binary (Expr_Op_Type_Add, $1, $3);
4392         }
4393         | expr_1 MINUS expr_1
4394         {
4395         $$ = binary (Expr_Op_Type_Sub, $1, $3);
4396         }
4397         | expr_1 LESS_LESS expr_1
4398         {
4399         $$ = binary (Expr_Op_Type_Lshift, $1, $3);
4400         }
4401         | expr_1 GREATER_GREATER expr_1
4402         {
4403         $$ = binary (Expr_Op_Type_Rshift, $1, $3);
4404         }
4405         | expr_1 AMPERSAND expr_1
4406         {
4407         $$ = binary (Expr_Op_Type_BAND, $1, $3);
4408         }
4409         | expr_1 CARET expr_1
4410         {
4411         $$ = binary (Expr_Op_Type_LOR, $1, $3);
4412         }
4413         | expr_1 BAR expr_1
4414         {
4415         $$ = binary (Expr_Op_Type_BOR, $1, $3);
4416         }
4417         | eterm
4418         {
4419         $$ = $1;
4420         }
4421         ;
4422
4423
4424 %%
4425
4426 EXPR_T
4427 mkexpr (int x, SYMBOL_T s)
4428 {
4429   EXPR_T e = (EXPR_T) ALLOCATE (sizeof (struct expression_cell));
4430   e->value = x;
4431   EXPR_SYMBOL(e) = s;
4432   return e;
4433 }
4434
4435 static int
4436 value_match (Expr_Node *exp, int sz, int sign, int mul, int issigned)
4437 {
4438   int umax = (1 << sz) - 1;
4439   int min = -1 << (sz - 1);
4440   int max = (1 << (sz - 1)) - 1;
4441
4442   int v = (EXPR_VALUE (exp)) & 0xffffffff;
4443
4444   if ((v % mul) != 0)
4445     {
4446       error ("%s:%d: Value Error -- Must align to %d\n", __FILE__, __LINE__, mul);
4447       return 0;
4448     }
4449
4450   v /= mul;
4451
4452   if (sign)
4453     v = -v;
4454
4455   if (issigned)
4456     {
4457       if (v >= min && v <= max) return 1;
4458
4459 #ifdef DEBUG
4460       fprintf(stderr, "signed value %lx out of range\n", v * mul);
4461 #endif
4462       return 0;
4463     }
4464   if (v <= umax && v >= 0)
4465     return 1;
4466 #ifdef DEBUG
4467   fprintf(stderr, "unsigned value %lx out of range\n", v * mul);
4468 #endif
4469   return 0;
4470 }
4471
4472 /* Return the expression structure that allows symbol operations.
4473    If the left and right children are constants, do the operation.  */
4474 static Expr_Node *
4475 binary (Expr_Op_Type op, Expr_Node *x, Expr_Node *y)
4476 {
4477   Expr_Node_Value val;
4478
4479   if (x->type == Expr_Node_Constant && y->type == Expr_Node_Constant)
4480     {
4481       switch (op)
4482         {
4483         case Expr_Op_Type_Add:
4484           x->value.i_value += y->value.i_value;
4485           break;
4486         case Expr_Op_Type_Sub:
4487           x->value.i_value -= y->value.i_value;
4488           break;
4489         case Expr_Op_Type_Mult:
4490           x->value.i_value *= y->value.i_value;
4491           break;
4492         case Expr_Op_Type_Div:
4493           if (y->value.i_value == 0)
4494             error ("Illegal Expression:  Division by zero.");
4495           else
4496             x->value.i_value /= y->value.i_value;
4497           break;
4498         case Expr_Op_Type_Mod:
4499           x->value.i_value %= y->value.i_value;
4500           break;
4501         case Expr_Op_Type_Lshift:
4502           x->value.i_value <<= y->value.i_value;
4503           break;
4504         case Expr_Op_Type_Rshift:
4505           x->value.i_value >>= y->value.i_value;
4506           break;
4507         case Expr_Op_Type_BAND:
4508           x->value.i_value &= y->value.i_value;
4509           break;
4510         case Expr_Op_Type_BOR:
4511           x->value.i_value |= y->value.i_value;
4512           break;
4513         case Expr_Op_Type_BXOR:
4514           x->value.i_value ^= y->value.i_value;
4515           break;
4516         case Expr_Op_Type_LAND:
4517           x->value.i_value = x->value.i_value && y->value.i_value;
4518           break;
4519         case Expr_Op_Type_LOR:
4520           x->value.i_value = x->value.i_value || y->value.i_value;
4521           break;
4522
4523         default:
4524           error ("%s:%d: Internal assembler error\n", __FILE__, __LINE__);
4525         }
4526       return x;
4527     }
4528   /* Canonicalize order to EXPR OP CONSTANT.  */
4529   if (x->type == Expr_Node_Constant)
4530     {
4531       Expr_Node *t = x;
4532       x = y;
4533       y = t;
4534     }
4535   /* Canonicalize subtraction of const to addition of negated const.  */
4536   if (op == Expr_Op_Type_Sub && y->type == Expr_Node_Constant)
4537     {
4538       op = Expr_Op_Type_Add;
4539       y->value.i_value = -y->value.i_value;
4540     }
4541   if (y->type == Expr_Node_Constant && x->type == Expr_Node_Binop
4542       && x->Right_Child->type == Expr_Node_Constant)
4543     {
4544       if (op == x->value.op_value && x->value.op_value == Expr_Op_Type_Add)
4545         {
4546           x->Right_Child->value.i_value += y->value.i_value;
4547           return x;
4548         }
4549     }
4550
4551   /* Create a new expression structure.  */
4552   val.op_value = op;
4553   return Expr_Node_Create (Expr_Node_Binop, val, x, y);
4554 }
4555
4556 static Expr_Node *
4557 unary (Expr_Op_Type op, Expr_Node *x)
4558 {
4559   if (x->type == Expr_Node_Constant)
4560     {
4561       switch (op)
4562         {
4563         case Expr_Op_Type_NEG:
4564           x->value.i_value = -x->value.i_value;
4565           break;
4566         case Expr_Op_Type_COMP:
4567           x->value.i_value = ~x->value.i_value;
4568           break;
4569         default:
4570           error ("%s:%d: Internal assembler error\n", __FILE__, __LINE__);
4571         }
4572       return x;
4573     }
4574   else
4575     {
4576       /* Create a new expression structure.  */
4577       Expr_Node_Value val;
4578       val.op_value = op;
4579       return Expr_Node_Create (Expr_Node_Unop, val, x, NULL);
4580     }
4581 }
4582
4583 int debug_codeselection = 0;
4584 static void
4585 notethat (char *format, ...)
4586 {
4587   va_list ap;
4588   va_start (ap, format);
4589   if (debug_codeselection)
4590     {
4591       vfprintf (errorf, format, ap);
4592     }
4593   va_end (ap);
4594 }
4595
4596 #ifdef TEST
4597 main (int argc, char **argv)
4598 {
4599   yyparse();
4600 }
4601 #endif
4602