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