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