1 /* rx-parse.y Renesas RX parser
3 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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.
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
24 #include "safe-ctype.h"
27 static int rx_lex (void);
39 static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
41 /* Ok, here are the rules for using these macros...
43 B*() is used to specify the base opcode bytes. Fields to be filled
44 in later, leave zero. Call this first.
46 F() and FE() are used to fill in fields within the base opcode bytes. You MUST
47 call B*() before any F() or FE().
49 [UN]*O*(), PC*() appends operands to the end of the opcode. You
50 must call P() and B*() before any of these, so that the fixups
51 have the right byte location.
52 O = signed, UO = unsigned, NO = negated, PC = pcrel
54 IMM() adds an immediate and fills in the field for it.
55 NIMM() same, but negates the immediate.
56 NBIMM() same, but negates the immediate, for sbb.
57 DSP() adds a displacement, and fills in the field for it.
59 Note that order is significant for the O, IMM, and DSP macros, as
60 they append their data to the operand buffer in the order that you
63 Use "disp" for displacements whenever possible; this handles the
66 #define B1(b1) rx_base1 (b1)
67 #define B2(b1, b2) rx_base2 (b1, b2)
68 #define B3(b1, b2, b3) rx_base3 (b1, b2, b3)
69 #define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4)
71 /* POS is bits from the MSB of the first byte to the LSB of the last byte. */
72 #define F(val,pos,sz) rx_field (val, pos, sz)
73 #define FE(exp,pos,sz) rx_field (exp_val (exp), pos, sz);
75 #define O1(v) rx_op (v, 1, RXREL_SIGNED)
76 #define O2(v) rx_op (v, 2, RXREL_SIGNED)
77 #define O3(v) rx_op (v, 3, RXREL_SIGNED)
78 #define O4(v) rx_op (v, 4, RXREL_SIGNED)
80 #define UO1(v) rx_op (v, 1, RXREL_UNSIGNED)
81 #define UO2(v) rx_op (v, 2, RXREL_UNSIGNED)
82 #define UO3(v) rx_op (v, 3, RXREL_UNSIGNED)
83 #define UO4(v) rx_op (v, 4, RXREL_UNSIGNED)
85 #define NO1(v) rx_op (v, 1, RXREL_NEGATIVE)
86 #define NO2(v) rx_op (v, 2, RXREL_NEGATIVE)
87 #define NO3(v) rx_op (v, 3, RXREL_NEGATIVE)
88 #define NO4(v) rx_op (v, 4, RXREL_NEGATIVE)
90 #define PC1(v) rx_op (v, 1, RXREL_PCREL)
91 #define PC2(v) rx_op (v, 2, RXREL_PCREL)
92 #define PC3(v) rx_op (v, 3, RXREL_PCREL)
94 #define IMM_(v,pos,size) F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \
95 if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
96 #define IMM(v,pos) IMM_ (v, pos, 32)
97 #define IMMW(v,pos) IMM_ (v, pos, 16)
98 #define IMMB(v,pos) IMM_ (v, pos, 8)
99 #define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2)
100 #define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2)
101 #define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
102 else rx_linkrelax_dsp (pos); \
103 F (displacement (v, msz), pos, 2)
105 #define id24(a,b2,b3) B3 (0xfb+a, b2, b3)
107 static int rx_intop (expressionS, int, int);
108 static int rx_uintop (expressionS, int);
109 static int rx_disp3op (expressionS);
110 static int rx_disp5op (expressionS *, int);
111 static int rx_disp5op0 (expressionS *, int);
112 static int exp_val (expressionS exp);
113 static expressionS zero_expr (void);
114 static int immediate (expressionS, int, int, int);
115 static int displacement (expressionS, int);
116 static void rtsd_immediate (expressionS);
118 static int need_flag = 0;
119 static int rx_in_brackets = 0;
120 static int rx_last_token = 0;
121 static char * rx_init_start;
122 static char * rx_last_exp_start = 0;
127 #define YYERROR_VERBOSE 1
138 %type <regno> REG FLAG CREG BCND BMCND SCCND
139 %type <regno> flag bwl bw memex
140 %type <exp> EXPR disp
144 %token EXPR UNKNOWN_OPCODE IS_OPCODE
146 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
148 %token ABS ADC ADD AND_
149 %token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST
152 %token EDIV EDIVU EMUL EMULU
153 %token FADD FCMP FDIV FMUL FREIT FSUB FTOI
156 %token MACHI MACLO MAX MIN MOV MOVU MUL MULHI MULLO MULU MVFACHI MVFACMI MVFACLO
157 %token MVFC MVTACHI MVTACLO MVTC MVTIPL
160 %token POP POPC POPM PUSH PUSHA PUSHC PUSHM
161 %token RACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND RTE RTFI RTS RTSD
162 %token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
163 %token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
169 /* ====================================================================== */
174 { as_bad (_("Unknown opcode: %s"), rx_init_start); }
176 /* ---------------------------------------------------------------------- */
190 /* ---------------------------------------------------------------------- */
193 { if (rx_disp3op ($2))
194 { B1 (0x08); rx_disp3 ($2, 5); }
195 else if (rx_intop ($2, 8, 8))
196 { B1 (0x2e); PC1 ($2); }
197 else if (rx_intop ($2, 16, 16))
198 { B1 (0x38); PC2 ($2); }
199 else if (rx_intop ($2, 24, 24))
200 { B1 (0x04); PC3 ($2); }
202 { rx_relax (RX_RELAX_BRANCH, 0);
203 rx_linkrelax_branch ();
204 /* We'll convert this to a longer one later if needed. */
205 B1 (0x08); rx_disp3 ($2, 5); } }
208 { B1 (0x04); PC3 ($3); }
211 { B1 (0x08); rx_disp3 ($3, 5); }
213 /* ---------------------------------------------------------------------- */
216 { if (rx_intop ($2, 16, 16))
217 { B1 (0x39); PC2 ($2); }
218 else if (rx_intop ($2, 24, 24))
219 { B1 (0x05); PC3 ($2); }
221 { rx_relax (RX_RELAX_BRANCH, 0);
222 rx_linkrelax_branch ();
223 B1 (0x39); PC2 ($2); } }
225 { B1 (0x05), PC3 ($3); }
227 /* ---------------------------------------------------------------------- */
230 { if ($1 == COND_EQ || $1 == COND_NE)
231 { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); }
233 as_bad (_("Only BEQ and BNE may have .S")); }
235 /* ---------------------------------------------------------------------- */
238 { B1 (0x20); F ($1, 4, 4); PC1 ($3); }
241 { B1 (0x2e), PC1 ($3); }
243 /* ---------------------------------------------------------------------- */
246 { B1 (0x38), PC2 ($3); }
248 { B1 (0x39), PC2 ($3); }
250 { if ($1 == COND_EQ || $1 == COND_NE)
251 { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); }
253 as_bad (_("Only BEQ and BNE may have .W")); }
255 { if ($1 == COND_EQ || $1 == COND_NE)
257 rx_relax (RX_RELAX_BRANCH, 0);
258 rx_linkrelax_branch ();
259 B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5);
263 rx_relax (RX_RELAX_BRANCH, 0);
264 /* This is because we might turn it into a
265 jump-over-jump long branch. */
266 rx_linkrelax_branch ();
267 B1 (0x20); F ($1, 4, 4); PC1 ($2);
270 /* ---------------------------------------------------------------------- */
272 | MOV DOT_B '#' EXPR ',' disp '[' REG ']'
273 /* rx_disp5op changes the value if it succeeds, so keep it last. */
274 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE))
275 { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
277 { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4);
278 if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } }
280 | MOV DOT_W '#' EXPR ',' disp '[' REG ']'
281 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
282 { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
284 { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } }
286 | MOV DOT_L '#' EXPR ',' disp '[' REG ']'
287 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
288 { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
290 { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } }
292 /* ---------------------------------------------------------------------- */
294 | RTSD '#' EXPR ',' REG '-' REG
295 { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3);
297 rx_error (_("RTSD cannot pop R0"));
299 rx_error (_("RTSD first reg must be <= second reg")); }
301 /* ---------------------------------------------------------------------- */
304 { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); }
306 /* ---------------------------------------------------------------------- */
308 | CMP disp '[' REG ']' DOT_UB ',' REG
309 { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); }
311 | CMP disp '[' REG ']' memex ',' REG
312 { B3 (MEMEX, 0x04, 0); F ($6, 8, 2); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); }
314 /* ---------------------------------------------------------------------- */
316 | MOVU bw REG ',' REG
317 { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); }
319 /* ---------------------------------------------------------------------- */
321 | MOVU bw '[' REG ']' ',' REG
322 { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); }
324 | MOVU bw EXPR '[' REG ']' ',' REG
325 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
326 { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
328 { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
330 /* ---------------------------------------------------------------------- */
332 | SUB '#' EXPR ',' REG
333 { if (rx_uintop ($3, 4))
334 { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
336 /* This is really an add, but we negate the immediate. */
337 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } }
339 | CMP '#' EXPR ',' REG
340 { if (rx_uintop ($3, 4))
341 { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); }
342 else if (rx_uintop ($3, 8))
343 { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); }
345 { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } }
347 | ADD '#' EXPR ',' REG
348 { if (rx_uintop ($3, 4))
349 { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); }
351 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } }
353 | MUL '#' EXPR ',' REG
354 { if (rx_uintop ($3, 4))
355 { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); }
357 { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } }
359 | AND_ '#' EXPR ',' REG
360 { if (rx_uintop ($3, 4))
361 { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); }
363 { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } }
365 | OR '#' EXPR ',' REG
366 { if (rx_uintop ($3, 4))
367 { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); }
369 { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } }
371 | MOV DOT_L '#' EXPR ',' REG
372 { if (rx_uintop ($4, 4))
373 { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); }
374 else if (rx_uintop ($4, 8))
375 { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); }
377 { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } }
379 | MOV '#' EXPR ',' REG
380 { if (rx_uintop ($3, 4))
381 { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); }
382 else if (rx_uintop ($3, 8))
383 { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); }
385 { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } }
387 /* ---------------------------------------------------------------------- */
390 { B1 (0x67); rtsd_immediate ($3); }
392 /* ---------------------------------------------------------------------- */
394 | SHLR { sub_op = 0; } op_shift
395 | SHAR { sub_op = 1; } op_shift
396 | SHLL { sub_op = 2; } op_shift
398 /* ---------------------------------------------------------------------- */
403 { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); }
405 { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); }
407 rx_error (_("PUSHM cannot push R0"));
409 rx_error (_("PUSHM first reg must be <= second reg")); }
411 /* ---------------------------------------------------------------------- */
416 { B2 (0x7e, 0xb0); F ($2, 12, 4); }
418 { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); }
420 rx_error (_("POPM cannot pop R0"));
422 rx_error (_("POPM first reg must be <= second reg")); }
424 /* ---------------------------------------------------------------------- */
426 | ADD '#' EXPR ',' REG ',' REG
427 { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); }
429 /* ---------------------------------------------------------------------- */
432 { B2(0x75, 0x60), UO1 ($3); }
434 /* ---------------------------------------------------------------------- */
436 | BSET '#' EXPR ',' REG
437 { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); }
438 | BCLR '#' EXPR ',' REG
439 { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); }
441 /* ---------------------------------------------------------------------- */
443 | BTST '#' EXPR ',' REG
444 { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); }
446 /* ---------------------------------------------------------------------- */
449 { B2 (0x7e, 0x30); F ($2, 12, 4); }
451 { B2 (0x7e, 0x40); F ($2, 12, 4); }
453 { B2 (0x7e, 0x50); F ($2, 12, 4); }
455 /* ---------------------------------------------------------------------- */
458 { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); }
460 /* ---------------------------------------------------------------------- */
463 { B2 (0x7e, 0xb0); F ($2, 12, 4); }
465 /* ---------------------------------------------------------------------- */
469 { B2 (0x7e, 0xc0); F ($2, 12, 4); }
471 as_bad (_("PUSHC can only push the first 16 control registers")); }
473 /* ---------------------------------------------------------------------- */
477 { B2 (0x7e, 0xe0); F ($2, 12, 4); }
479 as_bad (_("POPC can only pop the first 16 control registers")); }
481 /* ---------------------------------------------------------------------- */
484 { B2 (0x7f, 0xa0); F ($2, 12, 4); }
486 { B2 (0x7f, 0xb0); F ($2, 12, 4); }
488 /* ---------------------------------------------------------------------- */
491 { B2 (0x7f, 0x00); F ($2, 12, 4); }
493 { B2 (0x7f, 0x10); F ($2, 12, 4); }
495 { B2 (0x7f, 0x40); F ($3, 12, 4); }
497 { B2 (0x7f, 0x50); F ($3, 12, 4); }
499 /* ---------------------------------------------------------------------- */
510 /* ---------------------------------------------------------------------- */
513 { B2 (0x7f, 0x80); F ($2, 14, 2); }
515 { B2 (0x7f, 0x84); F ($2, 14, 2); }
517 { B2 (0x7f, 0x88); F ($2, 14, 2); }
519 /* ---------------------------------------------------------------------- */
522 { B2 (0x7f, 0x8c); F ($2, 14, 2); }
524 /* ---------------------------------------------------------------------- */
535 /* ---------------------------------------------------------------------- */
538 { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
540 /* ---------------------------------------------------------------------- */
542 /* rx_disp5op changes the value if it succeeds, so keep it last. */
543 | MOV bwl REG ',' EXPR '[' REG ']'
544 { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2))
545 { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); }
547 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }}
549 /* ---------------------------------------------------------------------- */
551 | MOV bwl EXPR '[' REG ']' ',' REG
552 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
553 { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
555 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
557 /* ---------------------------------------------------------------------- */
559 /* MOV a,b - if a is a reg and b is mem, src and dest are
562 /* We don't use "disp" here because it causes a shift/reduce
563 conflict with the other displacement-less patterns. */
565 | MOV bwl REG ',' '[' REG ']'
566 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); }
568 /* ---------------------------------------------------------------------- */
570 | MOV bwl '[' REG ']' ',' disp '[' REG ']'
571 { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); }
573 /* ---------------------------------------------------------------------- */
575 | MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']'
576 { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); }
578 /* ---------------------------------------------------------------------- */
580 | MOV bwl REG ',' REG
581 { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); }
583 /* ---------------------------------------------------------------------- */
585 | MOV bwl '[' REG ']' ',' REG
586 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); }
588 /* ---------------------------------------------------------------------- */
590 | BSET '#' EXPR ',' disp '[' REG ']' DOT_B
591 { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
592 | BCLR '#' EXPR ',' disp '[' REG ']' DOT_B
593 { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
594 | BTST '#' EXPR ',' disp '[' REG ']' DOT_B
595 { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
597 /* ---------------------------------------------------------------------- */
599 | PUSH bwl disp '[' REG ']'
600 { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); }
602 /* ---------------------------------------------------------------------- */
604 | SBB { sub_op = 0; } op_dp20_rm_l
605 | NEG { sub_op = 1; sub_op2 = 1; } op_dp20_rr
606 | ADC { sub_op = 2; } op_dp20_rim_l
607 | ABS { sub_op = 3; sub_op2 = 2; } op_dp20_rr
608 | MAX { sub_op = 4; } op_dp20_rim
609 | MIN { sub_op = 5; } op_dp20_rim
610 | EMUL { sub_op = 6; } op_dp20_i
611 | EMULU { sub_op = 7; } op_dp20_i
612 | DIV { sub_op = 8; } op_dp20_rim
613 | DIVU { sub_op = 9; } op_dp20_rim
614 | TST { sub_op = 12; } op_dp20_rim
615 | XOR { sub_op = 13; } op_dp20_rim
616 | NOT { sub_op = 14; sub_op2 = 0; } op_dp20_rr
617 | STZ { sub_op = 14; } op_dp20_i
618 | STNZ { sub_op = 15; } op_dp20_i
620 /* ---------------------------------------------------------------------- */
622 | EMUL { sub_op = 6; } op_xchg
623 | EMULU { sub_op = 7; } op_xchg
624 | XCHG { sub_op = 16; } op_xchg
625 | ITOF { sub_op = 17; } op_xchg
627 /* ---------------------------------------------------------------------- */
630 { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
632 { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
634 { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
636 { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
638 | BSET REG ',' disp '[' REG ']' DOT_B
639 { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
640 | BCLR REG ',' disp '[' REG ']' DOT_B
641 { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
642 | BTST REG ',' disp '[' REG ']' DOT_B
643 { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
644 | BNOT REG ',' disp '[' REG ']' DOT_B
645 { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
647 /* ---------------------------------------------------------------------- */
649 | FSUB { sub_op = 0; } float2_op
650 | FCMP { sub_op = 1; } float2_op
651 | FADD { sub_op = 2; } float2_op
652 | FMUL { sub_op = 3; } float2_op
653 | FDIV { sub_op = 4; } float2_op
654 | FTOI { sub_op = 5; } float2_op_ni
655 | ROUND { sub_op = 6; } float2_op_ni
657 /* ---------------------------------------------------------------------- */
660 { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
661 | SCCND bwl disp '[' REG ']'
662 { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); }
664 /* ---------------------------------------------------------------------- */
666 | BMCND '#' EXPR ',' disp '[' REG ']' DOT_B
667 { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
668 F ($7, 16, 4); DSP ($5, 14, BSIZE); }
670 /* ---------------------------------------------------------------------- */
672 | BNOT '#' EXPR ',' disp '[' REG ']' DOT_B
673 { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
674 DSP ($5, 14, BSIZE); }
676 /* ---------------------------------------------------------------------- */
679 { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
681 { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
683 { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
685 { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
687 /* ---------------------------------------------------------------------- */
689 /* We don't have syntax for these yet. */
691 { id24 (2, 0x17, 0x00); F ($2, 20, 4); }
693 { id24 (2, 0x17, 0x10); F ($2, 20, 4); }
695 { id24 (2, 0x1f, 0x00); F ($2, 20, 4); }
697 { id24 (2, 0x1f, 0x20); F ($2, 20, 4); }
699 { id24 (2, 0x1f, 0x10); F ($2, 20, 4); }
702 { id24 (2, 0x18, 0x00);
703 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
705 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
708 as_bad (_("RACW expects #1 or #2"));}
710 /* ---------------------------------------------------------------------- */
712 | MOV bwl REG ',' '[' REG '+' ']'
713 { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); }
714 | MOV bwl REG ',' '[' '-' REG ']'
715 { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); }
717 /* ---------------------------------------------------------------------- */
719 | MOV bwl '[' REG '+' ']' ',' REG
720 { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); }
721 | MOV bwl '[' '-' REG ']' ',' REG
722 { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); }
724 /* ---------------------------------------------------------------------- */
726 | MOVU bw '[' REG '+' ']' ',' REG
727 { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); }
728 | MOVU bw '[' '-' REG ']' ',' REG
729 { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); }
731 /* ---------------------------------------------------------------------- */
733 | ROTL { sub_op = 6; } op_shift_rot
734 | ROTR { sub_op = 4; } op_shift_rot
735 | REVW { sub_op = 5; } op_shift_rot
736 | REVL { sub_op = 7; } op_shift_rot
738 /* ---------------------------------------------------------------------- */
741 { id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1);
744 /* ---------------------------------------------------------------------- */
747 { id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); }
749 /* ---------------------------------------------------------------------- */
751 | ROTL '#' EXPR ',' REG
752 { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); }
753 | ROTR '#' EXPR ',' REG
754 { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); }
756 /* ---------------------------------------------------------------------- */
758 | MVTC '#' EXPR ',' CREG
759 { id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); }
761 /* ---------------------------------------------------------------------- */
763 | BMCND '#' EXPR ',' REG
764 { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5);
767 /* ---------------------------------------------------------------------- */
769 | BNOT '#' EXPR ',' REG
770 { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); }
772 /* ---------------------------------------------------------------------- */
774 | MOV bwl REG ',' '[' REG ',' REG ']'
775 { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); }
777 | MOV bwl '[' REG ',' REG ']' ',' REG
778 { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
780 | MOVU bw '[' REG ',' REG ']' ',' REG
781 { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
783 /* ---------------------------------------------------------------------- */
785 | SUB { sub_op = 0; } op_subadd
786 | ADD { sub_op = 2; } op_subadd
787 | MUL { sub_op = 3; } op_subadd
788 | AND_ { sub_op = 4; } op_subadd
789 | OR { sub_op = 5; } op_subadd
791 /* ---------------------------------------------------------------------- */
792 /* There is no SBB #imm so we fake it with ADC. */
794 | SBB '#' EXPR ',' REG
795 { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); }
797 /* ---------------------------------------------------------------------- */
801 /* ====================================================================== */
805 { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); }
806 | disp '[' REG ']' DOT_UB ',' REG
807 { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); }
808 | disp '[' REG ']' memex ',' REG
809 { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); }
810 | REG ',' REG ',' REG
811 { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
814 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
818 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
819 | disp '[' REG ']' opt_l ',' REG
820 { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00);
821 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); }
824 /* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
828 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
829 | disp '[' REG ']' DOT_UB ',' REG
830 { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
831 | disp '[' REG ']' memex ',' REG
832 { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00);
833 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); }
838 { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); }
853 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
855 { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
858 /* xchg, itof, emul, emulu */
861 { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); }
862 | disp '[' REG ']' DOT_UB ',' REG
863 { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
864 | disp '[' REG ']' memex ',' REG
865 { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4);
866 DSP ($1, 14, sizemap[$5]); }
869 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
872 { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); }
876 { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); }
877 | '#' EXPR ',' REG ',' REG
878 { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); }
886 { id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
891 { id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
892 | disp '[' REG ']' opt_l ',' REG
893 { id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
896 /* ====================================================================== */
898 disp : { $$ = zero_expr (); }
902 flag : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
905 /* DOT_UB is not listed here, it's handled with a separate pattern. */
906 /* Use sizemap[$n] to get LSIZE etc. */
907 memex : DOT_B { $$ = 0; }
914 bwl : { $$ = LSIZE; }
915 | DOT_B { $$ = BSIZE; }
916 | DOT_W { $$ = WSIZE; }
917 | DOT_L { $$ = LSIZE; }
930 /* ====================================================================== */
969 { "fintv", CREG, 11 },
970 { "intb", CREG, 12 },
973 { "pben", CREG, 17 },
975 { "bbpsw", CREG, 24 },
976 { "bbpc", CREG, 25 },
983 { ".ub", DOT_UB, 0 },
984 { ".uw", DOT_UW , 0},
993 #define OPC(x) { #x, x, IS_OPCODE }
997 { "and", AND_, IS_OPCODE },
1095 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1102 condition_opcode_table[] =
1109 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1140 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1143 rx_lex_init (char * beginning, char * ending)
1145 rx_init_start = beginning;
1146 rx_lex_start = beginning;
1147 rx_lex_end = ending;
1155 check_condition (char * base)
1160 if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
1162 if (memcmp (rx_lex_start, base, strlen (base)))
1164 cp = rx_lex_start + strlen (base);
1165 for (i = 0; i < NUM_CONDITIONS; i ++)
1167 if (strcasecmp (cp, condition_table[i].string) == 0)
1169 rx_lval.regno = condition_table[i].val;
1180 char * save_input_pointer;
1182 while (ISSPACE (*rx_lex_start)
1183 && rx_lex_start != rx_lex_end)
1186 rx_last_exp_start = rx_lex_start;
1188 if (rx_lex_start == rx_lex_end)
1191 if (ISALPHA (*rx_lex_start)
1192 || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0)
1193 || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0)
1194 || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
1200 for (e = rx_lex_start + 1;
1201 e < rx_lex_end && ISALNUM (*e);
1207 if (strcmp (rx_lex_start, "%pidreg") == 0)
1210 rx_lval.regno = rx_pid_register;
1213 rx_last_token = REG;
1218 if (strcmp (rx_lex_start, "%gpreg") == 0)
1221 rx_lval.regno = rx_gp_register;
1224 rx_last_token = REG;
1229 if (rx_last_token == 0)
1230 for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
1231 if (check_condition (condition_opcode_table[ci].string))
1235 rx_last_token = condition_opcode_table[ci].token;
1236 return condition_opcode_table[ci].token;
1239 for (i = 0; i < NUM_TOKENS; i++)
1240 if (strcasecmp (rx_lex_start, token_table[i].string) == 0
1241 && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
1242 && !(token_table[i].token == FLAG && !need_flag))
1244 rx_lval.regno = token_table[i].val;
1247 rx_last_token = token_table[i].token;
1248 return token_table[i].token;
1253 if (rx_last_token == 0)
1255 rx_last_token = UNKNOWN_OPCODE;
1256 return UNKNOWN_OPCODE;
1259 if (rx_last_token == UNKNOWN_OPCODE)
1262 if (*rx_lex_start == '[')
1264 if (*rx_lex_start == ']')
1268 || rx_last_token == REG
1269 || strchr ("[],#", *rx_lex_start))
1271 rx_last_token = *rx_lex_start;
1272 return *rx_lex_start ++;
1275 save_input_pointer = input_line_pointer;
1276 input_line_pointer = rx_lex_start;
1277 rx_lval.exp.X_md = 0;
1278 expression (&rx_lval.exp);
1280 /* We parse but ignore any :<size> modifier on expressions. */
1281 if (*input_line_pointer == ':')
1285 for (cp = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
1288 if (cp > input_line_pointer+1)
1289 input_line_pointer = cp;
1292 rx_lex_start = input_line_pointer;
1293 input_line_pointer = save_input_pointer;
1294 rx_last_token = EXPR;
1299 rx_error (const char * str)
1303 len = rx_last_exp_start - rx_init_start;
1305 as_bad ("%s", rx_init_start);
1306 as_bad ("%*s^ %s", len, "", str);
1311 rx_intop (expressionS exp, int nbits, int opbits)
1316 if (exp.X_op == O_big && nbits == 32)
1318 if (exp.X_op != O_constant)
1320 v = exp.X_add_number;
1322 msb = 1UL << (opbits - 1);
1323 mask = (1UL << opbits) - 1;
1325 if ((v & msb) && ! (v & ~mask))
1331 return -0x8 <= v && v <= 0x7;
1333 return -0x10 <= v && v <= 0x17;
1335 return -0x80 <= v && v <= 0x7f;
1337 return -0x8000 <= v && v <= 0x7fff;
1339 return -0x800000 <= v && v <= 0x7fffff;
1343 printf ("rx_intop passed %d\n", nbits);
1350 rx_uintop (expressionS exp, int nbits)
1354 if (exp.X_op != O_constant)
1356 v = exp.X_add_number;
1367 return v <= 0xffffff;
1369 printf ("rx_uintop passed %d\n", nbits);
1376 rx_disp3op (expressionS exp)
1380 if (exp.X_op != O_constant)
1382 v = exp.X_add_number;
1383 if (v < 3 || v > 10)
1389 rx_disp5op (expressionS * exp, int msize)
1393 if (exp->X_op != O_constant)
1395 v = exp->X_add_number;
1400 if (0 < v && v <= 31)
1406 if (0 < v && v <= 63)
1408 exp->X_add_number >>= 1;
1415 if (0 < v && v <= 127)
1417 exp->X_add_number >>= 2;
1425 /* Just like the above, but allows a zero displacement. */
1428 rx_disp5op0 (expressionS * exp, int msize)
1430 if (exp->X_op != O_constant)
1432 if (exp->X_add_number == 0)
1434 return rx_disp5op (exp, msize);
1438 exp_val (expressionS exp)
1440 if (exp.X_op != O_constant)
1442 rx_error (_("constant expected"));
1445 return exp.X_add_number;
1451 /* Static, so program load sets it to all zeros, which is what we want. */
1452 static expressionS zero;
1453 zero.X_op = O_constant;
1458 immediate (expressionS exp, int type, int pos, int bits)
1460 /* We will emit constants ourself here, so negate them. */
1461 if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
1462 exp.X_add_number = - exp.X_add_number;
1463 if (type == RXREL_NEGATIVE_BORROW)
1465 if (exp.X_op == O_constant)
1466 exp.X_add_number = - exp.X_add_number - 1;
1468 rx_error (_("sbb cannot use symbolic immediates"));
1471 if (rx_intop (exp, 8, bits))
1473 rx_op (exp, 1, type);
1476 else if (rx_intop (exp, 16, bits))
1478 rx_op (exp, 2, type);
1481 else if (rx_uintop (exp, 16) && bits == 16)
1483 rx_op (exp, 2, type);
1486 else if (rx_intop (exp, 24, bits))
1488 rx_op (exp, 3, type);
1491 else if (rx_intop (exp, 32, bits))
1493 rx_op (exp, 4, type);
1496 else if (type == RXREL_SIGNED)
1498 /* This is a symbolic immediate, we will relax it later. */
1499 rx_relax (RX_RELAX_IMM, pos);
1500 rx_op (exp, linkrelax ? 4 : 1, type);
1505 /* Let the linker deal with it. */
1506 rx_op (exp, 4, type);
1512 displacement (expressionS exp, int msize)
1517 if (exp.X_op == O_symbol
1522 case BFD_RELOC_GPREL16:
1526 exp.X_md = BFD_RELOC_RX_GPRELB;
1529 exp.X_md = BFD_RELOC_RX_GPRELW;
1532 exp.X_md = BFD_RELOC_RX_GPRELL;
1540 if (exp.X_op == O_subtract)
1542 exp.X_md = BFD_RELOC_RX_DIFF;
1547 if (exp.X_op != O_constant)
1549 rx_error (_("displacements must be constants"));
1552 val = exp.X_add_number;
1563 rx_error (_("word displacement not word-aligned"));
1568 rx_error (_("long displacement not long-aligned"));
1572 as_bad (_("displacement with unknown size (internal bug?)\n"));
1577 exp.X_add_number = val;
1579 if (0 <= val && val <= 255 )
1585 if (0 <= val && val <= 65535)
1591 rx_error (_("negative displacements not allowed"));
1593 rx_error (_("displacement too large"));
1598 rtsd_immediate (expressionS exp)
1602 if (exp.X_op != O_constant)
1604 rx_error (_("rtsd size must be constant"));
1607 val = exp.X_add_number;
1609 rx_error (_("rtsd size must be multiple of 4"));
1611 if (val < 0 || val > 1020)
1612 rx_error (_("rtsd size must be 0..1020"));
1615 exp.X_add_number = val;