1 /* rx-parse.y Renesas RX parser
2 Copyright (C) 2008-2016 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 ',' disp '[' REG ']'
278 /* rx_disp5op changes the value if it succeeds, so keep it last. */
279 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE))
280 { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
282 { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4);
283 if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } }
285 | MOV DOT_W '#' EXPR ',' disp '[' REG ']'
286 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
287 { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
289 { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } }
291 | MOV DOT_L '#' EXPR ',' disp '[' REG ']'
292 { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
293 { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
295 { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } }
297 /* ---------------------------------------------------------------------- */
299 | RTSD '#' EXPR ',' REG '-' REG
300 { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3);
302 rx_error (_("RTSD cannot pop R0"));
304 rx_error (_("RTSD first reg must be <= second reg")); }
306 /* ---------------------------------------------------------------------- */
309 { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); }
311 /* ---------------------------------------------------------------------- */
313 | CMP disp '[' REG ']' DOT_UB ',' REG
314 { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); }
316 | CMP disp '[' REG ']' memex ',' REG
317 { B3 (MEMEX, 0x04, 0); F ($6, 8, 2); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); }
319 /* ---------------------------------------------------------------------- */
321 | MOVU bw REG ',' REG
322 { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); }
324 /* ---------------------------------------------------------------------- */
326 | MOVU bw '[' REG ']' ',' REG
327 { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); }
329 | MOVU bw EXPR '[' REG ']' ',' REG
330 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
331 { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
333 { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
335 /* ---------------------------------------------------------------------- */
337 | SUB '#' EXPR ',' REG
338 { if (rx_uintop ($3, 4))
339 { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
341 /* This is really an add, but we negate the immediate. */
342 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } }
344 | CMP '#' EXPR ',' REG
345 { if (rx_uintop ($3, 4))
346 { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); }
347 else if (rx_uintop ($3, 8))
348 { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); }
350 { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } }
352 | ADD '#' EXPR ',' REG
353 { if (rx_uintop ($3, 4))
354 { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); }
356 { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } }
358 | MUL '#' EXPR ',' REG
359 { if (rx_uintop ($3, 4))
360 { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); }
362 { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } }
364 | AND_ '#' EXPR ',' REG
365 { if (rx_uintop ($3, 4))
366 { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); }
368 { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } }
370 | OR '#' EXPR ',' REG
371 { if (rx_uintop ($3, 4))
372 { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); }
374 { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } }
376 | MOV DOT_L '#' EXPR ',' REG
377 { if (rx_uintop ($4, 4))
378 { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); }
379 else if (rx_uintop ($4, 8))
380 { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); }
382 { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } }
384 | MOV '#' EXPR ',' REG
385 { if (rx_uintop ($3, 4))
386 { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); }
387 else if (rx_uintop ($3, 8))
388 { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); }
390 { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } }
392 /* ---------------------------------------------------------------------- */
395 { B1 (0x67); rtsd_immediate ($3); }
397 /* ---------------------------------------------------------------------- */
399 | SHLR { sub_op = 0; } op_shift
400 | SHAR { sub_op = 1; } op_shift
401 | SHLL { sub_op = 2; } op_shift
403 /* ---------------------------------------------------------------------- */
408 { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); }
410 { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); }
412 rx_error (_("PUSHM cannot push R0"));
414 rx_error (_("PUSHM first reg must be <= second reg")); }
416 /* ---------------------------------------------------------------------- */
421 { B2 (0x7e, 0xb0); F ($2, 12, 4); }
423 { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); }
425 rx_error (_("POPM cannot pop R0"));
427 rx_error (_("POPM first reg must be <= second reg")); }
429 /* ---------------------------------------------------------------------- */
431 | ADD '#' EXPR ',' REG ',' REG
432 { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); }
434 /* ---------------------------------------------------------------------- */
437 { B2(0x75, 0x60), UO1 ($3); }
439 /* ---------------------------------------------------------------------- */
441 | BSET '#' EXPR ',' REG
442 { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); }
443 | BCLR '#' EXPR ',' REG
444 { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); }
446 /* ---------------------------------------------------------------------- */
448 | BTST '#' EXPR ',' REG
449 { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); }
451 /* ---------------------------------------------------------------------- */
454 { B2 (0x7e, 0x30); F ($2, 12, 4); }
456 { B2 (0x7e, 0x40); F ($2, 12, 4); }
458 { B2 (0x7e, 0x50); F ($2, 12, 4); }
460 /* ---------------------------------------------------------------------- */
463 { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); }
465 /* ---------------------------------------------------------------------- */
468 { B2 (0x7e, 0xb0); F ($2, 12, 4); }
470 /* ---------------------------------------------------------------------- */
476 { B2 (0x7e, 0xc0); F ($2, 12, 4); }
478 as_bad (_("PUSHC can only push the first 16 control registers")); }
480 /* ---------------------------------------------------------------------- */
486 { B2 (0x7e, 0xe0); F ($2, 12, 4); }
488 as_bad (_("POPC can only pop the first 16 control registers")); }
490 /* ---------------------------------------------------------------------- */
493 { B2 (0x7f, 0xa0); F ($2, 12, 4); }
495 { B2 (0x7f, 0xb0); F ($2, 12, 4); }
497 /* ---------------------------------------------------------------------- */
500 { B2 (0x7f, 0x00); F ($2, 12, 4); }
502 { B2 (0x7f, 0x10); F ($2, 12, 4); }
504 { B2 (0x7f, 0x40); F ($3, 12, 4); }
506 { B2 (0x7f, 0x50); F ($3, 12, 4); }
508 /* ---------------------------------------------------------------------- */
511 { B2 (0x7f, 0x83); rx_note_string_insn_use (); }
513 { B2 (0x7f, 0x87); rx_note_string_insn_use (); }
515 { B2 (0x7f, 0x8b); rx_note_string_insn_use (); }
517 { B2 (0x7f, 0x8f); rx_note_string_insn_use (); }
519 /* ---------------------------------------------------------------------- */
522 { B2 (0x7f, 0x80); F ($2, 14, 2); rx_note_string_insn_use (); }
524 { B2 (0x7f, 0x84); F ($2, 14, 2); rx_note_string_insn_use (); }
526 { B2 (0x7f, 0x88); F ($2, 14, 2); }
528 /* ---------------------------------------------------------------------- */
531 { B2 (0x7f, 0x8c); F ($2, 14, 2); rx_note_string_insn_use (); }
533 /* ---------------------------------------------------------------------- */
544 /* ---------------------------------------------------------------------- */
547 { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
549 /* ---------------------------------------------------------------------- */
551 /* rx_disp5op changes the value if it succeeds, so keep it last. */
552 | MOV bwl REG ',' EXPR '[' REG ']'
553 { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2))
554 { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); }
556 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }}
558 /* ---------------------------------------------------------------------- */
560 | MOV bwl EXPR '[' REG ']' ',' REG
561 { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
562 { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
564 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
566 /* ---------------------------------------------------------------------- */
568 /* MOV a,b - if a is a reg and b is mem, src and dest are
571 /* We don't use "disp" here because it causes a shift/reduce
572 conflict with the other displacement-less patterns. */
574 | MOV bwl REG ',' '[' REG ']'
575 { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); }
577 /* ---------------------------------------------------------------------- */
579 | MOV bwl '[' REG ']' ',' disp '[' REG ']'
580 { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); }
582 /* ---------------------------------------------------------------------- */
584 | MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']'
585 { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); }
587 /* ---------------------------------------------------------------------- */
589 | MOV bwl REG ',' REG
590 { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); }
592 /* ---------------------------------------------------------------------- */
594 | MOV bwl '[' REG ']' ',' REG
595 { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); }
597 /* ---------------------------------------------------------------------- */
599 | BSET '#' EXPR ',' disp '[' REG ']' DOT_B
600 { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
601 | BCLR '#' EXPR ',' disp '[' REG ']' DOT_B
602 { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
603 | BTST '#' EXPR ',' disp '[' REG ']' DOT_B
604 { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
606 /* ---------------------------------------------------------------------- */
608 | PUSH bwl disp '[' REG ']'
609 { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); }
611 /* ---------------------------------------------------------------------- */
613 | SBB { sub_op = 0; } op_dp20_rm_l
614 | NEG { sub_op = 1; sub_op2 = 1; } op_dp20_rr
615 | ADC { sub_op = 2; } op_dp20_rim_l
616 | ABS { sub_op = 3; sub_op2 = 2; } op_dp20_rr
617 | MAX { sub_op = 4; } op_dp20_rim
618 | MIN { sub_op = 5; } op_dp20_rim
619 | EMUL { sub_op = 6; } op_dp20_i
620 | EMULU { sub_op = 7; } op_dp20_i
621 | DIV { sub_op = 8; } op_dp20_rim
622 | DIVU { sub_op = 9; } op_dp20_rim
623 | TST { sub_op = 12; } op_dp20_rim
624 | XOR { sub_op = 13; } op_dp20_rim
625 | NOT { sub_op = 14; sub_op2 = 0; } op_dp20_rr
626 | STZ { sub_op = 14; sub_op2 = 0; } op_dp20_ri
627 | STNZ { sub_op = 15; sub_op2 = 1; } op_dp20_ri
629 /* ---------------------------------------------------------------------- */
631 | EMUL { sub_op = 6; } op_xchg
632 | EMULU { sub_op = 7; } op_xchg
633 | XCHG { sub_op = 16; } op_xchg
634 | ITOF { sub_op = 17; } op_xchg
635 | UTOF { sub_op = 21; } op_xchg
637 /* ---------------------------------------------------------------------- */
640 { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
642 { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
644 { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
646 { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
648 | BSET REG ',' disp '[' REG ']' opt_b
649 { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
650 | BCLR REG ',' disp '[' REG ']' opt_b
651 { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
652 | BTST REG ',' disp '[' REG ']' opt_b
653 { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
654 | BNOT REG ',' disp '[' REG ']' opt_b
655 { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
657 /* ---------------------------------------------------------------------- */
659 | FSUB { sub_op = 0; } float3_op
660 | FCMP { sub_op = 1; } float2_op
661 | FADD { sub_op = 2; } float3_op
662 | FMUL { sub_op = 3; } float3_op
663 | FDIV { sub_op = 4; } float2_op
664 | FSQRT { sub_op = 8; } float2_op_ni
665 | FTOI { sub_op = 5; } float2_op_ni
666 | FTOU { sub_op = 9; } float2_op_ni
667 | ROUND { sub_op = 6; } float2_op_ni
669 /* ---------------------------------------------------------------------- */
672 /* ---------------------------------------------------------------------- */
675 { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
676 | SCCND bwl disp '[' REG ']'
677 { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); }
679 /* ---------------------------------------------------------------------- */
681 | BMCND '#' EXPR ',' disp '[' REG ']' opt_b
682 { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
683 F ($7, 16, 4); DSP ($5, 14, BSIZE); }
685 /* ---------------------------------------------------------------------- */
687 | BNOT '#' EXPR ',' disp '[' REG ']' opt_b
688 { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
689 DSP ($5, 14, BSIZE); }
691 /* ---------------------------------------------------------------------- */
694 { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
695 | MULHI REG ',' REG ',' ACC
696 { rx_check_v2 (); id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
698 { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
699 | MULLO REG ',' REG ',' ACC
700 { rx_check_v2 (); id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
702 { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
703 | MACHI REG ',' REG ',' ACC
704 { rx_check_v2 (); id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
706 { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
707 | MACLO REG ',' REG ',' ACC
708 { rx_check_v2 (); id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
710 /* ---------------------------------------------------------------------- */
712 /* We don't have syntax for these yet. */
714 { id24 (2, 0x17, 0x00); F ($2, 20, 4); }
715 | MVTACHI REG ',' ACC
716 { rx_check_v2 (); id24 (2, 0x17, 0x00); F ($2, 20, 4); F ($4, 16, 1); }
718 { id24 (2, 0x17, 0x10); F ($2, 20, 4); }
719 | MVTACLO REG ',' ACC
720 { rx_check_v2 (); id24 (2, 0x17, 0x10); F ($2, 20, 4); F ($4, 16, 1); }
722 { id24 (2, 0x1f, 0x00); F ($2, 20, 4); }
723 | MVFACHI { sub_op = 0; } mvfa_op
725 { id24 (2, 0x1f, 0x20); F ($2, 20, 4); }
726 | MVFACMI { sub_op = 2; } mvfa_op
728 { id24 (2, 0x1f, 0x10); F ($2, 20, 4); }
729 | MVFACLO { sub_op = 1; } mvfa_op
731 { id24 (2, 0x18, 0x00);
732 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
734 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
737 as_bad (_("RACW expects #1 or #2"));}
738 | RACW '#' EXPR ',' ACC
739 { rx_check_v2 (); id24 (2, 0x18, 0x00); F ($5, 16, 1);
740 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
742 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
745 as_bad (_("RACW expects #1 or #2"));}
747 /* ---------------------------------------------------------------------- */
749 | MOV bwl REG ',' '[' REG '+' ']'
750 { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); }
751 | MOV bwl REG ',' '[' '-' REG ']'
752 { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); }
754 /* ---------------------------------------------------------------------- */
756 | MOV bwl '[' REG '+' ']' ',' REG
757 { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); }
758 | MOV bwl '[' '-' REG ']' ',' REG
759 { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); }
761 /* ---------------------------------------------------------------------- */
763 | MOVU bw '[' REG '+' ']' ',' REG
764 { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); }
765 | MOVU bw '[' '-' REG ']' ',' REG
766 { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); }
768 /* ---------------------------------------------------------------------- */
770 | ROTL { sub_op = 6; } op_shift_rot
771 | ROTR { sub_op = 4; } op_shift_rot
772 | REVW { sub_op = 5; } op_shift_rot
773 | REVL { sub_op = 7; } op_shift_rot
775 /* ---------------------------------------------------------------------- */
780 id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1);
783 /* ---------------------------------------------------------------------- */
788 id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); }
790 /* ---------------------------------------------------------------------- */
792 | ROTL '#' EXPR ',' REG
793 { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); }
794 | ROTR '#' EXPR ',' REG
795 { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); }
797 /* ---------------------------------------------------------------------- */
799 | MVTC '#' EXPR ',' CREG
802 id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); }
804 /* ---------------------------------------------------------------------- */
806 | BMCND '#' EXPR ',' REG
807 { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5);
810 /* ---------------------------------------------------------------------- */
812 | BNOT '#' EXPR ',' REG
813 { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); }
815 /* ---------------------------------------------------------------------- */
817 | MOV bwl REG ',' '[' REG ',' REG ']'
818 { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); }
820 | MOV bwl '[' REG ',' REG ']' ',' REG
821 { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
823 | MOVU bw '[' REG ',' REG ']' ',' REG
824 { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
826 /* ---------------------------------------------------------------------- */
828 | SUB { sub_op = 0; } op_subadd
829 | ADD { sub_op = 2; } op_subadd
830 | MUL { sub_op = 3; } op_subadd
831 | AND_ { sub_op = 4; } op_subadd
832 | OR { sub_op = 5; } op_subadd
834 /* ---------------------------------------------------------------------- */
835 /* There is no SBB #imm so we fake it with ADC. */
837 | SBB '#' EXPR ',' REG
838 { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); }
840 /* ---------------------------------------------------------------------- */
842 | MOVCO REG ',' '[' REG ']'
843 { rx_check_v2 (); B3 (0xfd, 0x27, 0x00); F ($5, 16, 4); F ($2, 20, 4); }
845 /* ---------------------------------------------------------------------- */
847 | MOVLI '[' REG ']' ',' REG
848 { rx_check_v2 (); B3 (0xfd, 0x2f, 0x00); F ($3, 16, 4); F ($6, 20, 4); }
850 /* ---------------------------------------------------------------------- */
852 | EMACA REG ',' REG ',' ACC
853 { rx_check_v2 (); id24 (2, 0x07, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
854 | EMSBA REG ',' REG ',' ACC
855 { rx_check_v2 (); id24 (2, 0x47, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
856 | EMULA REG ',' REG ',' ACC
857 { rx_check_v2 (); id24 (2, 0x03, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
858 | MACLH REG ',' REG ',' ACC
859 { rx_check_v2 (); id24 (2, 0x06, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
860 | MSBHI REG ',' REG ',' ACC
861 { rx_check_v2 (); id24 (2, 0x44, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
862 | MSBLH REG ',' REG ',' ACC
863 { rx_check_v2 (); id24 (2, 0x46, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
864 | MSBLO REG ',' REG ',' ACC
865 { rx_check_v2 (); id24 (2, 0x45, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
866 | MULLH REG ',' REG ',' ACC
867 { rx_check_v2 (); id24 (2, 0x02, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
868 | MVFACGU { sub_op = 3; } mvfa_op
869 | MVTACGU REG ',' ACC
870 { rx_check_v2 (); id24 (2, 0x17, 0x30); F ($4, 16, 1); F ($2, 20, 4); }
871 | RACL '#' EXPR ',' ACC
872 { rx_check_v2 (); id24 (2, 0x19, 0x00); F ($5, 16, 1);
873 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
875 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
878 as_bad (_("RACL expects #1 or #2"));}
879 | RDACL '#' EXPR ',' ACC
880 { rx_check_v2 (); id24 (2, 0x19, 0x40); F ($5, 16, 1);
881 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
883 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
886 as_bad (_("RDACL expects #1 or #2"));}
887 | RDACW '#' EXPR ',' ACC
888 { rx_check_v2 (); id24 (2, 0x18, 0x40); F ($5, 16, 1);
889 if (rx_uintop ($3, 4) && $3.X_add_number == 1)
891 else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
894 as_bad (_("RDACW expects #1 or #2"));}
896 /* ---------------------------------------------------------------------- */
900 /* ====================================================================== */
904 { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); }
905 | disp '[' REG ']' DOT_UB ',' REG
906 { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); }
907 | disp '[' REG ']' memex ',' REG
908 { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); }
909 | REG ',' REG ',' REG
910 { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
913 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
917 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
918 | disp '[' REG ']' opt_l ',' REG
919 { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00);
920 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); }
923 /* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
927 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
928 | disp '[' REG ']' DOT_UB ',' REG
929 { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
930 | disp '[' REG ']' memex ',' REG
931 { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00);
932 F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); }
937 { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); }
952 { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
954 { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
959 { id24 (1, 0x4b + (sub_op2<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
963 : { rx_check_v2 (); }
968 /* xchg, utof, itof, emul, emulu */
971 { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); }
972 | disp '[' REG ']' DOT_UB ',' REG
973 { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
974 | disp '[' REG ']' memex ',' REG
975 { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4);
976 DSP ($1, 14, sizemap[$5]); }
979 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
982 { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); }
986 { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); }
987 | '#' EXPR ',' REG ',' REG
988 { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); }
994 { rx_check_float_support (); id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
996 { rx_check_float_support (); id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
997 | disp '[' REG ']' opt_l ',' REG
998 { rx_check_float_support (); id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
999 | REG ',' REG ',' REG
1000 { rx_check_v2 (); id24 (4, 0x80 + (sub_op << 4), 0 ); F ($1, 16, 4); F ($3, 20, 4); F ($5, 12, 4); }
1004 : { rx_check_float_support (); }
1006 { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); }
1011 : { rx_check_float_support (); }
1013 { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); }
1014 | { rx_check_float_support (); }
1015 disp '[' REG ']' opt_l ',' REG
1016 { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); }
1020 : { rx_check_v2 (); }
1021 '#' EXPR ',' ACC ',' REG
1022 { id24 (2, 0x1e, sub_op << 4); F ($7, 20, 4); F ($5, 16, 1);
1023 if (rx_uintop ($3, 4))
1025 switch (exp_val ($3))
1037 as_bad (_("IMM expects #0 to #2"));}
1039 as_bad (_("IMM expects #0 to #2"));}
1042 /* ====================================================================== */
1044 disp : { $$ = zero_expr (); }
1048 flag : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
1051 /* DOT_UB is not listed here, it's handled with a separate pattern. */
1052 /* Use sizemap[$n] to get LSIZE etc. */
1053 memex : DOT_B { $$ = 0; }
1057 | DOT_UW { $$ = 3; }
1060 bwl : { $$ = LSIZE; }
1061 | DOT_B { $$ = BSIZE; }
1062 | DOT_W { $$ = WSIZE; }
1063 | DOT_L { $$ = LSIZE; }
1080 /* ====================================================================== */
1084 const char * string;
1110 { "fpsw", CREG, 3 },
1116 { "bpsw", CREG, 8 },
1118 { "isp", CREG, 10 },
1119 { "fintv", CREG, 11 },
1120 { "intb", CREG, 12 },
1121 { "extb", CREG, 13 },
1123 { "pbp", CREG, 16 },
1124 { "pben", CREG, 17 },
1126 { "bbpsw", CREG, 24 },
1127 { "bbpc", CREG, 25 },
1134 { ".ub", DOT_UB, 0 },
1135 { ".uw", DOT_UW , 0},
1147 #define OPC(x) { #x, x, IS_OPCODE }
1151 { "and", AND_, IS_OPCODE },
1267 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1274 condition_opcode_table[] =
1281 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1312 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1315 rx_lex_init (char * beginning, char * ending)
1317 rx_init_start = beginning;
1318 rx_lex_start = beginning;
1319 rx_lex_end = ending;
1327 check_condition (char * base)
1332 if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
1334 if (memcmp (rx_lex_start, base, strlen (base)))
1336 cp = rx_lex_start + strlen (base);
1337 for (i = 0; i < NUM_CONDITIONS; i ++)
1339 if (strcasecmp (cp, condition_table[i].string) == 0)
1341 rx_lval.regno = condition_table[i].val;
1352 char * save_input_pointer;
1354 while (ISSPACE (*rx_lex_start)
1355 && rx_lex_start != rx_lex_end)
1358 rx_last_exp_start = rx_lex_start;
1360 if (rx_lex_start == rx_lex_end)
1363 if (ISALPHA (*rx_lex_start)
1364 || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0)
1365 || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0)
1366 || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
1372 for (e = rx_lex_start + 1;
1373 e < rx_lex_end && ISALNUM (*e);
1379 if (strcmp (rx_lex_start, "%pidreg") == 0)
1382 rx_lval.regno = rx_pid_register;
1385 rx_last_token = REG;
1390 if (strcmp (rx_lex_start, "%gpreg") == 0)
1393 rx_lval.regno = rx_gp_register;
1396 rx_last_token = REG;
1401 if (rx_last_token == 0)
1402 for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
1403 if (check_condition (condition_opcode_table[ci].string))
1407 rx_last_token = condition_opcode_table[ci].token;
1408 return condition_opcode_table[ci].token;
1411 for (i = 0; i < NUM_TOKENS; i++)
1412 if (strcasecmp (rx_lex_start, token_table[i].string) == 0
1413 && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
1414 && !(token_table[i].token == FLAG && !need_flag))
1416 rx_lval.regno = token_table[i].val;
1419 rx_last_token = token_table[i].token;
1420 return token_table[i].token;
1425 if (rx_last_token == 0)
1427 rx_last_token = UNKNOWN_OPCODE;
1428 return UNKNOWN_OPCODE;
1431 if (rx_last_token == UNKNOWN_OPCODE)
1434 if (*rx_lex_start == '[')
1436 if (*rx_lex_start == ']')
1440 || rx_last_token == REG
1441 || strchr ("[],#", *rx_lex_start))
1443 rx_last_token = *rx_lex_start;
1444 return *rx_lex_start ++;
1447 save_input_pointer = input_line_pointer;
1448 input_line_pointer = rx_lex_start;
1449 rx_lval.exp.X_md = 0;
1450 expression (&rx_lval.exp);
1452 /* We parse but ignore any :<size> modifier on expressions. */
1453 if (*input_line_pointer == ':')
1457 for (cp = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
1460 if (cp > input_line_pointer+1)
1461 input_line_pointer = cp;
1464 rx_lex_start = input_line_pointer;
1465 input_line_pointer = save_input_pointer;
1466 rx_last_token = EXPR;
1471 rx_error (const char * str)
1475 len = rx_last_exp_start - rx_init_start;
1477 as_bad ("%s", rx_init_start);
1478 as_bad ("%*s^ %s", len, "", str);
1483 rx_intop (expressionS exp, int nbits, int opbits)
1488 if (exp.X_op == O_big && nbits == 32)
1490 if (exp.X_op != O_constant)
1492 v = exp.X_add_number;
1494 msb = 1UL << (opbits - 1);
1495 mask = (1UL << opbits) - 1;
1497 if ((v & msb) && ! (v & ~mask))
1503 return -0x8 <= v && v <= 0x7;
1505 return -0x10 <= v && v <= 0x17;
1507 return -0x80 <= v && v <= 0x7f;
1509 return -0x8000 <= v && v <= 0x7fff;
1511 return -0x800000 <= v && v <= 0x7fffff;
1515 printf ("rx_intop passed %d\n", nbits);
1522 rx_uintop (expressionS exp, int nbits)
1526 if (exp.X_op != O_constant)
1528 v = exp.X_add_number;
1539 return v <= 0xffffff;
1541 printf ("rx_uintop passed %d\n", nbits);
1548 rx_disp3op (expressionS exp)
1552 if (exp.X_op != O_constant)
1554 v = exp.X_add_number;
1555 if (v < 3 || v > 10)
1561 rx_disp5op (expressionS * exp, int msize)
1565 if (exp->X_op != O_constant)
1567 v = exp->X_add_number;
1572 if (0 <= v && v <= 31)
1578 if (0 <= v && v <= 63)
1580 exp->X_add_number >>= 1;
1587 if (0 <= v && v <= 127)
1589 exp->X_add_number >>= 2;
1597 /* Just like the above, but allows a zero displacement. */
1600 rx_disp5op0 (expressionS * exp, int msize)
1602 if (exp->X_op != O_constant)
1604 if (exp->X_add_number == 0)
1606 return rx_disp5op (exp, msize);
1610 exp_val (expressionS exp)
1612 if (exp.X_op != O_constant)
1614 rx_error (_("constant expected"));
1617 return exp.X_add_number;
1623 /* Static, so program load sets it to all zeros, which is what we want. */
1624 static expressionS zero;
1625 zero.X_op = O_constant;
1630 immediate (expressionS exp, int type, int pos, int bits)
1632 /* We will emit constants ourself here, so negate them. */
1633 if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
1634 exp.X_add_number = - exp.X_add_number;
1635 if (type == RXREL_NEGATIVE_BORROW)
1637 if (exp.X_op == O_constant)
1638 exp.X_add_number = - exp.X_add_number - 1;
1640 rx_error (_("sbb cannot use symbolic immediates"));
1643 if (rx_intop (exp, 8, bits))
1645 rx_op (exp, 1, type);
1648 else if (rx_intop (exp, 16, bits))
1650 rx_op (exp, 2, type);
1653 else if (rx_uintop (exp, 16) && bits == 16)
1655 rx_op (exp, 2, type);
1658 else if (rx_intop (exp, 24, bits))
1660 rx_op (exp, 3, type);
1663 else if (rx_intop (exp, 32, bits))
1665 rx_op (exp, 4, type);
1668 else if (type == RXREL_SIGNED)
1670 /* This is a symbolic immediate, we will relax it later. */
1671 rx_relax (RX_RELAX_IMM, pos);
1672 rx_op (exp, linkrelax ? 4 : 1, type);
1677 /* Let the linker deal with it. */
1678 rx_op (exp, 4, type);
1684 displacement (expressionS exp, int msize)
1689 if (exp.X_op == O_symbol
1694 case BFD_RELOC_GPREL16:
1698 exp.X_md = BFD_RELOC_RX_GPRELB;
1701 exp.X_md = BFD_RELOC_RX_GPRELW;
1704 exp.X_md = BFD_RELOC_RX_GPRELL;
1712 if (exp.X_op == O_subtract)
1714 exp.X_md = BFD_RELOC_RX_DIFF;
1719 if (exp.X_op != O_constant)
1721 rx_error (_("displacements must be constants"));
1724 val = exp.X_add_number;
1735 rx_error (_("word displacement not word-aligned"));
1740 rx_error (_("long displacement not long-aligned"));
1744 as_bad (_("displacement with unknown size (internal bug?)\n"));
1749 exp.X_add_number = val;
1751 if (0 <= val && val <= 255 )
1757 if (0 <= val && val <= 65535)
1763 rx_error (_("negative displacements not allowed"));
1765 rx_error (_("displacement too large"));
1770 rtsd_immediate (expressionS exp)
1774 if (exp.X_op != O_constant)
1776 rx_error (_("rtsd size must be constant"));
1779 val = exp.X_add_number;
1781 rx_error (_("rtsd size must be multiple of 4"));
1783 if (val < 0 || val > 1020)
1784 rx_error (_("rtsd size must be 0..1020"));
1787 exp.X_add_number = val;
1792 rx_range (expressionS exp, int minv, int maxv)
1796 if (exp.X_op != O_constant)
1799 val = exp.X_add_number;
1800 if (val < minv || val > maxv)
1801 as_warn (_("Value %d out of range %d..%d"), val, minv, maxv);
1805 rx_check_float_support (void)
1807 if (rx_cpu == RX100 || rx_cpu == RX200)
1808 rx_error (_("target CPU type does not support floating point instructions"));
1815 rx_error (_("target CPU type does not support v2 instructions"));