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