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