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