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