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