1 /* rx-parse.y Renesas RX parser
3 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
24 #include "safe-ctype.h"
27 static int rx_lex
(void);
39 static int sizemap
[] = { BSIZE
, WSIZE
, LSIZE
, WSIZE
};
41 /* Ok, here are the rules for using these macros...
43 B*() is used to specify the base opcode bytes. Fields to be filled
44 in later, leave zero. Call this first.
46 F() and FE() are used to fill in fields within the base opcode bytes. You MUST
47 call B*() before any F() or FE().
49 [UN]*O*(), PC*() appends operands to the end of the opcode. You
50 must call P() and B*() before any of these, so that the fixups
51 have the right byte location.
52 O = signed, UO = unsigned, NO = negated, PC = pcrel
54 IMM() adds an immediate and fills in the field for it.
55 NIMM() same, but negates the immediate.
56 NBIMM() same, but negates the immediate, for sbb.
57 DSP() adds a displacement, and fills in the field for it.
59 Note that order is significant for the O, IMM, and DSP macros, as
60 they append their data to the operand buffer in the order that you
63 Use "disp" for displacements whenever possible; this handles the
66 #define B1(b1) rx_base1 (b1)
67 #define B2(b1, b2) rx_base2 (b1, b2)
68 #define B3(b1, b2, b3) rx_base3 (b1, b2, b3)
69 #define B4(b1, b2, b3, b4) rx_base4 (b1, b2, b3, b4)
71 /* POS is bits from the MSB of the first byte to the LSB of the last byte. */
72 #define F(val,pos,sz) rx_field (val, pos, sz)
73 #define FE(exp,pos,sz) rx_field (exp_val (exp), pos, sz);
75 #define O1(v) rx_op (v, 1, RXREL_SIGNED)
76 #define O2(v) rx_op (v, 2, RXREL_SIGNED)
77 #define O3(v) rx_op (v, 3, RXREL_SIGNED)
78 #define O4(v) rx_op (v, 4, RXREL_SIGNED)
80 #define UO1(v) rx_op (v, 1, RXREL_UNSIGNED)
81 #define UO2(v) rx_op (v, 2, RXREL_UNSIGNED)
82 #define UO3(v) rx_op (v, 3, RXREL_UNSIGNED)
83 #define UO4(v) rx_op (v, 4, RXREL_UNSIGNED)
85 #define NO1(v) rx_op (v, 1, RXREL_NEGATIVE)
86 #define NO2(v) rx_op (v, 2, RXREL_NEGATIVE)
87 #define NO3(v) rx_op (v, 3, RXREL_NEGATIVE)
88 #define NO4(v) rx_op (v, 4, RXREL_NEGATIVE)
90 #define PC1(v) rx_op (v, 1, RXREL_PCREL)
91 #define PC2(v) rx_op (v, 2, RXREL_PCREL)
92 #define PC3(v) rx_op (v, 3, RXREL_PCREL)
94 #define IMM(v,pos) F (immediate (v, RXREL_SIGNED, pos), pos, 2); \
95 if
(v.X_op
!= O_constant
&& v.X_op
!= O_big
) rx_linkrelax_imm
(pos
)
96 #define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos), pos, 2)
97 #define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos), pos, 2)
98 #define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
99 else rx_linkrelax_dsp
(pos
); \
100 F
(displacement
(v
, msz
), pos
, 2)
102 #define id24(a,b2,b3) B3 (0xfb+a, b2, b3)
104 static int rx_intop
(expressionS
, int);
105 static int rx_uintop
(expressionS
, int);
106 static int rx_disp3op
(expressionS
);
107 static int rx_disp5op
(expressionS
*, int);
108 static int rx_disp5op0
(expressionS
*, int);
109 static int exp_val
(expressionS exp
);
110 static expressionS zero_expr
(void);
111 static int immediate
(expressionS
, int, int);
112 static int displacement
(expressionS
, int);
113 static void rtsd_immediate
(expressionS
);
115 static int need_flag
= 0;
116 static int rx_in_brackets
= 0;
117 static int rx_last_token
= 0;
118 static char * rx_init_start
;
119 static char * rx_last_exp_start
= 0;
124 #define YYERROR_VERBOSE 1
135 %type
<regno
> REG FLAG CREG BCND BMCND SCCND
136 %type
<regno
> flag bwl bw memex
137 %type
<exp
> EXPR disp
141 %token EXPR UNKNOWN_OPCODE IS_OPCODE
143 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
145 %token ABS ADC ADD AND_
146 %token BCLR BCND BMCND BNOT BRA BRK BSET BSR BTST
149 %token EDIV EDIVU EMUL EMULU
150 %token FADD FCMP FDIV FMUL FREIT FSUB FTOI
153 %token MACHI MACLO MAX MIN MOV MOVU MUL MULHI MULLO MULU MVFACHI MVFACMI MVFACLO
154 %token MVFC MVTACHI MVTACLO MVTC MVTIPL
157 %token POP POPC POPM PUSH PUSHA PUSHC PUSHM
158 %token RACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND RTE RTFI RTS RTSD
159 %token SAT SATR SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
160 %token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
166 /* ====================================================================== */
171 { as_bad
(_
("Unknown opcode: %s"), rx_init_start
); }
173 /* ---------------------------------------------------------------------- */
187 /* ---------------------------------------------------------------------- */
190 { if
(rx_disp3op
($2))
191 { B1
(0x08); rx_disp3
($2, 5); }
192 else if
(rx_intop
($2, 8))
193 { B1
(0x2e); PC1
($2); }
194 else if
(rx_intop
($2, 16))
195 { B1
(0x38); PC2
($2); }
196 else if
(rx_intop
($2, 24))
197 { B1
(0x04); PC3
($2); }
199 { rx_relax
(RX_RELAX_BRANCH
, 0);
200 rx_linkrelax_branch
();
201 /* We'll convert this to a longer one later if needed. */
202 B1
(0x08); rx_disp3
($2, 5); } }
205 { B1
(0x04); PC3
($3); }
208 { B1
(0x08); rx_disp3
($3, 5); }
210 /* ---------------------------------------------------------------------- */
213 { if
(rx_intop
($2, 16))
214 { B1
(0x39); PC2
($2); }
215 else if
(rx_intop
($2, 24))
216 { B1
(0x05); PC3
($2); }
218 { rx_relax
(RX_RELAX_BRANCH
, 0);
219 rx_linkrelax_branch
();
220 B1
(0x39); PC2
($2); } }
222 { B1
(0x05), PC3
($3); }
224 /* ---------------------------------------------------------------------- */
227 { if
($1 == COND_EQ ||
$1 == COND_NE
)
228 { B1
($1 == COND_EQ ?
0x10 : 0x18); rx_disp3
($3, 5); }
230 as_bad
(_
("Only BEQ and BNE may have .S")); }
232 /* ---------------------------------------------------------------------- */
235 { B1
(0x20); F
($1, 4, 4); PC1
($3); }
238 { B1
(0x2e), PC1
($3); }
240 /* ---------------------------------------------------------------------- */
243 { B1
(0x38), PC2
($3); }
245 { B1
(0x39), PC2
($3); }
247 { if
($1 == COND_EQ ||
$1 == COND_NE
)
248 { B1
($1 == COND_EQ ?
0x3a : 0x3b); PC2
($3); }
250 as_bad
(_
("Only BEQ and BNE may have .W")); }
252 { if
($1 == COND_EQ ||
$1 == COND_NE
)
254 rx_relax
(RX_RELAX_BRANCH
, 0);
255 rx_linkrelax_branch
();
256 B1
($1 == COND_EQ ?
0x10 : 0x18); rx_disp3
($2, 5);
260 rx_relax
(RX_RELAX_BRANCH
, 0);
261 /* This is because we might turn it into a
262 jump-over-jump long branch. */
263 rx_linkrelax_branch
();
264 B1
(0x20); F
($1, 4, 4); PC1
($2);
267 /* ---------------------------------------------------------------------- */
269 | MOV DOT_B
'#' EXPR
',' disp
'[' REG
']'
270 /* rx_disp5op changes the value if it succeeds, so keep it last. */
271 { if
($8 <= 7 && rx_uintop
($4, 8) && rx_disp5op0
(&$6, BSIZE
))
272 { B2
(0x3c, 0); rx_field5s2
($6); F
($8, 9, 3); O1
($4); }
274 { B2
(0xf8, 0x04); F
($8, 8, 4); DSP
($6, 6, BSIZE
); O1
($4);
275 if
($4.X_op
!= O_constant
&& $4.X_op
!= O_big
) rx_linkrelax_imm
(12); } }
277 | MOV DOT_W
'#' EXPR
',' disp
'[' REG
']'
278 { if
($8 <= 7 && rx_uintop
($4, 8) && rx_disp5op0
(&$6, WSIZE
))
279 { B2
(0x3d, 0); rx_field5s2
($6); F
($8, 9, 3); O1
($4); }
281 { B2
(0xf8, 0x01); F
($8, 8, 4); DSP
($6, 6, WSIZE
); IMM
($4, 12); } }
283 | MOV DOT_L
'#' EXPR
',' disp
'[' REG
']'
284 { if
($8 <= 7 && rx_uintop
($4, 8) && rx_disp5op0
(&$6, LSIZE
))
285 { B2
(0x3e, 0); rx_field5s2
($6); F
($8, 9, 3); O1
($4); }
287 { B2
(0xf8, 0x02); F
($8, 8, 4); DSP
($6, 6, LSIZE
); IMM
($4, 12); } }
289 /* ---------------------------------------------------------------------- */
291 | RTSD
'#' EXPR
',' REG
'-' REG
292 { B2
(0x3f, 0); F
($5, 8, 4); F
($7, 12, 4); rtsd_immediate
($3);
294 rx_error
(_
("RTSD cannot pop R0"));
296 rx_error
(_
("RTSD first reg must be <= second reg")); }
298 /* ---------------------------------------------------------------------- */
301 { B2
(0x47, 0); F
($2, 8, 4); F
($4, 12, 4); }
303 /* ---------------------------------------------------------------------- */
305 | CMP disp
'[' REG
']' DOT_UB
',' REG
306 { B2
(0x44, 0); F
($4, 8, 4); F
($8, 12, 4); DSP
($2, 6, BSIZE
); }
308 | CMP disp
'[' REG
']' memex
',' REG
309 { B3
(MEMEX
, 0x04, 0); F
($6, 8, 2); F
($4, 16, 4); F
($8, 20, 4); DSP
($2, 14, sizemap
[$6]); }
311 /* ---------------------------------------------------------------------- */
313 | MOVU bw REG
',' REG
314 { B2
(0x5b, 0x00); F
($2, 5, 1); F
($3, 8, 4); F
($5, 12, 4); }
316 /* ---------------------------------------------------------------------- */
318 | MOVU bw
'[' REG
']' ',' REG
319 { B2
(0x58, 0x00); F
($2, 5, 1); F
($4, 8, 4); F
($7, 12, 4); }
321 | MOVU bw EXPR
'[' REG
']' ',' REG
322 { if
($5 <= 7 && $8 <= 7 && rx_disp5op
(&$3, $2))
323 { B2
(0xb0, 0); F
($2, 4, 1); F
($5, 9, 3); F
($8, 13, 3); rx_field5s
($3); }
325 { B2
(0x58, 0x00); F
($2, 5, 1); F
($5, 8, 4); F
($8, 12, 4); DSP
($3, 6, $2); } }
327 /* ---------------------------------------------------------------------- */
329 | SUB
'#' EXPR
',' REG
330 { if
(rx_uintop
($3, 4))
331 { B2
(0x60, 0); FE
($3, 8, 4); F
($5, 12, 4); }
333 /* This is really an add, but we negate the immediate. */
334 { B2
(0x70, 0); F
($5, 8, 4); F
($5, 12, 4); NIMM
($3, 6); } }
336 | CMP
'#' EXPR
',' REG
337 { if
(rx_uintop
($3, 4))
338 { B2
(0x61, 0); FE
($3, 8, 4); F
($5, 12, 4); }
339 else if
(rx_uintop
($3, 8))
340 { B2
(0x75, 0x50); F
($5, 12, 4); UO1
($3); }
342 { B2
(0x74, 0x00); F
($5, 12, 4); IMM
($3, 6); } }
344 | ADD
'#' EXPR
',' REG
345 { if
(rx_uintop
($3, 4))
346 { B2
(0x62, 0); FE
($3, 8, 4); F
($5, 12, 4); }
348 { B2
(0x70, 0); F
($5, 8, 4); F
($5, 12, 4); IMM
($3, 6); } }
350 | MUL
'#' EXPR
',' REG
351 { if
(rx_uintop
($3, 4))
352 { B2
(0x63, 0); FE
($3, 8, 4); F
($5, 12, 4); }
354 { B2
(0x74, 0x10); F
($5, 12, 4); IMM
($3, 6); } }
356 | AND_
'#' EXPR
',' REG
357 { if
(rx_uintop
($3, 4))
358 { B2
(0x64, 0); FE
($3, 8, 4); F
($5, 12, 4); }
360 { B2
(0x74, 0x20); F
($5, 12, 4); IMM
($3, 6); } }
362 | OR
'#' EXPR
',' REG
363 { if
(rx_uintop
($3, 4))
364 { B2
(0x65, 0); FE
($3, 8, 4); F
($5, 12, 4); }
366 { B2
(0x74, 0x30); F
($5, 12, 4); IMM
($3, 6); } }
368 | MOV DOT_L
'#' EXPR
',' REG
369 { if
(rx_uintop
($4, 4))
370 { B2
(0x66, 0); FE
($4, 8, 4); F
($6, 12, 4); }
371 else if
(rx_uintop
($4, 8))
372 { B2
(0x75, 0x40); F
($6, 12, 4); UO1
($4); }
374 { B2
(0xfb, 0x02); F
($6, 8, 4); IMM
($4, 12); } }
376 | MOV
'#' EXPR
',' REG
377 { if
(rx_uintop
($3, 4))
378 { B2
(0x66, 0); FE
($3, 8, 4); F
($5, 12, 4); }
379 else if
(rx_uintop
($3, 8))
380 { B2
(0x75, 0x40); F
($5, 12, 4); UO1
($3); }
382 { B2
(0xfb, 0x02); F
($5, 8, 4); IMM
($3, 12); } }
384 /* ---------------------------------------------------------------------- */
387 { B1
(0x67); rtsd_immediate
($3); }
389 /* ---------------------------------------------------------------------- */
391 | SHLR
{ sub_op
= 0; } op_shift
392 | SHAR
{ sub_op
= 1; } op_shift
393 | SHLL
{ sub_op
= 2; } op_shift
395 /* ---------------------------------------------------------------------- */
400 { B2
(0x7e, 0x80); F
(LSIZE
, 10, 2); F
($2, 12, 4); }
402 { B2
(0x6e, 0); F
($2, 8, 4); F
($4, 12, 4); }
404 rx_error
(_
("PUSHM cannot push R0"));
406 rx_error
(_
("PUSHM first reg must be <= second reg")); }
408 /* ---------------------------------------------------------------------- */
413 { B2
(0x7e, 0xb0); F
($2, 12, 4); }
415 { B2
(0x6f, 0); F
($2, 8, 4); F
($4, 12, 4); }
417 rx_error
(_
("POPM cannot pop R0"));
419 rx_error
(_
("POPM first reg must be <= second reg")); }
421 /* ---------------------------------------------------------------------- */
423 | ADD
'#' EXPR
',' REG
',' REG
424 { B2
(0x70, 0x00); F
($5, 8, 4); F
($7, 12, 4); IMM
($3, 6); }
426 /* ---------------------------------------------------------------------- */
429 { B2
(0x75, 0x60), UO1
($3); }
431 /* ---------------------------------------------------------------------- */
433 | BSET
'#' EXPR
',' REG
434 { B2
(0x78, 0); FE
($3, 7, 5); F
($5, 12, 4); }
435 | BCLR
'#' EXPR
',' REG
436 { B2
(0x7a, 0); FE
($3, 7, 5); F
($5, 12, 4); }
438 /* ---------------------------------------------------------------------- */
440 | BTST
'#' EXPR
',' REG
441 { B2
(0x7c, 0x00); FE
($3, 7, 5); F
($5, 12, 4); }
443 /* ---------------------------------------------------------------------- */
446 { B2
(0x7e, 0x30); F
($2, 12, 4); }
448 { B2
(0x7e, 0x40); F
($2, 12, 4); }
450 { B2
(0x7e, 0x50); F
($2, 12, 4); }
452 /* ---------------------------------------------------------------------- */
455 { B2
(0x7e, 0x80); F
($2, 10, 2); F
($3, 12, 4); }
457 /* ---------------------------------------------------------------------- */
460 { B2
(0x7e, 0xb0); F
($2, 12, 4); }
462 /* ---------------------------------------------------------------------- */
466 { B2
(0x7e, 0xc0); F
($2, 12, 4); }
468 as_bad
(_
("PUSHC can only push the first 16 control registers")); }
470 /* ---------------------------------------------------------------------- */
474 { B2
(0x7e, 0xe0); F
($2, 12, 4); }
476 as_bad
(_
("POPC can only pop the first 16 control registers")); }
478 /* ---------------------------------------------------------------------- */
481 { B2
(0x7f, 0xa0); F
($2, 12, 4); }
483 { B2
(0x7f, 0xb0); F
($2, 12, 4); }
485 /* ---------------------------------------------------------------------- */
488 { B2
(0x7f, 0x00); F
($2, 12, 4); }
490 { B2
(0x7f, 0x10); F
($2, 12, 4); }
492 { B2
(0x7f, 0x40); F
($3, 12, 4); }
494 { B2
(0x7f, 0x50); F
($3, 12, 4); }
496 /* ---------------------------------------------------------------------- */
507 /* ---------------------------------------------------------------------- */
510 { B2
(0x7f, 0x80); F
($2, 14, 2); }
512 { B2
(0x7f, 0x84); F
($2, 14, 2); }
514 { B2
(0x7f, 0x88); F
($2, 14, 2); }
516 /* ---------------------------------------------------------------------- */
519 { B2
(0x7f, 0x8c); F
($2, 14, 2); }
521 /* ---------------------------------------------------------------------- */
532 /* ---------------------------------------------------------------------- */
535 { B3
(0x75, 0x70, 0x00); FE
($3, 20, 4); }
537 /* ---------------------------------------------------------------------- */
539 /* rx_disp5op changes the value if it succeeds, so keep it last. */
540 | MOV bwl REG
',' EXPR
'[' REG
']'
541 { if
($3 <= 7 && $7 <= 7 && rx_disp5op
(&$5, $2))
542 { B2
(0x80, 0); F
($2, 2, 2); F
($7, 9, 3); F
($3, 13, 3); rx_field5s
($5); }
544 { B2
(0xc3, 0x00); F
($2, 2, 2); F
($7, 8, 4); F
($3, 12, 4); DSP
($5, 4, $2); }}
546 /* ---------------------------------------------------------------------- */
548 | MOV bwl EXPR
'[' REG
']' ',' REG
549 { if
($5 <= 7 && $8 <= 7 && rx_disp5op
(&$3, $2))
550 { B2
(0x88, 0); F
($2, 2, 2); F
($5, 9, 3); F
($8, 13, 3); rx_field5s
($3); }
552 { B2
(0xcc, 0x00); F
($2, 2, 2); F
($5, 8, 4); F
($8, 12, 4); DSP
($3, 6, $2); } }
554 /* ---------------------------------------------------------------------- */
556 /* MOV a,b - if a is a reg and b is mem, src and dest are
559 /* We don't use "disp" here because it causes a shift/reduce
560 conflict with the other displacement-less patterns. */
562 | MOV bwl REG
',' '[' REG
']'
563 { B2
(0xc3, 0x00); F
($2, 2, 2); F
($6, 8, 4); F
($3, 12, 4); }
565 /* ---------------------------------------------------------------------- */
567 | MOV bwl
'[' REG
']' ',' disp
'[' REG
']'
568 { B2
(0xc0, 0); F
($2, 2, 2); F
($4, 8, 4); F
($9, 12, 4); DSP
($7, 4, $2); }
570 /* ---------------------------------------------------------------------- */
572 | MOV bwl EXPR
'[' REG
']' ',' disp
'[' REG
']'
573 { B2
(0xc0, 0x00); F
($2, 2, 2); F
($5, 8, 4); F
($10, 12, 4); DSP
($3, 6, $2); DSP
($8, 4, $2); }
575 /* ---------------------------------------------------------------------- */
577 | MOV bwl REG
',' REG
578 { B2
(0xcf, 0x00); F
($2, 2, 2); F
($3, 8, 4); F
($5, 12, 4); }
580 /* ---------------------------------------------------------------------- */
582 | MOV bwl
'[' REG
']' ',' REG
583 { B2
(0xcc, 0x00); F
($2, 2, 2); F
($4, 8, 4); F
($7, 12, 4); }
585 /* ---------------------------------------------------------------------- */
587 | BSET
'#' EXPR
',' disp
'[' REG
']' DOT_B
588 { B2
(0xf0, 0x00); F
($7, 8, 4); FE
($3, 13, 3); DSP
($5, 6, BSIZE
); }
589 | BCLR
'#' EXPR
',' disp
'[' REG
']' DOT_B
590 { B2
(0xf0, 0x08); F
($7, 8, 4); FE
($3, 13, 3); DSP
($5, 6, BSIZE
); }
591 | BTST
'#' EXPR
',' disp
'[' REG
']' DOT_B
592 { B2
(0xf4, 0x00); F
($7, 8, 4); FE
($3, 13, 3); DSP
($5, 6, BSIZE
); }
594 /* ---------------------------------------------------------------------- */
596 | PUSH bwl disp
'[' REG
']'
597 { B2
(0xf4, 0x08); F
($2, 14, 2); F
($5, 8, 4); DSP
($3, 6, $2); }
599 /* ---------------------------------------------------------------------- */
601 | SBB
{ sub_op
= 0; } op_dp20_rm
602 | NEG
{ sub_op
= 1; sub_op2
= 1; } op_dp20_rms
603 | ADC
{ sub_op
= 2; } op_dp20_rim
604 | ABS
{ sub_op
= 3; sub_op2
= 2; } op_dp20_rms
605 | MAX
{ sub_op
= 4; } op_dp20_rim
606 | MIN
{ sub_op
= 5; } op_dp20_rim
607 | EMUL
{ sub_op
= 6; } op_dp20_i
608 | EMULU
{ sub_op
= 7; } op_dp20_i
609 | DIV
{ sub_op
= 8; } op_dp20_rim
610 | DIVU
{ sub_op
= 9; } op_dp20_rim
611 | TST
{ sub_op
= 12; } op_dp20_rim
612 | XOR
{ sub_op
= 13; } op_dp20_rim
613 | NOT
{ sub_op
= 14; sub_op2
= 0; } op_dp20_rms
614 | STZ
{ sub_op
= 14; } op_dp20_i
615 | STNZ
{ sub_op
= 15; } op_dp20_i
617 /* ---------------------------------------------------------------------- */
619 | EMUL
{ sub_op
= 6; } op_xchg
620 | EMULU
{ sub_op
= 7; } op_xchg
621 | XCHG
{ sub_op
= 16; } op_xchg
622 | ITOF
{ sub_op
= 17; } op_xchg
624 /* ---------------------------------------------------------------------- */
627 { id24
(1, 0x63, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
629 { id24
(1, 0x67, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
631 { id24
(1, 0x6b, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
633 { id24
(1, 0x6f, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
635 | BSET REG
',' disp
'[' REG
']' DOT_B
636 { id24
(1, 0x60, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
637 | BCLR REG
',' disp
'[' REG
']' DOT_B
638 { id24
(1, 0x64, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
639 | BTST REG
',' disp
'[' REG
']' DOT_B
640 { id24
(1, 0x68, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
641 | BNOT REG
',' disp
'[' REG
']' DOT_B
642 { id24
(1, 0x6c, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
644 /* ---------------------------------------------------------------------- */
646 | FSUB
{ sub_op
= 0; } float2_op
647 | FCMP
{ sub_op
= 1; } float2_op
648 | FADD
{ sub_op
= 2; } float2_op
649 | FMUL
{ sub_op
= 3; } float2_op
650 | FDIV
{ sub_op
= 4; } float2_op
651 | FTOI
{ sub_op
= 5; } float2_op_ni
652 | ROUND
{ sub_op
= 6; } float2_op_ni
654 /* ---------------------------------------------------------------------- */
657 { id24
(1, 0xdb, 0x00); F
($1, 20, 4); F
($3, 16, 4); }
658 | SCCND bwl disp
'[' REG
']'
659 { id24
(1, 0xd0, 0x00); F
($1, 20, 4); F
($2, 12, 2); F
($5, 16, 4); DSP
($3, 14, $2); }
661 /* ---------------------------------------------------------------------- */
663 | BMCND
'#' EXPR
',' disp
'[' REG
']' DOT_B
664 { id24
(1, 0xe0, 0x00); F
($1, 20, 4); FE
($3, 11, 3);
665 F
($7, 16, 4); DSP
($5, 14, BSIZE
); }
667 /* ---------------------------------------------------------------------- */
669 | BNOT
'#' EXPR
',' disp
'[' REG
']' DOT_B
670 { id24
(1, 0xe0, 0x0f); FE
($3, 11, 3); F
($7, 16, 4);
671 DSP
($5, 14, BSIZE
); }
673 /* ---------------------------------------------------------------------- */
676 { id24
(2, 0x00, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
678 { id24
(2, 0x01, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
680 { id24
(2, 0x04, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
682 { id24
(2, 0x05, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
684 /* ---------------------------------------------------------------------- */
686 /* We don't have syntax for these yet. */
688 { id24
(2, 0x17, 0x00); F
($2, 20, 4); }
690 { id24
(2, 0x17, 0x10); F
($2, 20, 4); }
692 { id24
(2, 0x1f, 0x00); F
($2, 20, 4); }
694 { id24
(2, 0x1f, 0x20); F
($2, 20, 4); }
696 { id24
(2, 0x1f, 0x10); F
($2, 20, 4); }
699 { id24
(2, 0x18, 0x00);
700 if
(rx_uintop
($3, 4) && $3.X_add_number
== 1)
702 else if
(rx_uintop
($3, 4) && $3.X_add_number
== 2)
705 as_bad
(_
("RACW expects #1 or #2"));}
707 /* ---------------------------------------------------------------------- */
709 | MOV bwl REG
',' '[' REG
'+' ']'
710 { id24
(2, 0x20, 0); F
($2, 14, 2); F
($6, 16, 4); F
($3, 20, 4); }
711 | MOV bwl REG
',' '[' '-' REG
']'
712 { id24
(2, 0x24, 0); F
($2, 14, 2); F
($7, 16, 4); F
($3, 20, 4); }
714 /* ---------------------------------------------------------------------- */
716 | MOV bwl
'[' REG
'+' ']' ',' REG
717 { id24
(2, 0x28, 0); F
($2, 14, 2); F
($4, 16, 4); F
($8, 20, 4); }
718 | MOV bwl
'[' '-' REG
']' ',' REG
719 { id24
(2, 0x2c, 0); F
($2, 14, 2); F
($5, 16, 4); F
($8, 20, 4); }
721 /* ---------------------------------------------------------------------- */
723 | MOVU bw
'[' REG
'+' ']' ',' REG
724 { id24
(2, 0x38, 0); F
($2, 15, 1); F
($4, 16, 4); F
($8, 20, 4); }
725 | MOVU bw
'[' '-' REG
']' ',' REG
726 { id24
(2, 0x3c, 0); F
($2, 15, 1); F
($5, 16, 4); F
($8, 20, 4); }
728 /* ---------------------------------------------------------------------- */
730 | ROTL
{ sub_op
= 6; } op_shift_rot
731 | ROTR
{ sub_op
= 4; } op_shift_rot
732 | REVW
{ sub_op
= 5; } op_shift_rot
733 | REVL
{ sub_op
= 7; } op_shift_rot
735 /* ---------------------------------------------------------------------- */
738 { id24
(2, 0x68, 0x00); F
($4 %
16, 20, 4); F
($4 / 16, 15, 1);
741 /* ---------------------------------------------------------------------- */
744 { id24
(2, 0x6a, 0); F
($2, 15, 5); F
($4, 20, 4); }
746 /* ---------------------------------------------------------------------- */
748 | ROTL
'#' EXPR
',' REG
749 { id24
(2, 0x6e, 0); FE
($3, 15, 5); F
($5, 20, 4); }
750 | ROTR
'#' EXPR
',' REG
751 { id24
(2, 0x6c, 0); FE
($3, 15, 5); F
($5, 20, 4); }
753 /* ---------------------------------------------------------------------- */
755 | MVTC
'#' EXPR
',' CREG
756 { id24
(2, 0x73, 0x00); F
($5, 19, 5); IMM
($3, 12); }
758 /* ---------------------------------------------------------------------- */
760 | BMCND
'#' EXPR
',' REG
761 { id24
(2, 0xe0, 0x00); F
($1, 16, 4); FE
($3, 11, 5);
764 /* ---------------------------------------------------------------------- */
766 | BNOT
'#' EXPR
',' REG
767 { id24
(2, 0xe0, 0xf0); FE
($3, 11, 5); F
($5, 20, 4); }
769 /* ---------------------------------------------------------------------- */
771 | MOV bwl REG
',' '[' REG
',' REG
']'
772 { id24
(3, 0x00, 0); F
($2, 10, 2); F
($6, 12, 4); F
($8, 16, 4); F
($3, 20, 4); }
774 | MOV bwl
'[' REG
',' REG
']' ',' REG
775 { id24
(3, 0x40, 0); F
($2, 10, 2); F
($4, 12, 4); F
($6, 16, 4); F
($9, 20, 4); }
777 | MOVU bw
'[' REG
',' REG
']' ',' REG
778 { id24
(3, 0xc0, 0); F
($2, 10, 2); F
($4, 12, 4); F
($6, 16, 4); F
($9, 20, 4); }
780 /* ---------------------------------------------------------------------- */
782 | SUB
{ sub_op
= 0; } op_subadd
783 | ADD
{ sub_op
= 2; } op_subadd
784 | MUL
{ sub_op
= 3; } op_subadd
785 | AND_
{ sub_op
= 4; } op_subadd
786 | OR
{ sub_op
= 5; } op_subadd
788 /* ---------------------------------------------------------------------- */
789 /* There is no SBB #imm so we fake it with ADC. */
791 | SBB
'#' EXPR
',' REG
792 { id24
(2, 0x70, 0x20); F
($5, 20, 4); NBIMM
($3, 12); }
794 /* ---------------------------------------------------------------------- */
798 /* ====================================================================== */
802 { B2
(0x43 + (sub_op
<<2), 0); F
($1, 8, 4); F
($3, 12, 4); }
803 | disp
'[' REG
']' DOT_UB
',' REG
804 { B2
(0x40 + (sub_op
<<2), 0); F
($3, 8, 4); F
($7, 12, 4); DSP
($1, 6, BSIZE
); }
805 | disp
'[' REG
']' memex
',' REG
806 { B3
(MEMEX
, sub_op
<<2, 0); F
($5, 8, 2); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, sizemap
[$5]); }
807 | REG
',' REG
',' REG
808 { id24
(4, sub_op
<<4, 0), F
($5, 12, 4), F
($1, 16, 4), F
($3, 20, 4); }
811 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
815 { id24
(1, 0x03 + (sub_op
<<2), 0x00); F
($1, 16, 4); F
($3, 20, 4); }
816 | disp
'[' REG
']' DOT_UB
',' REG
817 { id24
(1, 0x00 + (sub_op
<<2), 0x00); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, BSIZE
); }
818 | disp
'[' REG
']' memex
',' REG
819 { B4
(MEMEX
, 0x20 + ($5 << 6), 0x00 + sub_op
, 0x00);
820 F
($3, 24, 4); F
($7, 28, 4); DSP
($1, 14, sizemap
[$5]); }
825 { id24
(2, 0x70, sub_op
<<4); F
($4, 20, 4); IMM
($2, 12); }
836 { B2
(0x7e, sub_op2
<< 4); F
($1, 12, 4); }
839 /* xchg, itof, emul, emulu */
842 { id24
(1, 0x03 + (sub_op
<<2), 0); F
($1, 16, 4); F
($3, 20, 4); }
843 | disp
'[' REG
']' DOT_UB
',' REG
844 { id24
(1, 0x00 + (sub_op
<<2), 0); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, BSIZE
); }
845 | disp
'[' REG
']' memex
',' REG
846 { B4
(MEMEX
, 0x20, 0x00 + sub_op
, 0); F
($5, 8, 2); F
($3, 24, 4); F
($7, 28, 4);
847 DSP
($1, 14, sizemap
[$5]); }
850 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
853 { id24
(2, 0x60 + sub_op
, 0); F
($1, 16, 4); F
($3, 20, 4); }
857 { B2
(0x68 + (sub_op
<<1), 0); FE
($2, 7, 5); F
($4, 12, 4); }
858 |
'#' EXPR
',' REG
',' REG
859 { id24
(2, 0x80 + (sub_op
<< 5), 0); FE
($2, 11, 5); F
($4, 16, 4); F
($6, 20, 4); }
867 { id24
(2, 0x72, sub_op
<< 4); F
($4, 20, 4); O4
($2); }
872 { id24
(1, 0x83 + (sub_op
<< 2), 0); F
($1, 16, 4); F
($3, 20, 4); }
873 | disp
'[' REG
']' opt_l
',' REG
874 { id24
(1, 0x80 + (sub_op
<< 2), 0); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, LSIZE
); }
877 /* ====================================================================== */
879 disp
: { $$
= zero_expr
(); }
883 flag
: { need_flag
= 1; } FLAG
{ need_flag
= 0; $$
= $2; }
886 /* DOT_UB is not listed here, it's handled with a separate pattern. */
887 /* Use sizemap[$n] to get LSIZE etc. */
888 memex
: DOT_B
{ $$
= 0; }
895 bwl
: { $$
= LSIZE
; }
896 | DOT_B
{ $$
= BSIZE
; }
897 | DOT_W
{ $$
= WSIZE
; }
898 | DOT_L
{ $$
= LSIZE
; }
911 /* ====================================================================== */
950 { "fintv", CREG
, 11 },
951 { "intb", CREG
, 12 },
954 { "pben", CREG
, 17 },
956 { "bbpsw", CREG
, 24 },
957 { "bbpc", CREG
, 25 },
964 { ".ub", DOT_UB
, 0 },
965 { ".uw", DOT_UW
, 0},
974 #define OPC(x) { #x, x, IS_OPCODE }
978 { "and", AND_
, IS_OPCODE
},
1076 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1083 condition_opcode_table
[] =
1090 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1121 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1124 rx_lex_init
(char * beginning
, char * ending
)
1126 rx_init_start
= beginning
;
1127 rx_lex_start
= beginning
;
1128 rx_lex_end
= ending
;
1136 check_condition
(char * base
)
1141 if
((unsigned) (rx_lex_end
- rx_lex_start
) < strlen
(base
) + 1)
1143 if
(memcmp
(rx_lex_start
, base
, strlen
(base
)))
1145 cp
= rx_lex_start
+ strlen
(base
);
1146 for
(i
= 0; i
< NUM_CONDITIONS
; i
++)
1148 if
(strcasecmp
(cp
, condition_table
[i
].
string) == 0)
1150 rx_lval.regno
= condition_table
[i
].val
;
1161 char * save_input_pointer
;
1163 while
(ISSPACE
(*rx_lex_start
)
1164 && rx_lex_start
!= rx_lex_end
)
1167 rx_last_exp_start
= rx_lex_start
;
1169 if
(rx_lex_start
== rx_lex_end
)
1172 if
(ISALPHA
(*rx_lex_start
)
1173 ||
(rx_pid_register
!= -1 && memcmp
(rx_lex_start
, "%pidreg", 7) == 0)
1174 ||
(rx_gp_register
!= -1 && memcmp
(rx_lex_start
, "%gpreg", 6) == 0)
1175 ||
(*rx_lex_start
== '.' && ISALPHA
(rx_lex_start
[1])))
1181 for
(e
= rx_lex_start
+ 1;
1182 e
< rx_lex_end
&& ISALNUM
(*e
);
1188 if
(strcmp
(rx_lex_start
, "%pidreg") == 0)
1191 rx_lval.regno
= rx_pid_register
;
1194 rx_last_token
= REG
;
1199 if
(strcmp
(rx_lex_start
, "%gpreg") == 0)
1202 rx_lval.regno
= rx_gp_register
;
1205 rx_last_token
= REG
;
1210 if
(rx_last_token
== 0)
1211 for
(ci
= 0; ci
< NUM_CONDITION_OPCODES
; ci
++)
1212 if
(check_condition
(condition_opcode_table
[ci
].
string))
1216 rx_last_token
= condition_opcode_table
[ci
].token
;
1217 return condition_opcode_table
[ci
].token
;
1220 for
(i
= 0; i
< NUM_TOKENS
; i
++)
1221 if
(strcasecmp
(rx_lex_start
, token_table
[i
].
string) == 0
1222 && !(token_table
[i
].val
== IS_OPCODE
&& rx_last_token
!= 0)
1223 && !(token_table
[i
].token
== FLAG
&& !need_flag
))
1225 rx_lval.regno
= token_table
[i
].val
;
1228 rx_last_token
= token_table
[i
].token
;
1229 return token_table
[i
].token
;
1234 if
(rx_last_token
== 0)
1236 rx_last_token
= UNKNOWN_OPCODE
;
1237 return UNKNOWN_OPCODE
;
1240 if
(rx_last_token
== UNKNOWN_OPCODE
)
1243 if
(*rx_lex_start
== '[')
1245 if
(*rx_lex_start
== ']')
1249 || rx_last_token
== REG
1250 || strchr
("[],#", *rx_lex_start
))
1252 rx_last_token
= *rx_lex_start
;
1253 return
*rx_lex_start
++;
1256 save_input_pointer
= input_line_pointer
;
1257 input_line_pointer
= rx_lex_start
;
1258 rx_lval.exp.X_md
= 0;
1259 expression
(&rx_lval.exp
);
1261 /* We parse but ignore any :<size> modifier on expressions. */
1262 if
(*input_line_pointer
== ':')
1266 for
(cp
= input_line_pointer
+ 1; *cp
&& cp
< rx_lex_end
; cp
++)
1269 if
(cp
> input_line_pointer
+1)
1270 input_line_pointer
= cp
;
1273 rx_lex_start
= input_line_pointer
;
1274 input_line_pointer
= save_input_pointer
;
1275 rx_last_token
= EXPR
;
1280 rx_error
(const char * str
)
1284 len
= rx_last_exp_start
- rx_init_start
;
1286 as_bad
("%s", rx_init_start
);
1287 as_bad
("%*s^ %s", len
, "", str
);
1292 rx_intop
(expressionS exp
, int nbits
)
1296 if
(exp.X_op
== O_big
&& nbits
== 32)
1298 if
(exp.X_op
!= O_constant
)
1300 v
= exp.X_add_number
;
1305 return
-0x8 <= v
&& v
<= 0x7;
1307 return
-0x10 <= v
&& v
<= 0x17;
1309 return
-0x80 <= v
&& v
<= 0x7f;
1311 return
-0x8000 <= v
&& v
<= 0x7fff;
1313 return
-0x800000 <= v
&& v
<= 0x7fffff;
1317 printf
("rx_intop passed %d\n", nbits
);
1324 rx_uintop
(expressionS exp
, int nbits
)
1328 if
(exp.X_op
!= O_constant
)
1330 v
= exp.X_add_number
;
1341 return v
<= 0xffffff;
1343 printf
("rx_uintop passed %d\n", nbits
);
1350 rx_disp3op
(expressionS exp
)
1354 if
(exp.X_op
!= O_constant
)
1356 v
= exp.X_add_number
;
1357 if
(v
< 3 || v
> 10)
1363 rx_disp5op
(expressionS
* exp
, int msize
)
1367 if
(exp
->X_op
!= O_constant
)
1369 v
= exp
->X_add_number
;
1374 if
(0 < v
&& v
<= 31)
1380 if
(0 < v
&& v
<= 63)
1382 exp
->X_add_number
>>= 1;
1389 if
(0 < v
&& v
<= 127)
1391 exp
->X_add_number
>>= 2;
1399 /* Just like the above, but allows a zero displacement. */
1402 rx_disp5op0
(expressionS
* exp
, int msize
)
1404 if
(exp
->X_op
!= O_constant
)
1406 if
(exp
->X_add_number
== 0)
1408 return rx_disp5op
(exp
, msize
);
1412 exp_val
(expressionS exp
)
1414 if
(exp.X_op
!= O_constant
)
1416 rx_error
(_
("constant expected"));
1419 return exp.X_add_number
;
1425 /* Static, so program load sets it to all zeros, which is what we want. */
1426 static expressionS zero
;
1427 zero.X_op
= O_constant
;
1432 immediate
(expressionS exp
, int type
, int pos
)
1434 /* We will emit constants ourself here, so negate them. */
1435 if
(type
== RXREL_NEGATIVE
&& exp.X_op
== O_constant
)
1436 exp.X_add_number
= - exp.X_add_number
;
1437 if
(type
== RXREL_NEGATIVE_BORROW
)
1439 if
(exp.X_op
== O_constant
)
1440 exp.X_add_number
= - exp.X_add_number
- 1;
1442 rx_error
(_
("sbb cannot use symbolic immediates"));
1445 if
(rx_intop
(exp
, 8))
1447 rx_op
(exp
, 1, type
);
1450 else if
(rx_intop
(exp
, 16))
1452 rx_op
(exp
, 2, type
);
1455 else if
(rx_intop
(exp
, 24))
1457 rx_op
(exp
, 3, type
);
1460 else if
(rx_intop
(exp
, 32))
1462 rx_op
(exp
, 4, type
);
1465 else if
(type
== RXREL_SIGNED
)
1467 /* This is a symbolic immediate, we will relax it later. */
1468 rx_relax
(RX_RELAX_IMM
, pos
);
1469 rx_op
(exp
, linkrelax ?
4 : 1, type
);
1474 /* Let the linker deal with it. */
1475 rx_op
(exp
, 4, type
);
1481 displacement
(expressionS exp
, int msize
)
1486 if
(exp.X_op
== O_symbol
1491 case BFD_RELOC_GPREL16
:
1495 exp.X_md
= BFD_RELOC_RX_GPRELB
;
1498 exp.X_md
= BFD_RELOC_RX_GPRELW
;
1501 exp.X_md
= BFD_RELOC_RX_GPRELL
;
1509 if
(exp.X_op
== O_subtract
)
1511 exp.X_md
= BFD_RELOC_RX_DIFF
;
1516 if
(exp.X_op
!= O_constant
)
1518 rx_error
(_
("displacements must be constants"));
1521 val
= exp.X_add_number
;
1532 rx_error
(_
("word displacement not word-aligned"));
1537 rx_error
(_
("long displacement not long-aligned"));
1541 as_bad
(_
("displacement with unknown size (internal bug?)\n"));
1546 exp.X_add_number
= val
;
1548 if
(0 <= val
&& val
<= 255 )
1554 if
(0 <= val
&& val
<= 65535)
1560 rx_error
(_
("negative displacements not allowed"));
1562 rx_error
(_
("displacement too large"));
1567 rtsd_immediate
(expressionS exp
)
1571 if
(exp.X_op
!= O_constant
)
1573 rx_error
(_
("rtsd size must be constant"));
1576 val
= exp.X_add_number
;
1578 rx_error
(_
("rtsd size must be multiple of 4"));
1580 if
(val
< 0 || val
> 1020)
1581 rx_error
(_
("rtsd size must be 0..1020"));
1584 exp.X_add_number
= val
;