Home | History | Annotate | Line # | Download | only in config
rx-parse.y revision 1.8
      1 /* rx-parse.y  Renesas RX parser
      2    Copyright (C) 2008-2022 Free Software Foundation, Inc.
      3 
      4    This file is part of GAS, the GNU Assembler.
      5 
      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)
      9    any later version.
     10 
     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.
     15 
     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
     19    02110-1301, USA.  */
     20 %{
     21 
     22 #include "as.h"
     23 #include "safe-ctype.h"
     24 #include "rx-defs.h"
     25 
     26 static int rx_lex (void);
     27 
     28 #define COND_EQ	0
     29 #define COND_NE	1
     30 
     31 #define MEMEX 0x06
     32 
     33 #define BSIZE 0
     34 #define WSIZE 1
     35 #define LSIZE 2
     36 #define DSIZE 3
     37 
     38 /*                       .sb    .sw    .l     .uw   */
     39 static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
     40 
     41 /* Ok, here are the rules for using these macros...
     42 
     43    B*() is used to specify the base opcode bytes.  Fields to be filled
     44         in later, leave zero.  Call this first.
     45 
     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().
     48 
     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
     53 
     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.
     58 
     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
     61    call them.
     62 
     63    Use "disp" for displacements whenever possible; this handles the
     64    "0" case properly.  */
     65 
     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)
     70 
     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);
     74 
     75 #define O1(v)              rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255)
     76 #define O2(v)              rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536)
     77 #define O3(v)              rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216)
     78 #define O4(v)              rx_op (v, 4, RXREL_SIGNED)
     79 
     80 #define UO1(v)             rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255)
     81 #define UO2(v)             rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536)
     82 #define UO3(v)             rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216)
     83 #define UO4(v)             rx_op (v, 4, RXREL_UNSIGNED)
     84 
     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)
     89 
     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)
     93 
     94 #define POST(v)            rx_post (v)
     95 
     96 #define IMM_(v,pos,size)   F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \
     97 			   if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
     98 #define IMM(v,pos)	   IMM_ (v, pos, 32)
     99 #define IMMW(v,pos)	   IMM_ (v, pos, 16); rx_range (v, -32768, 65536)
    100 #define IMMB(v,pos)	   IMM_ (v, pos, 8); rx_range (v, -128, 255)
    101 #define NIMM(v,pos)	   F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2)
    102 #define NBIMM(v,pos)	   F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2)
    103 #define DSP(v,pos,msz)	   if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
    104 			   else rx_linkrelax_dsp (pos); \
    105 			   F (displacement (v, msz), pos, 2)
    106 
    107 #define id24(a,b2,b3)	   B3 (0xfb + a, b2, b3)
    108 
    109 static void	   rx_check_float_support (void);
    110 static int         rx_intop (expressionS, int, int);
    111 static int         rx_uintop (expressionS, int);
    112 static int         rx_disp3op (expressionS);
    113 static int         rx_disp5op (expressionS *, int);
    114 static int         rx_disp5op0 (expressionS *, int);
    115 static int         exp_val (expressionS exp);
    116 static expressionS zero_expr (void);
    117 static int         immediate (expressionS, int, int, int);
    118 static int         displacement (expressionS, int);
    119 static void        rtsd_immediate (expressionS);
    120 static void	   rx_range (expressionS, int, int);
    121 static void        rx_check_v2 (void);
    122 static void        rx_check_v3 (void);
    123 static void        rx_check_dfpu (void);
    124 
    125 static int    need_flag = 0;
    126 static int    rx_in_brackets = 0;
    127 static int    rx_last_token = 0;
    128 static char * rx_init_start;
    129 static char * rx_last_exp_start = 0;
    130 static int    sub_op;
    131 static int    sub_op2;
    132 
    133 #define YYDEBUG 1
    134 #define YYERROR_VERBOSE 1
    135 
    136 %}
    137 
    138 %name-prefix="rx_"
    139 
    140 %union {
    141   int regno;
    142   expressionS exp;
    143 }
    144 
    145 %type <regno> REG FLAG CREG BCND BMCND SCCND ACC DREG DREGH DREGL DCREG DCMP
    146 %type <regno> flag bwl bw memex
    147 %type <exp> EXPR disp
    148 
    149 %token REG FLAG CREG ACC DREG DREGH DREGL DCREG
    150 
    151 %token EXPR UNKNOWN_OPCODE IS_OPCODE
    152 
    153 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW DOT_D
    154 
    155 %token ABS ADC ADD AND_
    156 %token BCLR BCND BFMOV BFMOVZ BMCND BNOT BRA BRK BSET BSR BTST
    157 %token CLRPSW CMP
    158 %token DABS DADD DBT DCMP DDIV DIV DIVU DMOV DMUL DNEG
    159 %token   DPOPM DPUSHM DROUND DSQRT DSUB DTOF DTOI DTOU
    160 %token EDIV EDIVU EMACA EMSBA EMUL EMULA EMULU
    161 %token FADD FCMP FDIV FMUL FREIT FSUB FSQRT FTOD FTOI FTOU
    162 %token INT ITOD ITOF
    163 %token JMP JSR
    164 %token MACHI MACLH MACLO MAX MIN MOV MOVCO MOVLI MOVU MSBHI MSBLH MSBLO MUL
    165 %token   MULHI MULLH MULLO MULU MVFACHI MVFACGU MVFACMI MVFACLO MVFC MVFDC
    166 %token     MVFDR MVTACGU MVTACHI MVTACLO MVTC MVTDC MVTIPL
    167 %token NEG NOP NOT
    168 %token OR
    169 %token POP POPC POPM PUSH PUSHA PUSHC PUSHM
    170 %token RACL RACW RDACL RDACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND
    171 %token   RSTR RTE RTFI RTS RTSD
    172 %token SAT SATR SAVE SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
    173 %token   SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
    174 %token TST
    175 %token UTOD UTOF
    176 %token WAIT
    177 %token XCHG XOR
    178 
    179 %%
    180 /* ====================================================================== */
    181 
    182 statement :
    183 
    184 	  UNKNOWN_OPCODE
    185 	  { as_bad (_("Unknown opcode: %s"), rx_init_start); }
    186 
    187 /* ---------------------------------------------------------------------- */
    188 
    189 	| BRK
    190 	  { B1 (0x00); }
    191 
    192 	| DBT
    193 	  { B1 (0x01); }
    194 
    195 	| RTS
    196 	  { B1 (0x02); }
    197 
    198 	| NOP
    199 	  { B1 (0x03); }
    200 
    201 /* ---------------------------------------------------------------------- */
    202 
    203 	| BRA EXPR
    204 	  { if (rx_disp3op ($2))
    205 	      { B1 (0x08); rx_disp3 ($2, 5); }
    206 	    else if (rx_intop ($2, 8, 8))
    207 	      { B1 (0x2e); PC1 ($2); }
    208 	    else if (rx_intop ($2, 16, 16))
    209 	      { B1 (0x38); PC2 ($2); }
    210 	    else if (rx_intop ($2, 24, 24))
    211 	      { B1 (0x04); PC3 ($2); }
    212 	    else
    213 	      { rx_relax (RX_RELAX_BRANCH, 0);
    214 		rx_linkrelax_branch ();
    215 		/* We'll convert this to a longer one later if needed.  */
    216 		B1 (0x08); rx_disp3 ($2, 5); } }
    217 
    218 	| BRA DOT_A EXPR
    219 	  { B1 (0x04); PC3 ($3); }
    220 
    221 	| BRA DOT_S EXPR
    222 	  { B1 (0x08); rx_disp3 ($3, 5); }
    223 
    224 /* ---------------------------------------------------------------------- */
    225 
    226 	| BSR EXPR
    227 	  { if (rx_intop ($2, 16, 16))
    228 	      { B1 (0x39); PC2 ($2); }
    229 	    else if (rx_intop ($2, 24, 24))
    230 	      { B1 (0x05); PC3 ($2); }
    231 	    else
    232 	      { rx_relax (RX_RELAX_BRANCH, 0);
    233 		rx_linkrelax_branch ();
    234 		B1 (0x39); PC2 ($2); } }
    235 	| BSR DOT_A EXPR
    236 	  { B1 (0x05), PC3 ($3); }
    237 
    238 /* ---------------------------------------------------------------------- */
    239 
    240 	| BCND DOT_S EXPR
    241 	  { if ($1 == COND_EQ || $1 == COND_NE)
    242 	      { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); }
    243 	    else
    244 	      as_bad (_("Only BEQ and BNE may have .S")); }
    245 
    246 /* ---------------------------------------------------------------------- */
    247 
    248 	| BCND DOT_B EXPR
    249 	  { B1 (0x20); F ($1, 4, 4); PC1 ($3); }
    250 
    251 	| BRA DOT_B EXPR
    252 	  { B1 (0x2e), PC1 ($3); }
    253 
    254 /* ---------------------------------------------------------------------- */
    255 
    256 	| BRA DOT_W EXPR
    257 	  { B1 (0x38), PC2 ($3); }
    258 	| BSR DOT_W EXPR
    259 	  { B1 (0x39), PC2 ($3); }
    260 	| BCND DOT_W EXPR
    261 	  { if ($1 == COND_EQ || $1 == COND_NE)
    262 	      { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); }
    263 	    else
    264 	      as_bad (_("Only BEQ and BNE may have .W")); }
    265 	| BCND EXPR
    266 	  { if ($1 == COND_EQ || $1 == COND_NE)
    267 	      {
    268 		rx_relax (RX_RELAX_BRANCH, 0);
    269 		rx_linkrelax_branch ();
    270 		B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5);
    271 	      }
    272 	    else
    273 	      {
    274 		rx_relax (RX_RELAX_BRANCH, 0);
    275 		/* This is because we might turn it into a
    276 		   jump-over-jump long branch.  */
    277 		rx_linkrelax_branch ();
    278 	        B1 (0x20); F ($1, 4, 4); PC1 ($2);
    279 	      } }
    280 
    281 /* ---------------------------------------------------------------------- */
    282 
    283 	| MOV DOT_B '#' EXPR ',' '[' REG ']'
    284 	  { B2 (0xf8, 0x04); F ($7, 8, 4); IMMB ($4, 12);}
    285 
    286 	| MOV DOT_W '#' EXPR ',' '[' REG ']'
    287           { B2 (0xf8, 0x01); F ($7, 8, 4); IMMW ($4, 12);}
    288 
    289 	| MOV DOT_L '#' EXPR ',' '[' REG ']'
    290 	  { B2 (0xf8, 0x02); F ($7, 8, 4); IMM ($4, 12);}
    291 
    292 	| MOV DOT_B '#' EXPR ',' disp '[' REG ']'
    293 	  /* rx_disp5op changes the value if it succeeds, so keep it last.  */
    294 	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE))
    295 	      { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
    296 	    else
    297 	      { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4);
    298 	      if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } }
    299 
    300 	| MOV DOT_W '#' EXPR ',' disp '[' REG ']'
    301 	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
    302 	      { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
    303 	    else
    304 	      { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } }
    305 
    306 	| MOV DOT_L '#' EXPR ',' disp '[' REG ']'
    307 	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
    308 	      { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
    309 	    else
    310 	      { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } }
    311 
    312 /* ---------------------------------------------------------------------- */
    313 
    314 	| RTSD '#' EXPR ',' REG '-' REG
    315 	  { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3);
    316 	    if ($5 == 0)
    317 	      rx_error (_("RTSD cannot pop R0"));
    318 	    if ($5 > $7)
    319 	      rx_error (_("RTSD first reg must be <= second reg")); }
    320 
    321 /* ---------------------------------------------------------------------- */
    322 
    323 	| CMP REG ',' REG
    324 	  { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); }
    325 
    326 /* ---------------------------------------------------------------------- */
    327 
    328 	| CMP disp '[' REG ']' DOT_UB ',' REG
    329 	  { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); }
    330 
    331 	| CMP disp '[' REG ']' memex ',' REG
    332 	  { B3 (MEMEX, 0x04, 0); F ($6, 8, 2);  F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); }
    333 
    334 /* ---------------------------------------------------------------------- */
    335 
    336 	| MOVU bw REG ',' REG
    337 	  { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); }
    338 
    339 /* ---------------------------------------------------------------------- */
    340 
    341 	| MOVU bw '[' REG ']' ',' REG
    342 	  { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); }
    343 
    344 	| MOVU bw EXPR '[' REG ']' ',' REG
    345 	  { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
    346 	      { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
    347 	    else
    348 	      { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
    349 
    350 /* ---------------------------------------------------------------------- */
    351 
    352 	| SUB '#' EXPR ',' REG
    353 	  { if (rx_uintop ($3, 4))
    354 	      { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    355 	    else
    356 	      /* This is really an add, but we negate the immediate.  */
    357 	      { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } }
    358 
    359 	| CMP '#' EXPR ',' REG
    360 	  { if (rx_uintop ($3, 4))
    361 	      { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    362 	    else if (rx_uintop ($3, 8))
    363 	      { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); }
    364 	    else
    365 	      { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } }
    366 
    367 	| ADD '#' EXPR ',' REG
    368 	  { if (rx_uintop ($3, 4))
    369 	      { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    370 	    else
    371 	      { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } }
    372 
    373 	| MUL '#' EXPR ',' REG
    374 	  { if (rx_uintop ($3, 4))
    375 	      { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    376 	    else
    377 	      { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } }
    378 
    379 	| AND_ '#' EXPR ',' REG
    380 	  { if (rx_uintop ($3, 4))
    381 	      { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    382 	    else
    383 	      { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } }
    384 
    385 	| OR '#' EXPR ',' REG
    386 	  { if (rx_uintop ($3, 4))
    387 	      { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    388 	    else
    389 	      { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } }
    390 
    391 	| MOV DOT_L '#' EXPR ',' REG
    392 	  { if (rx_uintop ($4, 4))
    393 	      { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); }
    394 	    else if (rx_uintop ($4, 8))
    395 	      { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); }
    396 	    else
    397 	      { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } }
    398 
    399 	| MOV '#' EXPR ',' REG
    400 	  { if (rx_uintop ($3, 4))
    401 	      { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    402 	    else if (rx_uintop ($3, 8))
    403 	      { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); }
    404 	    else
    405 	      { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } }
    406 
    407 /* ---------------------------------------------------------------------- */
    408 
    409 	| RTSD '#' EXPR
    410 	  { B1 (0x67); rtsd_immediate ($3); }
    411 
    412 /* ---------------------------------------------------------------------- */
    413 
    414 	| SHLR { sub_op = 0; } op_shift
    415 	| SHAR { sub_op = 1; } op_shift
    416 	| SHLL { sub_op = 2; } op_shift
    417 
    418 /* ---------------------------------------------------------------------- */
    419 
    420 	| PUSHM REG '-' REG
    421 	  {
    422 	    if ($2 == $4)
    423 	      { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); }
    424 	    else
    425 	     { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); }
    426 	    if ($2 == 0)
    427 	      rx_error (_("PUSHM cannot push R0"));
    428 	    if ($2 > $4)
    429 	      rx_error (_("PUSHM first reg must be <= second reg")); }
    430 
    431 /* ---------------------------------------------------------------------- */
    432 
    433 	| POPM REG '-' REG
    434 	  {
    435 	    if ($2 == $4)
    436 	      { B2 (0x7e, 0xb0); F ($2, 12, 4); }
    437 	    else
    438 	      { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); }
    439 	    if ($2 == 0)
    440 	      rx_error (_("POPM cannot pop R0"));
    441 	    if ($2 > $4)
    442 	      rx_error (_("POPM first reg must be <= second reg")); }
    443 
    444 /* ---------------------------------------------------------------------- */
    445 
    446 	| ADD '#' EXPR ',' REG ',' REG
    447 	  { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); }
    448 
    449 /* ---------------------------------------------------------------------- */
    450 
    451 	| INT '#' EXPR
    452 	  { B2(0x75, 0x60), UO1 ($3); }
    453 
    454 /* ---------------------------------------------------------------------- */
    455 
    456 	| BSET '#' EXPR ',' REG
    457 	  { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); }
    458 	| BCLR '#' EXPR ',' REG
    459 	  { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); }
    460 
    461 /* ---------------------------------------------------------------------- */
    462 
    463 	| BTST '#' EXPR ',' REG
    464 	  { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); }
    465 
    466 /* ---------------------------------------------------------------------- */
    467 
    468 	| SAT REG
    469 	  { B2 (0x7e, 0x30); F ($2, 12, 4); }
    470 	| RORC REG
    471 	  { B2 (0x7e, 0x40); F ($2, 12, 4); }
    472 	| ROLC REG
    473 	  { B2 (0x7e, 0x50); F ($2, 12, 4); }
    474 
    475 /* ---------------------------------------------------------------------- */
    476 
    477 	| PUSH bwl REG
    478 	  { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); }
    479 
    480 /* ---------------------------------------------------------------------- */
    481 
    482 	| POP REG
    483 	  { B2 (0x7e, 0xb0); F ($2, 12, 4); }
    484 
    485 /* ---------------------------------------------------------------------- */
    486 
    487 	| PUSHC CREG
    488 	  { if ($2 == 13)
    489 	      { rx_check_v2 (); }
    490 	    if ($2 < 16)
    491 	      { B2 (0x7e, 0xc0); F ($2, 12, 4); }
    492 	    else
    493 	      as_bad (_("PUSHC can only push the first 16 control registers")); }
    494 
    495 /* ---------------------------------------------------------------------- */
    496 
    497 	| POPC CREG
    498 	  { if ($2 == 13)
    499 	    { rx_check_v2 (); }
    500 	    if ($2 < 16)
    501 	      { B2 (0x7e, 0xe0); F ($2, 12, 4); }
    502 	    else
    503 	      as_bad (_("POPC can only pop the first 16 control registers")); }
    504 
    505 /* ---------------------------------------------------------------------- */
    506 
    507 	| SETPSW flag
    508 	  { B2 (0x7f, 0xa0); F ($2, 12, 4); }
    509 	| CLRPSW flag
    510 	  { B2 (0x7f, 0xb0); F ($2, 12, 4); }
    511 
    512 /* ---------------------------------------------------------------------- */
    513 
    514 	| JMP REG
    515 	  { B2 (0x7f, 0x00); F ($2, 12, 4); }
    516 	| JSR REG
    517 	  { B2 (0x7f, 0x10); F ($2, 12, 4); }
    518 	| BRA opt_l REG
    519 	  { B2 (0x7f, 0x40); F ($3, 12, 4); }
    520 	| BSR opt_l REG
    521 	  { B2 (0x7f, 0x50); F ($3, 12, 4); }
    522 
    523 /* ---------------------------------------------------------------------- */
    524 
    525 	| SCMPU
    526 	  { B2 (0x7f, 0x83); rx_note_string_insn_use (); }
    527 	| SMOVU
    528 	  { B2 (0x7f, 0x87); rx_note_string_insn_use (); }
    529 	| SMOVB
    530 	  { B2 (0x7f, 0x8b); rx_note_string_insn_use (); }
    531 	| SMOVF
    532 	  { B2 (0x7f, 0x8f); rx_note_string_insn_use (); }
    533 
    534 /* ---------------------------------------------------------------------- */
    535 
    536 	| SUNTIL bwl
    537 	  { B2 (0x7f, 0x80); F ($2, 14, 2); rx_note_string_insn_use (); }
    538 	| SWHILE bwl
    539 	  { B2 (0x7f, 0x84); F ($2, 14, 2); rx_note_string_insn_use (); }
    540 	| SSTR bwl
    541 	  { B2 (0x7f, 0x88); F ($2, 14, 2); }
    542 
    543 /* ---------------------------------------------------------------------- */
    544 
    545 	| RMPA bwl
    546 	  { B2 (0x7f, 0x8c); F ($2, 14, 2); rx_note_string_insn_use (); }
    547 
    548 /* ---------------------------------------------------------------------- */
    549 
    550 	| RTFI
    551 	  { B2 (0x7f, 0x94); }
    552 	| RTE
    553 	  { B2 (0x7f, 0x95); }
    554 	| WAIT
    555 	  { B2 (0x7f, 0x96); }
    556 	| SATR
    557 	  { B2 (0x7f, 0x93); }
    558 
    559 /* ---------------------------------------------------------------------- */
    560 
    561 	| MVTIPL '#' EXPR
    562 	  { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
    563 
    564 /* ---------------------------------------------------------------------- */
    565 
    566 	/* rx_disp5op changes the value if it succeeds, so keep it last.  */
    567 	| MOV bwl REG ',' EXPR '[' REG ']'
    568 	  { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2))
    569 	      { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); }
    570 	    else
    571 	      { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }}
    572 
    573 /* ---------------------------------------------------------------------- */
    574 
    575 	| MOV bwl EXPR '[' REG ']' ',' REG
    576 	  { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
    577 	      { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
    578 	    else
    579 	      { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
    580 
    581 /* ---------------------------------------------------------------------- */
    582 
    583 	/* MOV a,b - if a is a reg and b is mem, src and dest are
    584 	   swapped.  */
    585 
    586 	/* We don't use "disp" here because it causes a shift/reduce
    587 	   conflict with the other displacement-less patterns.  */
    588 
    589 	| MOV bwl REG ',' '[' REG ']'
    590 	  { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); }
    591 
    592 /* ---------------------------------------------------------------------- */
    593 
    594 	| MOV bwl '[' REG ']' ',' disp '[' REG ']'
    595 	  { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); }
    596 
    597 /* ---------------------------------------------------------------------- */
    598 
    599 	| MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']'
    600 	  { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); }
    601 
    602 /* ---------------------------------------------------------------------- */
    603 
    604 	| MOV bwl REG ',' REG
    605 	  { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); }
    606 
    607 /* ---------------------------------------------------------------------- */
    608 
    609 	| MOV bwl '[' REG ']' ',' REG
    610 	  { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); }
    611 
    612 /* ---------------------------------------------------------------------- */
    613 
    614 	| BSET '#' EXPR ',' disp '[' REG ']' DOT_B
    615 	  { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
    616 	| BCLR '#' EXPR ',' disp '[' REG ']' DOT_B
    617 	  { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
    618 	| BTST '#' EXPR ',' disp '[' REG ']' DOT_B
    619 	  { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
    620 
    621 /* ---------------------------------------------------------------------- */
    622 
    623 	| PUSH bwl disp '[' REG ']'
    624 	  { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); }
    625 
    626 /* ---------------------------------------------------------------------- */
    627 
    628 	| SBB   { sub_op = 0; } op_dp20_rm_l
    629 	| NEG   { sub_op = 1; sub_op2 = 1; } op_dp20_rr
    630 	| ADC   { sub_op = 2; } op_dp20_rim_l
    631 	| ABS   { sub_op = 3; sub_op2 = 2; } op_dp20_rr
    632 	| MAX   { sub_op = 4; } op_dp20_rim
    633 	| MIN   { sub_op = 5; } op_dp20_rim
    634 	| EMUL  { sub_op = 6; } op_dp20_i
    635 	| EMULU { sub_op = 7; } op_dp20_i
    636 	| DIV   { sub_op = 8; } op_dp20_rim
    637 	| DIVU  { sub_op = 9; } op_dp20_rim
    638 	| TST   { sub_op = 12; } op_dp20_rim
    639 	| XOR   { sub_op = 13; } op_xor
    640 	| NOT   { sub_op = 14; sub_op2 = 0; } op_dp20_rr
    641 	| STZ   { sub_op = 14; sub_op2 = 0; } op_dp20_ri
    642 	| STNZ  { sub_op = 15; sub_op2 = 1; } op_dp20_ri
    643 
    644 /* ---------------------------------------------------------------------- */
    645 
    646 	| EMUL  { sub_op = 6; } op_xchg
    647 	| EMULU { sub_op = 7; } op_xchg
    648 	| XCHG  { sub_op = 16; } op_xchg
    649 	| ITOF  { sub_op = 17; } op_xchg
    650 	| UTOF  { sub_op = 21; } op_xchg
    651 
    652 /* ---------------------------------------------------------------------- */
    653 
    654 	| BSET REG ',' REG
    655 	  { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    656 	| BCLR REG ',' REG
    657 	  { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    658 	| BTST REG ',' REG
    659 	  { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    660 	| BNOT REG ',' REG
    661 	  { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    662 
    663 	| BSET REG ',' disp '[' REG ']' opt_b
    664 	  { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    665 	| BCLR REG ',' disp '[' REG ']' opt_b
    666 	  { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    667 	| BTST REG ',' disp '[' REG ']' opt_b
    668 	  { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    669 	| BNOT REG ',' disp '[' REG ']' opt_b
    670 	  { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    671 
    672 /* ---------------------------------------------------------------------- */
    673 
    674 	| FSUB  { sub_op = 0; } float3_op
    675 	| FCMP  { sub_op = 1; } float2_op
    676 	| FADD  { sub_op = 2; } float3_op
    677 	| FMUL  { sub_op = 3; } float3_op
    678 	| FDIV  { sub_op = 4; } float2_op
    679 	| FSQRT { sub_op = 8; } float2_op_ni
    680 	| FTOI  { sub_op = 5; } float2_op_ni
    681 	| FTOU  { sub_op = 9; } float2_op_ni
    682 	| ROUND { sub_op = 6; } float2_op_ni
    683 
    684 /* ---------------------------------------------------------------------- */
    685 
    686 
    687 /* ---------------------------------------------------------------------- */
    688 
    689 	| SCCND DOT_L REG
    690 	  { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
    691 	| SCCND bwl disp '[' REG ']'
    692 	  { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); }
    693 
    694 /* ---------------------------------------------------------------------- */
    695 
    696 	| BMCND '#' EXPR ',' disp '[' REG ']' opt_b
    697 	  { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
    698 	      F ($7, 16, 4); DSP ($5, 14, BSIZE); }
    699 
    700 /* ---------------------------------------------------------------------- */
    701 
    702 	| BNOT '#' EXPR ',' disp '[' REG ']' opt_b
    703 	  { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
    704 	      DSP ($5, 14, BSIZE); }
    705 
    706 /* ---------------------------------------------------------------------- */
    707 
    708 	| MULHI REG ',' REG
    709 	  { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    710 	| MULHI REG ',' REG ',' ACC
    711 	  { rx_check_v2 (); id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    712 	| MULLO REG ',' REG
    713 	  { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    714 	| MULLO REG ',' REG ',' ACC
    715 	  { rx_check_v2 (); id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    716 	| MACHI REG ',' REG
    717 	  { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    718 	| MACHI REG ',' REG ',' ACC
    719 	  { rx_check_v2 (); id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    720 	| MACLO REG ',' REG
    721 	  { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    722 	|  MACLO REG ',' REG ',' ACC
    723 	  { rx_check_v2 (); id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    724 
    725 /* ---------------------------------------------------------------------- */
    726 
    727 	/* We don't have syntax for these yet.  */
    728 	| MVTACHI REG
    729 	  { id24 (2, 0x17, 0x00); F ($2, 20, 4); }
    730 	|  MVTACHI REG ',' ACC
    731 	  { rx_check_v2 (); id24 (2, 0x17, 0x00); F ($2, 20, 4); F ($4, 16, 1); }
    732 	| MVTACLO REG
    733 	  { id24 (2, 0x17, 0x10); F ($2, 20, 4); }
    734 	| MVTACLO REG ',' ACC
    735 	  { rx_check_v2 (); id24 (2, 0x17, 0x10); F ($2, 20, 4); F ($4, 16, 1); }
    736 	| MVFACHI REG
    737 	  { id24 (2, 0x1f, 0x00); F ($2, 20, 4); }
    738 	| MVFACHI { sub_op = 0; } mvfa_op
    739 	| MVFACMI REG
    740 	  { id24 (2, 0x1f, 0x20); F ($2, 20, 4); }
    741 	| MVFACMI { sub_op = 2; } mvfa_op
    742 	| MVFACLO REG
    743 	  { id24 (2, 0x1f, 0x10); F ($2, 20, 4); }
    744 	| MVFACLO { sub_op = 1; } mvfa_op
    745 	| RACW '#' EXPR
    746 	  { id24 (2, 0x18, 0x00);
    747 	    if (rx_uintop ($3, 4) && exp_val($3) == 1)
    748 	      ;
    749 	    else if (rx_uintop ($3, 4) && exp_val($3) == 2)
    750 	      F (1, 19, 1);
    751 	    else
    752 	      as_bad (_("RACW expects #1 or #2"));}
    753 	| RACW '#' EXPR ',' ACC
    754 	    { rx_check_v2 (); id24 (2, 0x18, 0x00); F ($5, 16, 1);
    755 	    if (rx_uintop ($3, 4) && exp_val($3) == 1)
    756 	      ;
    757 	    else if (rx_uintop ($3, 4) && exp_val($3) == 2)
    758 	      F (1, 19, 1);
    759 	    else
    760 	      as_bad (_("RACW expects #1 or #2"));}
    761 
    762 /* ---------------------------------------------------------------------- */
    763 
    764 	| MOV bwl REG ',' '[' REG '+' ']'
    765 	  { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); }
    766 	| MOV bwl REG ',' '[' '-' REG ']'
    767 	  { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); }
    768 
    769 /* ---------------------------------------------------------------------- */
    770 
    771 	| MOV bwl '[' REG '+' ']' ',' REG
    772 	  { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); }
    773 	| MOV bwl '[' '-' REG ']' ',' REG
    774 	  { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); }
    775 
    776 /* ---------------------------------------------------------------------- */
    777 
    778 	| MOVU bw '[' REG '+' ']' ','  REG
    779 	  { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); }
    780 	| MOVU bw '[' '-' REG ']' ',' REG
    781 	  { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); }
    782 
    783 /* ---------------------------------------------------------------------- */
    784 
    785 	| ROTL { sub_op = 6; } op_shift_rot
    786 	| ROTR { sub_op = 4; } op_shift_rot
    787 	| REVW { sub_op = 5; } op_shift_rot
    788 	| REVL { sub_op = 7; } op_shift_rot
    789 
    790 /* ---------------------------------------------------------------------- */
    791 
    792 	| MVTC REG ',' CREG
    793 	  { if ($4 == 13)
    794 	      rx_check_v2 ();
    795 	  id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1);
    796 	    F ($2, 16, 4); }
    797 
    798 /* ---------------------------------------------------------------------- */
    799 
    800 	| MVFC CREG ',' REG
    801 	  { if ($2 == 13)
    802 	    rx_check_v2 ();
    803 	  id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); }
    804 
    805 /* ---------------------------------------------------------------------- */
    806 
    807 	| ROTL '#' EXPR ',' REG
    808 	  { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); }
    809 	| ROTR '#' EXPR ',' REG
    810 	  { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); }
    811 
    812 /* ---------------------------------------------------------------------- */
    813 
    814 	| MVTC '#' EXPR ',' CREG
    815 	  { if ($5 == 13)
    816 	      rx_check_v2 ();
    817 	    id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); }
    818 
    819 /* ---------------------------------------------------------------------- */
    820 
    821 	| BMCND '#' EXPR ',' REG
    822 	  { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5);
    823 	      F ($5, 20, 4); }
    824 
    825 /* ---------------------------------------------------------------------- */
    826 
    827 	| BNOT '#' EXPR ',' REG
    828 	  { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); }
    829 
    830 /* ---------------------------------------------------------------------- */
    831 
    832 	| MOV bwl REG ',' '[' REG ',' REG ']'
    833 	  { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); }
    834 
    835 	| MOV bwl '[' REG ',' REG ']' ',' REG
    836 	  { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
    837 
    838 	| MOVU bw '[' REG ',' REG ']' ',' REG
    839 	  { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
    840 
    841 /* ---------------------------------------------------------------------- */
    842 
    843 	| SUB { sub_op = 0; } op_subadd
    844 	| ADD { sub_op = 2; } op_subadd
    845 	| MUL { sub_op = 3; } op_subadd
    846 	| AND_ { sub_op = 4; } op_subadd
    847 	| OR  { sub_op = 5; } op_subadd
    848 
    849 /* ---------------------------------------------------------------------- */
    850 /* There is no SBB #imm so we fake it with ADC.  */
    851 
    852 	| SBB '#' EXPR ',' REG
    853 	  { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); }
    854 
    855 /* ---------------------------------------------------------------------- */
    856 
    857 	| MOVCO REG ',' '[' REG ']'
    858 	  { rx_check_v2 (); B3 (0xfd, 0x27, 0x00); F ($5, 16, 4); F ($2, 20, 4); }
    859 
    860 /* ---------------------------------------------------------------------- */
    861 
    862 	| MOVLI '[' REG ']' ',' REG
    863 	  { rx_check_v2 (); B3 (0xfd, 0x2f, 0x00); F ($3, 16, 4); F ($6, 20, 4); }
    864 
    865 /* ---------------------------------------------------------------------- */
    866 
    867 	| EMACA REG ',' REG ',' ACC
    868 	  { rx_check_v2 (); id24 (2, 0x07, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    869 	| EMSBA REG ',' REG ',' ACC
    870 	  { rx_check_v2 (); id24 (2, 0x47, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    871 	| EMULA REG ',' REG ',' ACC
    872 	  { rx_check_v2 (); id24 (2, 0x03, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    873 	| MACLH REG ',' REG ',' ACC
    874 	  { rx_check_v2 (); id24 (2, 0x06, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    875 	| MSBHI REG ',' REG ',' ACC
    876 	  { rx_check_v2 (); id24 (2, 0x44, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    877 	| MSBLH REG ',' REG ',' ACC
    878 	  { rx_check_v2 (); id24 (2, 0x46, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    879 	| MSBLO REG ',' REG ',' ACC
    880 	  { rx_check_v2 (); id24 (2, 0x45, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    881 	| MULLH REG ',' REG ',' ACC
    882 	  { rx_check_v2 (); id24 (2, 0x02, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
    883 	| MVFACGU { sub_op = 3; } mvfa_op
    884 	| MVTACGU REG ',' ACC
    885 	  { rx_check_v2 (); id24 (2, 0x17, 0x30); F ($4, 16, 1); F ($2, 20, 4); }
    886 	| RACL '#' EXPR ',' ACC
    887 	{ rx_check_v2 (); id24 (2, 0x19, 0x00); F ($5, 16, 1);
    888 	    if (rx_uintop ($3, 4) && $3.X_add_number == 1)
    889 	      ;
    890 	    else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
    891 	      F (1, 19, 1);
    892 	    else
    893 	      as_bad (_("RACL expects #1 or #2"));}
    894 	| RDACL '#' EXPR ',' ACC
    895 	{ rx_check_v2 (); id24 (2, 0x19, 0x40); F ($5, 16, 1);
    896 	    if (rx_uintop ($3, 4) && $3.X_add_number == 1)
    897 	      ;
    898 	    else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
    899 	      F (1, 19, 1);
    900 	    else
    901 	      as_bad (_("RDACL expects #1 or #2"));}
    902 	| RDACW '#' EXPR ',' ACC
    903 	{ rx_check_v2 (); id24 (2, 0x18, 0x40); F ($5, 16, 1);
    904 	    if (rx_uintop ($3, 4) && $3.X_add_number == 1)
    905 	      ;
    906 	    else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
    907 	      F (1, 19, 1);
    908 	    else
    909 	      as_bad (_("RDACW expects #1 or #2"));}
    910 
    911 /* ---------------------------------------------------------------------- */
    912 	| BFMOV { rx_check_v3(); sub_op = 1; } op_bfield
    913 	| BFMOVZ { rx_check_v3(); sub_op = 0; } op_bfield
    914 
    915 /* ---------------------------------------------------------------------- */
    916 	| RSTR { rx_check_v3(); sub_op = 1; } op_save_rstr
    917 	| SAVE { rx_check_v3(); sub_op = 0; } op_save_rstr
    918 
    919 /* ---------------------------------------------------------------------- */
    920 	| DABS { rx_check_dfpu(); sub_op = 0x0c; sub_op2 = 0x01; } double2_op
    921 	| DNEG { rx_check_dfpu(); sub_op = 0x0c; sub_op2 = 0x02; } double2_op
    922 	| DROUND { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x0d; } double2_op
    923 	| DSQRT { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x00; } double2_op
    924 	| DTOF { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x0c; } double2_op
    925 	| DTOI { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x08;} double2_op
    926 	| DTOU { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x09; } double2_op
    927 	| DADD { rx_check_dfpu(); sub_op = 0x00; } double3_op
    928 	| DDIV { rx_check_dfpu(); sub_op = 0x05; } double3_op
    929 	| DMUL { rx_check_dfpu(); sub_op = 0x02; } double3_op
    930 	| DSUB { rx_check_dfpu(); sub_op = 0x01; } double3_op
    931 	| DCMP DREG ',' DREG { rx_check_dfpu();
    932 	    B4(0x76, 0x90, 0x08, 0x00); F($1, 24, 4); F($2, 28, 4); F($4, 16, 4); }
    933 	| DMOV DOT_D REG ',' DREGH
    934 	{ rx_check_dfpu();
    935 	  B4(0xfd, 0x77, 0x80, 0x03); F($3, 20, 4); F($5, 24, 4); }
    936 	| DMOV DOT_L REG ',' DREGH
    937 	{ rx_check_dfpu();
    938 	  B4(0xfd, 0x77, 0x80, 0x02); F($3, 20, 4); F($5, 24, 4); }
    939 	| DMOV DOT_L REG ',' DREGL
    940 	{ rx_check_dfpu();
    941 	  B4(0xfd, 0x77, 0x80, 0x00); F($3, 20, 4); F($5, 24, 4); }
    942 	| DMOV DOT_L DREGH ',' REG
    943 	{ rx_check_dfpu();
    944 	  B4(0xfd, 0x75, 0x80, 0x02); F($3, 24, 4); F($5, 20, 4); }
    945 	| DMOV DOT_L DREGL ',' REG
    946 	{ rx_check_dfpu();
    947 	  B4(0xfd, 0x75, 0x80, 0x00); F($3, 24, 4); F($5, 20, 4); }
    948 	| DMOV DOT_D DREG ',' DREG
    949 	{ rx_check_dfpu();
    950 	  B4(0x76, 0x90, 0x0c, 0x00); F($3, 16, 4); F($5, 24, 4); }
    951 	| DMOV DOT_D DREG ',' '[' REG ']'
    952 	{ rx_check_dfpu();
    953 	  B4(0xfc, 0x78, 0x08, 0x00); F($6, 16, 4); F($3, 24, 4); }
    954 	| DMOV DOT_D DREG ',' disp '[' REG ']'
    955 	{ rx_check_dfpu();
    956 	  B3(0xfc, 0x78, 0x08); F($7, 16, 4); DSP($5, 14, DSIZE);
    957 	  POST($3 << 4); }
    958 	| DMOV DOT_D '[' REG ']' ',' DREG
    959 	{ rx_check_dfpu();
    960 	  B4(0xfc, 0xc8, 0x08, 0x00); F($4, 16, 4); F($7, 24, 4); }
    961 	| DMOV DOT_D disp '[' REG ']' ',' DREG
    962 	{ rx_check_dfpu();
    963 	  B3(0xfc, 0xc8, 0x08); F($5, 16, 4); DSP($3, 14, DSIZE);
    964 	  POST($8 << 4); }
    965 	| DMOV DOT_D '#' EXPR ',' DREGH
    966 	{ rx_check_dfpu();
    967 	  B3(0xf9, 0x03, 0x03); F($6, 16, 4); IMM($4, -1); }
    968 	| DMOV DOT_L '#' EXPR ',' DREGH
    969 	{ rx_check_dfpu();
    970 	  B3(0xf9, 0x03, 0x02); F($6, 16, 4); IMM($4, -1); }
    971 	| DMOV DOT_L '#' EXPR ',' DREGL
    972 	{ rx_check_dfpu();
    973 	  B3(0xf9, 0x03, 0x00); F($6, 16, 4); IMM($4, -1); }
    974 	| DPOPM DOT_D DREG '-' DREG
    975 	{ rx_check_dfpu();
    976 	  B3(0x75, 0xb8, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
    977 	| DPOPM DOT_L DCREG '-' DCREG
    978 	{ rx_check_dfpu();
    979 	  B3(0x75, 0xa8, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
    980 	| DPUSHM DOT_D DREG '-' DREG
    981 	{ rx_check_dfpu();
    982 	  B3(0x75, 0xb0, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
    983 	| DPUSHM DOT_L DCREG '-' DCREG
    984 	{ rx_check_dfpu();
    985 	  B3(0x75, 0xa0, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
    986 	| MVFDC DCREG ',' REG
    987 	{ rx_check_dfpu();
    988 	  B4(0xfd, 0x75, 0x80, 0x04); F($2, 24, 4); F($4, 20, 4); }
    989 	| MVFDR
    990 	{ rx_check_dfpu(); B3(0x75, 0x90, 0x1b); }
    991 	| MVTDC REG ',' DCREG
    992 	{ rx_check_dfpu();
    993 	  B4(0xfd, 0x77, 0x80, 0x04); F($2, 24, 4); F($4, 20, 4); }
    994 	| FTOD REG ',' DREG
    995 	{ rx_check_dfpu();
    996 	  B4(0xfd, 0x77, 0x80, 0x0a); F($2, 24, 4); F($4, 20, 4); }
    997 	| ITOD REG ',' DREG
    998 	{ rx_check_dfpu();
    999 	  B4(0xfd, 0x77, 0x80, 0x09); F($2, 24, 4); F($4, 20, 4); }
   1000 	| UTOD REG ',' DREG
   1001 	{ rx_check_dfpu();
   1002 	  B4(0xfd, 0x77, 0x80, 0x0d); F($2, 24, 4); F($4, 20, 4); }
   1003 
   1004 /* ---------------------------------------------------------------------- */
   1005 
   1006 	;
   1007 
   1008 /* ====================================================================== */
   1009 
   1010 op_subadd
   1011 	: REG ',' REG
   1012 	  { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); }
   1013 	| disp '[' REG ']' DOT_UB ',' REG
   1014 	  { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); }
   1015 	| disp '[' REG ']' memex ',' REG
   1016 	  { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); }
   1017 	| REG ',' REG ',' REG
   1018 	  { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
   1019 	;
   1020 
   1021 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
   1022 
   1023 op_dp20_rm_l
   1024 	: REG ',' REG
   1025 	  { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
   1026 	| disp '[' REG ']' opt_l ',' REG
   1027 	  { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00);
   1028 	  F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); }
   1029 	;
   1030 
   1031 /* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
   1032 
   1033 op_dp20_rm
   1034 	: REG ',' REG
   1035 	  { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
   1036 	| disp '[' REG ']' DOT_UB ',' REG
   1037 	  { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
   1038 	| disp '[' REG ']' memex ',' REG
   1039 	  { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00);
   1040 	  F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); }
   1041 	;
   1042 
   1043 op_dp20_i
   1044 	: '#' EXPR ',' REG
   1045 	  { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); }
   1046 	;
   1047 
   1048 op_dp20_rim
   1049 	: op_dp20_rm
   1050 	| op_dp20_i
   1051 	;
   1052 
   1053 op_dp20_rim_l
   1054 	: op_dp20_rm_l
   1055 	| op_dp20_i
   1056 	;
   1057 
   1058 op_dp20_rr
   1059 	: REG ',' REG
   1060 	  { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
   1061 	| REG
   1062 	  { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
   1063 	;
   1064 
   1065 op_dp20_r
   1066 	: REG ',' REG
   1067 	  { id24 (1, 0x4b + (sub_op2<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
   1068 	;
   1069 
   1070 op_dp20_ri
   1071 	: { rx_check_v2 (); }
   1072 	  op_dp20_r
   1073 	| op_dp20_i
   1074 	;
   1075 
   1076 /* xchg, utof, itof, emul, emulu */
   1077 op_xchg
   1078 	: REG ',' REG
   1079 	  { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); }
   1080 	| disp '[' REG ']' DOT_UB ',' REG
   1081 	  { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
   1082 	| disp '[' REG ']' memex ',' REG
   1083 	  { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4);
   1084 	    DSP ($1, 14, sizemap[$5]); }
   1085 	;
   1086 
   1087 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
   1088 op_shift_rot
   1089 	: REG ',' REG
   1090 	  { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); }
   1091 	;
   1092 op_shift
   1093 	: '#' EXPR ',' REG
   1094 	  { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); }
   1095 	| '#' EXPR ',' REG ',' REG
   1096 	  { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); }
   1097 	| op_shift_rot
   1098 	;
   1099 
   1100 float3_op
   1101 	: '#' EXPR ',' REG
   1102 	  { rx_check_float_support (); id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
   1103 	| REG ',' REG
   1104 	  { rx_check_float_support (); id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
   1105 	| disp '[' REG ']' opt_l ',' REG
   1106 	  { rx_check_float_support (); id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
   1107 	| REG ',' REG ',' REG
   1108 	  { rx_check_v2 (); id24 (4, 0x80 + (sub_op << 4), 0 ); F ($1, 16, 4); F ($3, 20, 4); F ($5, 12, 4); }
   1109 	;
   1110 
   1111 float2_op
   1112 	: { rx_check_float_support (); }
   1113 	  '#' EXPR ',' REG
   1114 	  { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); }
   1115 	| float2_op_ni
   1116 	;
   1117 
   1118 float2_op_ni
   1119 	: { rx_check_float_support (); }
   1120 	  REG ',' REG
   1121 	  { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); }
   1122 	| { rx_check_float_support (); }
   1123 	  disp '[' REG ']' opt_l ',' REG
   1124 	  { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); }
   1125 	;
   1126 
   1127 mvfa_op
   1128 	: { rx_check_v2 (); }
   1129 	  '#' EXPR ',' ACC ',' REG
   1130 	  { id24 (2, 0x1e, sub_op << 4); F ($7, 20, 4); F ($5, 16, 1);
   1131 	    if (rx_uintop ($3, 4))
   1132 	      {
   1133 		switch (exp_val ($3))
   1134 		  {
   1135 		  case 0:
   1136 		    F (1, 15, 1);
   1137 		    break;
   1138 		  case 1:
   1139 		    F (1, 15, 1);
   1140 		    F (1, 17, 1);
   1141 		    break;
   1142 		  case 2:
   1143 		    break;
   1144 		  default:
   1145 		    as_bad (_("IMM expects #0 to #2"));}
   1146 	      } else
   1147 	        as_bad (_("IMM expects #0 to #2"));}
   1148 	;
   1149 
   1150 op_xor
   1151 	: op_dp20_rim
   1152 	| REG ',' REG ',' REG
   1153 	  { rx_check_v3(); B3(0xff,0x60,0x00), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
   1154 	;
   1155 
   1156 op_bfield
   1157 	: { rx_check_v3(); }
   1158 	  '#' EXPR ',' '#' EXPR ',' '#' EXPR ',' REG ',' REG
   1159 	  { rx_range($3, 0, 31); rx_range($6, 0, 31); rx_range($9, 1, 31);
   1160 	    B3(0xfc, 0x5a + (sub_op << 2), 0); F($11, 16, 4); F($13, 20, 4);
   1161 	  rx_bfield($3, $6, $9);}
   1162 	;
   1163 
   1164 op_save_rstr
   1165 	: '#' EXPR
   1166 	  { B3(0xfd,0x76,0xe0 + (sub_op << 4)); UO1($2); }
   1167 	| REG
   1168 	  { B4(0xfd,0x76,0xc0 + (sub_op << 4), 0x00); F($1, 20, 4); }
   1169 	;
   1170 
   1171 double2_op
   1172 	: DREG ',' DREG
   1173 	{ B4(0x76, 0x90, sub_op, sub_op2); F($1, 16, 4); F($3, 24, 4);}
   1174 
   1175 double3_op
   1176 	: DREG ',' DREG ',' DREG
   1177 	{ B4(0x76, 0x90, sub_op, 0x00); F($1, 28, 4); F($3, 16,4); F($5, 24, 4);}
   1178 
   1179 /* ====================================================================== */
   1180 
   1181 disp	:      { $$ = zero_expr (); }
   1182 	| EXPR { $$ = $1; }
   1183 	;
   1184 
   1185 flag	: { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
   1186 	;
   1187 
   1188 /* DOT_UB is not listed here, it's handled with a separate pattern.  */
   1189 /* Use sizemap[$n] to get LSIZE etc.  */
   1190 memex	: DOT_B  { $$ = 0; }
   1191 	| DOT_W  { $$ = 1; }
   1192 	|        { $$ = 2; }
   1193 	| DOT_L  { $$ = 2; }
   1194 	| DOT_UW { $$ = 3; }
   1195 	;
   1196 
   1197 bwl	:       { $$ = LSIZE; }
   1198 	| DOT_B { $$ = BSIZE; }
   1199 	| DOT_W { $$ = WSIZE; }
   1200 	| DOT_L { $$ = LSIZE; }
   1201 	;
   1202 
   1203 bw	:       { $$ = 1; }
   1204 	| DOT_B { $$ = 0; }
   1205 	| DOT_W { $$ = 1; }
   1206 	;
   1207 
   1208 opt_l	: 	{}
   1209 	| DOT_L {}
   1210 	;
   1211 
   1212 opt_b	: 	{}
   1213 	| DOT_B {}
   1214 	;
   1215 
   1216 %%
   1217 /* ====================================================================== */
   1218 
   1219 static struct
   1220 {
   1221   const char * string;
   1222   int          token;
   1223   int          val;
   1224 }
   1225 token_table[] =
   1226 {
   1227   { "r0", REG, 0 },
   1228   { "r1", REG, 1 },
   1229   { "r2", REG, 2 },
   1230   { "r3", REG, 3 },
   1231   { "r4", REG, 4 },
   1232   { "r5", REG, 5 },
   1233   { "r6", REG, 6 },
   1234   { "r7", REG, 7 },
   1235   { "r8", REG, 8 },
   1236   { "r9", REG, 9 },
   1237   { "r10", REG, 10 },
   1238   { "r11", REG, 11 },
   1239   { "r12", REG, 12 },
   1240   { "r13", REG, 13 },
   1241   { "r14", REG, 14 },
   1242   { "r15", REG, 15 },
   1243 
   1244   { "psw", CREG, 0 },
   1245   { "pc", CREG, 1 },
   1246   { "usp", CREG, 2 },
   1247   { "fpsw", CREG, 3 },
   1248   /* reserved */
   1249   /* reserved */
   1250   /* reserved */
   1251   { "wr", CREG, 7 },
   1252 
   1253   { "bpsw", CREG, 8 },
   1254   { "bpc", CREG, 9 },
   1255   { "isp", CREG, 10 },
   1256   { "fintv", CREG, 11 },
   1257   { "intb", CREG, 12 },
   1258   { "extb", CREG, 13 },
   1259 
   1260   { "pbp", CREG, 16 },
   1261   { "pben", CREG, 17 },
   1262 
   1263   { "bbpsw", CREG, 24 },
   1264   { "bbpc", CREG, 25 },
   1265 
   1266   { "dr0", DREG, 0 },
   1267   { "dr1", DREG, 1 },
   1268   { "dr2", DREG, 2 },
   1269   { "dr3", DREG, 3 },
   1270   { "dr4", DREG, 4 },
   1271   { "dr5", DREG, 5 },
   1272   { "dr6", DREG, 6 },
   1273   { "dr7", DREG, 7 },
   1274   { "dr8", DREG, 8 },
   1275   { "dr9", DREG, 9 },
   1276   { "dr10", DREG, 10 },
   1277   { "dr11", DREG, 11 },
   1278   { "dr12", DREG, 12 },
   1279   { "dr13", DREG, 13 },
   1280   { "dr14", DREG, 14 },
   1281   { "dr15", DREG, 15 },
   1282 
   1283   { "drh0", DREGH, 0 },
   1284   { "drh1", DREGH, 1 },
   1285   { "drh2", DREGH, 2 },
   1286   { "drh3", DREGH, 3 },
   1287   { "drh4", DREGH, 4 },
   1288   { "drh5", DREGH, 5 },
   1289   { "drh6", DREGH, 6 },
   1290   { "drh7", DREGH, 7 },
   1291   { "drh8", DREGH, 8 },
   1292   { "drh9", DREGH, 9 },
   1293   { "drh10", DREGH, 10 },
   1294   { "drh11", DREGH, 11 },
   1295   { "drh12", DREGH, 12 },
   1296   { "drh13", DREGH, 13 },
   1297   { "drh14", DREGH, 14 },
   1298   { "drh15", DREGH, 15 },
   1299 
   1300   { "drl0", DREGL, 0 },
   1301   { "drl1", DREGL, 1 },
   1302   { "drl2", DREGL, 2 },
   1303   { "drl3", DREGL, 3 },
   1304   { "drl4", DREGL, 4 },
   1305   { "drl5", DREGL, 5 },
   1306   { "drl6", DREGL, 6 },
   1307   { "drl7", DREGL, 7 },
   1308   { "drl8", DREGL, 8 },
   1309   { "drl9", DREGL, 9 },
   1310   { "drl10", DREGL, 10 },
   1311   { "drl11", DREGL, 11 },
   1312   { "drl12", DREGL, 12 },
   1313   { "drl13", DREGL, 13 },
   1314   { "drl14", DREGL, 14 },
   1315   { "drl15", DREGL, 15 },
   1316 
   1317   { "DPSW", DCREG, 0 },
   1318   { "DCMR", DCREG, 1 },
   1319   { "DECNT", DCREG, 2 },
   1320   { "DEPC", DCREG, 3 },
   1321   { "DCR0", DCREG, 0 },
   1322   { "DCR1", DCREG, 1 },
   1323   { "DCR2", DCREG, 2 },
   1324   { "DCR3", DCREG, 3 },
   1325 
   1326   { ".s", DOT_S, 0 },
   1327   { ".b", DOT_B, 0 },
   1328   { ".w", DOT_W, 0 },
   1329   { ".l", DOT_L, 0 },
   1330   { ".a", DOT_A , 0},
   1331   { ".ub", DOT_UB, 0 },
   1332   { ".uw", DOT_UW , 0},
   1333   { ".d", DOT_D , 0},
   1334 
   1335   { "c", FLAG, 0 },
   1336   { "z", FLAG, 1 },
   1337   { "s", FLAG, 2 },
   1338   { "o", FLAG, 3 },
   1339   { "i", FLAG, 8 },
   1340   { "u", FLAG, 9 },
   1341 
   1342   { "a0", ACC, 0 },
   1343   { "a1", ACC, 1 },
   1344 
   1345 #define OPC(x) { #x, x, IS_OPCODE }
   1346   OPC(ABS),
   1347   OPC(ADC),
   1348   OPC(ADD),
   1349   { "and", AND_, IS_OPCODE },
   1350   OPC(BCLR),
   1351   OPC(BCND),
   1352   OPC(BFMOV),
   1353   OPC(BFMOVZ),
   1354   OPC(BMCND),
   1355   OPC(BNOT),
   1356   OPC(BRA),
   1357   OPC(BRK),
   1358   OPC(BSET),
   1359   OPC(BSR),
   1360   OPC(BTST),
   1361   OPC(CLRPSW),
   1362   OPC(CMP),
   1363   OPC(DABS),
   1364   OPC(DADD),
   1365   OPC(DBT),
   1366   OPC(DDIV),
   1367   OPC(DIV),
   1368   OPC(DIVU),
   1369   OPC(DMOV),
   1370   OPC(DMUL),
   1371   OPC(DNEG),
   1372   OPC(DPOPM),
   1373   OPC(DPUSHM),
   1374   OPC(DROUND),
   1375   OPC(DSQRT),
   1376   OPC(DSUB),
   1377   OPC(DTOF),
   1378   OPC(DTOI),
   1379   OPC(DTOU),
   1380   OPC(EDIV),
   1381   OPC(EDIVU),
   1382   OPC(EMACA),
   1383   OPC(EMSBA),
   1384   OPC(EMUL),
   1385   OPC(EMULA),
   1386   OPC(EMULU),
   1387   OPC(FADD),
   1388   OPC(FCMP),
   1389   OPC(FDIV),
   1390   OPC(FMUL),
   1391   OPC(FREIT),
   1392   OPC(FSQRT),
   1393   OPC(FTOD),
   1394   OPC(FTOU),
   1395   OPC(FSUB),
   1396   OPC(FTOI),
   1397   OPC(INT),
   1398   OPC(ITOD),
   1399   OPC(ITOF),
   1400   OPC(JMP),
   1401   OPC(JSR),
   1402   OPC(MVFACGU),
   1403   OPC(MVFACHI),
   1404   OPC(MVFACMI),
   1405   OPC(MVFACLO),
   1406   OPC(MVFC),
   1407   OPC(MVFDC),
   1408   OPC(MVFDR),
   1409   OPC(MVTDC),
   1410   OPC(MVTACGU),
   1411   OPC(MVTACHI),
   1412   OPC(MVTACLO),
   1413   OPC(MVTC),
   1414   OPC(MVTIPL),
   1415   OPC(MACHI),
   1416   OPC(MACLO),
   1417   OPC(MACLH),
   1418   OPC(MAX),
   1419   OPC(MIN),
   1420   OPC(MOV),
   1421   OPC(MOVCO),
   1422   OPC(MOVLI),
   1423   OPC(MOVU),
   1424   OPC(MSBHI),
   1425   OPC(MSBLH),
   1426   OPC(MSBLO),
   1427   OPC(MUL),
   1428   OPC(MULHI),
   1429   OPC(MULLH),
   1430   OPC(MULLO),
   1431   OPC(MULU),
   1432   OPC(NEG),
   1433   OPC(NOP),
   1434   OPC(NOT),
   1435   OPC(OR),
   1436   OPC(POP),
   1437   OPC(POPC),
   1438   OPC(POPM),
   1439   OPC(PUSH),
   1440   OPC(PUSHA),
   1441   OPC(PUSHC),
   1442   OPC(PUSHM),
   1443   OPC(RACL),
   1444   OPC(RACW),
   1445   OPC(RDACL),
   1446   OPC(RDACW),
   1447   OPC(REIT),
   1448   OPC(REVL),
   1449   OPC(REVW),
   1450   OPC(RMPA),
   1451   OPC(ROLC),
   1452   OPC(RORC),
   1453   OPC(ROTL),
   1454   OPC(ROTR),
   1455   OPC(ROUND),
   1456   OPC(RSTR),
   1457   OPC(RTE),
   1458   OPC(RTFI),
   1459   OPC(RTS),
   1460   OPC(RTSD),
   1461   OPC(SAT),
   1462   OPC(SATR),
   1463   OPC(SAVE),
   1464   OPC(SBB),
   1465   OPC(SCCND),
   1466   OPC(SCMPU),
   1467   OPC(SETPSW),
   1468   OPC(SHAR),
   1469   OPC(SHLL),
   1470   OPC(SHLR),
   1471   OPC(SMOVB),
   1472   OPC(SMOVF),
   1473   OPC(SMOVU),
   1474   OPC(SSTR),
   1475   OPC(STNZ),
   1476   OPC(STOP),
   1477   OPC(STZ),
   1478   OPC(SUB),
   1479   OPC(SUNTIL),
   1480   OPC(SWHILE),
   1481   OPC(TST),
   1482   OPC(UTOD),
   1483   OPC(UTOF),
   1484   OPC(WAIT),
   1485   OPC(XCHG),
   1486   OPC(XOR),
   1487 };
   1488 
   1489 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
   1490 
   1491 static struct
   1492 {
   1493   const char * string;
   1494   int    token;
   1495 }
   1496 condition_opcode_table[] =
   1497 {
   1498   { "b", BCND },
   1499   { "bm", BMCND },
   1500   { "sc", SCCND },
   1501 };
   1502 
   1503 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
   1504 
   1505 struct condition_symbol
   1506 {
   1507   const char * string;
   1508   int    val;
   1509 };
   1510 
   1511 static struct condition_symbol condition_table[] =
   1512 {
   1513   { "z", 0 },
   1514   { "eq", 0 },
   1515   { "geu",  2 },
   1516   { "c",  2 },
   1517   { "gtu", 4 },
   1518   { "pz", 6 },
   1519   { "ge", 8 },
   1520   { "gt", 10 },
   1521   { "o",  12},
   1522   /* always = 14 */
   1523   { "nz", 1 },
   1524   { "ne", 1 },
   1525   { "ltu", 3 },
   1526   { "nc", 3 },
   1527   { "leu", 5 },
   1528   { "n", 7 },
   1529   { "lt", 9 },
   1530   { "le", 11 },
   1531   { "no", 13 },
   1532   /* never = 15 */
   1533 };
   1534 
   1535 static struct condition_symbol double_condition_table[] =
   1536 {
   1537   { "un", 1 },
   1538   { "eq", 2 },
   1539   { "lt", 4 },
   1540   { "le", 6 },
   1541 };
   1542 
   1543 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
   1544 #define NUM_DOUBLE_CONDITIONS (sizeof (double_condition_table) / sizeof (double_condition_table[0]))
   1545 
   1546 void
   1547 rx_lex_init (char * beginning, char * ending)
   1548 {
   1549   rx_init_start = beginning;
   1550   rx_lex_start = beginning;
   1551   rx_lex_end = ending;
   1552   rx_in_brackets = 0;
   1553   rx_last_token = 0;
   1554 
   1555   setbuf (stdout, 0);
   1556 }
   1557 
   1558 static int
   1559 check_condition (const char * base, struct condition_symbol *t, unsigned int num)
   1560 {
   1561   char * cp;
   1562   unsigned int i;
   1563 
   1564   if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
   1565     return 0;
   1566   if (memcmp (rx_lex_start, base, strlen (base)))
   1567     return 0;
   1568   cp = rx_lex_start + strlen (base);
   1569   for (i = 0; i < num; i ++)
   1570     {
   1571       if (strcasecmp (cp, t[i].string) == 0)
   1572 	{
   1573 	  rx_lval.regno = t[i].val;
   1574 	  return 1;
   1575 	}
   1576     }
   1577   return 0;
   1578 }
   1579 
   1580 static int
   1581 rx_lex (void)
   1582 {
   1583   unsigned int ci;
   1584   char * save_input_pointer;
   1585 
   1586   while (ISSPACE (*rx_lex_start)
   1587 	 && rx_lex_start != rx_lex_end)
   1588     rx_lex_start ++;
   1589 
   1590   rx_last_exp_start = rx_lex_start;
   1591 
   1592   if (rx_lex_start == rx_lex_end)
   1593     return 0;
   1594 
   1595   if (ISALPHA (*rx_lex_start)
   1596       || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0)
   1597       || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0)
   1598       || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
   1599     {
   1600       unsigned int i;
   1601       char * e;
   1602       char save;
   1603 
   1604       for (e = rx_lex_start + 1;
   1605 	   e < rx_lex_end && ISALNUM (*e);
   1606 	   e ++)
   1607 	;
   1608       save = *e;
   1609       *e = 0;
   1610 
   1611       if (strcmp (rx_lex_start, "%pidreg") == 0)
   1612 	{
   1613 	  {
   1614 	    rx_lval.regno = rx_pid_register;
   1615 	    *e = save;
   1616 	    rx_lex_start = e;
   1617 	    rx_last_token = REG;
   1618 	    return REG;
   1619 	  }
   1620 	}
   1621 
   1622       if (strcmp (rx_lex_start, "%gpreg") == 0)
   1623 	{
   1624 	  {
   1625 	    rx_lval.regno = rx_gp_register;
   1626 	    *e = save;
   1627 	    rx_lex_start = e;
   1628 	    rx_last_token = REG;
   1629 	    return REG;
   1630 	  }
   1631 	}
   1632 
   1633       if (rx_last_token == 0)
   1634 	{
   1635 	  for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
   1636 	    if (check_condition (condition_opcode_table[ci].string,
   1637 				 condition_table, NUM_CONDITIONS))
   1638 	      {
   1639 		*e = save;
   1640 		rx_lex_start = e;
   1641 		rx_last_token = condition_opcode_table[ci].token;
   1642 		return condition_opcode_table[ci].token;
   1643 	      }
   1644 	  if  (check_condition ("dcmp", double_condition_table,
   1645 				NUM_DOUBLE_CONDITIONS))
   1646 	    {
   1647 	      *e = save;
   1648 	      rx_lex_start = e;
   1649 	      rx_last_token = DCMP;
   1650 	      return DCMP;
   1651 	    }
   1652 	}
   1653 
   1654       for (i = 0; i < NUM_TOKENS; i++)
   1655 	if (strcasecmp (rx_lex_start, token_table[i].string) == 0
   1656 	    && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
   1657 	    && !(token_table[i].token == FLAG && !need_flag))
   1658 	  {
   1659 	    rx_lval.regno = token_table[i].val;
   1660 	    *e = save;
   1661 	    rx_lex_start = e;
   1662 	    rx_last_token = token_table[i].token;
   1663 	    return token_table[i].token;
   1664 	  }
   1665       *e = save;
   1666     }
   1667 
   1668   if (rx_last_token == 0)
   1669     {
   1670       rx_last_token = UNKNOWN_OPCODE;
   1671       return UNKNOWN_OPCODE;
   1672     }
   1673 
   1674   if (rx_last_token == UNKNOWN_OPCODE)
   1675     return 0;
   1676 
   1677   if (*rx_lex_start == '[')
   1678     rx_in_brackets = 1;
   1679   if (*rx_lex_start == ']')
   1680     rx_in_brackets = 0;
   1681 
   1682   if (rx_in_brackets
   1683       || rx_last_token == REG || rx_last_token == DREG || rx_last_token == DCREG
   1684       || strchr ("[],#", *rx_lex_start))
   1685     {
   1686       rx_last_token = *rx_lex_start;
   1687       return *rx_lex_start ++;
   1688     }
   1689 
   1690   save_input_pointer = input_line_pointer;
   1691   input_line_pointer = rx_lex_start;
   1692   rx_lval.exp.X_md = 0;
   1693   expression (&rx_lval.exp);
   1694 
   1695   /* We parse but ignore any :<size> modifier on expressions.  */
   1696   if (*input_line_pointer == ':')
   1697     {
   1698       char *cp;
   1699 
   1700       for (cp  = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
   1701 	if (!ISDIGIT (*cp))
   1702 	  break;
   1703       if (cp > input_line_pointer+1)
   1704 	input_line_pointer = cp;
   1705     }
   1706 
   1707   rx_lex_start = input_line_pointer;
   1708   input_line_pointer = save_input_pointer;
   1709   rx_last_token = EXPR;
   1710   return EXPR;
   1711 }
   1712 
   1713 int
   1714 rx_error (const char * str)
   1715 {
   1716   int len;
   1717 
   1718   len = rx_last_exp_start - rx_init_start;
   1719 
   1720   as_bad ("%s", rx_init_start);
   1721   as_bad ("%*s^ %s", len, "", str);
   1722   return 0;
   1723 }
   1724 
   1725 static int
   1726 rx_intop (expressionS exp, int nbits, int opbits)
   1727 {
   1728   valueT v;
   1729   valueT mask, msb;
   1730 
   1731   if (exp.X_op == O_big)
   1732     {
   1733       if (nbits == 32)
   1734 	return 1;
   1735       if (exp.X_add_number == -1)
   1736 	return 0;
   1737     }
   1738   else if (exp.X_op != O_constant)
   1739     return 0;
   1740   v = exp.X_add_number;
   1741 
   1742   msb = (valueT) 1 << (opbits - 1);
   1743   mask = (msb << 1) - 1;
   1744 
   1745   if ((v & msb) && ! (v & ~mask))
   1746     v -= mask + 1;
   1747 
   1748   switch (nbits)
   1749     {
   1750     case 4:
   1751       return v + 0x8 <= 0x7 + 0x8;
   1752     case 5:
   1753       return v + 0x10 <= 0xf + 0x10;
   1754     case 8:
   1755       return v + 0x80 <= 0x7f + 0x80;
   1756     case 16:
   1757       return v + 0x8000 <= 0x7fff + 0x8000;
   1758     case 24:
   1759       return v + 0x800000 <= 0x7fffff + 0x800000;
   1760     case 32:
   1761       return 1;
   1762     default:
   1763       printf ("rx_intop passed %d\n", nbits);
   1764       abort ();
   1765     }
   1766   return 1;
   1767 }
   1768 
   1769 static int
   1770 rx_uintop (expressionS exp, int nbits)
   1771 {
   1772   valueT v;
   1773 
   1774   if (exp.X_op != O_constant)
   1775     return 0;
   1776   v = exp.X_add_number;
   1777 
   1778   switch (nbits)
   1779     {
   1780     case 4:
   1781       return v <= 0xf;
   1782     case 8:
   1783       return v <= 0xff;
   1784     case 16:
   1785       return v <= 0xffff;
   1786     case 24:
   1787       return v <= 0xffffff;
   1788     default:
   1789       printf ("rx_uintop passed %d\n", nbits);
   1790       abort ();
   1791     }
   1792   return 1;
   1793 }
   1794 
   1795 static int
   1796 rx_disp3op (expressionS exp)
   1797 {
   1798   valueT v;
   1799 
   1800   if (exp.X_op != O_constant)
   1801     return 0;
   1802   v = exp.X_add_number;
   1803   if (v < 3 || v > 10)
   1804     return 0;
   1805   return 1;
   1806 }
   1807 
   1808 static int
   1809 rx_disp5op (expressionS * exp, int msize)
   1810 {
   1811   valueT v;
   1812 
   1813   if (exp->X_op != O_constant)
   1814     return 0;
   1815   v = exp->X_add_number;
   1816 
   1817   switch (msize)
   1818     {
   1819     case BSIZE:
   1820       if (v <= 31)
   1821 	return 1;
   1822       break;
   1823     case WSIZE:
   1824       if (v & 1)
   1825 	return 0;
   1826       if (v <= 63)
   1827 	{
   1828 	  exp->X_add_number >>= 1;
   1829 	  return 1;
   1830 	}
   1831       break;
   1832     case LSIZE:
   1833       if (v & 3)
   1834 	return 0;
   1835       if (v <= 127)
   1836 	{
   1837 	  exp->X_add_number >>= 2;
   1838 	  return 1;
   1839 	}
   1840       break;
   1841     }
   1842   return 0;
   1843 }
   1844 
   1845 /* Just like the above, but allows a zero displacement.  */
   1846 
   1847 static int
   1848 rx_disp5op0 (expressionS * exp, int msize)
   1849 {
   1850   if (exp->X_op != O_constant)
   1851     return 0;
   1852   if (exp->X_add_number == 0)
   1853     return 1;
   1854   return rx_disp5op (exp, msize);
   1855 }
   1856 
   1857 static int
   1858 exp_val (expressionS exp)
   1859 {
   1860   if (exp.X_op != O_constant)
   1861   {
   1862     rx_error (_("constant expected"));
   1863     return 0;
   1864   }
   1865   return exp.X_add_number;
   1866 }
   1867 
   1868 static expressionS
   1869 zero_expr (void)
   1870 {
   1871   /* Static, so program load sets it to all zeros, which is what we want.  */
   1872   static expressionS zero;
   1873   zero.X_op = O_constant;
   1874   return zero;
   1875 }
   1876 
   1877 static int
   1878 immediate (expressionS exp, int type, int pos, int bits)
   1879 {
   1880   /* We will emit constants ourselves here, so negate them.  */
   1881   if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
   1882     exp.X_add_number = - exp.X_add_number;
   1883   if (type == RXREL_NEGATIVE_BORROW)
   1884     {
   1885       if (exp.X_op == O_constant)
   1886 	exp.X_add_number = - exp.X_add_number - 1;
   1887       else
   1888 	rx_error (_("sbb cannot use symbolic immediates"));
   1889     }
   1890 
   1891   if (pos >= 0 && rx_intop (exp, 8, bits))
   1892     {
   1893       rx_op (exp, 1, type);
   1894       return 1;
   1895     }
   1896   else if (pos >= 0 && rx_intop (exp, 16, bits))
   1897     {
   1898       rx_op (exp, 2, type);
   1899       return 2;
   1900     }
   1901   else if (pos >= 0 && rx_uintop (exp, 16) && bits == 16)
   1902     {
   1903       rx_op (exp, 2, type);
   1904       return 2;
   1905     }
   1906   else if (pos >= 0 && rx_intop (exp, 24, bits))
   1907     {
   1908       rx_op (exp, 3, type);
   1909       return 3;
   1910     }
   1911   else if (pos < 0 || rx_intop (exp, 32, bits))
   1912     {
   1913       rx_op (exp, 4, type);
   1914       return 0;
   1915     }
   1916   else if (type == RXREL_SIGNED && pos >= 0)
   1917     {
   1918       /* This is a symbolic immediate, we will relax it later.  */
   1919       rx_relax (RX_RELAX_IMM, pos);
   1920       rx_op (exp, linkrelax ? 4 : 1, type);
   1921       return 1;
   1922     }
   1923   else
   1924     {
   1925       /* Let the linker deal with it.  */
   1926       rx_op (exp, 4, type);
   1927       return 0;
   1928     }
   1929 }
   1930 
   1931 static int
   1932 displacement (expressionS exp, int msize)
   1933 {
   1934   valueT val;
   1935   int vshift = 0;
   1936 
   1937   if (exp.X_op == O_symbol
   1938       && exp.X_md)
   1939     {
   1940       switch (exp.X_md)
   1941 	{
   1942 	case BFD_RELOC_GPREL16:
   1943 	  switch (msize)
   1944 	    {
   1945 	    case BSIZE:
   1946 	      exp.X_md = BFD_RELOC_RX_GPRELB;
   1947 	      break;
   1948 	    case WSIZE:
   1949 	      exp.X_md = BFD_RELOC_RX_GPRELW;
   1950 	      break;
   1951 	    case LSIZE:
   1952 	      exp.X_md = BFD_RELOC_RX_GPRELL;
   1953 	      break;
   1954 	    }
   1955 	  O2 (exp);
   1956 	  return 2;
   1957 	}
   1958     }
   1959 
   1960   if (exp.X_op == O_subtract)
   1961     {
   1962       exp.X_md = BFD_RELOC_RX_DIFF;
   1963       O2 (exp);
   1964       return 2;
   1965     }
   1966 
   1967   if (exp.X_op != O_constant)
   1968     {
   1969       rx_error (_("displacements must be constants"));
   1970       return -1;
   1971     }
   1972   val = exp.X_add_number;
   1973 
   1974   if (val == 0)
   1975     return 0;
   1976 
   1977   switch (msize)
   1978     {
   1979     case BSIZE:
   1980       break;
   1981     case WSIZE:
   1982       if (val & 1)
   1983 	rx_error (_("word displacement not word-aligned"));
   1984       vshift = 1;
   1985       break;
   1986     case LSIZE:
   1987       if (val & 3)
   1988 	rx_error (_("long displacement not long-aligned"));
   1989       vshift = 2;
   1990       break;
   1991     case DSIZE:
   1992       if (val & 7)
   1993 	rx_error (_("double displacement not double-aligned"));
   1994       vshift = 3;
   1995       break;
   1996     default:
   1997       as_bad (_("displacement with unknown size (internal bug?)\n"));
   1998       break;
   1999     }
   2000 
   2001   val >>= vshift;
   2002   exp.X_add_number = val;
   2003 
   2004   if (val <= 255 )
   2005     {
   2006       O1 (exp);
   2007       return 1;
   2008     }
   2009 
   2010   if (val <= 65535)
   2011     {
   2012       O2 (exp);
   2013       return 2;
   2014     }
   2015   if ((offsetT) val < 0)
   2016     rx_error (_("negative displacements not allowed"));
   2017   else
   2018     rx_error (_("displacement too large"));
   2019   return -1;
   2020 }
   2021 
   2022 static void
   2023 rtsd_immediate (expressionS exp)
   2024 {
   2025   valueT val;
   2026 
   2027   if (exp.X_op != O_constant)
   2028     {
   2029       rx_error (_("rtsd size must be constant"));
   2030       return;
   2031     }
   2032   val = exp.X_add_number;
   2033   if (val & 3)
   2034     rx_error (_("rtsd size must be multiple of 4"));
   2035 
   2036   if (val > 1020)
   2037     rx_error (_("rtsd size must be 0..1020"));
   2038 
   2039   val >>= 2;
   2040   exp.X_add_number = val;
   2041   O1 (exp);
   2042 }
   2043 
   2044 static void
   2045 rx_range (expressionS exp, int minv, int maxv)
   2046 {
   2047   offsetT val;
   2048 
   2049   if (exp.X_op != O_constant)
   2050     return;
   2051 
   2052   val = exp.X_add_number;
   2053   if (val < minv || val > maxv)
   2054     as_warn (_("Value %ld out of range %d..%d"), (long) val, minv, maxv);
   2055 }
   2056 
   2057 static void
   2058 rx_check_float_support (void)
   2059 {
   2060   if (rx_cpu == RX100 || rx_cpu == RX200)
   2061     rx_error (_("target CPU type does not support floating point instructions"));
   2062 }
   2063 
   2064 static void
   2065 rx_check_v2 (void)
   2066 {
   2067   if (rx_cpu < RXV2)
   2068     rx_error (_("target CPU type does not support v2 instructions"));
   2069 }
   2070 
   2071 static void
   2072 rx_check_v3 (void)
   2073 {
   2074   if (rx_cpu < RXV3)
   2075     rx_error (_("target CPU type does not support v3 instructions"));
   2076 }
   2077 
   2078 static void
   2079 rx_check_dfpu (void)
   2080 {
   2081   if (rx_cpu != RXV3FPU)
   2082     rx_error (_("target CPU type does not support double float instructions"));
   2083 }
   2084