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