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