d93b4f66b5088159fcd105f810cfa697bb59cccd
[external/binutils.git] / gas / config / rx-parse.y
1 /* rx-parse.y  Renesas RX parser
2    Copyright (C) 2008-2014 Free Software Foundation, Inc.
3
4    This file is part of GAS, the GNU Assembler.
5
6    GAS is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    GAS is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GAS; see the file COPYING.  If not, write to the Free
18    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19    02110-1301, USA.  */
20 %{
21
22 #include "as.h"
23 #include "safe-ctype.h"
24 #include "rx-defs.h"
25
26 static int rx_lex (void);
27
28 #define COND_EQ 0
29 #define COND_NE 1
30
31 #define MEMEX 0x06
32
33 #define BSIZE 0
34 #define WSIZE 1
35 #define LSIZE 2
36
37 /*                       .sb    .sw    .l     .uw   */
38 static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
39
40 /* Ok, here are the rules for using these macros...
41
42    B*() is used to specify the base opcode bytes.  Fields to be filled
43         in later, leave zero.  Call this first.
44
45    F() and FE() are used to fill in fields within the base opcode bytes.  You MUST
46         call B*() before any F() or FE().
47
48    [UN]*O*(), PC*() appends operands to the end of the opcode.  You
49         must call P() and B*() before any of these, so that the fixups
50         have the right byte location.
51         O = signed, UO = unsigned, NO = negated, PC = pcrel
52
53    IMM() adds an immediate and fills in the field for it.
54    NIMM() same, but negates the immediate.
55    NBIMM() same, but negates the immediate, for sbb.
56    DSP() adds a displacement, and fills in the field for it.
57
58    Note that order is significant for the O, IMM, and DSP macros, as
59    they append their data to the operand buffer in the order that you
60    call them.
61
62    Use "disp" for displacements whenever possible; this handles the
63    "0" case properly.  */
64
65 #define B1(b1)             rx_base1 (b1)
66 #define B2(b1, b2)         rx_base2 (b1, b2)
67 #define B3(b1, b2, b3)     rx_base3 (b1, b2, b3)
68 #define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4)
69
70 /* POS is bits from the MSB of the first byte to the LSB of the last byte.  */
71 #define F(val,pos,sz)      rx_field (val, pos, sz)
72 #define FE(exp,pos,sz)     rx_field (exp_val (exp), pos, sz);
73
74 #define O1(v)              rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255)
75 #define O2(v)              rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536)
76 #define O3(v)              rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216)
77 #define O4(v)              rx_op (v, 4, RXREL_SIGNED)
78
79 #define UO1(v)             rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255)
80 #define UO2(v)             rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536)
81 #define UO3(v)             rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216)
82 #define UO4(v)             rx_op (v, 4, RXREL_UNSIGNED)
83
84 #define NO1(v)             rx_op (v, 1, RXREL_NEGATIVE)
85 #define NO2(v)             rx_op (v, 2, RXREL_NEGATIVE)
86 #define NO3(v)             rx_op (v, 3, RXREL_NEGATIVE)
87 #define NO4(v)             rx_op (v, 4, RXREL_NEGATIVE)
88
89 #define PC1(v)             rx_op (v, 1, RXREL_PCREL)
90 #define PC2(v)             rx_op (v, 2, RXREL_PCREL)
91 #define PC3(v)             rx_op (v, 3, RXREL_PCREL)
92
93 #define IMM_(v,pos,size)   F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \
94                            if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
95 #define IMM(v,pos)         IMM_ (v, pos, 32)
96 #define IMMW(v,pos)        IMM_ (v, pos, 16); rx_range (v, -32768, 65536)
97 #define IMMB(v,pos)        IMM_ (v, pos, 8); rx_range (v, -128, 255)
98 #define NIMM(v,pos)        F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2)
99 #define NBIMM(v,pos)       F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2)
100 #define DSP(v,pos,msz)     if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
101                            else rx_linkrelax_dsp (pos); \
102                            F (displacement (v, msz), pos, 2)
103
104 #define id24(a,b2,b3)      B3 (0xfb+a, b2, b3)
105
106 static void        rx_check_float_support (void);
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 ']' opt_b
640           { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
641         | BCLR REG ',' disp '[' REG ']' opt_b
642           { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
643         | BTST REG ',' disp '[' REG ']' opt_b
644           { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
645         | BNOT REG ',' disp '[' REG ']' opt_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 ']' opt_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 ']' opt_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 float2_op
885         : { rx_check_float_support (); }
886           '#' EXPR ',' REG
887           { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); }
888         | float2_op_ni
889         ;
890
891 float2_op_ni
892         : { rx_check_float_support (); } 
893           REG ',' REG
894           { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); }
895         | { rx_check_float_support (); }
896           disp '[' REG ']' opt_l ',' REG
897           { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); }
898         ;
899
900 /* ====================================================================== */
901
902 disp    :      { $$ = zero_expr (); }
903         | EXPR { $$ = $1; }
904         ;
905
906 flag    : { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
907         ;
908
909 /* DOT_UB is not listed here, it's handled with a separate pattern.  */
910 /* Use sizemap[$n] to get LSIZE etc.  */
911 memex   : DOT_B  { $$ = 0; }
912         | DOT_W  { $$ = 1; }
913         |        { $$ = 2; }
914         | DOT_L  { $$ = 2; }
915         | DOT_UW { $$ = 3; }
916         ;
917
918 bwl     :       { $$ = LSIZE; }
919         | DOT_B { $$ = BSIZE; }
920         | DOT_W { $$ = WSIZE; }
921         | DOT_L { $$ = LSIZE; }
922         ;
923
924 bw      :       { $$ = 1; }
925         | DOT_B { $$ = 0; }
926         | DOT_W { $$ = 1; }
927         ;
928
929 opt_l   :       {}
930         | DOT_L {}
931         ;
932
933 opt_b   :       {}
934         | DOT_B {}
935         ;
936
937 %%
938 /* ====================================================================== */
939
940 static struct
941 {
942   const char * string;
943   int          token;
944   int          val;
945 }
946 token_table[] =
947 {
948   { "r0", REG, 0 },
949   { "r1", REG, 1 },
950   { "r2", REG, 2 },
951   { "r3", REG, 3 },
952   { "r4", REG, 4 },
953   { "r5", REG, 5 },
954   { "r6", REG, 6 },
955   { "r7", REG, 7 },
956   { "r8", REG, 8 },
957   { "r9", REG, 9 },
958   { "r10", REG, 10 },
959   { "r11", REG, 11 },
960   { "r12", REG, 12 },
961   { "r13", REG, 13 },
962   { "r14", REG, 14 },
963   { "r15", REG, 15 },
964
965   { "psw", CREG, 0 },
966   { "pc", CREG, 1 },
967   { "usp", CREG, 2 },
968   { "fpsw", CREG, 3 },
969   /* reserved */
970   /* reserved */
971   /* reserved */
972   { "wr", CREG, 7 },
973
974   { "bpsw", CREG, 8 },
975   { "bpc", CREG, 9 },
976   { "isp", CREG, 10 },
977   { "fintv", CREG, 11 },
978   { "intb", CREG, 12 },
979
980   { "pbp", CREG, 16 },
981   { "pben", CREG, 17 },
982
983   { "bbpsw", CREG, 24 },
984   { "bbpc", CREG, 25 },
985
986   { ".s", DOT_S, 0 },
987   { ".b", DOT_B, 0 },
988   { ".w", DOT_W, 0 },
989   { ".l", DOT_L, 0 },
990   { ".a", DOT_A , 0},
991   { ".ub", DOT_UB, 0 },
992   { ".uw", DOT_UW , 0},
993
994   { "c", FLAG, 0 },
995   { "z", FLAG, 1 },
996   { "s", FLAG, 2 },
997   { "o", FLAG, 3 },
998   { "i", FLAG, 8 },
999   { "u", FLAG, 9 },
1000
1001 #define OPC(x) { #x, x, IS_OPCODE }
1002   OPC(ABS),
1003   OPC(ADC),
1004   OPC(ADD),
1005   { "and", AND_, IS_OPCODE },
1006   OPC(BCLR),
1007   OPC(BCND),
1008   OPC(BMCND),
1009   OPC(BNOT),
1010   OPC(BRA),
1011   OPC(BRK),
1012   OPC(BSET),
1013   OPC(BSR),
1014   OPC(BTST),
1015   OPC(CLRPSW),
1016   OPC(CMP),
1017   OPC(DBT),
1018   OPC(DIV),
1019   OPC(DIVU),
1020   OPC(EDIV),
1021   OPC(EDIVU),
1022   OPC(EMUL),
1023   OPC(EMULU),
1024   OPC(FADD),
1025   OPC(FCMP),
1026   OPC(FDIV),
1027   OPC(FMUL),
1028   OPC(FREIT),
1029   OPC(FSUB),
1030   OPC(FTOI),
1031   OPC(INT),
1032   OPC(ITOF),
1033   OPC(JMP),
1034   OPC(JSR),
1035   OPC(MVFACHI),
1036   OPC(MVFACMI),
1037   OPC(MVFACLO),
1038   OPC(MVFC),
1039   OPC(MVTACHI),
1040   OPC(MVTACLO),
1041   OPC(MVTC),
1042   OPC(MVTIPL),
1043   OPC(MACHI),
1044   OPC(MACLO),
1045   OPC(MAX),
1046   OPC(MIN),
1047   OPC(MOV),
1048   OPC(MOVU),
1049   OPC(MUL),
1050   OPC(MULHI),
1051   OPC(MULLO),
1052   OPC(MULU),
1053   OPC(NEG),
1054   OPC(NOP),
1055   OPC(NOT),
1056   OPC(OR),
1057   OPC(POP),
1058   OPC(POPC),
1059   OPC(POPM),
1060   OPC(PUSH),
1061   OPC(PUSHA),
1062   OPC(PUSHC),
1063   OPC(PUSHM),
1064   OPC(RACW),
1065   OPC(REIT),
1066   OPC(REVL),
1067   OPC(REVW),
1068   OPC(RMPA),
1069   OPC(ROLC),
1070   OPC(RORC),
1071   OPC(ROTL),
1072   OPC(ROTR),
1073   OPC(ROUND),
1074   OPC(RTE),
1075   OPC(RTFI),
1076   OPC(RTS),
1077   OPC(RTSD),
1078   OPC(SAT),
1079   OPC(SATR),
1080   OPC(SBB),
1081   OPC(SCCND),
1082   OPC(SCMPU),
1083   OPC(SETPSW),
1084   OPC(SHAR),
1085   OPC(SHLL),
1086   OPC(SHLR),
1087   OPC(SMOVB),
1088   OPC(SMOVF),
1089   OPC(SMOVU),
1090   OPC(SSTR),
1091   OPC(STNZ),
1092   OPC(STOP),
1093   OPC(STZ),
1094   OPC(SUB),
1095   OPC(SUNTIL),
1096   OPC(SWHILE),
1097   OPC(TST),
1098   OPC(WAIT),
1099   OPC(XCHG),
1100   OPC(XOR),
1101 };
1102
1103 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1104
1105 static struct
1106 {
1107   char * string;
1108   int    token;
1109 }
1110 condition_opcode_table[] =
1111 {
1112   { "b", BCND },
1113   { "bm", BMCND },
1114   { "sc", SCCND },
1115 };
1116
1117 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1118
1119 static struct
1120 {
1121   char * string;
1122   int    val;
1123 }
1124 condition_table[] =
1125 {
1126   { "z", 0 },
1127   { "eq", 0 },
1128   { "geu",  2 },
1129   { "c",  2 },
1130   { "gtu", 4 },
1131   { "pz", 6 },
1132   { "ge", 8 },
1133   { "gt", 10 },
1134   { "o",  12},
1135   /* always = 14 */
1136   { "nz", 1 },
1137   { "ne", 1 },
1138   { "ltu", 3 },
1139   { "nc", 3 },
1140   { "leu", 5 },
1141   { "n", 7 },
1142   { "lt", 9 },
1143   { "le", 11 },
1144   { "no", 13 }
1145   /* never = 15 */
1146 };
1147
1148 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1149
1150 void
1151 rx_lex_init (char * beginning, char * ending)
1152 {
1153   rx_init_start = beginning;
1154   rx_lex_start = beginning;
1155   rx_lex_end = ending;
1156   rx_in_brackets = 0;
1157   rx_last_token = 0;
1158
1159   setbuf (stdout, 0);
1160 }
1161
1162 static int
1163 check_condition (char * base)
1164 {
1165   char * cp;
1166   unsigned int i;
1167
1168   if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
1169     return 0;
1170   if (memcmp (rx_lex_start, base, strlen (base)))
1171     return 0;
1172   cp = rx_lex_start + strlen (base);
1173   for (i = 0; i < NUM_CONDITIONS; i ++)
1174     {
1175       if (strcasecmp (cp, condition_table[i].string) == 0)
1176         {
1177           rx_lval.regno = condition_table[i].val;
1178           return 1;
1179         }
1180     }
1181   return 0;
1182 }
1183
1184 static int
1185 rx_lex (void)
1186 {
1187   unsigned int ci;
1188   char * save_input_pointer;
1189
1190   while (ISSPACE (*rx_lex_start)
1191          && rx_lex_start != rx_lex_end)
1192     rx_lex_start ++;
1193
1194   rx_last_exp_start = rx_lex_start;
1195
1196   if (rx_lex_start == rx_lex_end)
1197     return 0;
1198
1199   if (ISALPHA (*rx_lex_start)
1200       || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0)
1201       || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0)
1202       || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
1203     {
1204       unsigned int i;
1205       char * e;
1206       char save;
1207
1208       for (e = rx_lex_start + 1;
1209            e < rx_lex_end && ISALNUM (*e);
1210            e ++)
1211         ;
1212       save = *e;
1213       *e = 0;
1214
1215       if (strcmp (rx_lex_start, "%pidreg") == 0)
1216         {
1217           {
1218             rx_lval.regno = rx_pid_register;
1219             *e = save;
1220             rx_lex_start = e;
1221             rx_last_token = REG;
1222             return REG;
1223           }
1224         }
1225
1226       if (strcmp (rx_lex_start, "%gpreg") == 0)
1227         {
1228           {
1229             rx_lval.regno = rx_gp_register;
1230             *e = save;
1231             rx_lex_start = e;
1232             rx_last_token = REG;
1233             return REG;
1234           }
1235         }
1236
1237       if (rx_last_token == 0)
1238         for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
1239           if (check_condition (condition_opcode_table[ci].string))
1240             {
1241               *e = save;
1242               rx_lex_start = e;
1243               rx_last_token = condition_opcode_table[ci].token;
1244               return condition_opcode_table[ci].token;
1245             }
1246
1247       for (i = 0; i < NUM_TOKENS; i++)
1248         if (strcasecmp (rx_lex_start, token_table[i].string) == 0
1249             && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
1250             && !(token_table[i].token == FLAG && !need_flag))
1251           {
1252             rx_lval.regno = token_table[i].val;
1253             *e = save;
1254             rx_lex_start = e;
1255             rx_last_token = token_table[i].token;
1256             return token_table[i].token;
1257           }
1258       *e = save;
1259     }
1260
1261   if (rx_last_token == 0)
1262     {
1263       rx_last_token = UNKNOWN_OPCODE;
1264       return UNKNOWN_OPCODE;
1265     }
1266
1267   if (rx_last_token == UNKNOWN_OPCODE)
1268     return 0;
1269
1270   if (*rx_lex_start == '[')
1271     rx_in_brackets = 1;
1272   if (*rx_lex_start == ']')
1273     rx_in_brackets = 0;
1274
1275   if (rx_in_brackets
1276       || rx_last_token == REG
1277       || strchr ("[],#", *rx_lex_start))
1278     {
1279       rx_last_token = *rx_lex_start;
1280       return *rx_lex_start ++;
1281     }
1282
1283   save_input_pointer = input_line_pointer;
1284   input_line_pointer = rx_lex_start;
1285   rx_lval.exp.X_md = 0;
1286   expression (&rx_lval.exp);
1287
1288   /* We parse but ignore any :<size> modifier on expressions.  */
1289   if (*input_line_pointer == ':')
1290     {
1291       char *cp;
1292
1293       for (cp  = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
1294         if (!ISDIGIT (*cp))
1295           break;
1296       if (cp > input_line_pointer+1)
1297         input_line_pointer = cp;
1298     }
1299
1300   rx_lex_start = input_line_pointer;
1301   input_line_pointer = save_input_pointer;
1302   rx_last_token = EXPR;
1303   return EXPR;
1304 }
1305
1306 int
1307 rx_error (const char * str)
1308 {
1309   int len;
1310
1311   len = rx_last_exp_start - rx_init_start;
1312
1313   as_bad ("%s", rx_init_start);
1314   as_bad ("%*s^ %s", len, "", str);
1315   return 0;
1316 }
1317
1318 static int
1319 rx_intop (expressionS exp, int nbits, int opbits)
1320 {
1321   long v;
1322   long mask, msb;
1323
1324   if (exp.X_op == O_big && nbits == 32)
1325       return 1;
1326   if (exp.X_op != O_constant)
1327     return 0;
1328   v = exp.X_add_number;
1329
1330   msb = 1UL << (opbits - 1);
1331   mask = (1UL << opbits) - 1;
1332
1333   if ((v & msb) && ! (v & ~mask))
1334     v -= 1UL << opbits;
1335
1336   switch (nbits)
1337     {
1338     case 4:
1339       return -0x8 <= v && v <= 0x7;
1340     case 5:
1341       return -0x10 <= v && v <= 0x17;
1342     case 8:
1343       return -0x80 <= v && v <= 0x7f;
1344     case 16:
1345       return -0x8000 <= v && v <= 0x7fff;
1346     case 24:
1347       return -0x800000 <= v && v <= 0x7fffff;
1348     case 32:
1349       return 1;
1350     default:
1351       printf ("rx_intop passed %d\n", nbits);
1352       abort ();
1353     }
1354   return 1;
1355 }
1356
1357 static int
1358 rx_uintop (expressionS exp, int nbits)
1359 {
1360   unsigned long v;
1361
1362   if (exp.X_op != O_constant)
1363     return 0;
1364   v = exp.X_add_number;
1365
1366   switch (nbits)
1367     {
1368     case 4:
1369       return v <= 0xf;
1370     case 8:
1371       return v <= 0xff;
1372     case 16:
1373       return v <= 0xffff;
1374     case 24:
1375       return v <= 0xffffff;
1376     default:
1377       printf ("rx_uintop passed %d\n", nbits);
1378       abort ();
1379     }
1380   return 1;
1381 }
1382
1383 static int
1384 rx_disp3op (expressionS exp)
1385 {
1386   unsigned long v;
1387
1388   if (exp.X_op != O_constant)
1389     return 0;
1390   v = exp.X_add_number;
1391   if (v < 3 || v > 10)
1392     return 0;
1393   return 1;
1394 }
1395
1396 static int
1397 rx_disp5op (expressionS * exp, int msize)
1398 {
1399   long v;
1400
1401   if (exp->X_op != O_constant)
1402     return 0;
1403   v = exp->X_add_number;
1404
1405   switch (msize)
1406     {
1407     case BSIZE:
1408       if (0 < v && v <= 31)
1409         return 1;
1410       break;
1411     case WSIZE:
1412       if (v & 1)
1413         return 0;
1414       if (0 < v && v <= 63)
1415         {
1416           exp->X_add_number >>= 1;
1417           return 1;
1418         }
1419       break;
1420     case LSIZE:
1421       if (v & 3)
1422         return 0;
1423       if (0 < v && v <= 127)
1424         {
1425           exp->X_add_number >>= 2;
1426           return 1;
1427         }
1428       break;
1429     }
1430   return 0;
1431 }
1432
1433 /* Just like the above, but allows a zero displacement.  */
1434
1435 static int
1436 rx_disp5op0 (expressionS * exp, int msize)
1437 {
1438   if (exp->X_op != O_constant)
1439     return 0;
1440   if (exp->X_add_number == 0)
1441     return 1;
1442   return rx_disp5op (exp, msize);
1443 }
1444
1445 static int
1446 exp_val (expressionS exp)
1447 {
1448   if (exp.X_op != O_constant)
1449   {
1450     rx_error (_("constant expected"));
1451     return 0;
1452   }
1453   return exp.X_add_number;
1454 }
1455
1456 static expressionS
1457 zero_expr (void)
1458 {
1459   /* Static, so program load sets it to all zeros, which is what we want.  */
1460   static expressionS zero;
1461   zero.X_op = O_constant;
1462   return zero;
1463 }
1464
1465 static int
1466 immediate (expressionS exp, int type, int pos, int bits)
1467 {
1468   /* We will emit constants ourself here, so negate them.  */
1469   if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
1470     exp.X_add_number = - exp.X_add_number;
1471   if (type == RXREL_NEGATIVE_BORROW)
1472     {
1473       if (exp.X_op == O_constant)
1474         exp.X_add_number = - exp.X_add_number - 1;
1475       else
1476         rx_error (_("sbb cannot use symbolic immediates"));
1477     }
1478
1479   if (rx_intop (exp, 8, bits))
1480     {
1481       rx_op (exp, 1, type);
1482       return 1;
1483     }
1484   else if (rx_intop (exp, 16, bits))
1485     {
1486       rx_op (exp, 2, type);
1487       return 2;
1488     }
1489   else if (rx_uintop (exp, 16) && bits == 16)
1490     {
1491       rx_op (exp, 2, type);
1492       return 2;
1493     }
1494   else if (rx_intop (exp, 24, bits))
1495     {
1496       rx_op (exp, 3, type);
1497       return 3;
1498     }
1499   else if (rx_intop (exp, 32, bits))
1500     {
1501       rx_op (exp, 4, type);
1502       return 0;
1503     }
1504   else if (type == RXREL_SIGNED)
1505     {
1506       /* This is a symbolic immediate, we will relax it later.  */
1507       rx_relax (RX_RELAX_IMM, pos);
1508       rx_op (exp, linkrelax ? 4 : 1, type);
1509       return 1;
1510     }
1511   else
1512     {
1513       /* Let the linker deal with it.  */
1514       rx_op (exp, 4, type);
1515       return 0;
1516     }
1517 }
1518
1519 static int
1520 displacement (expressionS exp, int msize)
1521 {
1522   int val;
1523   int vshift = 0;
1524
1525   if (exp.X_op == O_symbol
1526       && exp.X_md)
1527     {
1528       switch (exp.X_md)
1529         {
1530         case BFD_RELOC_GPREL16:
1531           switch (msize)
1532             {
1533             case BSIZE:
1534               exp.X_md = BFD_RELOC_RX_GPRELB;
1535               break;
1536             case WSIZE:
1537               exp.X_md = BFD_RELOC_RX_GPRELW;
1538               break;
1539             case LSIZE:
1540               exp.X_md = BFD_RELOC_RX_GPRELL;
1541               break;
1542             }
1543           O2 (exp);
1544           return 2;
1545         }
1546     }
1547
1548   if (exp.X_op == O_subtract)
1549     {
1550       exp.X_md = BFD_RELOC_RX_DIFF;
1551       O2 (exp);
1552       return 2;
1553     }
1554
1555   if (exp.X_op != O_constant)
1556     {
1557       rx_error (_("displacements must be constants"));
1558       return -1;
1559     }
1560   val = exp.X_add_number;
1561
1562   if (val == 0)
1563     return 0;
1564
1565   switch (msize)
1566     {
1567     case BSIZE:
1568       break;
1569     case WSIZE:
1570       if (val & 1)
1571         rx_error (_("word displacement not word-aligned"));
1572       vshift = 1;
1573       break;
1574     case LSIZE:
1575       if (val & 3)
1576         rx_error (_("long displacement not long-aligned"));
1577       vshift = 2;
1578       break;
1579     default:
1580       as_bad (_("displacement with unknown size (internal bug?)\n"));
1581       break;
1582     }
1583
1584   val >>= vshift;
1585   exp.X_add_number = val;
1586
1587   if (0 <= val && val <= 255 )
1588     {
1589       O1 (exp);
1590       return 1;
1591     }
1592
1593   if (0 <= val && val <= 65535)
1594     {
1595       O2 (exp);
1596       return 2;
1597     }
1598   if (val < 0)
1599     rx_error (_("negative displacements not allowed"));
1600   else
1601     rx_error (_("displacement too large"));
1602   return -1;
1603 }
1604
1605 static void
1606 rtsd_immediate (expressionS exp)
1607 {
1608   int val;
1609
1610   if (exp.X_op != O_constant)
1611     {
1612       rx_error (_("rtsd size must be constant"));
1613       return;
1614     }
1615   val = exp.X_add_number;
1616   if (val & 3)
1617     rx_error (_("rtsd size must be multiple of 4"));
1618
1619   if (val < 0 || val > 1020)
1620     rx_error (_("rtsd size must be 0..1020"));
1621
1622   val >>= 2;
1623   exp.X_add_number = val;
1624   O1 (exp);
1625 }
1626
1627 static void
1628 rx_range (expressionS exp, int minv, int maxv)
1629 {
1630   int val;
1631
1632   if (exp.X_op != O_constant)
1633     return;
1634
1635   val = exp.X_add_number;
1636   if (val < minv || val > maxv)
1637     as_warn (_("Value %d out of range %d..%d"), val, minv, maxv);
1638 }
1639
1640 static void
1641 rx_check_float_support (void)
1642 {
1643   if (rx_cpu == RX100 || rx_cpu == RX200)
1644     rx_error (_("target CPU type does not support floating point instructions"));
1645 }