1 /* rx-parse.y Renesas RX parser
2 Copyright (C) 2008-2019 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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)
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.
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
23 #include "safe-ctype.h"
26 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); rx_range (v, -128, 255)
76 #define O2(v) rx_op (v, 2, RXREL_SIGNED); rx_range (v, -32768, 65536)
77 #define O3(v) rx_op (v, 3, RXREL_SIGNED); rx_range (v, -8388608, 16777216)
78 #define O4(v) rx_op (v, 4, RXREL_SIGNED)
80 #define UO1(v) rx_op (v, 1, RXREL_UNSIGNED); rx_range (v, 0, 255)
81 #define UO2(v) rx_op (v, 2, RXREL_UNSIGNED); rx_range (v, 0, 65536)
82 #define UO3(v) rx_op (v, 3, RXREL_UNSIGNED); rx_range (v, 0, 16777216)
83 #define UO4(v) rx_op (v, 4, RXREL_UNSIGNED)
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 POST(v) rx_post (v)
96 #define IMM_(v,pos,size) F (immediate (v, RXREL_SIGNED, pos, size), pos, 2); \
97 if
(v.X_op
!= O_constant
&& v.X_op
!= O_big
) rx_linkrelax_imm
(pos
)
98 #define IMM(v,pos) IMM_ (v, pos, 32)
99 #define IMMW(v,pos) IMM_ (v, pos, 16); rx_range (v, -32768, 65536)
100 #define IMMB(v,pos) IMM_ (v, pos, 8); rx_range (v, -128, 255)
101 #define NIMM(v,pos) F (immediate (v, RXREL_NEGATIVE, pos, 32), pos, 2)
102 #define NBIMM(v,pos) F (immediate (v, RXREL_NEGATIVE_BORROW, pos, 32), pos, 2)
103 #define DSP(v,pos,msz) if (!v.X_md) rx_relax (RX_RELAX_DISP, pos); \
104 else rx_linkrelax_dsp
(pos
); \
105 F
(displacement
(v
, msz
), pos
, 2)
107 #define id24(a,b2,b3) B3 (0xfb + a, b2, b3)
109 static void rx_check_float_support
(void);
110 static int rx_intop
(expressionS
, int, int);
111 static int rx_uintop
(expressionS
, int);
112 static int rx_disp3op
(expressionS
);
113 static int rx_disp5op
(expressionS
*, int);
114 static int rx_disp5op0
(expressionS
*, int);
115 static int exp_val
(expressionS exp
);
116 static expressionS zero_expr
(void);
117 static int immediate
(expressionS
, int, int, int);
118 static int displacement
(expressionS
, int);
119 static void rtsd_immediate
(expressionS
);
120 static void rx_range
(expressionS
, int, int);
121 static void rx_check_v2
(void);
122 static void rx_check_v3
(void);
123 static void rx_check_dfpu
(void);
125 static int need_flag
= 0;
126 static int rx_in_brackets
= 0;
127 static int rx_last_token
= 0;
128 static char * rx_init_start
;
129 static char * rx_last_exp_start
= 0;
134 #define YYERROR_VERBOSE 1
145 %type
<regno
> REG FLAG CREG BCND BMCND SCCND ACC DREG DREGH DREGL DCREG DCMP
146 %type
<regno
> flag bwl bw memex
147 %type
<exp
> EXPR disp
149 %token REG FLAG CREG ACC DREG DREGH DREGL DCREG
151 %token EXPR UNKNOWN_OPCODE IS_OPCODE
153 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW DOT_D
155 %token ABS ADC ADD AND_
156 %token BCLR BCND BFMOV BFMOVZ BMCND BNOT BRA BRK BSET BSR BTST
158 %token DABS DADD DBT DCMP DDIV DIV DIVU DMOV DMUL DNEG
159 %token DPOPM DPUSHM DROUND DSQRT DSUB DTOF DTOI DTOU
160 %token EDIV EDIVU EMACA EMSBA EMUL EMULA EMULU
161 %token FADD FCMP FDIV FMUL FREIT FSUB FSQRT FTOD FTOI FTOU
164 %token MACHI MACLH MACLO MAX MIN MOV MOVCO MOVLI MOVU MSBHI MSBLH MSBLO MUL
165 %token MULHI MULLH MULLO MULU MVFACHI MVFACGU MVFACMI MVFACLO MVFC MVFDC
166 %token MVFDR MVTACGU MVTACHI MVTACLO MVTC MVTDC MVTIPL
169 %token POP POPC POPM PUSH PUSHA PUSHC PUSHM
170 %token RACL RACW RDACL RDACW REIT REVL REVW RMPA ROLC RORC ROTL ROTR ROUND
171 %token RSTR RTE RTFI RTS RTSD
172 %token SAT SATR SAVE SBB SCCND SCMPU SETPSW SHAR SHLL SHLR SMOVB SMOVF
173 %token SMOVU SSTR STNZ STOP STZ SUB SUNTIL SWHILE
180 /* ====================================================================== */
185 { as_bad
(_
("Unknown opcode: %s"), rx_init_start
); }
187 /* ---------------------------------------------------------------------- */
201 /* ---------------------------------------------------------------------- */
204 { if
(rx_disp3op
($2))
205 { B1
(0x08); rx_disp3
($2, 5); }
206 else if
(rx_intop
($2, 8, 8))
207 { B1
(0x2e); PC1
($2); }
208 else if
(rx_intop
($2, 16, 16))
209 { B1
(0x38); PC2
($2); }
210 else if
(rx_intop
($2, 24, 24))
211 { B1
(0x04); PC3
($2); }
213 { rx_relax
(RX_RELAX_BRANCH
, 0);
214 rx_linkrelax_branch
();
215 /* We'll convert this to a longer one later if needed. */
216 B1
(0x08); rx_disp3
($2, 5); } }
219 { B1
(0x04); PC3
($3); }
222 { B1
(0x08); rx_disp3
($3, 5); }
224 /* ---------------------------------------------------------------------- */
227 { if
(rx_intop
($2, 16, 16))
228 { B1
(0x39); PC2
($2); }
229 else if
(rx_intop
($2, 24, 24))
230 { B1
(0x05); PC3
($2); }
232 { rx_relax
(RX_RELAX_BRANCH
, 0);
233 rx_linkrelax_branch
();
234 B1
(0x39); PC2
($2); } }
236 { B1
(0x05), PC3
($3); }
238 /* ---------------------------------------------------------------------- */
241 { if
($1 == COND_EQ ||
$1 == COND_NE
)
242 { B1
($1 == COND_EQ ?
0x10 : 0x18); rx_disp3
($3, 5); }
244 as_bad
(_
("Only BEQ and BNE may have .S")); }
246 /* ---------------------------------------------------------------------- */
249 { B1
(0x20); F
($1, 4, 4); PC1
($3); }
252 { B1
(0x2e), PC1
($3); }
254 /* ---------------------------------------------------------------------- */
257 { B1
(0x38), PC2
($3); }
259 { B1
(0x39), PC2
($3); }
261 { if
($1 == COND_EQ ||
$1 == COND_NE
)
262 { B1
($1 == COND_EQ ?
0x3a : 0x3b); PC2
($3); }
264 as_bad
(_
("Only BEQ and BNE may have .W")); }
266 { if
($1 == COND_EQ ||
$1 == COND_NE
)
268 rx_relax
(RX_RELAX_BRANCH
, 0);
269 rx_linkrelax_branch
();
270 B1
($1 == COND_EQ ?
0x10 : 0x18); rx_disp3
($2, 5);
274 rx_relax
(RX_RELAX_BRANCH
, 0);
275 /* This is because we might turn it into a
276 jump-over-jump long branch. */
277 rx_linkrelax_branch
();
278 B1
(0x20); F
($1, 4, 4); PC1
($2);
281 /* ---------------------------------------------------------------------- */
283 | MOV DOT_B
'#' EXPR
',' '[' REG
']'
284 { B2
(0xf8, 0x04); F
($7, 8, 4); IMMB
($4, 12);}
286 | MOV DOT_W
'#' EXPR
',' '[' REG
']'
287 { B2
(0xf8, 0x01); F
($7, 8, 4); IMMW
($4, 12);}
289 | MOV DOT_L
'#' EXPR
',' '[' REG
']'
290 { B2
(0xf8, 0x02); F
($7, 8, 4); IMM
($4, 12);}
292 | MOV DOT_B
'#' EXPR
',' disp
'[' REG
']'
293 /* rx_disp5op changes the value if it succeeds, so keep it last. */
294 { if
($8 <= 7 && rx_uintop
($4, 8) && rx_disp5op0
(&$6, BSIZE
))
295 { B2
(0x3c, 0); rx_field5s2
($6); F
($8, 9, 3); O1
($4); }
297 { B2
(0xf8, 0x04); F
($8, 8, 4); DSP
($6, 6, BSIZE
); O1
($4);
298 if
($4.X_op
!= O_constant
&& $4.X_op
!= O_big
) rx_linkrelax_imm
(12); } }
300 | MOV DOT_W
'#' EXPR
',' disp
'[' REG
']'
301 { if
($8 <= 7 && rx_uintop
($4, 8) && rx_disp5op0
(&$6, WSIZE
))
302 { B2
(0x3d, 0); rx_field5s2
($6); F
($8, 9, 3); O1
($4); }
304 { B2
(0xf8, 0x01); F
($8, 8, 4); DSP
($6, 6, WSIZE
); IMMW
($4, 12); } }
306 | MOV DOT_L
'#' EXPR
',' disp
'[' REG
']'
307 { if
($8 <= 7 && rx_uintop
($4, 8) && rx_disp5op0
(&$6, LSIZE
))
308 { B2
(0x3e, 0); rx_field5s2
($6); F
($8, 9, 3); O1
($4); }
310 { B2
(0xf8, 0x02); F
($8, 8, 4); DSP
($6, 6, LSIZE
); IMM
($4, 12); } }
312 /* ---------------------------------------------------------------------- */
314 | RTSD
'#' EXPR
',' REG
'-' REG
315 { B2
(0x3f, 0); F
($5, 8, 4); F
($7, 12, 4); rtsd_immediate
($3);
317 rx_error
(_
("RTSD cannot pop R0"));
319 rx_error
(_
("RTSD first reg must be <= second reg")); }
321 /* ---------------------------------------------------------------------- */
324 { B2
(0x47, 0); F
($2, 8, 4); F
($4, 12, 4); }
326 /* ---------------------------------------------------------------------- */
328 | CMP disp
'[' REG
']' DOT_UB
',' REG
329 { B2
(0x44, 0); F
($4, 8, 4); F
($8, 12, 4); DSP
($2, 6, BSIZE
); }
331 | CMP disp
'[' REG
']' memex
',' REG
332 { B3
(MEMEX
, 0x04, 0); F
($6, 8, 2); F
($4, 16, 4); F
($8, 20, 4); DSP
($2, 14, sizemap
[$6]); }
334 /* ---------------------------------------------------------------------- */
336 | MOVU bw REG
',' REG
337 { B2
(0x5b, 0x00); F
($2, 5, 1); F
($3, 8, 4); F
($5, 12, 4); }
339 /* ---------------------------------------------------------------------- */
341 | MOVU bw
'[' REG
']' ',' REG
342 { B2
(0x58, 0x00); F
($2, 5, 1); F
($4, 8, 4); F
($7, 12, 4); }
344 | MOVU bw EXPR
'[' REG
']' ',' REG
345 { if
($5 <= 7 && $8 <= 7 && rx_disp5op
(&$3, $2))
346 { B2
(0xb0, 0); F
($2, 4, 1); F
($5, 9, 3); F
($8, 13, 3); rx_field5s
($3); }
348 { B2
(0x58, 0x00); F
($2, 5, 1); F
($5, 8, 4); F
($8, 12, 4); DSP
($3, 6, $2); } }
350 /* ---------------------------------------------------------------------- */
352 | SUB
'#' EXPR
',' REG
353 { if
(rx_uintop
($3, 4))
354 { B2
(0x60, 0); FE
($3, 8, 4); F
($5, 12, 4); }
356 /* This is really an add, but we negate the immediate. */
357 { B2
(0x70, 0); F
($5, 8, 4); F
($5, 12, 4); NIMM
($3, 6); } }
359 | CMP
'#' EXPR
',' REG
360 { if
(rx_uintop
($3, 4))
361 { B2
(0x61, 0); FE
($3, 8, 4); F
($5, 12, 4); }
362 else if
(rx_uintop
($3, 8))
363 { B2
(0x75, 0x50); F
($5, 12, 4); UO1
($3); }
365 { B2
(0x74, 0x00); F
($5, 12, 4); IMM
($3, 6); } }
367 | ADD
'#' EXPR
',' REG
368 { if
(rx_uintop
($3, 4))
369 { B2
(0x62, 0); FE
($3, 8, 4); F
($5, 12, 4); }
371 { B2
(0x70, 0); F
($5, 8, 4); F
($5, 12, 4); IMM
($3, 6); } }
373 | MUL
'#' EXPR
',' REG
374 { if
(rx_uintop
($3, 4))
375 { B2
(0x63, 0); FE
($3, 8, 4); F
($5, 12, 4); }
377 { B2
(0x74, 0x10); F
($5, 12, 4); IMM
($3, 6); } }
379 | AND_
'#' EXPR
',' REG
380 { if
(rx_uintop
($3, 4))
381 { B2
(0x64, 0); FE
($3, 8, 4); F
($5, 12, 4); }
383 { B2
(0x74, 0x20); F
($5, 12, 4); IMM
($3, 6); } }
385 | OR
'#' EXPR
',' REG
386 { if
(rx_uintop
($3, 4))
387 { B2
(0x65, 0); FE
($3, 8, 4); F
($5, 12, 4); }
389 { B2
(0x74, 0x30); F
($5, 12, 4); IMM
($3, 6); } }
391 | MOV DOT_L
'#' EXPR
',' REG
392 { if
(rx_uintop
($4, 4))
393 { B2
(0x66, 0); FE
($4, 8, 4); F
($6, 12, 4); }
394 else if
(rx_uintop
($4, 8))
395 { B2
(0x75, 0x40); F
($6, 12, 4); UO1
($4); }
397 { B2
(0xfb, 0x02); F
($6, 8, 4); IMM
($4, 12); } }
399 | MOV
'#' EXPR
',' REG
400 { if
(rx_uintop
($3, 4))
401 { B2
(0x66, 0); FE
($3, 8, 4); F
($5, 12, 4); }
402 else if
(rx_uintop
($3, 8))
403 { B2
(0x75, 0x40); F
($5, 12, 4); UO1
($3); }
405 { B2
(0xfb, 0x02); F
($5, 8, 4); IMM
($3, 12); } }
407 /* ---------------------------------------------------------------------- */
410 { B1
(0x67); rtsd_immediate
($3); }
412 /* ---------------------------------------------------------------------- */
414 | SHLR
{ sub_op
= 0; } op_shift
415 | SHAR
{ sub_op
= 1; } op_shift
416 | SHLL
{ sub_op
= 2; } op_shift
418 /* ---------------------------------------------------------------------- */
423 { B2
(0x7e, 0x80); F
(LSIZE
, 10, 2); F
($2, 12, 4); }
425 { B2
(0x6e, 0); F
($2, 8, 4); F
($4, 12, 4); }
427 rx_error
(_
("PUSHM cannot push R0"));
429 rx_error
(_
("PUSHM first reg must be <= second reg")); }
431 /* ---------------------------------------------------------------------- */
436 { B2
(0x7e, 0xb0); F
($2, 12, 4); }
438 { B2
(0x6f, 0); F
($2, 8, 4); F
($4, 12, 4); }
440 rx_error
(_
("POPM cannot pop R0"));
442 rx_error
(_
("POPM first reg must be <= second reg")); }
444 /* ---------------------------------------------------------------------- */
446 | ADD
'#' EXPR
',' REG
',' REG
447 { B2
(0x70, 0x00); F
($5, 8, 4); F
($7, 12, 4); IMM
($3, 6); }
449 /* ---------------------------------------------------------------------- */
452 { B2
(0x75, 0x60), UO1
($3); }
454 /* ---------------------------------------------------------------------- */
456 | BSET
'#' EXPR
',' REG
457 { B2
(0x78, 0); FE
($3, 7, 5); F
($5, 12, 4); }
458 | BCLR
'#' EXPR
',' REG
459 { B2
(0x7a, 0); FE
($3, 7, 5); F
($5, 12, 4); }
461 /* ---------------------------------------------------------------------- */
463 | BTST
'#' EXPR
',' REG
464 { B2
(0x7c, 0x00); FE
($3, 7, 5); F
($5, 12, 4); }
466 /* ---------------------------------------------------------------------- */
469 { B2
(0x7e, 0x30); F
($2, 12, 4); }
471 { B2
(0x7e, 0x40); F
($2, 12, 4); }
473 { B2
(0x7e, 0x50); F
($2, 12, 4); }
475 /* ---------------------------------------------------------------------- */
478 { B2
(0x7e, 0x80); F
($2, 10, 2); F
($3, 12, 4); }
480 /* ---------------------------------------------------------------------- */
483 { B2
(0x7e, 0xb0); F
($2, 12, 4); }
485 /* ---------------------------------------------------------------------- */
491 { B2
(0x7e, 0xc0); F
($2, 12, 4); }
493 as_bad
(_
("PUSHC can only push the first 16 control registers")); }
495 /* ---------------------------------------------------------------------- */
501 { B2
(0x7e, 0xe0); F
($2, 12, 4); }
503 as_bad
(_
("POPC can only pop the first 16 control registers")); }
505 /* ---------------------------------------------------------------------- */
508 { B2
(0x7f, 0xa0); F
($2, 12, 4); }
510 { B2
(0x7f, 0xb0); F
($2, 12, 4); }
512 /* ---------------------------------------------------------------------- */
515 { B2
(0x7f, 0x00); F
($2, 12, 4); }
517 { B2
(0x7f, 0x10); F
($2, 12, 4); }
519 { B2
(0x7f, 0x40); F
($3, 12, 4); }
521 { B2
(0x7f, 0x50); F
($3, 12, 4); }
523 /* ---------------------------------------------------------------------- */
526 { B2
(0x7f, 0x83); rx_note_string_insn_use
(); }
528 { B2
(0x7f, 0x87); rx_note_string_insn_use
(); }
530 { B2
(0x7f, 0x8b); rx_note_string_insn_use
(); }
532 { B2
(0x7f, 0x8f); rx_note_string_insn_use
(); }
534 /* ---------------------------------------------------------------------- */
537 { B2
(0x7f, 0x80); F
($2, 14, 2); rx_note_string_insn_use
(); }
539 { B2
(0x7f, 0x84); F
($2, 14, 2); rx_note_string_insn_use
(); }
541 { B2
(0x7f, 0x88); F
($2, 14, 2); }
543 /* ---------------------------------------------------------------------- */
546 { B2
(0x7f, 0x8c); F
($2, 14, 2); rx_note_string_insn_use
(); }
548 /* ---------------------------------------------------------------------- */
559 /* ---------------------------------------------------------------------- */
562 { B3
(0x75, 0x70, 0x00); FE
($3, 20, 4); }
564 /* ---------------------------------------------------------------------- */
566 /* rx_disp5op changes the value if it succeeds, so keep it last. */
567 | MOV bwl REG
',' EXPR
'[' REG
']'
568 { if
($3 <= 7 && $7 <= 7 && rx_disp5op
(&$5, $2))
569 { B2
(0x80, 0); F
($2, 2, 2); F
($7, 9, 3); F
($3, 13, 3); rx_field5s
($5); }
571 { B2
(0xc3, 0x00); F
($2, 2, 2); F
($7, 8, 4); F
($3, 12, 4); DSP
($5, 4, $2); }}
573 /* ---------------------------------------------------------------------- */
575 | MOV bwl EXPR
'[' REG
']' ',' REG
576 { if
($5 <= 7 && $8 <= 7 && rx_disp5op
(&$3, $2))
577 { B2
(0x88, 0); F
($2, 2, 2); F
($5, 9, 3); F
($8, 13, 3); rx_field5s
($3); }
579 { B2
(0xcc, 0x00); F
($2, 2, 2); F
($5, 8, 4); F
($8, 12, 4); DSP
($3, 6, $2); } }
581 /* ---------------------------------------------------------------------- */
583 /* MOV a,b - if a is a reg and b is mem, src and dest are
586 /* We don't use "disp" here because it causes a shift/reduce
587 conflict with the other displacement-less patterns. */
589 | MOV bwl REG
',' '[' REG
']'
590 { B2
(0xc3, 0x00); F
($2, 2, 2); F
($6, 8, 4); F
($3, 12, 4); }
592 /* ---------------------------------------------------------------------- */
594 | MOV bwl
'[' REG
']' ',' disp
'[' REG
']'
595 { B2
(0xc0, 0); F
($2, 2, 2); F
($4, 8, 4); F
($9, 12, 4); DSP
($7, 4, $2); }
597 /* ---------------------------------------------------------------------- */
599 | MOV bwl EXPR
'[' REG
']' ',' disp
'[' REG
']'
600 { B2
(0xc0, 0x00); F
($2, 2, 2); F
($5, 8, 4); F
($10, 12, 4); DSP
($3, 6, $2); DSP
($8, 4, $2); }
602 /* ---------------------------------------------------------------------- */
604 | MOV bwl REG
',' REG
605 { B2
(0xcf, 0x00); F
($2, 2, 2); F
($3, 8, 4); F
($5, 12, 4); }
607 /* ---------------------------------------------------------------------- */
609 | MOV bwl
'[' REG
']' ',' REG
610 { B2
(0xcc, 0x00); F
($2, 2, 2); F
($4, 8, 4); F
($7, 12, 4); }
612 /* ---------------------------------------------------------------------- */
614 | BSET
'#' EXPR
',' disp
'[' REG
']' DOT_B
615 { B2
(0xf0, 0x00); F
($7, 8, 4); FE
($3, 13, 3); DSP
($5, 6, BSIZE
); }
616 | BCLR
'#' EXPR
',' disp
'[' REG
']' DOT_B
617 { B2
(0xf0, 0x08); F
($7, 8, 4); FE
($3, 13, 3); DSP
($5, 6, BSIZE
); }
618 | BTST
'#' EXPR
',' disp
'[' REG
']' DOT_B
619 { B2
(0xf4, 0x00); F
($7, 8, 4); FE
($3, 13, 3); DSP
($5, 6, BSIZE
); }
621 /* ---------------------------------------------------------------------- */
623 | PUSH bwl disp
'[' REG
']'
624 { B2
(0xf4, 0x08); F
($2, 14, 2); F
($5, 8, 4); DSP
($3, 6, $2); }
626 /* ---------------------------------------------------------------------- */
628 | SBB
{ sub_op
= 0; } op_dp20_rm_l
629 | NEG
{ sub_op
= 1; sub_op2
= 1; } op_dp20_rr
630 | ADC
{ sub_op
= 2; } op_dp20_rim_l
631 | ABS
{ sub_op
= 3; sub_op2
= 2; } op_dp20_rr
632 | MAX
{ sub_op
= 4; } op_dp20_rim
633 | MIN
{ sub_op
= 5; } op_dp20_rim
634 | EMUL
{ sub_op
= 6; } op_dp20_i
635 | EMULU
{ sub_op
= 7; } op_dp20_i
636 | DIV
{ sub_op
= 8; } op_dp20_rim
637 | DIVU
{ sub_op
= 9; } op_dp20_rim
638 | TST
{ sub_op
= 12; } op_dp20_rim
639 | XOR
{ sub_op
= 13; } op_xor
640 | NOT
{ sub_op
= 14; sub_op2
= 0; } op_dp20_rr
641 | STZ
{ sub_op
= 14; sub_op2
= 0; } op_dp20_ri
642 | STNZ
{ sub_op
= 15; sub_op2
= 1; } op_dp20_ri
644 /* ---------------------------------------------------------------------- */
646 | EMUL
{ sub_op
= 6; } op_xchg
647 | EMULU
{ sub_op
= 7; } op_xchg
648 | XCHG
{ sub_op
= 16; } op_xchg
649 | ITOF
{ sub_op
= 17; } op_xchg
650 | UTOF
{ sub_op
= 21; } op_xchg
652 /* ---------------------------------------------------------------------- */
655 { id24
(1, 0x63, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
657 { id24
(1, 0x67, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
659 { id24
(1, 0x6b, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
661 { id24
(1, 0x6f, 0x00); F
($4, 16, 4); F
($2, 20, 4); }
663 | BSET REG
',' disp
'[' REG
']' opt_b
664 { id24
(1, 0x60, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
665 | BCLR REG
',' disp
'[' REG
']' opt_b
666 { id24
(1, 0x64, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
667 | BTST REG
',' disp
'[' REG
']' opt_b
668 { id24
(1, 0x68, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
669 | BNOT REG
',' disp
'[' REG
']' opt_b
670 { id24
(1, 0x6c, 0x00); F
($6, 16, 4); F
($2, 20, 4); DSP
($4, 14, BSIZE
); }
672 /* ---------------------------------------------------------------------- */
674 | FSUB
{ sub_op
= 0; } float3_op
675 | FCMP
{ sub_op
= 1; } float2_op
676 | FADD
{ sub_op
= 2; } float3_op
677 | FMUL
{ sub_op
= 3; } float3_op
678 | FDIV
{ sub_op
= 4; } float2_op
679 | FSQRT
{ sub_op
= 8; } float2_op_ni
680 | FTOI
{ sub_op
= 5; } float2_op_ni
681 | FTOU
{ sub_op
= 9; } float2_op_ni
682 | ROUND
{ sub_op
= 6; } float2_op_ni
684 /* ---------------------------------------------------------------------- */
687 /* ---------------------------------------------------------------------- */
690 { id24
(1, 0xdb, 0x00); F
($1, 20, 4); F
($3, 16, 4); }
691 | SCCND bwl disp
'[' REG
']'
692 { id24
(1, 0xd0, 0x00); F
($1, 20, 4); F
($2, 12, 2); F
($5, 16, 4); DSP
($3, 14, $2); }
694 /* ---------------------------------------------------------------------- */
696 | BMCND
'#' EXPR
',' disp
'[' REG
']' opt_b
697 { id24
(1, 0xe0, 0x00); F
($1, 20, 4); FE
($3, 11, 3);
698 F
($7, 16, 4); DSP
($5, 14, BSIZE
); }
700 /* ---------------------------------------------------------------------- */
702 | BNOT
'#' EXPR
',' disp
'[' REG
']' opt_b
703 { id24
(1, 0xe0, 0x0f); FE
($3, 11, 3); F
($7, 16, 4);
704 DSP
($5, 14, BSIZE
); }
706 /* ---------------------------------------------------------------------- */
709 { id24
(2, 0x00, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
710 | MULHI REG
',' REG
',' ACC
711 { rx_check_v2
(); id24
(2, 0x00, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
713 { id24
(2, 0x01, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
714 | MULLO REG
',' REG
',' ACC
715 { rx_check_v2
(); id24
(2, 0x01, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
717 { id24
(2, 0x04, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
718 | MACHI REG
',' REG
',' ACC
719 { rx_check_v2
(); id24
(2, 0x04, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
721 { id24
(2, 0x05, 0x00); F
($2, 16, 4); F
($4, 20, 4); }
722 | MACLO REG
',' REG
',' ACC
723 { rx_check_v2
(); id24
(2, 0x05, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
725 /* ---------------------------------------------------------------------- */
727 /* We don't have syntax for these yet. */
729 { id24
(2, 0x17, 0x00); F
($2, 20, 4); }
730 | MVTACHI REG
',' ACC
731 { rx_check_v2
(); id24
(2, 0x17, 0x00); F
($2, 20, 4); F
($4, 16, 1); }
733 { id24
(2, 0x17, 0x10); F
($2, 20, 4); }
734 | MVTACLO REG
',' ACC
735 { rx_check_v2
(); id24
(2, 0x17, 0x10); F
($2, 20, 4); F
($4, 16, 1); }
737 { id24
(2, 0x1f, 0x00); F
($2, 20, 4); }
738 | MVFACHI
{ sub_op
= 0; } mvfa_op
740 { id24
(2, 0x1f, 0x20); F
($2, 20, 4); }
741 | MVFACMI
{ sub_op
= 2; } mvfa_op
743 { id24
(2, 0x1f, 0x10); F
($2, 20, 4); }
744 | MVFACLO
{ sub_op
= 1; } mvfa_op
746 { id24
(2, 0x18, 0x00);
747 if
(rx_uintop
($3, 4) && exp_val
($3) == 1)
749 else if
(rx_uintop
($3, 4) && exp_val
($3) == 2)
752 as_bad
(_
("RACW expects #1 or #2"));}
753 | RACW
'#' EXPR
',' ACC
754 { rx_check_v2
(); id24
(2, 0x18, 0x00); F
($5, 16, 1);
755 if
(rx_uintop
($3, 4) && exp_val
($3) == 1)
757 else if
(rx_uintop
($3, 4) && exp_val
($3) == 2)
760 as_bad
(_
("RACW expects #1 or #2"));}
762 /* ---------------------------------------------------------------------- */
764 | MOV bwl REG
',' '[' REG
'+' ']'
765 { id24
(2, 0x20, 0); F
($2, 14, 2); F
($6, 16, 4); F
($3, 20, 4); }
766 | MOV bwl REG
',' '[' '-' REG
']'
767 { id24
(2, 0x24, 0); F
($2, 14, 2); F
($7, 16, 4); F
($3, 20, 4); }
769 /* ---------------------------------------------------------------------- */
771 | MOV bwl
'[' REG
'+' ']' ',' REG
772 { id24
(2, 0x28, 0); F
($2, 14, 2); F
($4, 16, 4); F
($8, 20, 4); }
773 | MOV bwl
'[' '-' REG
']' ',' REG
774 { id24
(2, 0x2c, 0); F
($2, 14, 2); F
($5, 16, 4); F
($8, 20, 4); }
776 /* ---------------------------------------------------------------------- */
778 | MOVU bw
'[' REG
'+' ']' ',' REG
779 { id24
(2, 0x38, 0); F
($2, 15, 1); F
($4, 16, 4); F
($8, 20, 4); }
780 | MOVU bw
'[' '-' REG
']' ',' REG
781 { id24
(2, 0x3c, 0); F
($2, 15, 1); F
($5, 16, 4); F
($8, 20, 4); }
783 /* ---------------------------------------------------------------------- */
785 | ROTL
{ sub_op
= 6; } op_shift_rot
786 | ROTR
{ sub_op
= 4; } op_shift_rot
787 | REVW
{ sub_op
= 5; } op_shift_rot
788 | REVL
{ sub_op
= 7; } op_shift_rot
790 /* ---------------------------------------------------------------------- */
795 id24
(2, 0x68, 0x00); F
($4 %
16, 20, 4); F
($4 / 16, 15, 1);
798 /* ---------------------------------------------------------------------- */
803 id24
(2, 0x6a, 0); F
($2, 15, 5); F
($4, 20, 4); }
805 /* ---------------------------------------------------------------------- */
807 | ROTL
'#' EXPR
',' REG
808 { id24
(2, 0x6e, 0); FE
($3, 15, 5); F
($5, 20, 4); }
809 | ROTR
'#' EXPR
',' REG
810 { id24
(2, 0x6c, 0); FE
($3, 15, 5); F
($5, 20, 4); }
812 /* ---------------------------------------------------------------------- */
814 | MVTC
'#' EXPR
',' CREG
817 id24
(2, 0x73, 0x00); F
($5, 19, 5); IMM
($3, 12); }
819 /* ---------------------------------------------------------------------- */
821 | BMCND
'#' EXPR
',' REG
822 { id24
(2, 0xe0, 0x00); F
($1, 16, 4); FE
($3, 11, 5);
825 /* ---------------------------------------------------------------------- */
827 | BNOT
'#' EXPR
',' REG
828 { id24
(2, 0xe0, 0xf0); FE
($3, 11, 5); F
($5, 20, 4); }
830 /* ---------------------------------------------------------------------- */
832 | MOV bwl REG
',' '[' REG
',' REG
']'
833 { id24
(3, 0x00, 0); F
($2, 10, 2); F
($6, 12, 4); F
($8, 16, 4); F
($3, 20, 4); }
835 | MOV bwl
'[' REG
',' REG
']' ',' REG
836 { id24
(3, 0x40, 0); F
($2, 10, 2); F
($4, 12, 4); F
($6, 16, 4); F
($9, 20, 4); }
838 | MOVU bw
'[' REG
',' REG
']' ',' REG
839 { id24
(3, 0xc0, 0); F
($2, 10, 2); F
($4, 12, 4); F
($6, 16, 4); F
($9, 20, 4); }
841 /* ---------------------------------------------------------------------- */
843 | SUB
{ sub_op
= 0; } op_subadd
844 | ADD
{ sub_op
= 2; } op_subadd
845 | MUL
{ sub_op
= 3; } op_subadd
846 | AND_
{ sub_op
= 4; } op_subadd
847 | OR
{ sub_op
= 5; } op_subadd
849 /* ---------------------------------------------------------------------- */
850 /* There is no SBB #imm so we fake it with ADC. */
852 | SBB
'#' EXPR
',' REG
853 { id24
(2, 0x70, 0x20); F
($5, 20, 4); NBIMM
($3, 12); }
855 /* ---------------------------------------------------------------------- */
857 | MOVCO REG
',' '[' REG
']'
858 { rx_check_v2
(); B3
(0xfd, 0x27, 0x00); F
($5, 16, 4); F
($2, 20, 4); }
860 /* ---------------------------------------------------------------------- */
862 | MOVLI
'[' REG
']' ',' REG
863 { rx_check_v2
(); B3
(0xfd, 0x2f, 0x00); F
($3, 16, 4); F
($6, 20, 4); }
865 /* ---------------------------------------------------------------------- */
867 | EMACA REG
',' REG
',' ACC
868 { rx_check_v2
(); id24
(2, 0x07, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
869 | EMSBA REG
',' REG
',' ACC
870 { rx_check_v2
(); id24
(2, 0x47, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
871 | EMULA REG
',' REG
',' ACC
872 { rx_check_v2
(); id24
(2, 0x03, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
873 | MACLH REG
',' REG
',' ACC
874 { rx_check_v2
(); id24
(2, 0x06, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
875 | MSBHI REG
',' REG
',' ACC
876 { rx_check_v2
(); id24
(2, 0x44, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
877 | MSBLH REG
',' REG
',' ACC
878 { rx_check_v2
(); id24
(2, 0x46, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
879 | MSBLO REG
',' REG
',' ACC
880 { rx_check_v2
(); id24
(2, 0x45, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
881 | MULLH REG
',' REG
',' ACC
882 { rx_check_v2
(); id24
(2, 0x02, 0x00); F
($2, 16, 4); F
($4, 20, 4); F
($6, 12, 1); }
883 | MVFACGU
{ sub_op
= 3; } mvfa_op
884 | MVTACGU REG
',' ACC
885 { rx_check_v2
(); id24
(2, 0x17, 0x30); F
($4, 16, 1); F
($2, 20, 4); }
886 | RACL
'#' EXPR
',' ACC
887 { rx_check_v2
(); id24
(2, 0x19, 0x00); F
($5, 16, 1);
888 if
(rx_uintop
($3, 4) && $3.X_add_number
== 1)
890 else if
(rx_uintop
($3, 4) && $3.X_add_number
== 2)
893 as_bad
(_
("RACL expects #1 or #2"));}
894 | RDACL
'#' EXPR
',' ACC
895 { rx_check_v2
(); id24
(2, 0x19, 0x40); F
($5, 16, 1);
896 if
(rx_uintop
($3, 4) && $3.X_add_number
== 1)
898 else if
(rx_uintop
($3, 4) && $3.X_add_number
== 2)
901 as_bad
(_
("RDACL expects #1 or #2"));}
902 | RDACW
'#' EXPR
',' ACC
903 { rx_check_v2
(); id24
(2, 0x18, 0x40); F
($5, 16, 1);
904 if
(rx_uintop
($3, 4) && $3.X_add_number
== 1)
906 else if
(rx_uintop
($3, 4) && $3.X_add_number
== 2)
909 as_bad
(_
("RDACW expects #1 or #2"));}
911 /* ---------------------------------------------------------------------- */
912 | BFMOV
{ rx_check_v3
(); sub_op
= 1; } op_bfield
913 | BFMOVZ
{ rx_check_v3
(); sub_op
= 0; } op_bfield
915 /* ---------------------------------------------------------------------- */
916 | RSTR
{ rx_check_v3
(); sub_op
= 1; } op_save_rstr
917 | SAVE
{ rx_check_v3
(); sub_op
= 0; } op_save_rstr
919 /* ---------------------------------------------------------------------- */
920 | DABS
{ rx_check_dfpu
(); sub_op
= 0x0c; sub_op2
= 0x01; } double2_op
921 | DNEG
{ rx_check_dfpu
(); sub_op
= 0x0c; sub_op2
= 0x02; } double2_op
922 | DROUND
{ rx_check_dfpu
(); sub_op
= 0x0d; sub_op2
= 0x0d; } double2_op
923 | DSQRT
{ rx_check_dfpu
(); sub_op
= 0x0d; sub_op2
= 0x00; } double2_op
924 | DTOF
{ rx_check_dfpu
(); sub_op
= 0x0d; sub_op2
= 0x0c; } double2_op
925 | DTOI
{ rx_check_dfpu
(); sub_op
= 0x0d; sub_op2
= 0x08;} double2_op
926 | DTOU
{ rx_check_dfpu
(); sub_op
= 0x0d; sub_op2
= 0x09; } double2_op
927 | DADD
{ rx_check_dfpu
(); sub_op
= 0x00; } double3_op
928 | DDIV
{ rx_check_dfpu
(); sub_op
= 0x05; } double3_op
929 | DMUL
{ rx_check_dfpu
(); sub_op
= 0x02; } double3_op
930 | DSUB
{ rx_check_dfpu
(); sub_op
= 0x01; } double3_op
931 | DCMP DREG
',' DREG
{ rx_check_dfpu
();
932 B4
(0x76, 0x90, 0x08, 0x00); F
($1, 24, 4); F
($2, 28, 4); F
($4, 16, 4); }
933 | DMOV DOT_D REG
',' DREGH
935 B4
(0xfd, 0x77, 0x80, 0x03); F
($3, 20, 4); F
($5, 24, 4); }
936 | DMOV DOT_L REG
',' DREGH
938 B4
(0xfd, 0x77, 0x80, 0x02); F
($3, 20, 4); F
($5, 24, 4); }
939 | DMOV DOT_L REG
',' DREGL
941 B4
(0xfd, 0x77, 0x80, 0x00); F
($3, 20, 4); F
($5, 24, 4); }
942 | DMOV DOT_L DREGH
',' REG
944 B4
(0xfd, 0x75, 0x80, 0x02); F
($3, 24, 4); F
($5, 20, 4); }
945 | DMOV DOT_L DREGL
',' REG
947 B4
(0xfd, 0x75, 0x80, 0x00); F
($3, 24, 4); F
($5, 20, 4); }
948 | DMOV DOT_D DREG
',' DREG
950 B4
(0x76, 0x90, 0x0c, 0x00); F
($3, 16, 4); F
($5, 24, 4); }
951 | DMOV DOT_D DREG
',' '[' REG
']'
953 B4
(0xfc, 0x78, 0x08, 0x00); F
($6, 16, 4); F
($3, 24, 4); }
954 | DMOV DOT_D DREG
',' disp
'[' REG
']'
956 B3
(0xfc, 0x78, 0x08); F
($7, 16, 4); DSP
($5, 14, DSIZE
);
958 | DMOV DOT_D
'[' REG
']' ',' DREG
960 B4
(0xfc, 0xc8, 0x08, 0x00); F
($4, 16, 4); F
($7, 24, 4); }
961 | DMOV DOT_D disp
'[' REG
']' ',' DREG
963 B3
(0xfc, 0xc8, 0x08); F
($5, 16, 4); DSP
($3, 14, DSIZE
);
965 | DMOV DOT_D
'#' EXPR
',' DREGH
967 B3
(0xf9, 0x03, 0x03); F
($6, 16, 4); IMM
($4, -1); }
968 | DMOV DOT_L
'#' EXPR
',' DREGH
970 B3
(0xf9, 0x03, 0x02); F
($6, 16, 4); IMM
($4, -1); }
971 | DMOV DOT_L
'#' EXPR
',' DREGL
973 B3
(0xf9, 0x03, 0x00); F
($6, 16, 4); IMM
($4, -1); }
974 | DPOPM DOT_D DREG
'-' DREG
976 B3
(0x75, 0xb8, 0x00); F
($3, 16, 4); F
($5 - $3, 20, 4); }
977 | DPOPM DOT_L DCREG
'-' DCREG
979 B3
(0x75, 0xa8, 0x00); F
($3, 16, 4); F
($5 - $3, 20, 4); }
980 | DPUSHM DOT_D DREG
'-' DREG
982 B3
(0x75, 0xb0, 0x00); F
($3, 16, 4); F
($5 - $3, 20, 4); }
983 | DPUSHM DOT_L DCREG
'-' DCREG
985 B3
(0x75, 0xa0, 0x00); F
($3, 16, 4); F
($5 - $3, 20, 4); }
986 | MVFDC DCREG
',' REG
988 B4
(0xfd, 0x75, 0x80, 0x04); F
($2, 24, 4); F
($4, 20, 4); }
990 { rx_check_dfpu
(); B3
(0x75, 0x90, 0x1b); }
991 | MVTDC REG
',' DCREG
993 B4
(0xfd, 0x77, 0x80, 0x04); F
($2, 24, 4); F
($4, 20, 4); }
996 B4
(0xfd, 0x77, 0x80, 0x0a); F
($2, 24, 4); F
($4, 20, 4); }
999 B4
(0xfd, 0x77, 0x80, 0x09); F
($2, 24, 4); F
($4, 20, 4); }
1002 B4
(0xfd, 0x77, 0x80, 0x0d); F
($2, 24, 4); F
($4, 20, 4); }
1004 /* ---------------------------------------------------------------------- */
1008 /* ====================================================================== */
1012 { B2
(0x43 + (sub_op
<<2), 0); F
($1, 8, 4); F
($3, 12, 4); }
1013 | disp
'[' REG
']' DOT_UB
',' REG
1014 { B2
(0x40 + (sub_op
<<2), 0); F
($3, 8, 4); F
($7, 12, 4); DSP
($1, 6, BSIZE
); }
1015 | disp
'[' REG
']' memex
',' REG
1016 { B3
(MEMEX
, sub_op
<<2, 0); F
($5, 8, 2); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, sizemap
[$5]); }
1017 | REG
',' REG
',' REG
1018 { id24
(4, sub_op
<<4, 0), F
($5, 12, 4), F
($1, 16, 4), F
($3, 20, 4); }
1021 /* sbb, neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
1025 { id24
(1, 0x03 + (sub_op
<<2), 0x00); F
($1, 16, 4); F
($3, 20, 4); }
1026 | disp
'[' REG
']' opt_l
',' REG
1027 { B4
(MEMEX
, 0xa0, 0x00 + sub_op
, 0x00);
1028 F
($3, 24, 4); F
($7, 28, 4); DSP
($1, 14, LSIZE
); }
1031 /* neg, adc, abs, max, min, div, divu, tst, not, xor, stz, stnz, emul, emulu */
1035 { id24
(1, 0x03 + (sub_op
<<2), 0x00); F
($1, 16, 4); F
($3, 20, 4); }
1036 | disp
'[' REG
']' DOT_UB
',' REG
1037 { id24
(1, 0x00 + (sub_op
<<2), 0x00); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, BSIZE
); }
1038 | disp
'[' REG
']' memex
',' REG
1039 { B4
(MEMEX
, 0x20 + ($5 << 6), 0x00 + sub_op
, 0x00);
1040 F
($3, 24, 4); F
($7, 28, 4); DSP
($1, 14, sizemap
[$5]); }
1045 { id24
(2, 0x70, sub_op
<<4); F
($4, 20, 4); IMM
($2, 12); }
1060 { id24
(1, 0x03 + (sub_op
<<2), 0x00); F
($1, 16, 4); F
($3, 20, 4); }
1062 { B2
(0x7e, sub_op2
<< 4); F
($1, 12, 4); }
1067 { id24
(1, 0x4b + (sub_op2
<<2), 0x00); F
($1, 16, 4); F
($3, 20, 4); }
1071 : { rx_check_v2
(); }
1076 /* xchg, utof, itof, emul, emulu */
1079 { id24
(1, 0x03 + (sub_op
<<2), 0); F
($1, 16, 4); F
($3, 20, 4); }
1080 | disp
'[' REG
']' DOT_UB
',' REG
1081 { id24
(1, 0x00 + (sub_op
<<2), 0); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, BSIZE
); }
1082 | disp
'[' REG
']' memex
',' REG
1083 { B4
(MEMEX
, 0x20, 0x00 + sub_op
, 0); F
($5, 8, 2); F
($3, 24, 4); F
($7, 28, 4);
1084 DSP
($1, 14, sizemap
[$5]); }
1087 /* 000:SHLR, 001:SHAR, 010:SHLL, 011:-, 100:ROTR, 101:REVW, 110:ROTL, 111:REVL */
1090 { id24
(2, 0x60 + sub_op
, 0); F
($1, 16, 4); F
($3, 20, 4); }
1094 { B2
(0x68 + (sub_op
<<1), 0); FE
($2, 7, 5); F
($4, 12, 4); }
1095 |
'#' EXPR
',' REG
',' REG
1096 { id24
(2, 0x80 + (sub_op
<< 5), 0); FE
($2, 11, 5); F
($4, 16, 4); F
($6, 20, 4); }
1102 { rx_check_float_support
(); id24
(2, 0x72, sub_op
<< 4); F
($4, 20, 4); O4
($2); }
1104 { rx_check_float_support
(); id24
(1, 0x83 + (sub_op
<< 2), 0); F
($1, 16, 4); F
($3, 20, 4); }
1105 | disp
'[' REG
']' opt_l
',' REG
1106 { rx_check_float_support
(); id24
(1, 0x80 + (sub_op
<< 2), 0); F
($3, 16, 4); F
($7, 20, 4); DSP
($1, 14, LSIZE
); }
1107 | REG
',' REG
',' REG
1108 { rx_check_v2
(); id24
(4, 0x80 + (sub_op
<< 4), 0 ); F
($1, 16, 4); F
($3, 20, 4); F
($5, 12, 4); }
1112 : { rx_check_float_support
(); }
1114 { id24
(2, 0x72, sub_op
<< 4); F
($5, 20, 4); O4
($3); }
1119 : { rx_check_float_support
(); }
1121 { id24
(1, 0x83 + (sub_op
<< 2), 0); F
($2, 16, 4); F
($4, 20, 4); }
1122 |
{ rx_check_float_support
(); }
1123 disp
'[' REG
']' opt_l
',' REG
1124 { id24
(1, 0x80 + (sub_op
<< 2), 0); F
($4, 16, 4); F
($8, 20, 4); DSP
($2, 14, LSIZE
); }
1128 : { rx_check_v2
(); }
1129 '#' EXPR
',' ACC
',' REG
1130 { id24
(2, 0x1e, sub_op
<< 4); F
($7, 20, 4); F
($5, 16, 1);
1131 if
(rx_uintop
($3, 4))
1133 switch
(exp_val
($3))
1145 as_bad
(_
("IMM expects #0 to #2"));}
1147 as_bad
(_
("IMM expects #0 to #2"));}
1152 | REG
',' REG
',' REG
1153 { rx_check_v3
(); B3
(0xff,0x60,0x00), F
($5, 12, 4), F
($1, 16, 4), F
($3, 20, 4); }
1157 : { rx_check_v3
(); }
1158 '#' EXPR
',' '#' EXPR
',' '#' EXPR
',' REG
',' REG
1159 { rx_range
($3, 0, 31); rx_range
($6, 0, 31); rx_range
($9, 1, 31);
1160 B3
(0xfc, 0x5a + (sub_op
<< 2), 0); F
($11, 16, 4); F
($13, 20, 4);
1161 rx_bfield
($3, $6, $9);}
1166 { B3
(0xfd,0x76,0xe0 + (sub_op
<< 4)); UO1
($2); }
1168 { B4
(0xfd,0x76,0xc0 + (sub_op
<< 4), 0x00); F
($1, 20, 4); }
1173 { B4
(0x76, 0x90, sub_op
, sub_op2
); F
($1, 16, 4); F
($3, 24, 4);}
1176 : DREG
',' DREG
',' DREG
1177 { B4
(0x76, 0x90, sub_op
, 0x00); F
($1, 28, 4); F
($3, 16,4); F
($5, 24, 4);}
1179 /* ====================================================================== */
1181 disp
: { $$
= zero_expr
(); }
1185 flag
: { need_flag
= 1; } FLAG
{ need_flag
= 0; $$
= $2; }
1188 /* DOT_UB is not listed here, it's handled with a separate pattern. */
1189 /* Use sizemap[$n] to get LSIZE etc. */
1190 memex
: DOT_B
{ $$
= 0; }
1194 | DOT_UW
{ $$
= 3; }
1197 bwl
: { $$
= LSIZE
; }
1198 | DOT_B
{ $$
= BSIZE
; }
1199 | DOT_W
{ $$
= WSIZE
; }
1200 | DOT_L
{ $$
= LSIZE
; }
1217 /* ====================================================================== */
1221 const char * string;
1247 { "fpsw", CREG
, 3 },
1253 { "bpsw", CREG
, 8 },
1255 { "isp", CREG
, 10 },
1256 { "fintv", CREG
, 11 },
1257 { "intb", CREG
, 12 },
1258 { "extb", CREG
, 13 },
1260 { "pbp", CREG
, 16 },
1261 { "pben", CREG
, 17 },
1263 { "bbpsw", CREG
, 24 },
1264 { "bbpc", CREG
, 25 },
1276 { "dr10", DREG
, 10 },
1277 { "dr11", DREG
, 11 },
1278 { "dr12", DREG
, 12 },
1279 { "dr13", DREG
, 13 },
1280 { "dr14", DREG
, 14 },
1281 { "dr15", DREG
, 15 },
1283 { "drh0", DREGH
, 0 },
1284 { "drh1", DREGH
, 1 },
1285 { "drh2", DREGH
, 2 },
1286 { "drh3", DREGH
, 3 },
1287 { "drh4", DREGH
, 4 },
1288 { "drh5", DREGH
, 5 },
1289 { "drh6", DREGH
, 6 },
1290 { "drh7", DREGH
, 7 },
1291 { "drh8", DREGH
, 8 },
1292 { "drh9", DREGH
, 9 },
1293 { "drh10", DREGH
, 10 },
1294 { "drh11", DREGH
, 11 },
1295 { "drh12", DREGH
, 12 },
1296 { "drh13", DREGH
, 13 },
1297 { "drh14", DREGH
, 14 },
1298 { "drh15", DREGH
, 15 },
1300 { "drl0", DREGL
, 0 },
1301 { "drl1", DREGL
, 1 },
1302 { "drl2", DREGL
, 2 },
1303 { "drl3", DREGL
, 3 },
1304 { "drl4", DREGL
, 4 },
1305 { "drl5", DREGL
, 5 },
1306 { "drl6", DREGL
, 6 },
1307 { "drl7", DREGL
, 7 },
1308 { "drl8", DREGL
, 8 },
1309 { "drl9", DREGL
, 9 },
1310 { "drl10", DREGL
, 10 },
1311 { "drl11", DREGL
, 11 },
1312 { "drl12", DREGL
, 12 },
1313 { "drl13", DREGL
, 13 },
1314 { "drl14", DREGL
, 14 },
1315 { "drl15", DREGL
, 15 },
1317 { "DPSW", DCREG
, 0 },
1318 { "DCMR", DCREG
, 1 },
1319 { "DCENT", DCREG
, 2 },
1320 { "DEPC", DCREG
, 3 },
1321 { "DCR0", DCREG
, 0 },
1322 { "DCR1", DCREG
, 1 },
1323 { "DCR2", DCREG
, 2 },
1324 { "DCR3", DCREG
, 3 },
1331 { ".ub", DOT_UB
, 0 },
1332 { ".uw", DOT_UW
, 0},
1345 #define OPC(x) { #x, x, IS_OPCODE }
1349 { "and", AND_
, IS_OPCODE
},
1489 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1493 const char * string;
1496 condition_opcode_table
[] =
1503 #define NUM_CONDITION_OPCODES (sizeof (condition_opcode_table) / sizeof (condition_opcode_table[0]))
1505 struct condition_symbol
1507 const char * string;
1511 static struct condition_symbol condition_table
[] =
1535 static struct condition_symbol double_condition_table
[] =
1543 #define NUM_CONDITIONS (sizeof (condition_table) / sizeof (condition_table[0]))
1544 #define NUM_DOUBLE_CONDITIONS (sizeof (double_condition_table) / sizeof (double_condition_table[0]))
1547 rx_lex_init
(char * beginning
, char * ending
)
1549 rx_init_start
= beginning
;
1550 rx_lex_start
= beginning
;
1551 rx_lex_end
= ending
;
1559 check_condition
(const char * base
, struct condition_symbol
*t
, unsigned int num
)
1564 if
((unsigned) (rx_lex_end
- rx_lex_start
) < strlen
(base
) + 1)
1566 if
(memcmp
(rx_lex_start
, base
, strlen
(base
)))
1568 cp
= rx_lex_start
+ strlen
(base
);
1569 for
(i
= 0; i
< num
; i
++)
1571 if
(strcasecmp
(cp
, t
[i
].
string) == 0)
1573 rx_lval.regno
= t
[i
].val
;
1584 char * save_input_pointer
;
1586 while
(ISSPACE
(*rx_lex_start
)
1587 && rx_lex_start
!= rx_lex_end
)
1590 rx_last_exp_start
= rx_lex_start
;
1592 if
(rx_lex_start
== rx_lex_end
)
1595 if
(ISALPHA
(*rx_lex_start
)
1596 ||
(rx_pid_register
!= -1 && memcmp
(rx_lex_start
, "%pidreg", 7) == 0)
1597 ||
(rx_gp_register
!= -1 && memcmp
(rx_lex_start
, "%gpreg", 6) == 0)
1598 ||
(*rx_lex_start
== '.' && ISALPHA
(rx_lex_start
[1])))
1604 for
(e
= rx_lex_start
+ 1;
1605 e
< rx_lex_end
&& ISALNUM
(*e
);
1611 if
(strcmp
(rx_lex_start
, "%pidreg") == 0)
1614 rx_lval.regno
= rx_pid_register
;
1617 rx_last_token
= REG
;
1622 if
(strcmp
(rx_lex_start
, "%gpreg") == 0)
1625 rx_lval.regno
= rx_gp_register
;
1628 rx_last_token
= REG
;
1633 if
(rx_last_token
== 0)
1635 for
(ci
= 0; ci
< NUM_CONDITION_OPCODES
; ci
++)
1636 if
(check_condition
(condition_opcode_table
[ci
].
string,
1637 condition_table
, NUM_CONDITIONS
))
1641 rx_last_token
= condition_opcode_table
[ci
].token
;
1642 return condition_opcode_table
[ci
].token
;
1644 if
(check_condition
("dcmp", double_condition_table
,
1645 NUM_DOUBLE_CONDITIONS
))
1649 rx_last_token
= DCMP
;
1654 for
(i
= 0; i
< NUM_TOKENS
; i
++)
1655 if
(strcasecmp
(rx_lex_start
, token_table
[i
].
string) == 0
1656 && !(token_table
[i
].val
== IS_OPCODE
&& rx_last_token
!= 0)
1657 && !(token_table
[i
].token
== FLAG
&& !need_flag
))
1659 rx_lval.regno
= token_table
[i
].val
;
1662 rx_last_token
= token_table
[i
].token
;
1663 return token_table
[i
].token
;
1668 if
(rx_last_token
== 0)
1670 rx_last_token
= UNKNOWN_OPCODE
;
1671 return UNKNOWN_OPCODE
;
1674 if
(rx_last_token
== UNKNOWN_OPCODE
)
1677 if
(*rx_lex_start
== '[')
1679 if
(*rx_lex_start
== ']')
1683 || rx_last_token
== REG || rx_last_token
== DREG || rx_last_token
== DCREG
1684 || strchr
("[],#", *rx_lex_start
))
1686 rx_last_token
= *rx_lex_start
;
1687 return
*rx_lex_start
++;
1690 save_input_pointer
= input_line_pointer
;
1691 input_line_pointer
= rx_lex_start
;
1692 rx_lval.exp.X_md
= 0;
1693 expression
(&rx_lval.exp
);
1695 /* We parse but ignore any :<size> modifier on expressions. */
1696 if
(*input_line_pointer
== ':')
1700 for
(cp
= input_line_pointer
+ 1; *cp
&& cp
< rx_lex_end
; cp
++)
1703 if
(cp
> input_line_pointer
+1)
1704 input_line_pointer
= cp
;
1707 rx_lex_start
= input_line_pointer
;
1708 input_line_pointer
= save_input_pointer
;
1709 rx_last_token
= EXPR
;
1714 rx_error
(const char * str
)
1718 len
= rx_last_exp_start
- rx_init_start
;
1720 as_bad
("%s", rx_init_start
);
1721 as_bad
("%*s^ %s", len
, "", str
);
1726 rx_intop
(expressionS exp
, int nbits
, int opbits
)
1731 if
(exp.X_op
== O_big
)
1735 if
(exp.X_add_number
== -1)
1738 else if
(exp.X_op
!= O_constant
)
1740 v
= exp.X_add_number
;
1742 msb
= 1UL << (opbits
- 1);
1743 mask
= (1UL << opbits
) - 1;
1745 if
((v
& msb
) && ! (v
& ~mask
))
1751 return
-0x8 <= v
&& v
<= 0x7;
1753 return
-0x10 <= v
&& v
<= 0x17;
1755 return
-0x80 <= v
&& v
<= 0x7f;
1757 return
-0x8000 <= v
&& v
<= 0x7fff;
1759 return
-0x800000 <= v
&& v
<= 0x7fffff;
1763 printf
("rx_intop passed %d\n", nbits
);
1770 rx_uintop
(expressionS exp
, int nbits
)
1774 if
(exp.X_op
!= O_constant
)
1776 v
= exp.X_add_number
;
1787 return v
<= 0xffffff;
1789 printf
("rx_uintop passed %d\n", nbits
);
1796 rx_disp3op
(expressionS exp
)
1800 if
(exp.X_op
!= O_constant
)
1802 v
= exp.X_add_number
;
1803 if
(v
< 3 || v
> 10)
1809 rx_disp5op
(expressionS
* exp
, int msize
)
1813 if
(exp
->X_op
!= O_constant
)
1815 v
= exp
->X_add_number
;
1820 if
(0 <= v
&& v
<= 31)
1826 if
(0 <= v
&& v
<= 63)
1828 exp
->X_add_number
>>= 1;
1835 if
(0 <= v
&& v
<= 127)
1837 exp
->X_add_number
>>= 2;
1845 /* Just like the above, but allows a zero displacement. */
1848 rx_disp5op0
(expressionS
* exp
, int msize
)
1850 if
(exp
->X_op
!= O_constant
)
1852 if
(exp
->X_add_number
== 0)
1854 return rx_disp5op
(exp
, msize
);
1858 exp_val
(expressionS exp
)
1860 if
(exp.X_op
!= O_constant
)
1862 rx_error
(_
("constant expected"));
1865 return exp.X_add_number
;
1871 /* Static, so program load sets it to all zeros, which is what we want. */
1872 static expressionS zero
;
1873 zero.X_op
= O_constant
;
1878 immediate
(expressionS exp
, int type
, int pos
, int bits
)
1880 /* We will emit constants ourselves here, so negate them. */
1881 if
(type
== RXREL_NEGATIVE
&& exp.X_op
== O_constant
)
1882 exp.X_add_number
= - exp.X_add_number
;
1883 if
(type
== RXREL_NEGATIVE_BORROW
)
1885 if
(exp.X_op
== O_constant
)
1886 exp.X_add_number
= - exp.X_add_number
- 1;
1888 rx_error
(_
("sbb cannot use symbolic immediates"));
1891 if
(pos
>= 0 && rx_intop
(exp
, 8, bits
))
1893 rx_op
(exp
, 1, type
);
1896 else if
(pos
>= 0 && rx_intop
(exp
, 16, bits
))
1898 rx_op
(exp
, 2, type
);
1901 else if
(pos
>= 0 && rx_uintop
(exp
, 16) && bits
== 16)
1903 rx_op
(exp
, 2, type
);
1906 else if
(pos
>= 0 && rx_intop
(exp
, 24, bits
))
1908 rx_op
(exp
, 3, type
);
1911 else if
(pos
< 0 || rx_intop
(exp
, 32, bits
))
1913 rx_op
(exp
, 4, type
);
1916 else if
(type
== RXREL_SIGNED
&& pos
>= 0)
1918 /* This is a symbolic immediate, we will relax it later. */
1919 rx_relax
(RX_RELAX_IMM
, pos
);
1920 rx_op
(exp
, linkrelax ?
4 : 1, type
);
1925 /* Let the linker deal with it. */
1926 rx_op
(exp
, 4, type
);
1932 displacement
(expressionS exp
, int msize
)
1937 if
(exp.X_op
== O_symbol
1942 case BFD_RELOC_GPREL16
:
1946 exp.X_md
= BFD_RELOC_RX_GPRELB
;
1949 exp.X_md
= BFD_RELOC_RX_GPRELW
;
1952 exp.X_md
= BFD_RELOC_RX_GPRELL
;
1960 if
(exp.X_op
== O_subtract
)
1962 exp.X_md
= BFD_RELOC_RX_DIFF
;
1967 if
(exp.X_op
!= O_constant
)
1969 rx_error
(_
("displacements must be constants"));
1972 val
= exp.X_add_number
;
1983 rx_error
(_
("word displacement not word-aligned"));
1988 rx_error
(_
("long displacement not long-aligned"));
1993 rx_error
(_
("double displacement not double-aligned"));
1997 as_bad
(_
("displacement with unknown size (internal bug?)\n"));
2002 exp.X_add_number
= val
;
2004 if
(0 <= val
&& val
<= 255 )
2010 if
(0 <= val
&& val
<= 65535)
2016 rx_error
(_
("negative displacements not allowed"));
2018 rx_error
(_
("displacement too large"));
2023 rtsd_immediate
(expressionS exp
)
2027 if
(exp.X_op
!= O_constant
)
2029 rx_error
(_
("rtsd size must be constant"));
2032 val
= exp.X_add_number
;
2034 rx_error
(_
("rtsd size must be multiple of 4"));
2036 if
(val
< 0 || val
> 1020)
2037 rx_error
(_
("rtsd size must be 0..1020"));
2040 exp.X_add_number
= val
;
2045 rx_range
(expressionS exp
, int minv
, int maxv
)
2049 if
(exp.X_op
!= O_constant
)
2052 val
= exp.X_add_number
;
2053 if
(val
< minv || val
> maxv
)
2054 as_warn
(_
("Value %d out of range %d..%d"), val
, minv
, maxv
);
2058 rx_check_float_support
(void)
2060 if
(rx_cpu
== RX100 || rx_cpu
== RX200
)
2061 rx_error
(_
("target CPU type does not support floating point instructions"));
2068 rx_error
(_
("target CPU type does not support v2 instructions"));
2075 rx_error
(_
("target CPU type does not support v3 instructions"));
2079 rx_check_dfpu
(void)
2081 if
(rx_cpu
!= RXV3FPU
)
2082 rx_error
(_
("target CPU type does not support double float instructions"));