Home | History | Annotate | Line # | Download | only in config
rx-parse.y revision 1.1.1.1
      1 /* rx-parse.y  Renesas RX parser
      2    Copyright 2008, 2009
      3    Free Software Foundation, Inc.
      4 
      5    This file is part of GAS, the GNU Assembler.
      6 
      7    GAS is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3, or (at your option)
     10    any later version.
     11 
     12    GAS is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with GAS; see the file COPYING.  If not, write to the Free
     19    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     20    02110-1301, USA.  */
     21 %{
     22 
     23 #include "as.h"
     24 #include "safe-ctype.h"
     25 #include "rx-defs.h"
     26 
     27 static int rx_lex (void);
     28 
     29 #define COND_EQ	0
     30 #define COND_NE	1
     31 
     32 #define MEMEX 0x06
     33 
     34 #define BSIZE 0
     35 #define WSIZE 1
     36 #define LSIZE 2
     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)
     76 #define O2(v)              rx_op (v, 2, RXREL_SIGNED)
     77 #define O3(v)              rx_op (v, 3, RXREL_SIGNED)
     78 #define O4(v)              rx_op (v, 4, RXREL_SIGNED)
     79 
     80 #define UO1(v)             rx_op (v, 1, RXREL_UNSIGNED)
     81 #define UO2(v)             rx_op (v, 2, RXREL_UNSIGNED)
     82 #define UO3(v)             rx_op (v, 3, RXREL_UNSIGNED)
     83 #define UO4(v)             rx_op (v, 4, RXREL_UNSIGNED)
     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 IMM(v,pos)	   F (immediate (v, RXREL_SIGNED, pos), pos, 2); \
     95 			   if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
     96 #define NIMM(v,pos)	   F (immediate (v, RXREL_NEGATIVE, pos), pos, 2)
     97 #define NBIMM(v,pos)	   F (immediate (v, RXREL_NEGATIVE_BORROW, pos), pos, 2)
     98 #define DSP(v,pos,msz)	   if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
     99 			   else rx_linkrelax_dsp (pos); \
    100 			   F (displacement (v, msz), pos, 2)
    101 
    102 #define id24(a,b2,b3)	   B3 (0xfb+a, b2, b3)
    103 
    104 static int         rx_intop (expressionS, int);
    105 static int         rx_uintop (expressionS, int);
    106 static int         rx_disp3op (expressionS);
    107 static int         rx_disp5op (expressionS *, int);
    108 static int         rx_disp5op0 (expressionS *, int);
    109 static int         exp_val (expressionS exp);
    110 static expressionS zero_expr (void);
    111 static int         immediate (expressionS, int, int);
    112 static int         displacement (expressionS, int);
    113 static void        rtsd_immediate (expressionS);
    114 
    115 static int    need_flag = 0;
    116 static int    rx_in_brackets = 0;
    117 static int    rx_last_token = 0;
    118 static char * rx_init_start;
    119 static char * rx_last_exp_start = 0;
    120 static int    sub_op;
    121 static int    sub_op2;
    122 
    123 #define YYDEBUG 1
    124 #define YYERROR_VERBOSE 1
    125 
    126 %}
    127 
    128 %name-prefix="rx_"
    129 
    130 %union {
    131   int regno;
    132   expressionS exp;
    133 }
    134 
    135 %type <regno> REG FLAG CREG BCND BMCND SCCND
    136 %type <regno> flag bwl bw memex
    137 %type <exp> EXPR disp
    138 
    139 %token REG FLAG CREG
    140 
    141 %token EXPR UNKNOWN_OPCODE IS_OPCODE
    142 
    143 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
    144 
    145 %token ABS ADC ADD AND_
    146 %token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST
    147 %token CLRPSW CMP
    148 %token DBT DIV DIVU
    149 %token EDIV EDIVU EMUL EMULU
    150 %token FADD FCMP FDIV FMUL FREIT FSUB FTOI
    151 %token INT ITOF
    152 %token JMP JSR
    153 %token MACHI MACLO MAX MIN MOV MOVU MUL MULHI MULLO MULU MVFACHI MVFACMI MVFACLO
    154 %token   MVFC MVTACHI MVTACLO MVTC MVTIPL
    155 %token NEG NOP NOT
    156 %token OR
    157 %token POP POPC POPM PUSH PUSHA PUSHC PUSHM
    158 %token RACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND RTE RTFI RTS RTSD
    159 %token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
    160 %token   SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
    161 %token TST
    162 %token WAIT
    163 %token XCHG XOR
    164 
    165 %%
    166 /* ====================================================================== */
    167 
    168 statement :
    169 
    170 	  UNKNOWN_OPCODE
    171 	  { as_bad (_("Unknown opcode: %s"), rx_init_start); }
    172 
    173 /* ---------------------------------------------------------------------- */
    174 
    175 	| BRK
    176 	  { B1 (0x00); }
    177 
    178 	| DBT
    179 	  { B1 (0x01); }
    180 
    181 	| RTS
    182 	  { B1 (0x02); }
    183 
    184 	| NOP
    185 	  { B1 (0x03); }
    186 
    187 /* ---------------------------------------------------------------------- */
    188 
    189 	| BRA EXPR
    190 	  { if (rx_disp3op ($2))
    191 	      { B1 (0x08); rx_disp3 ($2, 5); }
    192 	    else if (rx_intop ($2, 8))
    193 	      { B1 (0x2e); PC1 ($2); }
    194 	    else if (rx_intop ($2, 16))
    195 	      { B1 (0x38); PC2 ($2); }
    196 	    else if (rx_intop ($2, 24))
    197 	      { B1 (0x04); PC3 ($2); }
    198 	    else
    199 	      { rx_relax (RX_RELAX_BRANCH, 0);
    200 		rx_linkrelax_branch ();
    201 		/* We'll convert this to a longer one later if needed.  */
    202 		B1 (0x08); rx_disp3 ($2, 5); } }
    203 
    204 	| BRA DOT_A EXPR
    205 	  { B1 (0x04); PC3 ($3); }
    206 
    207 	| BRA DOT_S EXPR
    208 	  { B1 (0x08); rx_disp3 ($3, 5); }
    209 
    210 /* ---------------------------------------------------------------------- */
    211 
    212 	| BSR EXPR
    213 	  { if (rx_intop ($2, 16))
    214 	      { B1 (0x39); PC2 ($2); }
    215 	    else if (rx_intop ($2, 24))
    216 	      { B1 (0x05); PC3 ($2); }
    217 	    else
    218 	      { rx_relax (RX_RELAX_BRANCH, 0);
    219 		rx_linkrelax_branch ();
    220 		B1 (0x39); PC2 ($2); } }
    221 	| BSR DOT_A EXPR
    222 	  { B1 (0x05), PC3 ($3); }
    223 
    224 /* ---------------------------------------------------------------------- */
    225 
    226 	| BCND DOT_S EXPR
    227 	  { if ($1 == COND_EQ || $1 == COND_NE)
    228 	      { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); }
    229 	    else
    230 	      as_bad (_("Only BEQ and BNE may have .S")); }
    231 
    232 /* ---------------------------------------------------------------------- */
    233 
    234 	| BCND DOT_B EXPR
    235 	  { B1 (0x20); F ($1, 4, 4); PC1 ($3); }
    236 
    237 	| BRA DOT_B EXPR
    238 	  { B1 (0x2e), PC1 ($3); }
    239 
    240 /* ---------------------------------------------------------------------- */
    241 
    242 	| BRA DOT_W EXPR
    243 	  { B1 (0x38), PC2 ($3); }
    244 	| BSR DOT_W EXPR
    245 	  { B1 (0x39), PC2 ($3); }
    246 	| BCND DOT_W EXPR
    247 	  { if ($1 == COND_EQ || $1 == COND_NE)
    248 	      { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); }
    249 	    else
    250 	      as_bad (_("Only BEQ and BNE may have .W")); }
    251 	| BCND EXPR
    252 	  { if ($1 == COND_EQ || $1 == COND_NE)
    253 	      {
    254 		rx_relax (RX_RELAX_BRANCH, 0);
    255 		rx_linkrelax_branch ();
    256 		B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5);
    257 	      }
    258 	    else
    259 	      {
    260 		rx_relax (RX_RELAX_BRANCH, 0);
    261 		/* This is because we might turn it into a
    262 		   jump-over-jump long branch.  */
    263 		rx_linkrelax_branch ();
    264 	        B1 (0x20); F ($1, 4, 4); PC1 ($2);
    265 	      } }
    266 
    267 /* ---------------------------------------------------------------------- */
    268 
    269 	| MOV DOT_B '#' EXPR ',' disp '[' REG ']'
    270 	  /* rx_disp5op changes the value if it succeeds, so keep it last.  */
    271 	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE))
    272 	      { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
    273 	    else
    274 	      { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4);
    275 	      if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } }
    276 
    277 	| MOV DOT_W '#' EXPR ',' disp '[' REG ']'
    278 	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
    279 	      { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
    280 	    else
    281 	      { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMM ($4, 12); } }
    282 
    283 	| MOV DOT_L '#' EXPR ',' disp '[' REG ']'
    284 	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
    285 	      { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
    286 	    else
    287 	      { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } }
    288 
    289 /* ---------------------------------------------------------------------- */
    290 
    291 	| RTSD '#' EXPR ',' REG '-' REG
    292 	  { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3);
    293 	    if ($5 == 0)
    294 	      rx_error (_("RTSD cannot pop R0"));
    295 	    if ($5 > $7)
    296 	      rx_error (_("RTSD first reg must be <= second reg")); }
    297 
    298 /* ---------------------------------------------------------------------- */
    299 
    300 	| CMP REG ',' REG
    301 	  { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); }
    302 
    303 /* ---------------------------------------------------------------------- */
    304 
    305 	| CMP disp '[' REG ']' DOT_UB ',' REG
    306 	  { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); }
    307 
    308 	| CMP disp '[' REG ']' memex ',' REG
    309 	  { B3 (MEMEX, 0x04, 0); F ($6, 8, 2);  F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); }
    310 
    311 /* ---------------------------------------------------------------------- */
    312 
    313 	| MOVU bw REG ',' REG
    314 	  { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); }
    315 
    316 /* ---------------------------------------------------------------------- */
    317 
    318 	| MOVU bw '[' REG ']' ',' REG
    319 	  { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); }
    320 
    321 	| MOVU bw EXPR '[' REG ']' ',' REG
    322 	  { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
    323 	      { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
    324 	    else
    325 	      { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
    326 
    327 /* ---------------------------------------------------------------------- */
    328 
    329 	| SUB '#' EXPR ',' REG
    330 	  { if (rx_uintop ($3, 4))
    331 	      { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    332 	    else
    333 	      /* This is really an add, but we negate the immediate.  */
    334 	      { B2 (0x38, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } } /* ? */
    335 
    336 	| CMP '#' EXPR ',' REG
    337 	  { if (rx_uintop ($3, 4))
    338 	      { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    339 	    else if (rx_uintop ($3, 8))
    340 	      { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); }
    341 	    else
    342 	      { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } }
    343 
    344 	| ADD '#' EXPR ',' REG
    345 	  { if (rx_uintop ($3, 4))
    346 	      { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    347 	    else
    348 	      { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } }
    349 
    350 	| MUL '#' EXPR ',' REG
    351 	  { if (rx_uintop ($3, 4))
    352 	      { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    353 	    else
    354 	      { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } }
    355 
    356 	| AND_ '#' EXPR ',' REG
    357 	  { if (rx_uintop ($3, 4))
    358 	      { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    359 	    else
    360 	      { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } }
    361 
    362 	| OR '#' EXPR ',' REG
    363 	  { if (rx_uintop ($3, 4))
    364 	      { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    365 	    else
    366 	      { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } }
    367 
    368 	| MOV DOT_L '#' EXPR ',' REG
    369 	  { if (rx_uintop ($4, 4))
    370 	      { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); }
    371 	    else if (rx_uintop ($4, 8))
    372 	      { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); }
    373 	    else
    374 	      { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } }
    375 
    376 	| MOV '#' EXPR ',' REG
    377 	  { if (rx_uintop ($3, 4))
    378 	      { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); }
    379 	    else if (rx_uintop ($3, 8))
    380 	      { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); }
    381 	    else
    382 	      { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } }
    383 
    384 /* ---------------------------------------------------------------------- */
    385 
    386 	| RTSD '#' EXPR
    387 	  { B1 (0x67); rtsd_immediate ($3); }
    388 
    389 /* ---------------------------------------------------------------------- */
    390 
    391 	| SHLR { sub_op = 0; } op_shift
    392 	| SHAR { sub_op = 1; } op_shift
    393 	| SHLL { sub_op = 2; } op_shift
    394 
    395 /* ---------------------------------------------------------------------- */
    396 
    397 	| PUSHM REG '-' REG
    398 	  {
    399 	    if ($2 == $4)
    400 	      { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); }
    401 	    else
    402 	     { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); }
    403 	    if ($2 == 0)
    404 	      rx_error (_("PUSHM cannot push R0"));
    405 	    if ($2 > $4)
    406 	      rx_error (_("PUSHM first reg must be <= second reg")); }
    407 
    408 /* ---------------------------------------------------------------------- */
    409 
    410 	| POPM REG '-' REG
    411 	  {
    412 	    if ($2 == $4)
    413 	      { B2 (0x7e, 0xb0); F ($2, 12, 4); }
    414 	    else
    415 	      { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); }
    416 	    if ($2 == 0)
    417 	      rx_error (_("POPM cannot pop R0"));
    418 	    if ($2 > $4)
    419 	      rx_error (_("POPM first reg must be <= second reg")); }
    420 
    421 /* ---------------------------------------------------------------------- */
    422 
    423 	| ADD '#' EXPR ',' REG ',' REG
    424 	  { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); }
    425 
    426 /* ---------------------------------------------------------------------- */
    427 
    428 	| INT '#' EXPR
    429 	  { B2(0x75, 0x60), UO1 ($3); }
    430 
    431 /* ---------------------------------------------------------------------- */
    432 
    433 	| BSET '#' EXPR ',' REG
    434 	  { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); }
    435 	| BCLR '#' EXPR ',' REG
    436 	  { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); }
    437 
    438 /* ---------------------------------------------------------------------- */
    439 
    440 	| BTST '#' EXPR ',' REG
    441 	  { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); }
    442 
    443 /* ---------------------------------------------------------------------- */
    444 
    445 	| SAT REG
    446 	  { B2 (0x7e, 0x30); F ($2, 12, 4); }
    447 	| RORC REG
    448 	  { B2 (0x7e, 0x40); F ($2, 12, 4); }
    449 	| ROLC REG
    450 	  { B2 (0x7e, 0x50); F ($2, 12, 4); }
    451 
    452 /* ---------------------------------------------------------------------- */
    453 
    454 	| PUSH bwl REG
    455 	  { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); }
    456 
    457 /* ---------------------------------------------------------------------- */
    458 
    459 	| POP REG
    460 	  { B2 (0x7e, 0xb0); F ($2, 12, 4); }
    461 
    462 /* ---------------------------------------------------------------------- */
    463 
    464 	| PUSHC CREG
    465 	  { if ($2 < 16)
    466 	      { B2 (0x7e, 0xc0); F ($2, 12, 4); }
    467 	    else
    468 	      as_bad (_("PUSHC can only push the first 16 control registers")); }
    469 
    470 /* ---------------------------------------------------------------------- */
    471 
    472 	| POPC CREG
    473 	  { if ($2 < 16)
    474 	      { B2 (0x7e, 0xe0); F ($2, 12, 4); }
    475 	    else
    476 	      as_bad (_("POPC can only pop the first 16 control registers")); }
    477 
    478 /* ---------------------------------------------------------------------- */
    479 
    480 	| SETPSW flag
    481 	  { B2 (0x7f, 0xa0); F ($2, 12, 4); }
    482 	| CLRPSW flag
    483 	  { B2 (0x7f, 0xb0); F ($2, 12, 4); }
    484 
    485 /* ---------------------------------------------------------------------- */
    486 
    487 	| JMP REG
    488 	  { B2 (0x7f, 0x00); F ($2, 12, 4); }
    489 	| JSR REG
    490 	  { B2 (0x7f, 0x10); F ($2, 12, 4); }
    491 	| BRA opt_l REG
    492 	  { B2 (0x7f, 0x40); F ($3, 12, 4); }
    493 	| BSR opt_l REG
    494 	  { B2 (0x7f, 0x50); F ($3, 12, 4); }
    495 
    496 /* ---------------------------------------------------------------------- */
    497 
    498 	| SCMPU
    499 	  { B2 (0x7f, 0x83); }
    500 	| SMOVU
    501 	  { B2 (0x7f, 0x87); }
    502 	| SMOVB
    503 	  { B2 (0x7f, 0x8b); }
    504 	| SMOVF
    505 	  { B2 (0x7f, 0x8f); }
    506 
    507 /* ---------------------------------------------------------------------- */
    508 
    509 	| SUNTIL bwl
    510 	  { B2 (0x7f, 0x80); F ($2, 14, 2); }
    511 	| SWHILE bwl
    512 	  { B2 (0x7f, 0x84); F ($2, 14, 2); }
    513 	| SSTR bwl
    514 	  { B2 (0x7f, 0x88); F ($2, 14, 2); }
    515 
    516 /* ---------------------------------------------------------------------- */
    517 
    518 	| RMPA bwl
    519 	  { B2 (0x7f, 0x8c); F ($2, 14, 2); }
    520 
    521 /* ---------------------------------------------------------------------- */
    522 
    523 	| RTFI
    524 	  { B2 (0x7f, 0x94); }
    525 	| RTE
    526 	  { B2 (0x7f, 0x95); }
    527 	| WAIT
    528 	  { B2 (0x7f, 0x96); }
    529 	| SATR
    530 	  { B2 (0x7f, 0x93); }
    531 
    532 /* ---------------------------------------------------------------------- */
    533 
    534 	| MVTIPL '#' EXPR
    535 	  { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
    536 
    537 /* ---------------------------------------------------------------------- */
    538 
    539 	/* rx_disp5op changes the value if it succeeds, so keep it last.  */
    540 	| MOV bwl REG ',' EXPR '[' REG ']'
    541 	  { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2))
    542 	      { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); }
    543 	    else
    544 	      { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }}
    545 
    546 /* ---------------------------------------------------------------------- */
    547 
    548 	| MOV bwl EXPR '[' REG ']' ',' REG
    549 	  { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
    550 	      { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
    551 	    else
    552 	      { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
    553 
    554 /* ---------------------------------------------------------------------- */
    555 
    556 	/* MOV a,b - if a is a reg and b is mem, src and dest are
    557 	   swapped.  */
    558 
    559 	/* We don't use "disp" here because it causes a shift/reduce
    560 	   conflict with the other displacement-less patterns.  */
    561 
    562 	| MOV bwl REG ',' '[' REG ']'
    563 	  { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); }
    564 
    565 /* ---------------------------------------------------------------------- */
    566 
    567 	| MOV bwl '[' REG ']' ',' disp '[' REG ']'
    568 	  { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); }
    569 
    570 /* ---------------------------------------------------------------------- */
    571 
    572 	| MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']'
    573 	  { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); }
    574 
    575 /* ---------------------------------------------------------------------- */
    576 
    577 	| MOV bwl REG ',' REG
    578 	  { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); }
    579 
    580 /* ---------------------------------------------------------------------- */
    581 
    582 	| MOV bwl '[' REG ']' ',' REG
    583 	  { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); }
    584 
    585 /* ---------------------------------------------------------------------- */
    586 
    587 	| BSET '#' EXPR ',' disp '[' REG ']' DOT_B
    588 	  { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
    589 	| BCLR '#' EXPR ',' disp '[' REG ']' DOT_B
    590 	  { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
    591 	| BTST '#' EXPR ',' disp '[' REG ']' DOT_B
    592 	  { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
    593 
    594 /* ---------------------------------------------------------------------- */
    595 
    596 	| PUSH bwl disp '[' REG ']'
    597 	  { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); }
    598 
    599 /* ---------------------------------------------------------------------- */
    600 
    601 	| SBB   { sub_op = 0; } op_dp20_rm
    602 	| NEG   { sub_op = 1; sub_op2 = 1; } op_dp20_rms
    603 	| ADC   { sub_op = 2; } op_dp20_rim
    604 	| ABS   { sub_op = 3; sub_op2 = 2; } op_dp20_rms
    605 	| MAX   { sub_op = 4; } op_dp20_rim
    606 	| MIN   { sub_op = 5; } op_dp20_rim
    607 	| EMUL  { sub_op = 6; } op_dp20_i
    608 	| EMULU { sub_op = 7; } op_dp20_i
    609 	| DIV   { sub_op = 8; } op_dp20_rim
    610 	| DIVU  { sub_op = 9; } op_dp20_rim
    611 	| TST   { sub_op = 12; } op_dp20_rim
    612 	| XOR   { sub_op = 13; } op_dp20_rim
    613 	| NOT   { sub_op = 14; sub_op2 = 0; } op_dp20_rms
    614 	| STZ   { sub_op = 14; } op_dp20_i
    615 	| STNZ  { sub_op = 15; } op_dp20_i
    616 
    617 /* ---------------------------------------------------------------------- */
    618 
    619 	| EMUL  { sub_op = 6; } op_xchg
    620 	| EMULU { sub_op = 7; } op_xchg
    621 	| XCHG  { sub_op = 16; } op_xchg
    622 	| ITOF  { sub_op = 17; } op_xchg
    623 
    624 /* ---------------------------------------------------------------------- */
    625 
    626 	| BSET REG ',' REG
    627 	  { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    628 	| BCLR REG ',' REG
    629 	  { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    630 	| BTST REG ',' REG
    631 	  { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    632 	| BNOT REG ',' REG
    633 	  { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
    634 
    635 	| BSET REG ',' disp '[' REG ']' DOT_B
    636 	  { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    637 	| BCLR REG ',' disp '[' REG ']' DOT_B
    638 	  { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    639 	| BTST REG ',' disp '[' REG ']' DOT_B
    640 	  { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    641 	| BNOT REG ',' disp '[' REG ']' DOT_B
    642 	  { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
    643 
    644 /* ---------------------------------------------------------------------- */
    645 
    646 	| FSUB  { sub_op = 0; } float2_op
    647 	| FCMP  { sub_op = 1; } float2_op
    648 	| FADD  { sub_op = 2; } float2_op
    649 	| FMUL  { sub_op = 3; } float2_op
    650 	| FDIV  { sub_op = 4; } float2_op
    651 	| FTOI  { sub_op = 5; } float2_op_ni
    652 	| ROUND { sub_op = 6; } float2_op_ni
    653 
    654 /* ---------------------------------------------------------------------- */
    655 
    656 	| SCCND DOT_L REG
    657 	  { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
    658 	| SCCND bwl disp '[' REG ']'
    659 	  { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); }
    660 
    661 /* ---------------------------------------------------------------------- */
    662 
    663 	| BMCND '#' EXPR ',' disp '[' REG ']' DOT_B
    664 	  { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
    665 	      F ($7, 16, 4); DSP ($5, 14, BSIZE); }
    666 
    667 /* ---------------------------------------------------------------------- */
    668 
    669 	| BNOT '#' EXPR ',' disp '[' REG ']' DOT_B
    670 	  { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
    671 	      DSP ($5, 14, BSIZE); }
    672 
    673 /* ---------------------------------------------------------------------- */
    674 
    675 	| MULHI REG ',' REG
    676 	  { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    677 	| MULLO REG ',' REG
    678 	  { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    679 	| MACHI REG ',' REG
    680 	  { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    681 	| MACLO REG ',' REG
    682 	  { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
    683 
    684 /* ---------------------------------------------------------------------- */
    685 
    686 	/* We don't have syntax for these yet.  */
    687 	| MVTACHI REG
    688 	  { id24 (2, 0x17, 0x00); F ($2, 20, 4); }
    689 	| MVTACLO REG
    690 	  { id24 (2, 0x17, 0x10); F ($2, 20, 4); }
    691 	| MVFACHI REG
    692 	  { id24 (2, 0x1f, 0x00); F ($2, 20, 4); }
    693 	| MVFACMI REG
    694 	  { id24 (2, 0x1f, 0x20); F ($2, 20, 4); }
    695 	| MVFACLO REG
    696 	  { id24 (2, 0x1f, 0x10); F ($2, 20, 4); }
    697 
    698 	| RACW '#' EXPR
    699 	  { id24 (2, 0x18, 0x00);
    700 	    if (rx_uintop ($3, 4) && $3.X_add_number == 1)
    701 	      ;
    702 	    else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
    703 	      F (1, 19, 1);
    704 	    else
    705 	      as_bad (_("RACW expects #1 or #2"));}
    706 
    707 /* ---------------------------------------------------------------------- */
    708 
    709 	| MOV bwl REG ',' '[' REG '+' ']'
    710 	  { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); }
    711 	| MOV bwl REG ',' '[' '-' REG ']'
    712 	  { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); }
    713 
    714 /* ---------------------------------------------------------------------- */
    715 
    716 	| MOV bwl '[' REG '+' ']' ',' REG
    717 	  { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); }
    718 	| MOV bwl '[' '-' REG ']' ',' REG
    719 	  { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); }
    720 
    721 /* ---------------------------------------------------------------------- */
    722 
    723 	| MOVU bw '[' REG '+' ']' ','  REG
    724 	  { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); }
    725 	| MOVU bw '[' '-' REG ']' ',' REG
    726 	  { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); }
    727 
    728 /* ---------------------------------------------------------------------- */
    729 
    730 	| ROTL { sub_op = 6; } op_shift_rot
    731 	| ROTR { sub_op = 4; } op_shift_rot
    732 	| REVW { sub_op = 5; } op_shift_rot
    733 	| REVL { sub_op = 7; } op_shift_rot
    734 
    735 /* ---------------------------------------------------------------------- */
    736 
    737 	| MVTC REG ',' CREG
    738 	  { id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1);
    739 	    F ($2, 16, 4); }
    740 
    741 /* ---------------------------------------------------------------------- */
    742 
    743 	| MVFC CREG ',' REG
    744 	  { id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); }
    745 
    746 /* ---------------------------------------------------------------------- */
    747 
    748 	| ROTL '#' EXPR ',' REG
    749 	  { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); }
    750 	| ROTR '#' EXPR ',' REG
    751 	  { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); }
    752 
    753 /* ---------------------------------------------------------------------- */
    754 
    755 	| MVTC '#' EXPR ',' CREG
    756 	  { id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); }
    757 
    758 /* ---------------------------------------------------------------------- */
    759 
    760 	| BMCND '#' EXPR ',' REG
    761 	  { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5);
    762 	      F ($5, 20, 4); }
    763 
    764 /* ---------------------------------------------------------------------- */
    765 
    766 	| BNOT '#' EXPR ',' REG
    767 	  { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); }
    768 
    769 /* ---------------------------------------------------------------------- */
    770 
    771 	| MOV bwl REG ',' '[' REG ',' REG ']'
    772 	  { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); }
    773 
    774 	| MOV bwl '[' REG ',' REG ']' ',' REG
    775 	  { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
    776 
    777 	| MOVU bw '[' REG ',' REG ']' ',' REG
    778 	  { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
    779 
    780 /* ---------------------------------------------------------------------- */
    781 
    782 	| SUB { sub_op = 0; } op_subadd
    783 	| ADD { sub_op = 2; } op_subadd
    784 	| MUL { sub_op = 3; } op_subadd
    785 	| AND_ { sub_op = 4; } op_subadd
    786 	| OR  { sub_op = 5; } op_subadd
    787 
    788 /* ---------------------------------------------------------------------- */
    789 /* There is no SBB #imm so we fake it with ADC.  */
    790 
    791 	| SBB '#' EXPR ',' REG
    792 	  { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); }
    793 
    794 /* ---------------------------------------------------------------------- */
    795 
    796 	;
    797 
    798 /* ====================================================================== */
    799 
    800 op_subadd
    801 	: REG ',' REG
    802 	  { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); }
    803 	| disp '[' REG ']' DOT_UB ',' REG
    804 	  { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); }
    805 	| disp '[' REG ']' memex ',' REG
    806 	  { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); }
    807 	| REG ',' REG ',' REG
    808 	  { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
    809 	;
    810 
    811 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
    812 
    813 op_dp20_rm
    814 	: REG ',' REG
    815 	  { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
    816 	| disp '[' REG ']' DOT_UB ',' REG
    817 	  { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
    818 	| disp '[' REG ']' memex ',' REG
    819 	  { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00);
    820 	  F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); }
    821 	;
    822 
    823 op_dp20_i
    824 	: '#' EXPR ',' REG
    825 	  { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); }
    826 	;
    827 
    828 op_dp20_rim
    829 	: op_dp20_rm
    830 	| op_dp20_i
    831 	;
    832 
    833 op_dp20_rms
    834 	: op_dp20_rm
    835 	| REG
    836 	  { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
    837 	;
    838 
    839 /* xchg, itof, emul, emulu */
    840 op_xchg
    841 	: REG ',' REG
    842 	  { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); }
    843 	| disp '[' REG ']' DOT_UB ',' REG
    844 	  { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
    845 	| disp '[' REG ']' memex ',' REG
    846 	  { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4);
    847 	    DSP ($1, 14, sizemap[$5]); }
    848 	;
    849 
    850 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
    851 op_shift_rot
    852 	: REG ',' REG
    853 	  { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); }
    854 	;
    855 op_shift
    856 	: '#' EXPR ',' REG
    857 	  { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); }
    858 	| '#' EXPR ',' REG ',' REG
    859 	  { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); }
    860 	| op_shift_rot
    861 	;
    862 
    863 
    864 
    865 float2_op
    866 	: '#' EXPR ',' REG
    867 	  { id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
    868 	| float2_op_ni
    869 	;
    870 float2_op_ni
    871 	: REG ',' REG
    872 	  { id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
    873 	| disp '[' REG ']' opt_l ',' REG
    874 	  { id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
    875 	;
    876 
    877 /* ====================================================================== */
    878 
    879 disp	:      { $$ = zero_expr (); }
    880 	| EXPR { $$ = $1; }
    881 	;
    882 
    883 flag	: { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
    884 	;
    885 
    886 /* DOT_UB is not listed here, it's handled with a separate pattern.  */
    887 /* Use sizemap[$n] to get LSIZE etc.  */
    888 memex	: DOT_B  { $$ = 0; }
    889 	| DOT_W  { $$ = 1; }
    890 	|        { $$ = 2; }
    891 	| DOT_L  { $$ = 2; }
    892 	| DOT_UW { $$ = 3; }
    893 	;
    894 
    895 bwl	:       { $$ = LSIZE; }
    896 	| DOT_B { $$ = BSIZE; }
    897 	| DOT_W { $$ = WSIZE; }
    898 	| DOT_L { $$ = LSIZE; }
    899 	;
    900 
    901 bw	:       { $$ = 1; }
    902 	| DOT_B { $$ = 0; }
    903 	| DOT_W { $$ = 1; }
    904 	;
    905 
    906 opt_l	: 	{}
    907 	| DOT_L {}
    908 	;
    909 
    910 %%
    911 /* ====================================================================== */
    912 
    913 static struct
    914 {
    915   const char * string;
    916   int          token;
    917   int          val;
    918 }
    919 token_table[] =
    920 {
    921   { "r0", REG, 0 },
    922   { "r1", REG, 1 },
    923   { "r2", REG, 2 },
    924   { "r3", REG, 3 },
    925   { "r4", REG, 4 },
    926   { "r5", REG, 5 },
    927   { "r6", REG, 6 },
    928   { "r7", REG, 7 },
    929   { "r8", REG, 8 },
    930   { "r9", REG, 9 },
    931   { "r10", REG, 10 },
    932   { "r11", REG, 11 },
    933   { "r12", REG, 12 },
    934   { "r13", REG, 13 },
    935   { "r14", REG, 14 },
    936   { "r15", REG, 15 },
    937 
    938   { "psw", CREG, 0 },
    939   { "pc", CREG, 1 },
    940   { "usp", CREG, 2 },
    941   { "fpsw", CREG, 3 },
    942   /* reserved */
    943   /* reserved */
    944   /* reserved */
    945   { "wr", CREG, 7 },
    946 
    947   { "bpsw", CREG, 8 },
    948   { "bpc", CREG, 9 },
    949   { "isp", CREG, 10 },
    950   { "fintv", CREG, 11 },
    951   { "intb", CREG, 12 },
    952 
    953   { "pbp", CREG, 16 },
    954   { "pben", CREG, 17 },
    955 
    956   { "bbpsw", CREG, 24 },
    957   { "bbpc", CREG, 25 },
    958 
    959   { ".s", DOT_S, 0 },
    960   { ".b", DOT_B, 0 },
    961   { ".w", DOT_W, 0 },
    962   { ".l", DOT_L, 0 },
    963   { ".a", DOT_A , 0},
    964   { ".ub", DOT_UB, 0 },
    965   { ".uw", DOT_UW , 0},
    966 
    967   { "c", FLAG, 0 },
    968   { "z", FLAG, 1 },
    969   { "s", FLAG, 2 },
    970   { "o", FLAG, 3 },
    971   { "i", FLAG, 8 },
    972   { "u", FLAG, 9 },
    973 
    974 #define OPC(x) { #x, x, IS_OPCODE }
    975   OPC(ABS),
    976   OPC(ADC),
    977   OPC(ADD),
    978   { "and", AND_, IS_OPCODE },
    979   OPC(BCLR),
    980   OPC(BCND),
    981   OPC(BMCND),
    982   OPC(BNOT),
    983   OPC(BRA),
    984   OPC(BRK),
    985   OPC(BSET),
    986   OPC(BSR),
    987   OPC(BTST),
    988   OPC(CLRPSW),
    989   OPC(CMP),
    990   OPC(DBT),
    991   OPC(DIV),
    992   OPC(DIVU),
    993   OPC(EDIV),
    994   OPC(EDIVU),
    995   OPC(EMUL),
    996   OPC(EMULU),
    997   OPC(FADD),
    998   OPC(FCMP),
    999   OPC(FDIV),
   1000   OPC(FMUL),
   1001   OPC(FREIT),
   1002   OPC(FSUB),
   1003   OPC(FTOI),
   1004   OPC(INT),
   1005   OPC(ITOF),
   1006   OPC(JMP),
   1007   OPC(JSR),
   1008   OPC(MVFACHI),
   1009   OPC(MVFACMI),
   1010   OPC(MVFACLO),
   1011   OPC(MVFC),
   1012   OPC(MVTACHI),
   1013   OPC(MVTACLO),
   1014   OPC(MVTC),
   1015   OPC(MVTIPL),
   1016   OPC(MACHI),
   1017   OPC(MACLO),
   1018   OPC(MAX),
   1019   OPC(MIN),
   1020   OPC(MOV),
   1021   OPC(MOVU),
   1022   OPC(MUL),
   1023   OPC(MULHI),
   1024   OPC(MULLO),
   1025   OPC(MULU),
   1026   OPC(NEG),
   1027   OPC(NOP),
   1028   OPC(NOT),
   1029   OPC(OR),
   1030   OPC(POP),
   1031   OPC(POPC),
   1032   OPC(POPM),
   1033   OPC(PUSH),
   1034   OPC(PUSHA),
   1035   OPC(PUSHC),
   1036   OPC(PUSHM),
   1037   OPC(RACW),
   1038   OPC(REIT),
   1039   OPC(REVL),
   1040   OPC(REVW),
   1041   OPC(RMPA),
   1042   OPC(ROLC),
   1043   OPC(RORC),
   1044   OPC(ROTL),
   1045   OPC(ROTR),
   1046   OPC(ROUND),
   1047   OPC(RTE),
   1048   OPC(RTFI),
   1049   OPC(RTS),
   1050   OPC(RTSD),
   1051   OPC(SAT),
   1052   OPC(SATR),
   1053   OPC(SBB),
   1054   OPC(SCCND),
   1055   OPC(SCMPU),
   1056   OPC(SETPSW),
   1057   OPC(SHAR),
   1058   OPC(SHLL),
   1059   OPC(SHLR),
   1060   OPC(SMOVB),
   1061   OPC(SMOVF),
   1062   OPC(SMOVU),
   1063   OPC(SSTR),
   1064   OPC(STNZ),
   1065   OPC(STOP),
   1066   OPC(STZ),
   1067   OPC(SUB),
   1068   OPC(SUNTIL),
   1069   OPC(SWHILE),
   1070   OPC(TST),
   1071   OPC(WAIT),
   1072   OPC(XCHG),
   1073   OPC(XOR),
   1074 };
   1075 
   1076 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
   1077 
   1078 static struct
   1079 {
   1080   char * string;
   1081   int    token;
   1082 }
   1083 condition_opcode_table[] =
   1084 {
   1085   { "b", BCND },
   1086   { "bm", BMCND },
   1087   { "sc", SCCND },
   1088 };
   1089 
   1090 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
   1091 
   1092 static struct
   1093 {
   1094   char * string;
   1095   int    val;
   1096 }
   1097 condition_table[] =
   1098 {
   1099   { "z", 0 },
   1100   { "eq", 0 },
   1101   { "geu",  2 },
   1102   { "c",  2 },
   1103   { "gtu", 4 },
   1104   { "pz", 6 },
   1105   { "ge", 8 },
   1106   { "gt", 10 },
   1107   { "o",  12},
   1108   /* always = 14 */
   1109   { "nz", 1 },
   1110   { "ne", 1 },
   1111   { "ltu", 3 },
   1112   { "nc", 3 },
   1113   { "leu", 5 },
   1114   { "n", 7 },
   1115   { "lt", 9 },
   1116   { "le", 11 },
   1117   { "no", 13 }
   1118   /* never = 15 */
   1119 };
   1120 
   1121 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
   1122 
   1123 void
   1124 rx_lex_init (char * beginning, char * ending)
   1125 {
   1126   rx_init_start = beginning;
   1127   rx_lex_start = beginning;
   1128   rx_lex_end = ending;
   1129   rx_in_brackets = 0;
   1130   rx_last_token = 0;
   1131 
   1132   setbuf (stdout, 0);
   1133 }
   1134 
   1135 static int
   1136 check_condition (char * base)
   1137 {
   1138   char * cp;
   1139   unsigned int i;
   1140 
   1141   if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
   1142     return 0;
   1143   if (memcmp (rx_lex_start, base, strlen (base)))
   1144     return 0;
   1145   cp = rx_lex_start + strlen (base);
   1146   for (i = 0; i < NUM_CONDITIONS; i ++)
   1147     {
   1148       if (strcasecmp (cp, condition_table[i].string) == 0)
   1149 	{
   1150 	  rx_lval.regno = condition_table[i].val;
   1151 	  return 1;
   1152 	}
   1153     }
   1154   return 0;
   1155 }
   1156 
   1157 static int
   1158 rx_lex (void)
   1159 {
   1160   unsigned int ci;
   1161   char * save_input_pointer;
   1162 
   1163   while (ISSPACE (*rx_lex_start)
   1164 	 && rx_lex_start != rx_lex_end)
   1165     rx_lex_start ++;
   1166 
   1167   rx_last_exp_start = rx_lex_start;
   1168 
   1169   if (rx_lex_start == rx_lex_end)
   1170     return 0;
   1171 
   1172   if (ISALPHA (*rx_lex_start)
   1173       || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
   1174     {
   1175       unsigned int i;
   1176       char * e;
   1177       char save;
   1178 
   1179       for (e = rx_lex_start + 1;
   1180 	   e < rx_lex_end && ISALNUM (*e);
   1181 	   e ++)
   1182 	;
   1183       save = *e;
   1184       *e = 0;
   1185 
   1186       if (rx_last_token == 0)
   1187 	for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
   1188 	  if (check_condition (condition_opcode_table[ci].string))
   1189 	    {
   1190 	      *e = save;
   1191 	      rx_lex_start = e;
   1192 	      rx_last_token = condition_opcode_table[ci].token;
   1193 	      return condition_opcode_table[ci].token;
   1194 	    }
   1195 
   1196       for (i = 0; i < NUM_TOKENS; i++)
   1197 	if (strcasecmp (rx_lex_start, token_table[i].string) == 0
   1198 	    && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
   1199 	    && !(token_table[i].token == FLAG && !need_flag))
   1200 	  {
   1201 	    rx_lval.regno = token_table[i].val;
   1202 	    *e = save;
   1203 	    rx_lex_start = e;
   1204 	    rx_last_token = token_table[i].token;
   1205 	    return token_table[i].token;
   1206 	  }
   1207       *e = save;
   1208     }
   1209 
   1210   if (rx_last_token == 0)
   1211     {
   1212       rx_last_token = UNKNOWN_OPCODE;
   1213       return UNKNOWN_OPCODE;
   1214     }
   1215 
   1216   if (rx_last_token == UNKNOWN_OPCODE)
   1217     return 0;
   1218 
   1219   if (*rx_lex_start == '[')
   1220     rx_in_brackets = 1;
   1221   if (*rx_lex_start == ']')
   1222     rx_in_brackets = 0;
   1223 
   1224   if (rx_in_brackets
   1225       || rx_last_token == REG
   1226       || strchr ("[],#", *rx_lex_start))
   1227     {
   1228       rx_last_token = *rx_lex_start;
   1229       return *rx_lex_start ++;
   1230     }
   1231 
   1232   save_input_pointer = input_line_pointer;
   1233   input_line_pointer = rx_lex_start;
   1234   rx_lval.exp.X_md = 0;
   1235   expression (&rx_lval.exp);
   1236 
   1237   /* We parse but ignore any :<size> modifier on expressions.  */
   1238   if (*input_line_pointer == ':')
   1239     {
   1240       char *cp;
   1241 
   1242       for (cp  = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
   1243 	if (!ISDIGIT (*cp))
   1244 	  break;
   1245       if (cp > input_line_pointer+1)
   1246 	input_line_pointer = cp;
   1247     }
   1248 
   1249   rx_lex_start = input_line_pointer;
   1250   input_line_pointer = save_input_pointer;
   1251   rx_last_token = EXPR;
   1252   return EXPR;
   1253 }
   1254 
   1255 int
   1256 rx_error (char * str)
   1257 {
   1258   int len;
   1259 
   1260   len = rx_last_exp_start - rx_init_start;
   1261 
   1262   as_bad ("%s", rx_init_start);
   1263   as_bad ("%*s^ %s", len, "", str);
   1264   return 0;
   1265 }
   1266 
   1267 static int
   1268 rx_intop (expressionS exp, int nbits)
   1269 {
   1270   long v;
   1271 
   1272   if (exp.X_op == O_big && nbits == 32)
   1273       return 1;
   1274   if (exp.X_op != O_constant)
   1275     return 0;
   1276   v = exp.X_add_number;
   1277 
   1278   switch (nbits)
   1279     {
   1280     case 4:
   1281       return -0x8 <= v && v <= 0x7;
   1282     case 5:
   1283       return -0x10 <= v && v <= 0x17;
   1284     case 8:
   1285       return -0x80 <= v && v <= 0x7f;
   1286     case 16:
   1287       return -0x8000 <= v && v <= 0x7fff;
   1288     case 24:
   1289       return -0x800000 <= v && v <= 0x7fffff;
   1290     case 32:
   1291       return 1;
   1292     default:
   1293       printf ("rx_intop passed %d\n", nbits);
   1294       abort ();
   1295     }
   1296   return 1;
   1297 }
   1298 
   1299 static int
   1300 rx_uintop (expressionS exp, int nbits)
   1301 {
   1302   unsigned long v;
   1303 
   1304   if (exp.X_op != O_constant)
   1305     return 0;
   1306   v = exp.X_add_number;
   1307 
   1308   switch (nbits)
   1309     {
   1310     case 4:
   1311       return v <= 0xf;
   1312     case 8:
   1313       return v <= 0xff;
   1314     case 16:
   1315       return v <= 0xffff;
   1316     case 24:
   1317       return v <= 0xffffff;
   1318     default:
   1319       printf ("rx_uintop passed %d\n", nbits);
   1320       abort ();
   1321     }
   1322   return 1;
   1323 }
   1324 
   1325 static int
   1326 rx_disp3op (expressionS exp)
   1327 {
   1328   unsigned long v;
   1329 
   1330   if (exp.X_op != O_constant)
   1331     return 0;
   1332   v = exp.X_add_number;
   1333   if (v < 3 || v > 10)
   1334     return 0;
   1335   return 1;
   1336 }
   1337 
   1338 static int
   1339 rx_disp5op (expressionS * exp, int msize)
   1340 {
   1341   long v;
   1342 
   1343   if (exp->X_op != O_constant)
   1344     return 0;
   1345   v = exp->X_add_number;
   1346 
   1347   switch (msize)
   1348     {
   1349     case BSIZE:
   1350       if (0 < v && v <= 31)
   1351 	return 1;
   1352       break;
   1353     case WSIZE:
   1354       if (v & 1)
   1355 	return 0;
   1356       if (0 < v && v <= 63)
   1357 	{
   1358 	  exp->X_add_number >>= 1;
   1359 	  return 1;
   1360 	}
   1361       break;
   1362     case LSIZE:
   1363       if (v & 3)
   1364 	return 0;
   1365       if (0 < v && v <= 127)
   1366 	{
   1367 	  exp->X_add_number >>= 2;
   1368 	  return 1;
   1369 	}
   1370       break;
   1371     }
   1372   return 0;
   1373 }
   1374 
   1375 /* Just like the above, but allows a zero displacement.  */
   1376 
   1377 static int
   1378 rx_disp5op0 (expressionS * exp, int msize)
   1379 {
   1380   if (exp->X_op != O_constant)
   1381     return 0;
   1382   if (exp->X_add_number == 0)
   1383     return 1;
   1384   return rx_disp5op (exp, msize);
   1385 }
   1386 
   1387 static int
   1388 exp_val (expressionS exp)
   1389 {
   1390   if (exp.X_op != O_constant)
   1391   {
   1392     rx_error (_("constant expected"));
   1393     return 0;
   1394   }
   1395   return exp.X_add_number;
   1396 }
   1397 
   1398 static expressionS
   1399 zero_expr (void)
   1400 {
   1401   /* Static, so program load sets it to all zeros, which is what we want.  */
   1402   static expressionS zero;
   1403   zero.X_op = O_constant;
   1404   return zero;
   1405 }
   1406 
   1407 static int
   1408 immediate (expressionS exp, int type, int pos)
   1409 {
   1410   /* We will emit constants ourself here, so negate them.  */
   1411   if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
   1412     exp.X_add_number = - exp.X_add_number;
   1413   if (type == RXREL_NEGATIVE_BORROW)
   1414     {
   1415       if (exp.X_op == O_constant)
   1416 	exp.X_add_number = - exp.X_add_number - 1;
   1417       else
   1418 	rx_error (_("sbb cannot use symbolic immediates"));
   1419     }
   1420 
   1421   if (rx_intop (exp, 8))
   1422     {
   1423       rx_op (exp, 1, type);
   1424       return 1;
   1425     }
   1426   else if (rx_intop (exp, 16))
   1427     {
   1428       rx_op (exp, 2, type);
   1429       return 2;
   1430     }
   1431   else if (rx_intop (exp, 24))
   1432     {
   1433       rx_op (exp, 3, type);
   1434       return 3;
   1435     }
   1436   else if (rx_intop (exp, 32))
   1437     {
   1438       rx_op (exp, 4, type);
   1439       return 0;
   1440     }
   1441   else if (type == RXREL_SIGNED)
   1442     {
   1443       /* This is a symbolic immediate, we will relax it later.  */
   1444       rx_relax (RX_RELAX_IMM, pos);
   1445       rx_op (exp, linkrelax ? 4 : 1, type);
   1446       return 1;
   1447     }
   1448   else
   1449     {
   1450       /* Let the linker deal with it.  */
   1451       rx_op (exp, 4, type);
   1452       return 0;
   1453     }
   1454 }
   1455 
   1456 static int
   1457 displacement (expressionS exp, int msize)
   1458 {
   1459   int val;
   1460   int vshift = 0;
   1461 
   1462   if (exp.X_op == O_symbol
   1463       && exp.X_md)
   1464     {
   1465       switch (exp.X_md)
   1466 	{
   1467 	case BFD_RELOC_GPREL16:
   1468 	  switch (msize)
   1469 	    {
   1470 	    case BSIZE:
   1471 	      exp.X_md = BFD_RELOC_RX_GPRELB;
   1472 	      break;
   1473 	    case WSIZE:
   1474 	      exp.X_md = BFD_RELOC_RX_GPRELW;
   1475 	      break;
   1476 	    case LSIZE:
   1477 	      exp.X_md = BFD_RELOC_RX_GPRELL;
   1478 	      break;
   1479 	    }
   1480 	  O2 (exp);
   1481 	  return 2;
   1482 	}
   1483     }
   1484 
   1485   if (exp.X_op != O_constant)
   1486     {
   1487       rx_error (_("displacements must be constants"));
   1488       return -1;
   1489     }
   1490   val = exp.X_add_number;
   1491 
   1492   if (val == 0)
   1493     return 0;
   1494 
   1495   switch (msize)
   1496     {
   1497     case BSIZE:
   1498       break;
   1499     case WSIZE:
   1500       if (val & 1)
   1501 	rx_error (_("word displacement not word-aligned"));
   1502       vshift = 1;
   1503       break;
   1504     case LSIZE:
   1505       if (val & 3)
   1506 	rx_error (_("long displacement not long-aligned"));
   1507       vshift = 2;
   1508       break;
   1509     default:
   1510       as_bad (_("displacement with unknown size (internal bug?)\n"));
   1511       break;
   1512     }
   1513 
   1514   val >>= vshift;
   1515   exp.X_add_number = val;
   1516 
   1517   if (0 <= val && val <= 255 )
   1518     {
   1519       O1 (exp);
   1520       return 1;
   1521     }
   1522 
   1523   if (0 <= val && val <= 65535)
   1524     {
   1525       O2 (exp);
   1526       return 2;
   1527     }
   1528   if (val < 0)
   1529     rx_error (_("negative displacements not allowed"));
   1530   else
   1531     rx_error (_("displacement too large"));
   1532   return -1;
   1533 }
   1534 
   1535 static void
   1536 rtsd_immediate (expressionS exp)
   1537 {
   1538   int val;
   1539 
   1540   if (exp.X_op != O_constant)
   1541     {
   1542       rx_error (_("rtsd size must be constant"));
   1543       return;
   1544     }
   1545   val = exp.X_add_number;
   1546   if (val & 3)
   1547     rx_error (_("rtsd size must be multiple of 4"));
   1548 
   1549   if (val < 0 || val > 1020)
   1550     rx_error (_("rtsd size must be 0..1020"));
   1551 
   1552   val >>= 2;
   1553   exp.X_add_number = val;
   1554   O1 (exp);
   1555 }
   1556