rx-parse.y revision 1.1.1.6
1/* rx-parse.y  Renesas RX parser
2   Copyright (C) 2008-2020 Free Software Foundation, Inc.
3
4   This file is part of GAS, the GNU Assembler.
5
6   GAS is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3, or (at your option)
9   any later version.
10
11   GAS is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with GAS; see the file COPYING.  If not, write to the Free
18   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19   02110-1301, USA.  */
20%{
21
22#include "as.h"
23#include "safe-ctype.h"
24#include "rx-defs.h"
25
26static int rx_lex (void);
27
28#define COND_EQ	0
29#define COND_NE	1
30
31#define MEMEX 0x06
32
33#define BSIZE 0
34#define WSIZE 1
35#define LSIZE 2
36#define DSIZE 3
37
38/*                       .sb    .sw    .l     .uw   */
39static int sizemap[] = { BSIZE, WSIZE, LSIZE, WSIZE };
40
41/* Ok, here are the rules for using these macros...
42
43   B*() is used to specify the base opcode bytes.  Fields to be filled
44        in later, leave zero.  Call this first.
45
46   F() and FE() are used to fill in fields within the base opcode bytes.  You MUST
47        call B*() before any F() or FE().
48
49   [UN]*O*(), PC*() appends operands to the end of the opcode.  You
50        must call P() and B*() before any of these, so that the fixups
51        have the right byte location.
52        O = signed, UO = unsigned, NO = negated, PC = pcrel
53
54   IMM() adds an immediate and fills in the field for it.
55   NIMM() same, but negates the immediate.
56   NBIMM() same, but negates the immediate, for sbb.
57   DSP() adds a displacement, and fills in the field for it.
58
59   Note that order is significant for the O, IMM, and DSP macros, as
60   they append their data to the operand buffer in the order that you
61   call them.
62
63   Use "disp" for displacements whenever possible; this handles the
64   "0" case properly.  */
65
66#define B1(b1)             rx_base1 (b1)
67#define B2(b1, b2)         rx_base2 (b1, b2)
68#define B3(b1, b2, b3)     rx_base3 (b1, b2, b3)
69#define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4)
70
71/* POS is bits from the MSB of the first byte to the LSB of the last byte.  */
72#define F(val,pos,sz)      rx_field (val, pos, sz)
73#define FE(exp,pos,sz)	   rx_field (exp_val (exp), pos, sz);
74
75#define O1(v)              rx_op (v, 1, RXREL_SIGNED); rx_range (v, -128, 255)
76#define O2(v)              rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536)
77#define O3(v)              rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216)
78#define O4(v)              rx_op (v, 4, RXREL_SIGNED)
79
80#define UO1(v)             rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255)
81#define UO2(v)             rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536)
82#define UO3(v)             rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216)
83#define UO4(v)             rx_op (v, 4, RXREL_UNSIGNED)
84
85#define NO1(v)             rx_op (v, 1, RXREL_NEGATIVE)
86#define NO2(v)             rx_op (v, 2, RXREL_NEGATIVE)
87#define NO3(v)             rx_op (v, 3, RXREL_NEGATIVE)
88#define NO4(v)             rx_op (v, 4, RXREL_NEGATIVE)
89
90#define PC1(v)             rx_op (v, 1, RXREL_PCREL)
91#define PC2(v)             rx_op (v, 2, RXREL_PCREL)
92#define PC3(v)             rx_op (v, 3, RXREL_PCREL)
93
94#define POST(v)            rx_post (v)
95
96#define IMM_(v,pos,size)   F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \
97			   if (v.X_op != O_constant && v.X_op != O_big) rx_linkrelax_imm (pos)
98#define IMM(v,pos)	   IMM_ (v, pos, 32)
99#define IMMW(v,pos)	   IMM_ (v, pos, 16); rx_range (v, -32768, 65536)
100#define IMMB(v,pos)	   IMM_ (v, pos, 8); rx_range (v, -128, 255)
101#define NIMM(v,pos)	   F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2)
102#define NBIMM(v,pos)	   F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2)
103#define DSP(v,pos,msz)	   if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
104			   else rx_linkrelax_dsp (pos); \
105			   F (displacement (v, msz), pos, 2)
106
107#define id24(a,b2,b3)	   B3 (0xfb + a, b2, b3)
108
109static void	   rx_check_float_support (void);
110static int         rx_intop (expressionS, int, int);
111static int         rx_uintop (expressionS, int);
112static int         rx_disp3op (expressionS);
113static int         rx_disp5op (expressionS *, int);
114static int         rx_disp5op0 (expressionS *, int);
115static int         exp_val (expressionS exp);
116static expressionS zero_expr (void);
117static int         immediate (expressionS, int, int, int);
118static int         displacement (expressionS, int);
119static void        rtsd_immediate (expressionS);
120static void	   rx_range (expressionS, int, int);
121static void        rx_check_v2 (void);
122static void        rx_check_v3 (void);
123static void        rx_check_dfpu (void);
124
125static int    need_flag = 0;
126static int    rx_in_brackets = 0;
127static int    rx_last_token = 0;
128static char * rx_init_start;
129static char * rx_last_exp_start = 0;
130static int    sub_op;
131static int    sub_op2;
132
133#define YYDEBUG 1
134#define YYERROR_VERBOSE 1
135
136%}
137
138%name-prefix="rx_"
139
140%union {
141  int regno;
142  expressionS exp;
143}
144
145%type <regno> REG FLAG CREG BCND BMCND SCCND ACC DREG DREGH DREGL DCREG DCMP
146%type <regno> flag bwl bw memex
147%type <exp> EXPR disp
148
149%token REG FLAG CREG ACC DREG DREGH DREGL DCREG
150
151%token EXPR UNKNOWN_OPCODE IS_OPCODE
152
153%token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW DOT_D
154
155%token ABS ADC ADD AND_
156%token BCLR BCND BFMOV BFMOVZ BMCND BNOT BRA BRK BSET BSR BTST
157%token CLRPSW CMP
158%token DABS DADD DBT DCMP DDIV DIV DIVU DMOV DMUL DNEG
159%token   DPOPM DPUSHM DROUND DSQRT DSUB DTOF DTOI DTOU
160%token EDIV EDIVU EMACA EMSBA EMUL EMULA EMULU
161%token FADD FCMP FDIV FMUL FREIT FSUB FSQRT FTOD FTOI FTOU
162%token INT ITOD ITOF
163%token JMP JSR
164%token MACHI MACLH MACLO MAX MIN MOV MOVCO MOVLI MOVU MSBHI MSBLH MSBLO MUL
165%token   MULHI MULLH MULLO MULU MVFACHI MVFACGU MVFACMI MVFACLO MVFC MVFDC
166%token     MVFDR MVTACGU MVTACHI MVTACLO MVTC MVTDC MVTIPL
167%token NEG NOP NOT
168%token OR
169%token POP POPC POPM PUSH PUSHA PUSHC PUSHM
170%token RACL RACW RDACL RDACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND
171%token   RSTR RTE RTFI RTS RTSD
172%token SAT SATR SAVE SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
173%token   SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
174%token TST
175%token UTOD UTOF
176%token WAIT
177%token XCHG XOR
178
179%%
180/* ====================================================================== */
181
182statement :
183
184	  UNKNOWN_OPCODE
185	  { as_bad (_("Unknown opcode: %s"), rx_init_start); }
186
187/* ---------------------------------------------------------------------- */
188
189	| BRK
190	  { B1 (0x00); }
191
192	| DBT
193	  { B1 (0x01); }
194
195	| RTS
196	  { B1 (0x02); }
197
198	| NOP
199	  { B1 (0x03); }
200
201/* ---------------------------------------------------------------------- */
202
203	| BRA EXPR
204	  { if (rx_disp3op ($2))
205	      { B1 (0x08); rx_disp3 ($2, 5); }
206	    else if (rx_intop ($2, 8, 8))
207	      { B1 (0x2e); PC1 ($2); }
208	    else if (rx_intop ($2, 16, 16))
209	      { B1 (0x38); PC2 ($2); }
210	    else if (rx_intop ($2, 24, 24))
211	      { B1 (0x04); PC3 ($2); }
212	    else
213	      { rx_relax (RX_RELAX_BRANCH, 0);
214		rx_linkrelax_branch ();
215		/* We'll convert this to a longer one later if needed.  */
216		B1 (0x08); rx_disp3 ($2, 5); } }
217
218	| BRA DOT_A EXPR
219	  { B1 (0x04); PC3 ($3); }
220
221	| BRA DOT_S EXPR
222	  { B1 (0x08); rx_disp3 ($3, 5); }
223
224/* ---------------------------------------------------------------------- */
225
226	| BSR EXPR
227	  { if (rx_intop ($2, 16, 16))
228	      { B1 (0x39); PC2 ($2); }
229	    else if (rx_intop ($2, 24, 24))
230	      { B1 (0x05); PC3 ($2); }
231	    else
232	      { rx_relax (RX_RELAX_BRANCH, 0);
233		rx_linkrelax_branch ();
234		B1 (0x39); PC2 ($2); } }
235	| BSR DOT_A EXPR
236	  { B1 (0x05), PC3 ($3); }
237
238/* ---------------------------------------------------------------------- */
239
240	| BCND DOT_S EXPR
241	  { if ($1 == COND_EQ || $1 == COND_NE)
242	      { B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($3, 5); }
243	    else
244	      as_bad (_("Only BEQ and BNE may have .S")); }
245
246/* ---------------------------------------------------------------------- */
247
248	| BCND DOT_B EXPR
249	  { B1 (0x20); F ($1, 4, 4); PC1 ($3); }
250
251	| BRA DOT_B EXPR
252	  { B1 (0x2e), PC1 ($3); }
253
254/* ---------------------------------------------------------------------- */
255
256	| BRA DOT_W EXPR
257	  { B1 (0x38), PC2 ($3); }
258	| BSR DOT_W EXPR
259	  { B1 (0x39), PC2 ($3); }
260	| BCND DOT_W EXPR
261	  { if ($1 == COND_EQ || $1 == COND_NE)
262	      { B1 ($1 == COND_EQ ? 0x3a : 0x3b); PC2 ($3); }
263	    else
264	      as_bad (_("Only BEQ and BNE may have .W")); }
265	| BCND EXPR
266	  { if ($1 == COND_EQ || $1 == COND_NE)
267	      {
268		rx_relax (RX_RELAX_BRANCH, 0);
269		rx_linkrelax_branch ();
270		B1 ($1 == COND_EQ ? 0x10 : 0x18); rx_disp3 ($2, 5);
271	      }
272	    else
273	      {
274		rx_relax (RX_RELAX_BRANCH, 0);
275		/* This is because we might turn it into a
276		   jump-over-jump long branch.  */
277		rx_linkrelax_branch ();
278	        B1 (0x20); F ($1, 4, 4); PC1 ($2);
279	      } }
280
281/* ---------------------------------------------------------------------- */
282
283	| MOV DOT_B '#' EXPR ',' '[' REG ']'
284	  { B2 (0xf8, 0x04); F ($7, 8, 4); IMMB ($4, 12);}
285
286	| MOV DOT_W '#' EXPR ',' '[' REG ']'
287          { B2 (0xf8, 0x01); F ($7, 8, 4); IMMW ($4, 12);}
288
289	| MOV DOT_L '#' EXPR ',' '[' REG ']'
290	  { B2 (0xf8, 0x02); F ($7, 8, 4); IMM ($4, 12);}
291
292	| MOV DOT_B '#' EXPR ',' disp '[' REG ']'
293	  /* rx_disp5op changes the value if it succeeds, so keep it last.  */
294	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, BSIZE))
295	      { B2 (0x3c, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
296	    else
297	      { B2 (0xf8, 0x04); F ($8, 8, 4); DSP ($6, 6, BSIZE); O1 ($4);
298	      if ($4.X_op != O_constant && $4.X_op != O_big) rx_linkrelax_imm (12); } }
299
300	| MOV DOT_W '#' EXPR ',' disp '[' REG ']'
301	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, WSIZE))
302	      { B2 (0x3d, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
303	    else
304	      { B2 (0xf8, 0x01); F ($8, 8, 4); DSP ($6, 6, WSIZE); IMMW ($4, 12); } }
305
306	| MOV DOT_L '#' EXPR ',' disp '[' REG ']'
307	  { if ($8 <= 7 && rx_uintop ($4, 8) && rx_disp5op0 (&$6, LSIZE))
308	      { B2 (0x3e, 0); rx_field5s2 ($6); F ($8, 9, 3); O1 ($4); }
309	    else
310	      { B2 (0xf8, 0x02); F ($8, 8, 4); DSP ($6, 6, LSIZE); IMM ($4, 12); } }
311
312/* ---------------------------------------------------------------------- */
313
314	| RTSD '#' EXPR ',' REG '-' REG
315	  { B2 (0x3f, 0); F ($5, 8, 4); F ($7, 12, 4); rtsd_immediate ($3);
316	    if ($5 == 0)
317	      rx_error (_("RTSD cannot pop R0"));
318	    if ($5 > $7)
319	      rx_error (_("RTSD first reg must be <= second reg")); }
320
321/* ---------------------------------------------------------------------- */
322
323	| CMP REG ',' REG
324	  { B2 (0x47, 0); F ($2, 8, 4); F ($4, 12, 4); }
325
326/* ---------------------------------------------------------------------- */
327
328	| CMP disp '[' REG ']' DOT_UB ',' REG
329	  { B2 (0x44, 0); F ($4, 8, 4); F ($8, 12, 4); DSP ($2, 6, BSIZE); }
330
331	| CMP disp '[' REG ']' memex ',' REG
332	  { B3 (MEMEX, 0x04, 0); F ($6, 8, 2);  F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, sizemap[$6]); }
333
334/* ---------------------------------------------------------------------- */
335
336	| MOVU bw REG ',' REG
337	  { B2 (0x5b, 0x00); F ($2, 5, 1); F ($3, 8, 4); F ($5, 12, 4); }
338
339/* ---------------------------------------------------------------------- */
340
341	| MOVU bw '[' REG ']' ',' REG
342	  { B2 (0x58, 0x00); F ($2, 5, 1); F ($4, 8, 4); F ($7, 12, 4); }
343
344	| MOVU bw EXPR '[' REG ']' ',' REG
345	  { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
346	      { B2 (0xb0, 0); F ($2, 4, 1); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
347	    else
348	      { B2 (0x58, 0x00); F ($2, 5, 1); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
349
350/* ---------------------------------------------------------------------- */
351
352	| SUB '#' EXPR ',' REG
353	  { if (rx_uintop ($3, 4))
354	      { B2 (0x60, 0); FE ($3, 8, 4); F ($5, 12, 4); }
355	    else
356	      /* This is really an add, but we negate the immediate.  */
357	      { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); NIMM ($3, 6); } }
358
359	| CMP '#' EXPR ',' REG
360	  { if (rx_uintop ($3, 4))
361	      { B2 (0x61, 0); FE ($3, 8, 4); F ($5, 12, 4); }
362	    else if (rx_uintop ($3, 8))
363	      { B2 (0x75, 0x50); F ($5, 12, 4); UO1 ($3); }
364	    else
365	      { B2 (0x74, 0x00); F ($5, 12, 4); IMM ($3, 6); } }
366
367	| ADD '#' EXPR ',' REG
368	  { if (rx_uintop ($3, 4))
369	      { B2 (0x62, 0); FE ($3, 8, 4); F ($5, 12, 4); }
370	    else
371	      { B2 (0x70, 0); F ($5, 8, 4); F ($5, 12, 4); IMM ($3, 6); } }
372
373	| MUL '#' EXPR ',' REG
374	  { if (rx_uintop ($3, 4))
375	      { B2 (0x63, 0); FE ($3, 8, 4); F ($5, 12, 4); }
376	    else
377	      { B2 (0x74, 0x10); F ($5, 12, 4); IMM ($3, 6); } }
378
379	| AND_ '#' EXPR ',' REG
380	  { if (rx_uintop ($3, 4))
381	      { B2 (0x64, 0); FE ($3, 8, 4); F ($5, 12, 4); }
382	    else
383	      { B2 (0x74, 0x20); F ($5, 12, 4); IMM ($3, 6); } }
384
385	| OR '#' EXPR ',' REG
386	  { if (rx_uintop ($3, 4))
387	      { B2 (0x65, 0); FE ($3, 8, 4); F ($5, 12, 4); }
388	    else
389	      { B2 (0x74, 0x30); F ($5, 12, 4); IMM ($3, 6); } }
390
391	| MOV DOT_L '#' EXPR ',' REG
392	  { if (rx_uintop ($4, 4))
393	      { B2 (0x66, 0); FE ($4, 8, 4); F ($6, 12, 4); }
394	    else if (rx_uintop ($4, 8))
395	      { B2 (0x75, 0x40); F ($6, 12, 4); UO1 ($4); }
396	    else
397	      { B2 (0xfb, 0x02); F ($6, 8, 4); IMM ($4, 12); } }
398
399	| MOV '#' EXPR ',' REG
400	  { if (rx_uintop ($3, 4))
401	      { B2 (0x66, 0); FE ($3, 8, 4); F ($5, 12, 4); }
402	    else if (rx_uintop ($3, 8))
403	      { B2 (0x75, 0x40); F ($5, 12, 4); UO1 ($3); }
404	    else
405	      { B2 (0xfb, 0x02); F ($5, 8, 4); IMM ($3, 12); } }
406
407/* ---------------------------------------------------------------------- */
408
409	| RTSD '#' EXPR
410	  { B1 (0x67); rtsd_immediate ($3); }
411
412/* ---------------------------------------------------------------------- */
413
414	| SHLR { sub_op = 0; } op_shift
415	| SHAR { sub_op = 1; } op_shift
416	| SHLL { sub_op = 2; } op_shift
417
418/* ---------------------------------------------------------------------- */
419
420	| PUSHM REG '-' REG
421	  {
422	    if ($2 == $4)
423	      { B2 (0x7e, 0x80); F (LSIZE, 10, 2); F ($2, 12, 4); }
424	    else
425	     { B2 (0x6e, 0); F ($2, 8, 4); F ($4, 12, 4); }
426	    if ($2 == 0)
427	      rx_error (_("PUSHM cannot push R0"));
428	    if ($2 > $4)
429	      rx_error (_("PUSHM first reg must be <= second reg")); }
430
431/* ---------------------------------------------------------------------- */
432
433	| POPM REG '-' REG
434	  {
435	    if ($2 == $4)
436	      { B2 (0x7e, 0xb0); F ($2, 12, 4); }
437	    else
438	      { B2 (0x6f, 0); F ($2, 8, 4); F ($4, 12, 4); }
439	    if ($2 == 0)
440	      rx_error (_("POPM cannot pop R0"));
441	    if ($2 > $4)
442	      rx_error (_("POPM first reg must be <= second reg")); }
443
444/* ---------------------------------------------------------------------- */
445
446	| ADD '#' EXPR ',' REG ',' REG
447	  { B2 (0x70, 0x00); F ($5, 8, 4); F ($7, 12, 4); IMM ($3, 6); }
448
449/* ---------------------------------------------------------------------- */
450
451	| INT '#' EXPR
452	  { B2(0x75, 0x60), UO1 ($3); }
453
454/* ---------------------------------------------------------------------- */
455
456	| BSET '#' EXPR ',' REG
457	  { B2 (0x78, 0); FE ($3, 7, 5); F ($5, 12, 4); }
458	| BCLR '#' EXPR ',' REG
459	  { B2 (0x7a, 0); FE ($3, 7, 5); F ($5, 12, 4); }
460
461/* ---------------------------------------------------------------------- */
462
463	| BTST '#' EXPR ',' REG
464	  { B2 (0x7c, 0x00); FE ($3, 7, 5); F ($5, 12, 4); }
465
466/* ---------------------------------------------------------------------- */
467
468	| SAT REG
469	  { B2 (0x7e, 0x30); F ($2, 12, 4); }
470	| RORC REG
471	  { B2 (0x7e, 0x40); F ($2, 12, 4); }
472	| ROLC REG
473	  { B2 (0x7e, 0x50); F ($2, 12, 4); }
474
475/* ---------------------------------------------------------------------- */
476
477	| PUSH bwl REG
478	  { B2 (0x7e, 0x80); F ($2, 10, 2); F ($3, 12, 4); }
479
480/* ---------------------------------------------------------------------- */
481
482	| POP REG
483	  { B2 (0x7e, 0xb0); F ($2, 12, 4); }
484
485/* ---------------------------------------------------------------------- */
486
487	| PUSHC CREG
488	  { if ($2 == 13)
489	      { rx_check_v2 (); }
490	    if ($2 < 16)
491	      { B2 (0x7e, 0xc0); F ($2, 12, 4); }
492	    else
493	      as_bad (_("PUSHC can only push the first 16 control registers")); }
494
495/* ---------------------------------------------------------------------- */
496
497	| POPC CREG
498	  { if ($2 == 13)
499	    { rx_check_v2 (); }
500	    if ($2 < 16)
501	      { B2 (0x7e, 0xe0); F ($2, 12, 4); }
502	    else
503	      as_bad (_("POPC can only pop the first 16 control registers")); }
504
505/* ---------------------------------------------------------------------- */
506
507	| SETPSW flag
508	  { B2 (0x7f, 0xa0); F ($2, 12, 4); }
509	| CLRPSW flag
510	  { B2 (0x7f, 0xb0); F ($2, 12, 4); }
511
512/* ---------------------------------------------------------------------- */
513
514	| JMP REG
515	  { B2 (0x7f, 0x00); F ($2, 12, 4); }
516	| JSR REG
517	  { B2 (0x7f, 0x10); F ($2, 12, 4); }
518	| BRA opt_l REG
519	  { B2 (0x7f, 0x40); F ($3, 12, 4); }
520	| BSR opt_l REG
521	  { B2 (0x7f, 0x50); F ($3, 12, 4); }
522
523/* ---------------------------------------------------------------------- */
524
525	| SCMPU
526	  { B2 (0x7f, 0x83); rx_note_string_insn_use (); }
527	| SMOVU
528	  { B2 (0x7f, 0x87); rx_note_string_insn_use (); }
529	| SMOVB
530	  { B2 (0x7f, 0x8b); rx_note_string_insn_use (); }
531	| SMOVF
532	  { B2 (0x7f, 0x8f); rx_note_string_insn_use (); }
533
534/* ---------------------------------------------------------------------- */
535
536	| SUNTIL bwl
537	  { B2 (0x7f, 0x80); F ($2, 14, 2); rx_note_string_insn_use (); }
538	| SWHILE bwl
539	  { B2 (0x7f, 0x84); F ($2, 14, 2); rx_note_string_insn_use (); }
540	| SSTR bwl
541	  { B2 (0x7f, 0x88); F ($2, 14, 2); }
542
543/* ---------------------------------------------------------------------- */
544
545	| RMPA bwl
546	  { B2 (0x7f, 0x8c); F ($2, 14, 2); rx_note_string_insn_use (); }
547
548/* ---------------------------------------------------------------------- */
549
550	| RTFI
551	  { B2 (0x7f, 0x94); }
552	| RTE
553	  { B2 (0x7f, 0x95); }
554	| WAIT
555	  { B2 (0x7f, 0x96); }
556	| SATR
557	  { B2 (0x7f, 0x93); }
558
559/* ---------------------------------------------------------------------- */
560
561	| MVTIPL '#' EXPR
562	  { B3 (0x75, 0x70, 0x00); FE ($3, 20, 4); }
563
564/* ---------------------------------------------------------------------- */
565
566	/* rx_disp5op changes the value if it succeeds, so keep it last.  */
567	| MOV bwl REG ',' EXPR '[' REG ']'
568	  { if ($3 <= 7 && $7 <= 7 && rx_disp5op (&$5, $2))
569	      { B2 (0x80, 0); F ($2, 2, 2); F ($7, 9, 3); F ($3, 13, 3); rx_field5s ($5); }
570	    else
571	      { B2 (0xc3, 0x00); F ($2, 2, 2); F ($7, 8, 4); F ($3, 12, 4); DSP ($5, 4, $2); }}
572
573/* ---------------------------------------------------------------------- */
574
575	| MOV bwl EXPR '[' REG ']' ',' REG
576	  { if ($5 <= 7 && $8 <= 7 && rx_disp5op (&$3, $2))
577	      { B2 (0x88, 0); F ($2, 2, 2); F ($5, 9, 3); F ($8, 13, 3); rx_field5s ($3); }
578	    else
579	      { B2 (0xcc, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($8, 12, 4); DSP ($3, 6, $2); } }
580
581/* ---------------------------------------------------------------------- */
582
583	/* MOV a,b - if a is a reg and b is mem, src and dest are
584	   swapped.  */
585
586	/* We don't use "disp" here because it causes a shift/reduce
587	   conflict with the other displacement-less patterns.  */
588
589	| MOV bwl REG ',' '[' REG ']'
590	  { B2 (0xc3, 0x00); F ($2, 2, 2); F ($6, 8, 4); F ($3, 12, 4); }
591
592/* ---------------------------------------------------------------------- */
593
594	| MOV bwl '[' REG ']' ',' disp '[' REG ']'
595	  { B2 (0xc0, 0); F ($2, 2, 2); F ($4, 8, 4); F ($9, 12, 4); DSP ($7, 4, $2); }
596
597/* ---------------------------------------------------------------------- */
598
599	| MOV bwl EXPR '[' REG ']' ',' disp '[' REG ']'
600	  { B2 (0xc0, 0x00); F ($2, 2, 2); F ($5, 8, 4); F ($10, 12, 4); DSP ($3, 6, $2); DSP ($8, 4, $2); }
601
602/* ---------------------------------------------------------------------- */
603
604	| MOV bwl REG ',' REG
605	  { B2 (0xcf, 0x00); F ($2, 2, 2); F ($3, 8, 4); F ($5, 12, 4); }
606
607/* ---------------------------------------------------------------------- */
608
609	| MOV bwl '[' REG ']' ',' REG
610	  { B2 (0xcc, 0x00); F ($2, 2, 2); F ($4, 8, 4); F ($7, 12, 4); }
611
612/* ---------------------------------------------------------------------- */
613
614	| BSET '#' EXPR ',' disp '[' REG ']' DOT_B
615	  { B2 (0xf0, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
616	| BCLR '#' EXPR ',' disp '[' REG ']' DOT_B
617	  { B2 (0xf0, 0x08); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
618	| BTST '#' EXPR ',' disp '[' REG ']' DOT_B
619	  { B2 (0xf4, 0x00); F ($7, 8, 4); FE ($3, 13, 3); DSP ($5, 6, BSIZE); }
620
621/* ---------------------------------------------------------------------- */
622
623	| PUSH bwl disp '[' REG ']'
624	  { B2 (0xf4, 0x08); F ($2, 14, 2); F ($5, 8, 4); DSP ($3, 6, $2); }
625
626/* ---------------------------------------------------------------------- */
627
628	| SBB   { sub_op = 0; } op_dp20_rm_l
629	| NEG   { sub_op = 1; sub_op2 = 1; } op_dp20_rr
630	| ADC   { sub_op = 2; } op_dp20_rim_l
631	| ABS   { sub_op = 3; sub_op2 = 2; } op_dp20_rr
632	| MAX   { sub_op = 4; } op_dp20_rim
633	| MIN   { sub_op = 5; } op_dp20_rim
634	| EMUL  { sub_op = 6; } op_dp20_i
635	| EMULU { sub_op = 7; } op_dp20_i
636	| DIV   { sub_op = 8; } op_dp20_rim
637	| DIVU  { sub_op = 9; } op_dp20_rim
638	| TST   { sub_op = 12; } op_dp20_rim
639	| XOR   { sub_op = 13; } op_xor
640	| NOT   { sub_op = 14; sub_op2 = 0; } op_dp20_rr
641	| STZ   { sub_op = 14; sub_op2 = 0; } op_dp20_ri
642	| STNZ  { sub_op = 15; sub_op2 = 1; } op_dp20_ri
643
644/* ---------------------------------------------------------------------- */
645
646	| EMUL  { sub_op = 6; } op_xchg
647	| EMULU { sub_op = 7; } op_xchg
648	| XCHG  { sub_op = 16; } op_xchg
649	| ITOF  { sub_op = 17; } op_xchg
650	| UTOF  { sub_op = 21; } op_xchg
651
652/* ---------------------------------------------------------------------- */
653
654	| BSET REG ',' REG
655	  { id24 (1, 0x63, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
656	| BCLR REG ',' REG
657	  { id24 (1, 0x67, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
658	| BTST REG ',' REG
659	  { id24 (1, 0x6b, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
660	| BNOT REG ',' REG
661	  { id24 (1, 0x6f, 0x00); F ($4, 16, 4); F ($2, 20, 4); }
662
663	| BSET REG ',' disp '[' REG ']' opt_b
664	  { id24 (1, 0x60, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
665	| BCLR REG ',' disp '[' REG ']' opt_b
666	  { id24 (1, 0x64, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
667	| BTST REG ',' disp '[' REG ']' opt_b
668	  { id24 (1, 0x68, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
669	| BNOT REG ',' disp '[' REG ']' opt_b
670	  { id24 (1, 0x6c, 0x00); F ($6, 16, 4); F ($2, 20, 4); DSP ($4, 14, BSIZE); }
671
672/* ---------------------------------------------------------------------- */
673
674	| FSUB  { sub_op = 0; } float3_op
675	| FCMP  { sub_op = 1; } float2_op
676	| FADD  { sub_op = 2; } float3_op
677	| FMUL  { sub_op = 3; } float3_op
678	| FDIV  { sub_op = 4; } float2_op
679	| FSQRT { sub_op = 8; } float2_op_ni
680	| FTOI  { sub_op = 5; } float2_op_ni
681	| FTOU  { sub_op = 9; } float2_op_ni
682	| ROUND { sub_op = 6; } float2_op_ni
683
684/* ---------------------------------------------------------------------- */
685
686
687/* ---------------------------------------------------------------------- */
688
689	| SCCND DOT_L REG
690	  { id24 (1, 0xdb, 0x00); F ($1, 20, 4); F ($3, 16, 4); }
691	| SCCND bwl disp '[' REG ']'
692	  { id24 (1, 0xd0, 0x00); F ($1, 20, 4); F ($2, 12, 2); F ($5, 16, 4); DSP ($3, 14, $2); }
693
694/* ---------------------------------------------------------------------- */
695
696	| BMCND '#' EXPR ',' disp '[' REG ']' opt_b
697	  { id24 (1, 0xe0, 0x00); F ($1, 20, 4); FE ($3, 11, 3);
698	      F ($7, 16, 4); DSP ($5, 14, BSIZE); }
699
700/* ---------------------------------------------------------------------- */
701
702	| BNOT '#' EXPR ',' disp '[' REG ']' opt_b
703	  { id24 (1, 0xe0, 0x0f); FE ($3, 11, 3); F ($7, 16, 4);
704	      DSP ($5, 14, BSIZE); }
705
706/* ---------------------------------------------------------------------- */
707
708	| MULHI REG ',' REG
709	  { id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
710	| MULHI REG ',' REG ',' ACC
711	  { rx_check_v2 (); id24 (2, 0x00, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
712	| MULLO REG ',' REG
713	  { id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
714	| MULLO REG ',' REG ',' ACC
715	  { rx_check_v2 (); id24 (2, 0x01, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
716	| MACHI REG ',' REG
717	  { id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
718	| MACHI REG ',' REG ',' ACC
719	  { rx_check_v2 (); id24 (2, 0x04, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
720	| MACLO REG ',' REG
721	  { id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); }
722	|  MACLO REG ',' REG ',' ACC
723	  { rx_check_v2 (); id24 (2, 0x05, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
724
725/* ---------------------------------------------------------------------- */
726
727	/* We don't have syntax for these yet.  */
728	| MVTACHI REG
729	  { id24 (2, 0x17, 0x00); F ($2, 20, 4); }
730	|  MVTACHI REG ',' ACC
731	  { rx_check_v2 (); id24 (2, 0x17, 0x00); F ($2, 20, 4); F ($4, 16, 1); }
732	| MVTACLO REG
733	  { id24 (2, 0x17, 0x10); F ($2, 20, 4); }
734	| MVTACLO REG ',' ACC
735	  { rx_check_v2 (); id24 (2, 0x17, 0x10); F ($2, 20, 4); F ($4, 16, 1); }
736	| MVFACHI REG
737	  { id24 (2, 0x1f, 0x00); F ($2, 20, 4); }
738	| MVFACHI { sub_op = 0; } mvfa_op
739	| MVFACMI REG
740	  { id24 (2, 0x1f, 0x20); F ($2, 20, 4); }
741	| MVFACMI { sub_op = 2; } mvfa_op
742	| MVFACLO REG
743	  { id24 (2, 0x1f, 0x10); F ($2, 20, 4); }
744	| MVFACLO { sub_op = 1; } mvfa_op
745	| RACW '#' EXPR
746	  { id24 (2, 0x18, 0x00);
747	    if (rx_uintop ($3, 4) && exp_val($3) == 1)
748	      ;
749	    else if (rx_uintop ($3, 4) && exp_val($3) == 2)
750	      F (1, 19, 1);
751	    else
752	      as_bad (_("RACW expects #1 or #2"));}
753	| RACW '#' EXPR ',' ACC
754	    { rx_check_v2 (); id24 (2, 0x18, 0x00); F ($5, 16, 1);
755	    if (rx_uintop ($3, 4) && exp_val($3) == 1)
756	      ;
757	    else if (rx_uintop ($3, 4) && exp_val($3) == 2)
758	      F (1, 19, 1);
759	    else
760	      as_bad (_("RACW expects #1 or #2"));}
761
762/* ---------------------------------------------------------------------- */
763
764	| MOV bwl REG ',' '[' REG '+' ']'
765	  { id24 (2, 0x20, 0); F ($2, 14, 2); F ($6, 16, 4); F ($3, 20, 4); }
766	| MOV bwl REG ',' '[' '-' REG ']'
767	  { id24 (2, 0x24, 0); F ($2, 14, 2); F ($7, 16, 4); F ($3, 20, 4); }
768
769/* ---------------------------------------------------------------------- */
770
771	| MOV bwl '[' REG '+' ']' ',' REG
772	  { id24 (2, 0x28, 0); F ($2, 14, 2); F ($4, 16, 4); F ($8, 20, 4); }
773	| MOV bwl '[' '-' REG ']' ',' REG
774	  { id24 (2, 0x2c, 0); F ($2, 14, 2); F ($5, 16, 4); F ($8, 20, 4); }
775
776/* ---------------------------------------------------------------------- */
777
778	| MOVU bw '[' REG '+' ']' ','  REG
779	  { id24 (2, 0x38, 0); F ($2, 15, 1); F ($4, 16, 4); F ($8, 20, 4); }
780	| MOVU bw '[' '-' REG ']' ',' REG
781	  { id24 (2, 0x3c, 0); F ($2, 15, 1); F ($5, 16, 4); F ($8, 20, 4); }
782
783/* ---------------------------------------------------------------------- */
784
785	| ROTL { sub_op = 6; } op_shift_rot
786	| ROTR { sub_op = 4; } op_shift_rot
787	| REVW { sub_op = 5; } op_shift_rot
788	| REVL { sub_op = 7; } op_shift_rot
789
790/* ---------------------------------------------------------------------- */
791
792	| MVTC REG ',' CREG
793	  { if ($4 == 13)
794	      rx_check_v2 ();
795	  id24 (2, 0x68, 0x00); F ($4 % 16, 20, 4); F ($4 / 16, 15, 1);
796	    F ($2, 16, 4); }
797
798/* ---------------------------------------------------------------------- */
799
800	| MVFC CREG ',' REG
801	  { if ($2 == 13)
802	    rx_check_v2 ();
803	  id24 (2, 0x6a, 0); F ($2, 15, 5); F ($4, 20, 4); }
804
805/* ---------------------------------------------------------------------- */
806
807	| ROTL '#' EXPR ',' REG
808	  { id24 (2, 0x6e, 0); FE ($3, 15, 5); F ($5, 20, 4); }
809	| ROTR '#' EXPR ',' REG
810	  { id24 (2, 0x6c, 0); FE ($3, 15, 5); F ($5, 20, 4); }
811
812/* ---------------------------------------------------------------------- */
813
814	| MVTC '#' EXPR ',' CREG
815	  { if ($5 == 13)
816	      rx_check_v2 ();
817	    id24 (2, 0x73, 0x00); F ($5, 19, 5); IMM ($3, 12); }
818
819/* ---------------------------------------------------------------------- */
820
821	| BMCND '#' EXPR ',' REG
822	  { id24 (2, 0xe0, 0x00); F ($1, 16, 4); FE ($3, 11, 5);
823	      F ($5, 20, 4); }
824
825/* ---------------------------------------------------------------------- */
826
827	| BNOT '#' EXPR ',' REG
828	  { id24 (2, 0xe0, 0xf0); FE ($3, 11, 5); F ($5, 20, 4); }
829
830/* ---------------------------------------------------------------------- */
831
832	| MOV bwl REG ',' '[' REG ',' REG ']'
833	  { id24 (3, 0x00, 0); F ($2, 10, 2); F ($6, 12, 4); F ($8, 16, 4); F ($3, 20, 4); }
834
835	| MOV bwl '[' REG ',' REG ']' ',' REG
836	  { id24 (3, 0x40, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
837
838	| MOVU bw '[' REG ',' REG ']' ',' REG
839	  { id24 (3, 0xc0, 0); F ($2, 10, 2); F ($4, 12, 4); F ($6, 16, 4); F ($9, 20, 4); }
840
841/* ---------------------------------------------------------------------- */
842
843	| SUB { sub_op = 0; } op_subadd
844	| ADD { sub_op = 2; } op_subadd
845	| MUL { sub_op = 3; } op_subadd
846	| AND_ { sub_op = 4; } op_subadd
847	| OR  { sub_op = 5; } op_subadd
848
849/* ---------------------------------------------------------------------- */
850/* There is no SBB #imm so we fake it with ADC.  */
851
852	| SBB '#' EXPR ',' REG
853	  { id24 (2, 0x70, 0x20); F ($5, 20, 4); NBIMM ($3, 12); }
854
855/* ---------------------------------------------------------------------- */
856
857	| MOVCO REG ',' '[' REG ']'
858	  { rx_check_v2 (); B3 (0xfd, 0x27, 0x00); F ($5, 16, 4); F ($2, 20, 4); }
859
860/* ---------------------------------------------------------------------- */
861
862	| MOVLI '[' REG ']' ',' REG
863	  { rx_check_v2 (); B3 (0xfd, 0x2f, 0x00); F ($3, 16, 4); F ($6, 20, 4); }
864
865/* ---------------------------------------------------------------------- */
866
867	| EMACA REG ',' REG ',' ACC
868	  { rx_check_v2 (); id24 (2, 0x07, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
869	| EMSBA REG ',' REG ',' ACC
870	  { rx_check_v2 (); id24 (2, 0x47, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
871	| EMULA REG ',' REG ',' ACC
872	  { rx_check_v2 (); id24 (2, 0x03, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
873	| MACLH REG ',' REG ',' ACC
874	  { rx_check_v2 (); id24 (2, 0x06, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
875	| MSBHI REG ',' REG ',' ACC
876	  { rx_check_v2 (); id24 (2, 0x44, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
877	| MSBLH REG ',' REG ',' ACC
878	  { rx_check_v2 (); id24 (2, 0x46, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
879	| MSBLO REG ',' REG ',' ACC
880	  { rx_check_v2 (); id24 (2, 0x45, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
881	| MULLH REG ',' REG ',' ACC
882	  { rx_check_v2 (); id24 (2, 0x02, 0x00); F ($2, 16, 4); F ($4, 20, 4); F ($6, 12, 1); }
883	| MVFACGU { sub_op = 3; } mvfa_op
884	| MVTACGU REG ',' ACC
885	  { rx_check_v2 (); id24 (2, 0x17, 0x30); F ($4, 16, 1); F ($2, 20, 4); }
886	| RACL '#' EXPR ',' ACC
887	{ rx_check_v2 (); id24 (2, 0x19, 0x00); F ($5, 16, 1);
888	    if (rx_uintop ($3, 4) && $3.X_add_number == 1)
889	      ;
890	    else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
891	      F (1, 19, 1);
892	    else
893	      as_bad (_("RACL expects #1 or #2"));}
894	| RDACL '#' EXPR ',' ACC
895	{ rx_check_v2 (); id24 (2, 0x19, 0x40); F ($5, 16, 1);
896	    if (rx_uintop ($3, 4) && $3.X_add_number == 1)
897	      ;
898	    else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
899	      F (1, 19, 1);
900	    else
901	      as_bad (_("RDACL expects #1 or #2"));}
902	| RDACW '#' EXPR ',' ACC
903	{ rx_check_v2 (); id24 (2, 0x18, 0x40); F ($5, 16, 1);
904	    if (rx_uintop ($3, 4) && $3.X_add_number == 1)
905	      ;
906	    else if (rx_uintop ($3, 4) && $3.X_add_number == 2)
907	      F (1, 19, 1);
908	    else
909	      as_bad (_("RDACW expects #1 or #2"));}
910
911/* ---------------------------------------------------------------------- */
912	| BFMOV { rx_check_v3(); sub_op = 1; } op_bfield
913	| BFMOVZ { rx_check_v3(); sub_op = 0; } op_bfield
914
915/* ---------------------------------------------------------------------- */
916	| RSTR { rx_check_v3(); sub_op = 1; } op_save_rstr
917	| SAVE { rx_check_v3(); sub_op = 0; } op_save_rstr
918
919/* ---------------------------------------------------------------------- */
920	| DABS { rx_check_dfpu(); sub_op = 0x0c; sub_op2 = 0x01; } double2_op
921	| DNEG { rx_check_dfpu(); sub_op = 0x0c; sub_op2 = 0x02; } double2_op
922	| DROUND { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x0d; } double2_op
923	| DSQRT { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x00; } double2_op
924	| DTOF { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x0c; } double2_op
925	| DTOI { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x08;} double2_op
926	| DTOU { rx_check_dfpu(); sub_op = 0x0d; sub_op2 = 0x09; } double2_op
927	| DADD { rx_check_dfpu(); sub_op = 0x00; } double3_op
928	| DDIV { rx_check_dfpu(); sub_op = 0x05; } double3_op
929	| DMUL { rx_check_dfpu(); sub_op = 0x02; } double3_op
930	| DSUB { rx_check_dfpu(); sub_op = 0x01; } double3_op
931	| DCMP DREG ',' DREG { rx_check_dfpu();
932	    B4(0x76, 0x90, 0x08, 0x00); F($1, 24, 4); F($2, 28, 4); F($4, 16, 4); }
933	| DMOV DOT_D REG ',' DREGH
934	{ rx_check_dfpu();
935	  B4(0xfd, 0x77, 0x80, 0x03); F($3, 20, 4); F($5, 24, 4); }
936	| DMOV DOT_L REG ',' DREGH
937	{ rx_check_dfpu();
938	  B4(0xfd, 0x77, 0x80, 0x02); F($3, 20, 4); F($5, 24, 4); }
939	| DMOV DOT_L REG ',' DREGL
940	{ rx_check_dfpu();
941	  B4(0xfd, 0x77, 0x80, 0x00); F($3, 20, 4); F($5, 24, 4); }
942	| DMOV DOT_L DREGH ',' REG
943	{ rx_check_dfpu();
944	  B4(0xfd, 0x75, 0x80, 0x02); F($3, 24, 4); F($5, 20, 4); }
945	| DMOV DOT_L DREGL ',' REG
946	{ rx_check_dfpu();
947	  B4(0xfd, 0x75, 0x80, 0x00); F($3, 24, 4); F($5, 20, 4); }
948	| DMOV DOT_D DREG ',' DREG
949	{ rx_check_dfpu();
950	  B4(0x76, 0x90, 0x0c, 0x00); F($3, 16, 4); F($5, 24, 4); }
951	| DMOV DOT_D DREG ',' '[' REG ']'
952	{ rx_check_dfpu();
953	  B4(0xfc, 0x78, 0x08, 0x00); F($6, 16, 4); F($3, 24, 4); }
954	| DMOV DOT_D DREG ',' disp '[' REG ']'
955	{ rx_check_dfpu();
956	  B3(0xfc, 0x78, 0x08); F($7, 16, 4); DSP($5, 14, DSIZE);
957	  POST($3 << 4); }
958	| DMOV DOT_D '[' REG ']' ',' DREG
959	{ rx_check_dfpu();
960	  B4(0xfc, 0xc8, 0x08, 0x00); F($4, 16, 4); F($7, 24, 4); }
961	| DMOV DOT_D disp '[' REG ']' ',' DREG
962	{ rx_check_dfpu();
963	  B3(0xfc, 0xc8, 0x08); F($5, 16, 4); DSP($3, 14, DSIZE);
964	  POST($8 << 4); }
965	| DMOV DOT_D '#' EXPR ',' DREGH
966	{ rx_check_dfpu();
967	  B3(0xf9, 0x03, 0x03); F($6, 16, 4); IMM($4, -1); }
968	| DMOV DOT_L '#' EXPR ',' DREGH
969	{ rx_check_dfpu();
970	  B3(0xf9, 0x03, 0x02); F($6, 16, 4); IMM($4, -1); }
971	| DMOV DOT_L '#' EXPR ',' DREGL
972	{ rx_check_dfpu();
973	  B3(0xf9, 0x03, 0x00); F($6, 16, 4); IMM($4, -1); }
974	| DPOPM DOT_D DREG '-' DREG
975	{ rx_check_dfpu();
976	  B3(0x75, 0xb8, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
977	| DPOPM DOT_L DCREG '-' DCREG
978	{ rx_check_dfpu();
979	  B3(0x75, 0xa8, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
980	| DPUSHM DOT_D DREG '-' DREG
981	{ rx_check_dfpu();
982	  B3(0x75, 0xb0, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
983	| DPUSHM DOT_L DCREG '-' DCREG
984	{ rx_check_dfpu();
985	  B3(0x75, 0xa0, 0x00); F($3, 16, 4); F($5 - $3, 20, 4); }
986	| MVFDC DCREG ',' REG
987	{ rx_check_dfpu();
988	  B4(0xfd, 0x75, 0x80, 0x04); F($2, 24, 4); F($4, 20, 4); }
989	| MVFDR
990	{ rx_check_dfpu(); B3(0x75, 0x90, 0x1b); }
991	| MVTDC REG ',' DCREG
992	{ rx_check_dfpu();
993	  B4(0xfd, 0x77, 0x80, 0x04); F($2, 24, 4); F($4, 20, 4); }
994	| FTOD REG ',' DREG
995	{ rx_check_dfpu();
996	  B4(0xfd, 0x77, 0x80, 0x0a); F($2, 24, 4); F($4, 20, 4); }
997	| ITOD REG ',' DREG
998	{ rx_check_dfpu();
999	  B4(0xfd, 0x77, 0x80, 0x09); F($2, 24, 4); F($4, 20, 4); }
1000	| UTOD REG ',' DREG
1001	{ rx_check_dfpu();
1002	  B4(0xfd, 0x77, 0x80, 0x0d); F($2, 24, 4); F($4, 20, 4); }
1003
1004/* ---------------------------------------------------------------------- */
1005
1006	;
1007
1008/* ====================================================================== */
1009
1010op_subadd
1011	: REG ',' REG
1012	  { B2 (0x43 + (sub_op<<2), 0); F ($1, 8, 4); F ($3, 12, 4); }
1013	| disp '[' REG ']' DOT_UB ',' REG
1014	  { B2 (0x40 + (sub_op<<2), 0); F ($3, 8, 4); F ($7, 12, 4); DSP ($1, 6, BSIZE); }
1015	| disp '[' REG ']' memex ',' REG
1016	  { B3 (MEMEX, sub_op<<2, 0); F ($5, 8, 2); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, sizemap[$5]); }
1017	| REG ',' REG ',' REG
1018	  { id24 (4, sub_op<<4, 0), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
1019	;
1020
1021/* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
1022
1023op_dp20_rm_l
1024	: REG ',' REG
1025	  { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
1026	| disp '[' REG ']' opt_l ',' REG
1027	  { B4 (MEMEX, 0xa0, 0x00 + sub_op, 0x00);
1028	  F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, LSIZE); }
1029	;
1030
1031/* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
1032
1033op_dp20_rm
1034	: REG ',' REG
1035	  { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
1036	| disp '[' REG ']' DOT_UB ',' REG
1037	  { id24 (1, 0x00 + (sub_op<<2), 0x00); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
1038	| disp '[' REG ']' memex ',' REG
1039	  { B4 (MEMEX, 0x20 + ($5 << 6), 0x00 + sub_op, 0x00);
1040	  F ($3, 24, 4); F ($7, 28, 4); DSP ($1, 14, sizemap[$5]); }
1041	;
1042
1043op_dp20_i
1044	: '#' EXPR ',' REG
1045	  { id24 (2, 0x70, sub_op<<4); F ($4, 20, 4); IMM ($2, 12); }
1046	;
1047
1048op_dp20_rim
1049	: op_dp20_rm
1050	| op_dp20_i
1051	;
1052
1053op_dp20_rim_l
1054	: op_dp20_rm_l
1055	| op_dp20_i
1056	;
1057
1058op_dp20_rr
1059	: REG ',' REG
1060	  { id24 (1, 0x03 + (sub_op<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
1061	| REG
1062	  { B2 (0x7e, sub_op2 << 4); F ($1, 12, 4); }
1063	;
1064
1065op_dp20_r
1066	: REG ',' REG
1067	  { id24 (1, 0x4b + (sub_op2<<2), 0x00); F ($1, 16, 4); F ($3, 20, 4); }
1068	;
1069
1070op_dp20_ri
1071	: { rx_check_v2 (); }
1072	  op_dp20_r
1073	| op_dp20_i
1074	;
1075
1076/* xchg, utof, itof, emul, emulu */
1077op_xchg
1078	: REG ',' REG
1079	  { id24 (1, 0x03 + (sub_op<<2), 0); F ($1, 16, 4); F ($3, 20, 4); }
1080	| disp '[' REG ']' DOT_UB ',' REG
1081	  { id24 (1, 0x00 + (sub_op<<2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, BSIZE); }
1082	| disp '[' REG ']' memex ',' REG
1083	  { B4 (MEMEX, 0x20, 0x00 + sub_op, 0); F ($5, 8, 2); F ($3, 24, 4); F ($7, 28, 4);
1084	    DSP ($1, 14, sizemap[$5]); }
1085	;
1086
1087/* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
1088op_shift_rot
1089	: REG ',' REG
1090	  { id24 (2, 0x60 + sub_op, 0); F ($1, 16, 4); F ($3, 20, 4); }
1091	;
1092op_shift
1093	: '#' EXPR ',' REG
1094	  { B2 (0x68 + (sub_op<<1), 0); FE ($2, 7, 5); F ($4, 12, 4); }
1095	| '#' EXPR ',' REG ',' REG
1096	  { id24 (2, 0x80 + (sub_op << 5), 0); FE ($2, 11, 5); F ($4, 16, 4); F ($6, 20, 4); }
1097	| op_shift_rot
1098	;
1099
1100float3_op
1101	: '#' EXPR ',' REG
1102	  { rx_check_float_support (); id24 (2, 0x72, sub_op << 4); F ($4, 20, 4); O4 ($2); }
1103	| REG ',' REG
1104	  { rx_check_float_support (); id24 (1, 0x83 + (sub_op << 2), 0); F ($1, 16, 4); F ($3, 20, 4); }
1105	| disp '[' REG ']' opt_l ',' REG
1106	  { rx_check_float_support (); id24 (1, 0x80 + (sub_op << 2), 0); F ($3, 16, 4); F ($7, 20, 4); DSP ($1, 14, LSIZE); }
1107	| REG ',' REG ',' REG
1108	  { rx_check_v2 (); id24 (4, 0x80 + (sub_op << 4), 0 ); F ($1, 16, 4); F ($3, 20, 4); F ($5, 12, 4); }
1109	;
1110
1111float2_op
1112	: { rx_check_float_support (); }
1113	  '#' EXPR ',' REG
1114	  { id24 (2, 0x72, sub_op << 4); F ($5, 20, 4); O4 ($3); }
1115	| float2_op_ni
1116	;
1117
1118float2_op_ni
1119	: { rx_check_float_support (); }
1120	  REG ',' REG
1121	  { id24 (1, 0x83 + (sub_op << 2), 0); F ($2, 16, 4); F ($4, 20, 4); }
1122	| { rx_check_float_support (); }
1123	  disp '[' REG ']' opt_l ',' REG
1124	  { id24 (1, 0x80 + (sub_op << 2), 0); F ($4, 16, 4); F ($8, 20, 4); DSP ($2, 14, LSIZE); }
1125	;
1126
1127mvfa_op
1128	: { rx_check_v2 (); }
1129	  '#' EXPR ',' ACC ',' REG
1130	  { id24 (2, 0x1e, sub_op << 4); F ($7, 20, 4); F ($5, 16, 1);
1131	    if (rx_uintop ($3, 4))
1132	      {
1133		switch (exp_val ($3))
1134		  {
1135		  case 0:
1136		    F (1, 15, 1);
1137		    break;
1138		  case 1:
1139		    F (1, 15, 1);
1140		    F (1, 17, 1);
1141		    break;
1142		  case 2:
1143		    break;
1144		  default:
1145		    as_bad (_("IMM expects #0 to #2"));}
1146	      } else
1147	        as_bad (_("IMM expects #0 to #2"));}
1148	;
1149
1150op_xor
1151	: op_dp20_rim
1152	| REG ',' REG ',' REG
1153	  { rx_check_v3(); B3(0xff,0x60,0x00), F ($5, 12, 4), F ($1, 16, 4), F ($3, 20, 4); }
1154	;
1155
1156op_bfield
1157	: { rx_check_v3(); }
1158	  '#' EXPR ',' '#' EXPR ',' '#' EXPR ',' REG ',' REG
1159	  { rx_range($3, 0, 31); rx_range($6, 0, 31); rx_range($9, 1, 31);
1160	    B3(0xfc, 0x5a + (sub_op << 2), 0); F($11, 16, 4); F($13, 20, 4);
1161	  rx_bfield($3, $6, $9);}
1162	;
1163
1164op_save_rstr
1165	: '#' EXPR
1166	  { B3(0xfd,0x76,0xe0 + (sub_op << 4)); UO1($2); }
1167	| REG
1168	  { B4(0xfd,0x76,0xc0 + (sub_op << 4), 0x00); F($1, 20, 4); }
1169	;
1170
1171double2_op
1172	: DREG ',' DREG
1173	{ B4(0x76, 0x90, sub_op, sub_op2); F($1, 16, 4); F($3, 24, 4);}
1174
1175double3_op
1176	: DREG ',' DREG ',' DREG
1177	{ B4(0x76, 0x90, sub_op, 0x00); F($1, 28, 4); F($3, 16,4); F($5, 24, 4);}
1178
1179/* ====================================================================== */
1180
1181disp	:      { $$ = zero_expr (); }
1182	| EXPR { $$ = $1; }
1183	;
1184
1185flag	: { need_flag = 1; } FLAG { need_flag = 0; $$ = $2; }
1186	;
1187
1188/* DOT_UB is not listed here, it's handled with a separate pattern.  */
1189/* Use sizemap[$n] to get LSIZE etc.  */
1190memex	: DOT_B  { $$ = 0; }
1191	| DOT_W  { $$ = 1; }
1192	|        { $$ = 2; }
1193	| DOT_L  { $$ = 2; }
1194	| DOT_UW { $$ = 3; }
1195	;
1196
1197bwl	:       { $$ = LSIZE; }
1198	| DOT_B { $$ = BSIZE; }
1199	| DOT_W { $$ = WSIZE; }
1200	| DOT_L { $$ = LSIZE; }
1201	;
1202
1203bw	:       { $$ = 1; }
1204	| DOT_B { $$ = 0; }
1205	| DOT_W { $$ = 1; }
1206	;
1207
1208opt_l	: 	{}
1209	| DOT_L {}
1210	;
1211
1212opt_b	: 	{}
1213	| DOT_B {}
1214	;
1215
1216%%
1217/* ====================================================================== */
1218
1219static struct
1220{
1221  const char * string;
1222  int          token;
1223  int          val;
1224}
1225token_table[] =
1226{
1227  { "r0", REG, 0 },
1228  { "r1", REG, 1 },
1229  { "r2", REG, 2 },
1230  { "r3", REG, 3 },
1231  { "r4", REG, 4 },
1232  { "r5", REG, 5 },
1233  { "r6", REG, 6 },
1234  { "r7", REG, 7 },
1235  { "r8", REG, 8 },
1236  { "r9", REG, 9 },
1237  { "r10", REG, 10 },
1238  { "r11", REG, 11 },
1239  { "r12", REG, 12 },
1240  { "r13", REG, 13 },
1241  { "r14", REG, 14 },
1242  { "r15", REG, 15 },
1243
1244  { "psw", CREG, 0 },
1245  { "pc", CREG, 1 },
1246  { "usp", CREG, 2 },
1247  { "fpsw", CREG, 3 },
1248  /* reserved */
1249  /* reserved */
1250  /* reserved */
1251  { "wr", CREG, 7 },
1252
1253  { "bpsw", CREG, 8 },
1254  { "bpc", CREG, 9 },
1255  { "isp", CREG, 10 },
1256  { "fintv", CREG, 11 },
1257  { "intb", CREG, 12 },
1258  { "extb", CREG, 13 },
1259
1260  { "pbp", CREG, 16 },
1261  { "pben", CREG, 17 },
1262
1263  { "bbpsw", CREG, 24 },
1264  { "bbpc", CREG, 25 },
1265
1266  { "dr0", DREG, 0 },
1267  { "dr1", DREG, 1 },
1268  { "dr2", DREG, 2 },
1269  { "dr3", DREG, 3 },
1270  { "dr4", DREG, 4 },
1271  { "dr5", DREG, 5 },
1272  { "dr6", DREG, 6 },
1273  { "dr7", DREG, 7 },
1274  { "dr8", DREG, 8 },
1275  { "dr9", DREG, 9 },
1276  { "dr10", DREG, 10 },
1277  { "dr11", DREG, 11 },
1278  { "dr12", DREG, 12 },
1279  { "dr13", DREG, 13 },
1280  { "dr14", DREG, 14 },
1281  { "dr15", DREG, 15 },
1282
1283  { "drh0", DREGH, 0 },
1284  { "drh1", DREGH, 1 },
1285  { "drh2", DREGH, 2 },
1286  { "drh3", DREGH, 3 },
1287  { "drh4", DREGH, 4 },
1288  { "drh5", DREGH, 5 },
1289  { "drh6", DREGH, 6 },
1290  { "drh7", DREGH, 7 },
1291  { "drh8", DREGH, 8 },
1292  { "drh9", DREGH, 9 },
1293  { "drh10", DREGH, 10 },
1294  { "drh11", DREGH, 11 },
1295  { "drh12", DREGH, 12 },
1296  { "drh13", DREGH, 13 },
1297  { "drh14", DREGH, 14 },
1298  { "drh15", DREGH, 15 },
1299
1300  { "drl0", DREGL, 0 },
1301  { "drl1", DREGL, 1 },
1302  { "drl2", DREGL, 2 },
1303  { "drl3", DREGL, 3 },
1304  { "drl4", DREGL, 4 },
1305  { "drl5", DREGL, 5 },
1306  { "drl6", DREGL, 6 },
1307  { "drl7", DREGL, 7 },
1308  { "drl8", DREGL, 8 },
1309  { "drl9", DREGL, 9 },
1310  { "drl10", DREGL, 10 },
1311  { "drl11", DREGL, 11 },
1312  { "drl12", DREGL, 12 },
1313  { "drl13", DREGL, 13 },
1314  { "drl14", DREGL, 14 },
1315  { "drl15", DREGL, 15 },
1316
1317  { "DPSW", DCREG, 0 },
1318  { "DCMR", DCREG, 1 },
1319  { "DCENT", DCREG, 2 },
1320  { "DEPC", DCREG, 3 },
1321  { "DCR0", DCREG, 0 },
1322  { "DCR1", DCREG, 1 },
1323  { "DCR2", DCREG, 2 },
1324  { "DCR3", DCREG, 3 },
1325
1326  { ".s", DOT_S, 0 },
1327  { ".b", DOT_B, 0 },
1328  { ".w", DOT_W, 0 },
1329  { ".l", DOT_L, 0 },
1330  { ".a", DOT_A , 0},
1331  { ".ub", DOT_UB, 0 },
1332  { ".uw", DOT_UW , 0},
1333  { ".d", DOT_D , 0},
1334
1335  { "c", FLAG, 0 },
1336  { "z", FLAG, 1 },
1337  { "s", FLAG, 2 },
1338  { "o", FLAG, 3 },
1339  { "i", FLAG, 8 },
1340  { "u", FLAG, 9 },
1341
1342  { "a0", ACC, 0 },
1343  { "a1", ACC, 1 },
1344
1345#define OPC(x) { #x, x, IS_OPCODE }
1346  OPC(ABS),
1347  OPC(ADC),
1348  OPC(ADD),
1349  { "and", AND_, IS_OPCODE },
1350  OPC(BCLR),
1351  OPC(BCND),
1352  OPC(BFMOV),
1353  OPC(BFMOVZ),
1354  OPC(BMCND),
1355  OPC(BNOT),
1356  OPC(BRA),
1357  OPC(BRK),
1358  OPC(BSET),
1359  OPC(BSR),
1360  OPC(BTST),
1361  OPC(CLRPSW),
1362  OPC(CMP),
1363  OPC(DABS),
1364  OPC(DADD),
1365  OPC(DBT),
1366  OPC(DDIV),
1367  OPC(DIV),
1368  OPC(DIVU),
1369  OPC(DMOV),
1370  OPC(DMUL),
1371  OPC(DNEG),
1372  OPC(DPOPM),
1373  OPC(DPUSHM),
1374  OPC(DROUND),
1375  OPC(DSQRT),
1376  OPC(DSUB),
1377  OPC(DTOF),
1378  OPC(DTOI),
1379  OPC(DTOU),
1380  OPC(EDIV),
1381  OPC(EDIVU),
1382  OPC(EMACA),
1383  OPC(EMSBA),
1384  OPC(EMUL),
1385  OPC(EMULA),
1386  OPC(EMULU),
1387  OPC(FADD),
1388  OPC(FCMP),
1389  OPC(FDIV),
1390  OPC(FMUL),
1391  OPC(FREIT),
1392  OPC(FSQRT),
1393  OPC(FTOD),
1394  OPC(FTOU),
1395  OPC(FSUB),
1396  OPC(FTOI),
1397  OPC(INT),
1398  OPC(ITOD),
1399  OPC(ITOF),
1400  OPC(JMP),
1401  OPC(JSR),
1402  OPC(MVFACGU),
1403  OPC(MVFACHI),
1404  OPC(MVFACMI),
1405  OPC(MVFACLO),
1406  OPC(MVFC),
1407  OPC(MVFDC),
1408  OPC(MVFDR),
1409  OPC(MVTDC),
1410  OPC(MVTACGU),
1411  OPC(MVTACHI),
1412  OPC(MVTACLO),
1413  OPC(MVTC),
1414  OPC(MVTIPL),
1415  OPC(MACHI),
1416  OPC(MACLO),
1417  OPC(MACLH),
1418  OPC(MAX),
1419  OPC(MIN),
1420  OPC(MOV),
1421  OPC(MOVCO),
1422  OPC(MOVLI),
1423  OPC(MOVU),
1424  OPC(MSBHI),
1425  OPC(MSBLH),
1426  OPC(MSBLO),
1427  OPC(MUL),
1428  OPC(MULHI),
1429  OPC(MULLH),
1430  OPC(MULLO),
1431  OPC(MULU),
1432  OPC(NEG),
1433  OPC(NOP),
1434  OPC(NOT),
1435  OPC(OR),
1436  OPC(POP),
1437  OPC(POPC),
1438  OPC(POPM),
1439  OPC(PUSH),
1440  OPC(PUSHA),
1441  OPC(PUSHC),
1442  OPC(PUSHM),
1443  OPC(RACL),
1444  OPC(RACW),
1445  OPC(RDACL),
1446  OPC(RDACW),
1447  OPC(REIT),
1448  OPC(REVL),
1449  OPC(REVW),
1450  OPC(RMPA),
1451  OPC(ROLC),
1452  OPC(RORC),
1453  OPC(ROTL),
1454  OPC(ROTR),
1455  OPC(ROUND),
1456  OPC(RSTR),
1457  OPC(RTE),
1458  OPC(RTFI),
1459  OPC(RTS),
1460  OPC(RTSD),
1461  OPC(SAT),
1462  OPC(SATR),
1463  OPC(SAVE),
1464  OPC(SBB),
1465  OPC(SCCND),
1466  OPC(SCMPU),
1467  OPC(SETPSW),
1468  OPC(SHAR),
1469  OPC(SHLL),
1470  OPC(SHLR),
1471  OPC(SMOVB),
1472  OPC(SMOVF),
1473  OPC(SMOVU),
1474  OPC(SSTR),
1475  OPC(STNZ),
1476  OPC(STOP),
1477  OPC(STZ),
1478  OPC(SUB),
1479  OPC(SUNTIL),
1480  OPC(SWHILE),
1481  OPC(TST),
1482  OPC(UTOD),
1483  OPC(UTOF),
1484  OPC(WAIT),
1485  OPC(XCHG),
1486  OPC(XOR),
1487};
1488
1489#define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1490
1491static struct
1492{
1493  const char * string;
1494  int    token;
1495}
1496condition_opcode_table[] =
1497{
1498  { "b", BCND },
1499  { "bm", BMCND },
1500  { "sc", SCCND },
1501};
1502
1503#define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1504
1505struct condition_symbol
1506{
1507  const char * string;
1508  int    val;
1509};
1510
1511static struct condition_symbol condition_table[] =
1512{
1513  { "z", 0 },
1514  { "eq", 0 },
1515  { "geu",  2 },
1516  { "c",  2 },
1517  { "gtu", 4 },
1518  { "pz", 6 },
1519  { "ge", 8 },
1520  { "gt", 10 },
1521  { "o",  12},
1522  /* always = 14 */
1523  { "nz", 1 },
1524  { "ne", 1 },
1525  { "ltu", 3 },
1526  { "nc", 3 },
1527  { "leu", 5 },
1528  { "n", 7 },
1529  { "lt", 9 },
1530  { "le", 11 },
1531  { "no", 13 },
1532  /* never = 15 */
1533};
1534
1535static struct condition_symbol double_condition_table[] =
1536{
1537  { "un", 1 },
1538  { "eq", 2 },
1539  { "lt", 4 },
1540  { "le", 6 },
1541};
1542
1543#define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1544#define NUM_DOUBLE_CONDITIONS (sizeof (double_condition_table) / sizeof (double_condition_table[0]))
1545
1546void
1547rx_lex_init (char * beginning, char * ending)
1548{
1549  rx_init_start = beginning;
1550  rx_lex_start = beginning;
1551  rx_lex_end = ending;
1552  rx_in_brackets = 0;
1553  rx_last_token = 0;
1554
1555  setbuf (stdout, 0);
1556}
1557
1558static int
1559check_condition (const char * base, struct condition_symbol *t, unsigned int num)
1560{
1561  char * cp;
1562  unsigned int i;
1563
1564  if ((unsigned) (rx_lex_end - rx_lex_start) < strlen (base) + 1)
1565    return 0;
1566  if (memcmp (rx_lex_start, base, strlen (base)))
1567    return 0;
1568  cp = rx_lex_start + strlen (base);
1569  for (i = 0; i < num; i ++)
1570    {
1571      if (strcasecmp (cp, t[i].string) == 0)
1572	{
1573	  rx_lval.regno = t[i].val;
1574	  return 1;
1575	}
1576    }
1577  return 0;
1578}
1579
1580static int
1581rx_lex (void)
1582{
1583  unsigned int ci;
1584  char * save_input_pointer;
1585
1586  while (ISSPACE (*rx_lex_start)
1587	 && rx_lex_start != rx_lex_end)
1588    rx_lex_start ++;
1589
1590  rx_last_exp_start = rx_lex_start;
1591
1592  if (rx_lex_start == rx_lex_end)
1593    return 0;
1594
1595  if (ISALPHA (*rx_lex_start)
1596      || (rx_pid_register != -1 && memcmp (rx_lex_start, "%pidreg", 7) == 0)
1597      || (rx_gp_register != -1 && memcmp (rx_lex_start, "%gpreg", 6) == 0)
1598      || (*rx_lex_start == '.' && ISALPHA (rx_lex_start[1])))
1599    {
1600      unsigned int i;
1601      char * e;
1602      char save;
1603
1604      for (e = rx_lex_start + 1;
1605	   e < rx_lex_end && ISALNUM (*e);
1606	   e ++)
1607	;
1608      save = *e;
1609      *e = 0;
1610
1611      if (strcmp (rx_lex_start, "%pidreg") == 0)
1612	{
1613	  {
1614	    rx_lval.regno = rx_pid_register;
1615	    *e = save;
1616	    rx_lex_start = e;
1617	    rx_last_token = REG;
1618	    return REG;
1619	  }
1620	}
1621
1622      if (strcmp (rx_lex_start, "%gpreg") == 0)
1623	{
1624	  {
1625	    rx_lval.regno = rx_gp_register;
1626	    *e = save;
1627	    rx_lex_start = e;
1628	    rx_last_token = REG;
1629	    return REG;
1630	  }
1631	}
1632
1633      if (rx_last_token == 0)
1634	{
1635	  for (ci = 0; ci < NUM_CONDITION_OPCODES; ci ++)
1636	    if (check_condition (condition_opcode_table[ci].string,
1637				 condition_table, NUM_CONDITIONS))
1638	      {
1639		*e = save;
1640		rx_lex_start = e;
1641		rx_last_token = condition_opcode_table[ci].token;
1642		return condition_opcode_table[ci].token;
1643	      }
1644	  if  (check_condition ("dcmp", double_condition_table,
1645				NUM_DOUBLE_CONDITIONS))
1646	    {
1647	      *e = save;
1648	      rx_lex_start = e;
1649	      rx_last_token = DCMP;
1650	      return DCMP;
1651	    }
1652	}
1653
1654      for (i = 0; i < NUM_TOKENS; i++)
1655	if (strcasecmp (rx_lex_start, token_table[i].string) == 0
1656	    && !(token_table[i].val == IS_OPCODE && rx_last_token != 0)
1657	    && !(token_table[i].token == FLAG && !need_flag))
1658	  {
1659	    rx_lval.regno = token_table[i].val;
1660	    *e = save;
1661	    rx_lex_start = e;
1662	    rx_last_token = token_table[i].token;
1663	    return token_table[i].token;
1664	  }
1665      *e = save;
1666    }
1667
1668  if (rx_last_token == 0)
1669    {
1670      rx_last_token = UNKNOWN_OPCODE;
1671      return UNKNOWN_OPCODE;
1672    }
1673
1674  if (rx_last_token == UNKNOWN_OPCODE)
1675    return 0;
1676
1677  if (*rx_lex_start == '[')
1678    rx_in_brackets = 1;
1679  if (*rx_lex_start == ']')
1680    rx_in_brackets = 0;
1681
1682  if (rx_in_brackets
1683      || rx_last_token == REG || rx_last_token == DREG || rx_last_token == DCREG
1684      || strchr ("[],#", *rx_lex_start))
1685    {
1686      rx_last_token = *rx_lex_start;
1687      return *rx_lex_start ++;
1688    }
1689
1690  save_input_pointer = input_line_pointer;
1691  input_line_pointer = rx_lex_start;
1692  rx_lval.exp.X_md = 0;
1693  expression (&rx_lval.exp);
1694
1695  /* We parse but ignore any :<size> modifier on expressions.  */
1696  if (*input_line_pointer == ':')
1697    {
1698      char *cp;
1699
1700      for (cp  = input_line_pointer + 1; *cp && cp < rx_lex_end; cp++)
1701	if (!ISDIGIT (*cp))
1702	  break;
1703      if (cp > input_line_pointer+1)
1704	input_line_pointer = cp;
1705    }
1706
1707  rx_lex_start = input_line_pointer;
1708  input_line_pointer = save_input_pointer;
1709  rx_last_token = EXPR;
1710  return EXPR;
1711}
1712
1713int
1714rx_error (const char * str)
1715{
1716  int len;
1717
1718  len = rx_last_exp_start - rx_init_start;
1719
1720  as_bad ("%s", rx_init_start);
1721  as_bad ("%*s^ %s", len, "", str);
1722  return 0;
1723}
1724
1725static int
1726rx_intop (expressionS exp, int nbits, int opbits)
1727{
1728  long v;
1729  long mask, msb;
1730
1731  if (exp.X_op == O_big)
1732    {
1733      if (nbits == 32)
1734	return 1;
1735      if (exp.X_add_number == -1)
1736	return 0;
1737    }
1738  else if (exp.X_op != O_constant)
1739    return 0;
1740  v = exp.X_add_number;
1741
1742  msb = 1UL << (opbits - 1);
1743  mask = (1UL << opbits) - 1;
1744
1745  if ((v & msb) && ! (v & ~mask))
1746    v -= 1UL << opbits;
1747
1748  switch (nbits)
1749    {
1750    case 4:
1751      return -0x8 <= v && v <= 0x7;
1752    case 5:
1753      return -0x10 <= v && v <= 0x17;
1754    case 8:
1755      return -0x80 <= v && v <= 0x7f;
1756    case 16:
1757      return -0x8000 <= v && v <= 0x7fff;
1758    case 24:
1759      return -0x800000 <= v && v <= 0x7fffff;
1760    case 32:
1761      return 1;
1762    default:
1763      printf ("rx_intop passed %d\n", nbits);
1764      abort ();
1765    }
1766  return 1;
1767}
1768
1769static int
1770rx_uintop (expressionS exp, int nbits)
1771{
1772  unsigned long v;
1773
1774  if (exp.X_op != O_constant)
1775    return 0;
1776  v = exp.X_add_number;
1777
1778  switch (nbits)
1779    {
1780    case 4:
1781      return v <= 0xf;
1782    case 8:
1783      return v <= 0xff;
1784    case 16:
1785      return v <= 0xffff;
1786    case 24:
1787      return v <= 0xffffff;
1788    default:
1789      printf ("rx_uintop passed %d\n", nbits);
1790      abort ();
1791    }
1792  return 1;
1793}
1794
1795static int
1796rx_disp3op (expressionS exp)
1797{
1798  unsigned long v;
1799
1800  if (exp.X_op != O_constant)
1801    return 0;
1802  v = exp.X_add_number;
1803  if (v < 3 || v > 10)
1804    return 0;
1805  return 1;
1806}
1807
1808static int
1809rx_disp5op (expressionS * exp, int msize)
1810{
1811  long v;
1812
1813  if (exp->X_op != O_constant)
1814    return 0;
1815  v = exp->X_add_number;
1816
1817  switch (msize)
1818    {
1819    case BSIZE:
1820      if (0 <= v && v <= 31)
1821	return 1;
1822      break;
1823    case WSIZE:
1824      if (v & 1)
1825	return 0;
1826      if (0 <= v && v <= 63)
1827	{
1828	  exp->X_add_number >>= 1;
1829	  return 1;
1830	}
1831      break;
1832    case LSIZE:
1833      if (v & 3)
1834	return 0;
1835      if (0 <= v && v <= 127)
1836	{
1837	  exp->X_add_number >>= 2;
1838	  return 1;
1839	}
1840      break;
1841    }
1842  return 0;
1843}
1844
1845/* Just like the above, but allows a zero displacement.  */
1846
1847static int
1848rx_disp5op0 (expressionS * exp, int msize)
1849{
1850  if (exp->X_op != O_constant)
1851    return 0;
1852  if (exp->X_add_number == 0)
1853    return 1;
1854  return rx_disp5op (exp, msize);
1855}
1856
1857static int
1858exp_val (expressionS exp)
1859{
1860  if (exp.X_op != O_constant)
1861  {
1862    rx_error (_("constant expected"));
1863    return 0;
1864  }
1865  return exp.X_add_number;
1866}
1867
1868static expressionS
1869zero_expr (void)
1870{
1871  /* Static, so program load sets it to all zeros, which is what we want.  */
1872  static expressionS zero;
1873  zero.X_op = O_constant;
1874  return zero;
1875}
1876
1877static int
1878immediate (expressionS exp, int type, int pos, int bits)
1879{
1880  /* We will emit constants ourselves here, so negate them.  */
1881  if (type == RXREL_NEGATIVE && exp.X_op == O_constant)
1882    exp.X_add_number = - exp.X_add_number;
1883  if (type == RXREL_NEGATIVE_BORROW)
1884    {
1885      if (exp.X_op == O_constant)
1886	exp.X_add_number = - exp.X_add_number - 1;
1887      else
1888	rx_error (_("sbb cannot use symbolic immediates"));
1889    }
1890
1891  if (pos >= 0 && rx_intop (exp, 8, bits))
1892    {
1893      rx_op (exp, 1, type);
1894      return 1;
1895    }
1896  else if (pos >= 0 && rx_intop (exp, 16, bits))
1897    {
1898      rx_op (exp, 2, type);
1899      return 2;
1900    }
1901  else if (pos >= 0 && rx_uintop (exp, 16) && bits == 16)
1902    {
1903      rx_op (exp, 2, type);
1904      return 2;
1905    }
1906  else if (pos >= 0 && rx_intop (exp, 24, bits))
1907    {
1908      rx_op (exp, 3, type);
1909      return 3;
1910    }
1911  else if (pos < 0 || rx_intop (exp, 32, bits))
1912    {
1913      rx_op (exp, 4, type);
1914      return 0;
1915    }
1916  else if (type == RXREL_SIGNED && pos >= 0)
1917    {
1918      /* This is a symbolic immediate, we will relax it later.  */
1919      rx_relax (RX_RELAX_IMM, pos);
1920      rx_op (exp, linkrelax ? 4 : 1, type);
1921      return 1;
1922    }
1923  else
1924    {
1925      /* Let the linker deal with it.  */
1926      rx_op (exp, 4, type);
1927      return 0;
1928    }
1929}
1930
1931static int
1932displacement (expressionS exp, int msize)
1933{
1934  int val;
1935  int vshift = 0;
1936
1937  if (exp.X_op == O_symbol
1938      && exp.X_md)
1939    {
1940      switch (exp.X_md)
1941	{
1942	case BFD_RELOC_GPREL16:
1943	  switch (msize)
1944	    {
1945	    case BSIZE:
1946	      exp.X_md = BFD_RELOC_RX_GPRELB;
1947	      break;
1948	    case WSIZE:
1949	      exp.X_md = BFD_RELOC_RX_GPRELW;
1950	      break;
1951	    case LSIZE:
1952	      exp.X_md = BFD_RELOC_RX_GPRELL;
1953	      break;
1954	    }
1955	  O2 (exp);
1956	  return 2;
1957	}
1958    }
1959
1960  if (exp.X_op == O_subtract)
1961    {
1962      exp.X_md = BFD_RELOC_RX_DIFF;
1963      O2 (exp);
1964      return 2;
1965    }
1966
1967  if (exp.X_op != O_constant)
1968    {
1969      rx_error (_("displacements must be constants"));
1970      return -1;
1971    }
1972  val = exp.X_add_number;
1973
1974  if (val == 0)
1975    return 0;
1976
1977  switch (msize)
1978    {
1979    case BSIZE:
1980      break;
1981    case WSIZE:
1982      if (val & 1)
1983	rx_error (_("word displacement not word-aligned"));
1984      vshift = 1;
1985      break;
1986    case LSIZE:
1987      if (val & 3)
1988	rx_error (_("long displacement not long-aligned"));
1989      vshift = 2;
1990      break;
1991    case DSIZE:
1992      if (val & 7)
1993	rx_error (_("double displacement not double-aligned"));
1994      vshift = 3;
1995      break;
1996    default:
1997      as_bad (_("displacement with unknown size (internal bug?)\n"));
1998      break;
1999    }
2000
2001  val >>= vshift;
2002  exp.X_add_number = val;
2003
2004  if (0 <= val && val <= 255 )
2005    {
2006      O1 (exp);
2007      return 1;
2008    }
2009
2010  if (0 <= val && val <= 65535)
2011    {
2012      O2 (exp);
2013      return 2;
2014    }
2015  if (val < 0)
2016    rx_error (_("negative displacements not allowed"));
2017  else
2018    rx_error (_("displacement too large"));
2019  return -1;
2020}
2021
2022static void
2023rtsd_immediate (expressionS exp)
2024{
2025  int val;
2026
2027  if (exp.X_op != O_constant)
2028    {
2029      rx_error (_("rtsd size must be constant"));
2030      return;
2031    }
2032  val = exp.X_add_number;
2033  if (val & 3)
2034    rx_error (_("rtsd size must be multiple of 4"));
2035
2036  if (val < 0 || val > 1020)
2037    rx_error (_("rtsd size must be 0..1020"));
2038
2039  val >>= 2;
2040  exp.X_add_number = val;
2041  O1 (exp);
2042}
2043
2044static void
2045rx_range (expressionS exp, int minv, int maxv)
2046{
2047  int val;
2048
2049  if (exp.X_op != O_constant)
2050    return;
2051
2052  val = exp.X_add_number;
2053  if (val < minv || val > maxv)
2054    as_warn (_("Value %d out of range %d..%d"), val, minv, maxv);
2055}
2056
2057static void
2058rx_check_float_support (void)
2059{
2060  if (rx_cpu == RX100 || rx_cpu == RX200)
2061    rx_error (_("target CPU type does not support floating point instructions"));
2062}
2063
2064static void
2065rx_check_v2 (void)
2066{
2067  if (rx_cpu < RXV2)
2068    rx_error (_("target CPU type does not support v2 instructions"));
2069}
2070
2071static void
2072rx_check_v3 (void)
2073{
2074  if (rx_cpu < RXV3)
2075    rx_error (_("target CPU type does not support v3 instructions"));
2076}
2077
2078static void
2079rx_check_dfpu (void)
2080{
2081  if (rx_cpu != RXV3FPU)
2082    rx_error (_("target CPU type does not support double float instructions"));
2083}
2084