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