1 /* rx-parse.y Renesas RX parser
2 Copyright (C) 2008-2017 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
23 #include "safe-ctype.h"
26 static int rx_lex (void);
38 static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
40 /* Ok, here are the rules for using these macros...
42 B*() is used to specify the base opcode bytes. Fields to be filled
43 in later, leave zero. Call this first.
45 F() and FE() are used to fill in fields within the base opcode bytes. You MUST
46 call B*() before any F() or FE().
48 [UN]*O*(), PC*() appends operands to the end of the opcode. You
49 must call P() and B*() before any of these, so that the fixups
50 have the right byte location.
51 O = signed, UO = unsigned, NO = negated, PC = pcrel
53 IMM() adds an immediate and fills in the field for it.
54 NIMM() same, but negates the immediate.
55 NBIMM() same, but negates the immediate, for sbb.
56 DSP() adds a displacement, and fills in the field for it.
58 Note that order is significant for the O, IMM, and DSP macros, as
59 they append their data to the operand buffer in the order that you
62 Use "disp" for displacements whenever possible; this handles the
65 #define B1(b1) rx_base1 (b1)
66 #define B2(b1, b2) rx_base2 (b1, b2)
67 #define B3(b1, b2, b3) rx_base3 (b1, b2, b3)
68 #define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4)
70 /* POS is bits from the MSB of the first byte to the LSB of the last byte. */
71 #define F(val,pos,sz) rx_field (val, pos, sz)
72 #define FE(exp,pos,sz) rx_field (exp_val (exp), pos, sz);
74 #define O1(v) rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255)
75 #define O2(v) rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536)
76 #define O3(v) rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216)
77 #define O4(v) rx_op (v, 4, RXREL_SIGNED)
79 #define UO1(v) rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255)
80 #define UO2(v) rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536)
81 #define UO3(v) rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216)
82 #define UO4(v) rx_op (v, 4, RXREL_UNSIGNED)
84 #define NO1(v) rx_op (v, 1, RXREL_NEGATIVE)
85 #define NO2(v) rx_op (v, 2, RXREL_NEGATIVE)
86 #define NO3(v) rx_op (v, 3, RXREL_NEGATIVE)
87 #define NO4(v) rx_op (v, 4, RXREL_NEGATIVE)
89 #define PC1(v) rx_op (v, 1, RXREL_PCREL)
90 #define PC2(v) rx_op (v, 2, RXREL_PCREL)
91 #define PC3(v) rx_op (v, 3, RXREL_PCREL)
93 #define IMM_(v,pos,size) F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \
94 if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
95 #define IMM(v,pos) IMM_ (v, pos, 32)
96 #define IMMW(v,pos) IMM_ (v, pos, 16); rx_range (v, -32768, 65536)
97 #define IMMB(v,pos) IMM_ (v, pos, 8); rx_range (v, -128, 255)
98 #define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2)
99 #define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2)
100 #define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
101 else rx_linkrelax_dsp (pos); \
102 F (displacement (v, msz), pos, 2)
104 #define id24(a,b2,b3) B3 (0xfb + a, b2, b3)
106 static void rx_check_float_support (void);
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);
117 static void rx_range (expressionS, int, int);
118 static void rx_check_v2 (void);
120 static int need_flag = 0;
121 static int rx_in_brackets = 0;
122 static int rx_last_token = 0;
123 static char * rx_init_start;
124 static char * rx_last_exp_start = 0;
129 #define YYERROR_VERBOSE 1
140 %type <regno> REG FLAG CREG BCND BMCND SCCND ACC
141 %type <regno> flag bwl bw memex
142 %type <exp> EXPR disp
144 %token REG FLAG CREG ACC
146 %token EXPR UNKNOWN_OPCODE IS_OPCODE
148 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
150 %token ABS ADC ADD AND_
151 %token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST
154 %token EDIV EDIVU EMACA EMSBA EMUL EMULA EMULU
155 %token FADD FCMP FDIV FMUL FREIT FSUB FSQRT FTOI FTOU
158 %token MACHI MACLH MACLO MAX MIN MOV MOVCO MOVLI MOVU MSBHI MSBLH MSBLO MUL
159 %token MULHI MULLH MULLO MULU MVFACHI MVFACGU MVFACMI MVFACLO MVFC MVTACGU
160 %token MVTACHI MVTACLO MVTC MVTIPL
163 %token POP POPC POPM PUSH PUSHA PUSHC PUSHM
164 %token RACL RACW RDACL RDACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND
165 %token RTE RTFI RTS RTSD
166 %token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
167 %token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
174 /* ====================================================================== */
179 { as_bad (_("Unknown opcode: %s"), rx_init_start); }
181 /* ---------------------------------------------------------------------- */
195 /* ---------------------------------------------------------------------- */
198 { if (rx_disp3op ($2))
199 { B1 (0x08); rx_disp3 ($2, 5); }
200 else if (rx_intop ($2, 8, 8))
201 { B1 (0x2e); PC1 ($2); }
202 else if (rx_intop ($2, 16, 16))
203 { B1 (0x38); PC2 ($2); }
204 else if (rx_intop ($2, 24, 24))
205 { B1 (0x04); PC3 ($2); }
207 { rx_relax (RX_RELAX_BRANCH, 0);
208 rx_linkrelax_branch ();
209 /* We'll convert this to a longer one later if needed. */
210 B1 (0x08); rx_disp3 ($2, 5); } }
213 { B1 (0x04); PC3 ($3); }
216 { B1 (0x08); rx_disp3 ($3, 5); }
218 /* ---------------------------------------------------------------------- */
221 { if (rx_intop ($2, 16, 16))
222 { B1 (0x39); PC2 ($2); }
223 else if (rx_intop ($2, 24, 24))
224 { B1 (0x05); PC3 ($2); }
226 { rx_relax (RX_RELAX_BRANCH, 0);
227 rx_linkrelax_branch ();
228 B1 (0x39); PC2 ($2); } }
230 { B1 (0x05), PC3 ($3); }
232 /* ---------------------------------------------------------------------- */
235 { if ($1 == COND_EQ || $1 == COND_NE)
236 { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); }
238 as_bad (_("Only BEQ and BNE may have .S")); }
240 /* ---------------------------------------------------------------------- */
243 { B1 (0x20); F ($1, 4, 4); PC1 ($3); }
246 { B1 (0x2e), PC1 ($3); }
248 /* ---------------------------------------------------------------------- */
251 { B1 (0x38), PC2 ($3); }
253 { B1 (0x39), PC2 ($3); }
255 { if ($1 == COND_EQ || $1 == COND_NE)
256 { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); }
258 as_bad (_("Only BEQ and BNE may have .W")); }
260 { if ($1 == COND_EQ || $1 == COND_NE)
262 rx_relax (RX_RELAX_BRANCH, 0);
263 rx_linkrelax_branch ();
264 B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5);
268 rx_relax (RX_RELAX_BRANCH, 0);
269 /* This is because we might turn it into a
270 jump-over-jump long branch. */
271 rx_linkrelax_branch ();
272 B1 (0x20); F ($1, 4, 4); PC1 ($2);
275 /* ---------------------------------------------------------------------- */
277 | MOV DOT_B '#' EXPR ',' '[' REG ']'
278 { B2 (0xf8, 0x04); F ($7, 8, 4); IMMB ($4, 12);}
280 | MOV DOT_W '#' EXPR ',' '[' REG ']'
281 { B2 (0xf8, 0x01); F ($7, 8, 4); IMMW ($4, 12);}
283 | MOV DOT_L '#' EXPR ',' '[' REG ']'
284 { B2 (0xf8, 0x02); F ($7, 8, 4); IMM ($4, 12);}
286 | MOV DOT_B '#' EXPR ',' disp '[' REG ']'
287 /* rx_disp5op changes the value if it succeeds, so keep it last. */
288 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE))
289 { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
291 { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4);
292 if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } }
294 | MOV DOT_W '#' EXPR ',' disp '[' REG ']'
295 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
296 { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
298 { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } }
300 | MOV DOT_L '#' EXPR ',' disp '[' REG ']'
301 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
302 { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
304 { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } }
306 /* ---------------------------------------------------------------------- */
308 | RTSD '#' EXPR ',' REG '-' REG
309 { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3);
311 rx_error (_("RTSD cannot pop R0"));
313 rx_error (_("RTSD first reg must be <= second reg")); }
315 /* ---------------------------------------------------------------------- */
318 { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); }
320 /* ---------------------------------------------------------------------- */
322 | CMP disp '[' REG ']' DOT_UB ',' REG
323 { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); }
325 | CMP disp '[' REG ']' memex ',' REG
326 { B3 (MEMEX, 0x04, 0); F ($6, 8, 2); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); }
328 /* ---------------------------------------------------------------------- */
330 | MOVU bw REG ',' REG
331 { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); }
333 /* ---------------------------------------------------------------------- */
335 | MOVU bw '[' REG ']' ',' REG
336 { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); }
338 | MOVU bw EXPR '[' REG ']' ',' REG
339 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
340 { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
342 { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
344 /* ---------------------------------------------------------------------- */
346 | SUB '#' EXPR ',' REG
347 { if (rx_uintop ($3, 4))
348 { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
350 /* This is really an add, but we negate the immediate. */
351 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } }
353 | CMP '#' EXPR ',' REG
354 { if (rx_uintop ($3, 4))
355 { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); }
356 else if (rx_uintop ($3, 8))
357 { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); }
359 { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } }
361 | ADD '#' EXPR ',' REG
362 { if (rx_uintop ($3, 4))
363 { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); }
365 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } }
367 | MUL '#' EXPR ',' REG
368 { if (rx_uintop ($3, 4))
369 { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); }
371 { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } }
373 | AND_ '#' EXPR ',' REG
374 { if (rx_uintop ($3, 4))
375 { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); }
377 { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } }
379 | OR '#' EXPR ',' REG
380 { if (rx_uintop ($3, 4))
381 { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); }
383 { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } }
385 | MOV DOT_L '#' EXPR ',' REG
386 { if (rx_uintop ($4, 4))
387 { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); }
388 else if (rx_uintop ($4, 8))
389 { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); }
391 { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } }
393 | MOV '#' EXPR ',' REG
394 { if (rx_uintop ($3, 4))
395 { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); }
396 else if (rx_uintop ($3, 8))
397 { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); }
399 { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } }
401 /* ---------------------------------------------------------------------- */
404 { B1 (0x67); rtsd_immediate ($3); }
406 /* ---------------------------------------------------------------------- */
408 | SHLR { sub_op = 0; } op_shift
409 | SHAR { sub_op = 1; } op_shift
410 | SHLL { sub_op = 2; } op_shift
412 /* ---------------------------------------------------------------------- */
417 { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); }
419 { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); }
421 rx_error (_("PUSHM cannot push R0"));
423 rx_error (_("PUSHM first reg must be <= second reg")); }
425 /* ---------------------------------------------------------------------- */
430 { B2 (0x7e, 0xb0); F ($2, 12, 4); }
432 { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); }
434 rx_error (_("POPM cannot pop R0"));
436 rx_error (_("POPM first reg must be <= second reg")); }
438 /* ---------------------------------------------------------------------- */
440 | ADD '#' EXPR ',' REG ',' REG
441 { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); }
443 /* ---------------------------------------------------------------------- */
446 { B2(0x75, 0x60), UO1 ($3); }
448 /* ---------------------------------------------------------------------- */
450 | BSET '#' EXPR ',' REG
451 { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); }
452 | BCLR '#' EXPR ',' REG
453 { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); }
455 /* ---------------------------------------------------------------------- */
457 | BTST '#' EXPR ',' REG
458 { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); }
460 /* ---------------------------------------------------------------------- */
463 { B2 (0x7e, 0x30); F ($2, 12, 4); }
465 { B2 (0x7e, 0x40); F ($2, 12, 4); }
467 { B2 (0x7e, 0x50); F ($2, 12, 4); }
469 /* ---------------------------------------------------------------------- */
472 { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); }
474 /* ---------------------------------------------------------------------- */
477 { B2 (0x7e, 0xb0); F ($2, 12, 4); }
479 /* ---------------------------------------------------------------------- */
485 { B2 (0x7e, 0xc0); F ($2, 12, 4); }
487 as_bad (_("PUSHC can only push the first 16 control registers")); }
489 /* ---------------------------------------------------------------------- */
495 { B2 (0x7e, 0xe0); F ($2, 12, 4); }
497 as_bad (_("POPC can only pop the first 16 control registers")); }
499 /* ---------------------------------------------------------------------- */
502 { B2 (0x7f, 0xa0); F ($2, 12, 4); }
504 { B2 (0x7f, 0xb0); F ($2, 12, 4); }
506 /* ---------------------------------------------------------------------- */
509 { B2 (0x7f, 0x00); F ($2, 12, 4); }
511 { B2 (0x7f, 0x10); F ($2, 12, 4); }
513 { B2 (0x7f, 0x40); F ($3, 12, 4); }
515 { B2 (0x7f, 0x50); F ($3, 12, 4); }
517 /* ---------------------------------------------------------------------- */
520 { B2 (0x7f, 0x83); rx_note_string_insn_use (); }
522 { B2 (0x7f, 0x87); rx_note_string_insn_use (); }
524 { B2 (0x7f, 0x8b); rx_note_string_insn_use (); }
526 { B2 (0x7f, 0x8f); rx_note_string_insn_use (); }
528 /* ---------------------------------------------------------------------- */
531 { B2 (0x7f, 0x80); F ($2, 14, 2); rx_note_string_insn_use (); }
533 { B2 (0x7f, 0x84); F ($2, 14, 2); rx_note_string_insn_use (); }
535 { B2 (0x7f, 0x88); F ($2, 14, 2); }
537 /* ---------------------------------------------------------------------- */
540 { B2 (0x7f, 0x8c); F ($2, 14, 2); rx_note_string_insn_use (); }
542 /* ---------------------------------------------------------------------- */
553 /* ---------------------------------------------------------------------- */
556 { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
558 /* ---------------------------------------------------------------------- */
560 /* rx_disp5op changes the value if it succeeds, so keep it last. */
561 | MOV bwl REG ',' EXPR '[' REG ']'
562 { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2))
563 { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); }
565 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }}
567 /* ---------------------------------------------------------------------- */
569 | MOV bwl EXPR '[' REG ']' ',' REG
570 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
571 { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
573 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
575 /* ---------------------------------------------------------------------- */
577 /* MOV a,b - if a is a reg and b is mem, src and dest are
580 /* We don't use "disp" here because it causes a shift/reduce
581 conflict with the other displacement-less patterns. */
583 | MOV bwl REG ',' '[' REG ']'
584 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); }
586 /* ---------------------------------------------------------------------- */
588 | MOV bwl '[' REG ']' ',' disp '[' REG ']'
589 { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); }
591 /* ---------------------------------------------------------------------- */
593 | MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']'
594 { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); }
596 /* ---------------------------------------------------------------------- */
598 | MOV bwl REG ',' REG
599 { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); }
601 /* ---------------------------------------------------------------------- */
603 | MOV bwl '[' REG ']' ',' REG
604 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); }
606 /* ---------------------------------------------------------------------- */
608 | BSET '#' EXPR ',' disp '[' REG ']' DOT_B
609 { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
610 | BCLR '#' EXPR ',' disp '[' REG ']' DOT_B
611 { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
612 | BTST '#' EXPR ',' disp '[' REG ']' DOT_B
613 { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
615 /* ---------------------------------------------------------------------- */
617 | PUSH bwl disp '[' REG ']'
618 { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); }
620 /* ---------------------------------------------------------------------- */
622 | SBB { sub_op = 0; } op_dp20_rm_l
623 | NEG { sub_op = 1; sub_op2 = 1; } op_dp20_rr
624 | ADC { sub_op = 2; } op_dp20_rim_l
625 | ABS { sub_op = 3; sub_op2 = 2; } op_dp20_rr
626 | MAX { sub_op = 4; } op_dp20_rim
627 | MIN { sub_op = 5; } op_dp20_rim
628 | EMUL { sub_op = 6; } op_dp20_i
629 | EMULU { sub_op = 7; } op_dp20_i
630 | DIV { sub_op = 8; } op_dp20_rim
631 | DIVU { sub_op = 9; } op_dp20_rim
632 | TST { sub_op = 12; } op_dp20_rim
633 | XOR { sub_op = 13; } op_dp20_rim
634 | NOT { sub_op = 14; sub_op2 = 0; } op_dp20_rr
635 | STZ { sub_op = 14; sub_op2 = 0; } op_dp20_ri
636 | STNZ { sub_op = 15; sub_op2 = 1; } op_dp20_ri
638 /* ---------------------------------------------------------------------- */
640 | EMUL { sub_op = 6; } op_xchg
641 | EMULU { sub_op = 7; } op_xchg
642 | XCHG { sub_op = 16; } op_xchg
643 | ITOF { sub_op = 17; } op_xchg
644 | UTOF { sub_op = 21; } op_xchg
646 /* ---------------------------------------------------------------------- */
649 { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
651 { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
653 { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
655 { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
657 | BSET REG ',' disp '[' REG ']' opt_b
658 { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
659 | BCLR REG ',' disp '[' REG ']' opt_b
660 { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
661 | BTST REG ',' disp '[' REG ']' opt_b
662 { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
663 | BNOT REG ',' disp '[' REG ']' opt_b
664 { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
666 /* ---------------------------------------------------------------------- */
668 | FSUB { sub_op = 0; } float3_op
669 | FCMP { sub_op = 1; } float2_op
670 | FADD { sub_op = 2; } float3_op
671 | FMUL { sub_op = 3; } float3_op
672 | FDIV { sub_op = 4; } float2_op
673 | FSQRT { sub_op = 8; } float2_op_ni
674 | FTOI { sub_op = 5; } float2_op_ni
675 | FTOU { sub_op = 9; } float2_op_ni
676 | ROUND { sub_op = 6; } float2_op_ni
678 /* ---------------------------------------------------------------------- */
681 /* ---------------------------------------------------------------------- */
684 { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
685 | SCCND bwl disp '[' REG ']'
686 { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); }
688 /* ---------------------------------------------------------------------- */
690 | BMCND '#' EXPR ',' disp '[' REG ']' opt_b
691 { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
692 F ($7, 16, 4); DSP ($5, 14, BSIZE); }
694 /* ---------------------------------------------------------------------- */
696 | BNOT '#' EXPR ',' disp '[' REG ']' opt_b
697 { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
698 DSP ($5, 14, BSIZE); }
700 /* ---------------------------------------------------------------------- */
703 { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
704 | MULHI REG ',' REG ',' ACC
705 { rx_check_v2 (); id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
707 { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
708 | MULLO REG ',' REG ',' ACC
709 { rx_check_v2 (); id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
711 { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
712 | MACHI REG ',' REG ',' ACC
713 { rx_check_v2 (); id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
715 { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
716 | MACLO REG ',' REG ',' ACC
717 { rx_check_v2 (); id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
719 /* ---------------------------------------------------------------------- */
721 /* We don't have syntax for these yet. */
723 { id24 (2, 0x17, 0x00); F ($2, 20, 4); }
724 | MVTACHI REG ',' ACC
725 { rx_check_v2 (); id24 (2, 0x17, 0x00); F ($2, 20, 4); F ($4, 16, 1); }
727 { id24 (2, 0x17, 0x10); F ($2, 20, 4); }
728 | MVTACLO REG ',' ACC
729 { rx_check_v2 (); id24 (2, 0x17, 0x10); F ($2, 20, 4); F ($4, 16, 1); }
731 { id24 (2, 0x1f, 0x00); F ($2, 20, 4); }
732 | MVFACHI { sub_op = 0; } mvfa_op
734 { id24 (2, 0x1f, 0x20); F ($2, 20, 4); }
735 | MVFACMI { sub_op = 2; } mvfa_op
737 { id24 (2, 0x1f, 0x10); F ($2, 20, 4); }
738 | MVFACLO { sub_op = 1; } mvfa_op
740 { id24 (2, 0x18, 0x00);
741 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
743 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
746 as_bad (_("RACW expects #1 or #2"));}
747 | RACW '#' EXPR ',' ACC
748 { rx_check_v2 (); id24 (2, 0x18, 0x00); F ($5, 16, 1);
749 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
751 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
754 as_bad (_("RACW expects #1 or #2"));}
756 /* ---------------------------------------------------------------------- */
758 | MOV bwl REG ',' '[' REG '+' ']'
759 { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); }
760 | MOV bwl REG ',' '[' '-' REG ']'
761 { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); }
763 /* ---------------------------------------------------------------------- */
765 | MOV bwl '[' REG '+' ']' ',' REG
766 { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); }
767 | MOV bwl '[' '-' REG ']' ',' REG
768 { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); }
770 /* ---------------------------------------------------------------------- */
772 | MOVU bw '[' REG '+' ']' ',' REG
773 { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); }
774 | MOVU bw '[' '-' REG ']' ',' REG
775 { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); }
777 /* ---------------------------------------------------------------------- */
779 | ROTL { sub_op = 6; } op_shift_rot
780 | ROTR { sub_op = 4; } op_shift_rot
781 | REVW { sub_op = 5; } op_shift_rot
782 | REVL { sub_op = 7; } op_shift_rot
784 /* ---------------------------------------------------------------------- */
789 id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1);
792 /* ---------------------------------------------------------------------- */
797 id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); }
799 /* ---------------------------------------------------------------------- */
801 | ROTL '#' EXPR ',' REG
802 { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); }
803 | ROTR '#' EXPR ',' REG
804 { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); }
806 /* ---------------------------------------------------------------------- */
808 | MVTC '#' EXPR ',' CREG
811 id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); }
813 /* ---------------------------------------------------------------------- */
815 | BMCND '#' EXPR ',' REG
816 { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5);
819 /* ---------------------------------------------------------------------- */
821 | BNOT '#' EXPR ',' REG
822 { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); }
824 /* ---------------------------------------------------------------------- */
826 | MOV bwl REG ',' '[' REG ',' REG ']'
827 { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); }
829 | MOV bwl '[' REG ',' REG ']' ',' REG
830 { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
832 | MOVU bw '[' REG ',' REG ']' ',' REG
833 { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
835 /* ---------------------------------------------------------------------- */
837 | SUB { sub_op = 0; } op_subadd
838 | ADD { sub_op = 2; } op_subadd
839 | MUL { sub_op = 3; } op_subadd
840 | AND_ { sub_op = 4; } op_subadd
841 | OR { sub_op = 5; } op_subadd
843 /* ---------------------------------------------------------------------- */
844 /* There is no SBB #imm so we fake it with ADC. */
846 | SBB '#' EXPR ',' REG
847 { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); }
849 /* ---------------------------------------------------------------------- */
851 | MOVCO REG ',' '[' REG ']'
852 { rx_check_v2 (); B3 (0xfd, 0x27, 0x00); F ($5, 16, 4); F ($2, 20, 4); }
854 /* ---------------------------------------------------------------------- */
856 | MOVLI '[' REG ']' ',' REG
857 { rx_check_v2 (); B3 (0xfd, 0x2f, 0x00); F ($3, 16, 4); F ($6, 20, 4); }
859 /* ---------------------------------------------------------------------- */
861 | EMACA REG ',' REG ',' ACC
862 { rx_check_v2 (); id24 (2, 0x07, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
863 | EMSBA REG ',' REG ',' ACC
864 { rx_check_v2 (); id24 (2, 0x47, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
865 | EMULA REG ',' REG ',' ACC
866 { rx_check_v2 (); id24 (2, 0x03, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
867 | MACLH REG ',' REG ',' ACC
868 { rx_check_v2 (); id24 (2, 0x06, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
869 | MSBHI REG ',' REG ',' ACC
870 { rx_check_v2 (); id24 (2, 0x44, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
871 | MSBLH REG ',' REG ',' ACC
872 { rx_check_v2 (); id24 (2, 0x46, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
873 | MSBLO REG ',' REG ',' ACC
874 { rx_check_v2 (); id24 (2, 0x45, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
875 | MULLH REG ',' REG ',' ACC
876 { rx_check_v2 (); id24 (2, 0x02, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
877 | MVFACGU { sub_op = 3; } mvfa_op
878 | MVTACGU REG ',' ACC
879 { rx_check_v2 (); id24 (2, 0x17, 0x30); F ($4, 16, 1); F ($2, 20, 4); }
880 | RACL '#' EXPR ',' ACC
881 { rx_check_v2 (); id24 (2, 0x19, 0x00); F ($5, 16, 1);
882 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
884 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
887 as_bad (_("RACL expects #1 or #2"));}
888 | RDACL '#' EXPR ',' ACC
889 { rx_check_v2 (); id24 (2, 0x19, 0x40); F ($5, 16, 1);
890 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
892 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
895 as_bad (_("RDACL expects #1 or #2"));}
896 | RDACW '#' EXPR ',' ACC
897 { rx_check_v2 (); id24 (2, 0x18, 0x40); F ($5, 16, 1);
898 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
900 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
903 as_bad (_("RDACW expects #1 or #2"));}
905 /* ---------------------------------------------------------------------- */
909 /* ====================================================================== */
913 { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); }
914 | disp '[' REG ']' DOT_UB ',' REG
915 { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); }
916 | disp '[' REG ']' memex ',' REG
917 { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); }
918 | REG ',' REG ',' REG
919 { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
922 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
926 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
927 | disp '[' REG ']' opt_l ',' REG
928 { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00);
929 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); }
932 /* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
936 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
937 | disp '[' REG ']' DOT_UB ',' REG
938 { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
939 | disp '[' REG ']' memex ',' REG
940 { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00);
941 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); }
946 { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); }
961 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
963 { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
968 { id24 (1, 0x4b + (sub_op2<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
972 : { rx_check_v2 (); }
977 /* xchg, utof, itof, emul, emulu */
980 { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); }
981 | disp '[' REG ']' DOT_UB ',' REG
982 { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
983 | disp '[' REG ']' memex ',' REG
984 { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4);
985 DSP ($1, 14, sizemap[$5]); }
988 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
991 { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); }
995 { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); }
996 | '#' EXPR ',' REG ',' REG
997 { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); }
1003 { rx_check_float_support (); id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
1005 { rx_check_float_support (); id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
1006 | disp '[' REG ']' opt_l ',' REG
1007 { rx_check_float_support (); id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
1008 | REG ',' REG ',' REG
1009 { rx_check_v2 (); id24 (4, 0x80 + (sub_op << 4), 0 ); F ($1, 16, 4); F ($3, 20, 4); F ($5, 12, 4); }
1013 : { rx_check_float_support (); }
1015 { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); }
1020 : { rx_check_float_support (); }
1022 { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); }
1023 | { rx_check_float_support (); }
1024 disp '[' REG ']' opt_l ',' REG
1025 { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); }
1029 : { rx_check_v2 (); }
1030 '#' EXPR ',' ACC ',' REG
1031 { id24 (2, 0x1e, sub_op << 4); F ($7, 20, 4); F ($5, 16, 1);
1032 if (rx_uintop ($3, 4))
1034 switch (exp_val ($3))
1046 as_bad (_("IMM expects #0 to #2"));}
1048 as_bad (_("IMM expects #0 to #2"));}
1051 /* ====================================================================== */
1053 disp : { $$ = zero_expr (); }
1057 flag : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
1060 /* DOT_UB is not listed here, it's handled with a separate pattern. */
1061 /* Use sizemap[$n] to get LSIZE etc. */
1062 memex : DOT_B { $$ = 0; }
1066 | DOT_UW { $$ = 3; }
1069 bwl : { $$ = LSIZE; }
1070 | DOT_B { $$ = BSIZE; }
1071 | DOT_W { $$ = WSIZE; }
1072 | DOT_L { $$ = LSIZE; }
1089 /* ====================================================================== */
1093 const char * string;
1119 { "fpsw", CREG, 3 },
1125 { "bpsw", CREG, 8 },
1127 { "isp", CREG, 10 },
1128 { "fintv", CREG, 11 },
1129 { "intb", CREG, 12 },
1130 { "extb", CREG, 13 },
1132 { "pbp", CREG, 16 },
1133 { "pben", CREG, 17 },
1135 { "bbpsw", CREG, 24 },
1136 { "bbpc", CREG, 25 },
1143 { ".ub", DOT_UB, 0 },
1144 { ".uw", DOT_UW , 0},
1156 #define OPC(x) { #x, x, IS_OPCODE }
1160 { "and", AND_, IS_OPCODE },
1276 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1280 const char * string;
1283 condition_opcode_table[] =
1290 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1294 const char * string;
1321 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1324 rx_lex_init (char * beginning, char * ending)
1326 rx_init_start = beginning;
1327 rx_lex_start = beginning;
1328 rx_lex_end = ending;
1336 check_condition (const char * base)
1341 if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
1343 if (memcmp (rx_lex_start, base, strlen (base)))
1345 cp = rx_lex_start + strlen (base);
1346 for (i = 0; i < NUM_CONDITIONS; i ++)
1348 if (strcasecmp (cp, condition_table[i].string) == 0)
1350 rx_lval.regno = condition_table[i].val;
1361 char * save_input_pointer;
1363 while (ISSPACE (*rx_lex_start)
1364 && rx_lex_start != rx_lex_end)
1367 rx_last_exp_start = rx_lex_start;
1369 if (rx_lex_start == rx_lex_end)
1372 if (ISALPHA (*rx_lex_start)
1373 || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0)
1374 || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0)
1375 || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
1381 for (e = rx_lex_start + 1;
1382 e < rx_lex_end && ISALNUM (*e);
1388 if (strcmp (rx_lex_start, "%pidreg") == 0)
1391 rx_lval.regno = rx_pid_register;
1394 rx_last_token = REG;
1399 if (strcmp (rx_lex_start, "%gpreg") == 0)
1402 rx_lval.regno = rx_gp_register;
1405 rx_last_token = REG;
1410 if (rx_last_token == 0)
1411 for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
1412 if (check_condition (condition_opcode_table[ci].string))
1416 rx_last_token = condition_opcode_table[ci].token;
1417 return condition_opcode_table[ci].token;
1420 for (i = 0; i < NUM_TOKENS; i++)
1421 if (strcasecmp (rx_lex_start, token_table[i].string) == 0
1422 && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
1423 && !(token_table[i].token == FLAG && !need_flag))
1425 rx_lval.regno = token_table[i].val;
1428 rx_last_token = token_table[i].token;
1429 return token_table[i].token;
1434 if (rx_last_token == 0)
1436 rx_last_token = UNKNOWN_OPCODE;
1437 return UNKNOWN_OPCODE;
1440 if (rx_last_token == UNKNOWN_OPCODE)
1443 if (*rx_lex_start == '[')
1445 if (*rx_lex_start == ']')
1449 || rx_last_token == REG
1450 || strchr ("[],#", *rx_lex_start))
1452 rx_last_token = *rx_lex_start;
1453 return *rx_lex_start ++;
1456 save_input_pointer = input_line_pointer;
1457 input_line_pointer = rx_lex_start;
1458 rx_lval.exp.X_md = 0;
1459 expression (&rx_lval.exp);
1461 /* We parse but ignore any :<size> modifier on expressions. */
1462 if (*input_line_pointer == ':')
1466 for (cp = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
1469 if (cp > input_line_pointer+1)
1470 input_line_pointer = cp;
1473 rx_lex_start = input_line_pointer;
1474 input_line_pointer = save_input_pointer;
1475 rx_last_token = EXPR;
1480 rx_error (const char * str)
1484 len = rx_last_exp_start - rx_init_start;
1486 as_bad ("%s", rx_init_start);
1487 as_bad ("%*s^ %s", len, "", str);
1492 rx_intop (expressionS exp, int nbits, int opbits)
1497 if (exp.X_op == O_big)
1501 if (exp.X_add_number == -1)
1504 else if (exp.X_op != O_constant)
1506 v = exp.X_add_number;
1508 msb = 1UL << (opbits - 1);
1509 mask = (1UL << opbits) - 1;
1511 if ((v & msb) && ! (v & ~mask))
1517 return -0x8 <= v && v <= 0x7;
1519 return -0x10 <= v && v <= 0x17;
1521 return -0x80 <= v && v <= 0x7f;
1523 return -0x8000 <= v && v <= 0x7fff;
1525 return -0x800000 <= v && v <= 0x7fffff;
1529 printf ("rx_intop passed %d\n", nbits);
1536 rx_uintop (expressionS exp, int nbits)
1540 if (exp.X_op != O_constant)
1542 v = exp.X_add_number;
1553 return v <= 0xffffff;
1555 printf ("rx_uintop passed %d\n", nbits);
1562 rx_disp3op (expressionS exp)
1566 if (exp.X_op != O_constant)
1568 v = exp.X_add_number;
1569 if (v < 3 || v > 10)
1575 rx_disp5op (expressionS * exp, int msize)
1579 if (exp->X_op != O_constant)
1581 v = exp->X_add_number;
1586 if (0 <= v && v <= 31)
1592 if (0 <= v && v <= 63)
1594 exp->X_add_number >>= 1;
1601 if (0 <= v && v <= 127)
1603 exp->X_add_number >>= 2;
1611 /* Just like the above, but allows a zero displacement. */
1614 rx_disp5op0 (expressionS * exp, int msize)
1616 if (exp->X_op != O_constant)
1618 if (exp->X_add_number == 0)
1620 return rx_disp5op (exp, msize);
1624 exp_val (expressionS exp)
1626 if (exp.X_op != O_constant)
1628 rx_error (_("constant expected"));
1631 return exp.X_add_number;
1637 /* Static, so program load sets it to all zeros, which is what we want. */
1638 static expressionS zero;
1639 zero.X_op = O_constant;
1644 immediate (expressionS exp, int type, int pos, int bits)
1646 /* We will emit constants ourselves here, so negate them. */
1647 if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
1648 exp.X_add_number = - exp.X_add_number;
1649 if (type == RXREL_NEGATIVE_BORROW)
1651 if (exp.X_op == O_constant)
1652 exp.X_add_number = - exp.X_add_number - 1;
1654 rx_error (_("sbb cannot use symbolic immediates"));
1657 if (rx_intop (exp, 8, bits))
1659 rx_op (exp, 1, type);
1662 else if (rx_intop (exp, 16, bits))
1664 rx_op (exp, 2, type);
1667 else if (rx_uintop (exp, 16) && bits == 16)
1669 rx_op (exp, 2, type);
1672 else if (rx_intop (exp, 24, bits))
1674 rx_op (exp, 3, type);
1677 else if (rx_intop (exp, 32, bits))
1679 rx_op (exp, 4, type);
1682 else if (type == RXREL_SIGNED)
1684 /* This is a symbolic immediate, we will relax it later. */
1685 rx_relax (RX_RELAX_IMM, pos);
1686 rx_op (exp, linkrelax ? 4 : 1, type);
1691 /* Let the linker deal with it. */
1692 rx_op (exp, 4, type);
1698 displacement (expressionS exp, int msize)
1703 if (exp.X_op == O_symbol
1708 case BFD_RELOC_GPREL16:
1712 exp.X_md = BFD_RELOC_RX_GPRELB;
1715 exp.X_md = BFD_RELOC_RX_GPRELW;
1718 exp.X_md = BFD_RELOC_RX_GPRELL;
1726 if (exp.X_op == O_subtract)
1728 exp.X_md = BFD_RELOC_RX_DIFF;
1733 if (exp.X_op != O_constant)
1735 rx_error (_("displacements must be constants"));
1738 val = exp.X_add_number;
1749 rx_error (_("word displacement not word-aligned"));
1754 rx_error (_("long displacement not long-aligned"));
1758 as_bad (_("displacement with unknown size (internal bug?)\n"));
1763 exp.X_add_number = val;
1765 if (0 <= val && val <= 255 )
1771 if (0 <= val && val <= 65535)
1777 rx_error (_("negative displacements not allowed"));
1779 rx_error (_("displacement too large"));
1784 rtsd_immediate (expressionS exp)
1788 if (exp.X_op != O_constant)
1790 rx_error (_("rtsd size must be constant"));
1793 val = exp.X_add_number;
1795 rx_error (_("rtsd size must be multiple of 4"));
1797 if (val < 0 || val > 1020)
1798 rx_error (_("rtsd size must be 0..1020"));
1801 exp.X_add_number = val;
1806 rx_range (expressionS exp, int minv, int maxv)
1810 if (exp.X_op != O_constant)
1813 val = exp.X_add_number;
1814 if (val < minv || val > maxv)
1815 as_warn (_("Value %d out of range %d..%d"), val, minv, maxv);
1819 rx_check_float_support (void)
1821 if (rx_cpu == RX100 || rx_cpu == RX200)
1822 rx_error (_("target CPU type does not support floating point instructions"));
1829 rx_error (_("target CPU type does not support v2 instructions"));