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