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