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