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