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