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