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