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