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