OSDN Git Service

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