1 /* rl78-parse.y Renesas RL78 parser
2 Copyright (C) 2011-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"
24 #include "rl78-defs.h"
26 static int rl78_lex
(void);
28 /* Ok, here are the rules for using these macros...
30 B*() is used to specify the base opcode bytes. Fields to be filled
31 in later, leave zero. Call this first.
33 F() and FE() are used to fill in fields within the base opcode bytes. You MUST
34 call B*() before any F() or FE().
36 [UN]*O*(), PC*() appends operands to the end of the opcode. You
37 must call P() and B*() before any of these, so that the fixups
38 have the right byte location.
39 O = signed, UO = unsigned, NO = negated, PC = pcrel
41 IMM() adds an immediate and fills in the field for it.
42 NIMM() same, but negates the immediate.
43 NBIMM() same, but negates the immediate, for sbb.
44 DSP() adds a displacement, and fills in the field for it.
46 Note that order is significant for the O, IMM, and DSP macros, as
47 they append their data to the operand buffer in the order that you
50 Use "disp" for displacements whenever possible; this handles the
53 #define B1(b1) rl78_base1 (b1)
54 #define B2(b1, b2) rl78_base2 (b1, b2)
55 #define B3(b1, b2, b3) rl78_base3 (b1, b2, b3)
56 #define B4(b1, b2, b3, b4) rl78_base4 (b1, b2, b3, b4)
58 /* POS is bits from the MSB of the first byte to the LSB of the last byte. */
59 #define F(val,pos,sz) rl78_field (val, pos, sz)
60 #define FE(exp,pos,sz) rl78_field (exp_val (exp), pos, sz);
62 #define O1(v) rl78_op (v, 1, RL78REL_DATA)
63 #define O2(v) rl78_op (v, 2, RL78REL_DATA)
64 #define O3(v) rl78_op (v, 3, RL78REL_DATA)
65 #define O4(v) rl78_op (v, 4, RL78REL_DATA)
67 #define PC1(v) rl78_op (v, 1, RL78REL_PCREL)
68 #define PC2(v) rl78_op (v, 2, RL78REL_PCREL)
69 #define PC3(v) rl78_op (v, 3, RL78REL_PCREL)
71 #define IMM(v,pos) F (immediate (v, RL78REL_SIGNED, pos), pos, 2); \
72 if
(v.X_op
!= O_constant
&& v.X_op
!= O_big
) rl78_linkrelax_imm
(pos
)
73 #define NIMM(v,pos) F (immediate (v, RL78REL_NEGATIVE, pos), pos, 2)
74 #define NBIMM(v,pos) F (immediate (v, RL78REL_NEGATIVE_BORROW, pos), pos, 2)
75 #define DSP(v,pos,msz) if (!v.X_md) rl78_relax (RL78_RELAX_DISP, pos); \
76 else rl78_linkrelax_dsp
(pos
); \
77 F
(displacement
(v
, msz
), pos
, 2)
79 #define id24(a,b2,b3) B3 (0xfb+a, b2, b3)
81 static int expr_is_sfr
(expressionS
);
82 static int expr_is_saddr
(expressionS
);
83 static int expr_is_word_aligned
(expressionS
);
84 static int exp_val
(expressionS exp
);
86 static int need_flag
= 0;
87 static int rl78_in_brackets
= 0;
88 static int rl78_last_token
= 0;
89 static char * rl78_init_start
;
90 static char * rl78_last_exp_start
= 0;
91 static int rl78_bit_insn
= 0;
94 #define YYERROR_VERBOSE 1
96 #define NOT_SADDR rl78_error ("Expression not 0xFFE20 to 0xFFF1F")
97 #define SA(e) if (!expr_is_saddr (e)) NOT_SADDR;
99 #define SET_SA(e) e.X_md = BFD_RELOC_RL78_SADDR
101 #define NOT_SFR rl78_error ("Expression not 0xFFF00 to 0xFFFFF")
102 #define SFR(e) if (!expr_is_sfr (e)) NOT_SFR;
104 #define NOT_SFR_OR_SADDR rl78_error ("Expression not 0xFFE20 to 0xFFFFF")
106 #define NOT_ES if (rl78_has_prefix()) rl78_error ("ES: prefix not allowed here");
108 #define WA(x) if (!expr_is_word_aligned (x)) rl78_error ("Expression not word-aligned");
110 #define ISA_G10(s) if (!rl78_isa_g10()) rl78_error (s " is only supported on the G10")
111 #define ISA_G13(s) if (!rl78_isa_g13()) rl78_error (s " is only supported on the G13")
112 #define ISA_G14(s) if (!rl78_isa_g14()) rl78_error (s " is only supported on the G14")
114 static void check_expr_is_bit_index
(expressionS
);
115 #define Bit(e) check_expr_is_bit_index (e);
117 /* Returns TRUE (non-zero) if the expression is a constant in the
119 static int check_expr_is_const
(expressionS
, int vmin
, int vmax
);
121 /* Convert a "regb" value to a "reg_xbc" value. Error if other
122 registers are passed. Needed to avoid reduce-reduce conflicts. */
135 rl78_error
("Only X, B, or C allowed here");
149 %type
<regno
> regb regb_na regw regw_na FLAG sfr
150 %type
<regno
> A X B C D E H L AX BC DE HL
153 %type
<regno
> addsub addsubw andor1 bt_bf setclr1 oneclrb oneclrw
154 %type
<regno
> incdec incdecw
156 %token A X B C D E H L AX BC DE HL
157 %token SPL SPH PSW CS ES PMC MEM
159 %token RB0 RB1 RB2 RB3
161 %token EXPR UNKNOWN_OPCODE IS_OPCODE
163 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
165 %token ADD ADDC ADDW AND_ AND1
166 /* BC is also a register pair */
167 %token BF BH BNC BNH BNZ BR BRK BRK1 BT BTCLR BZ
168 %token CALL CALLT CLR1 CLRB CLRW CMP CMP0 CMPS CMPW
169 %token DEC DECW DI DIVHU DIVWU
173 %token MACH MACHU MOV MOV1 MOVS MOVW MULH MULHU MULU
175 %token ONEB ONEW OR OR1
177 %token RET RETI RETB ROL ROLC ROLWC ROR RORC
178 %token SAR SARW SEL SET1 SHL SHLW SHR SHRW
179 %token SKC SKH SKNC SKNH SKNZ SKZ STOP SUB SUBC SUBW
180 %token XCH XCHW XOR XOR1
183 /* ====================================================================== */
188 { as_bad
(_
("Unknown opcode: %s"), rl78_init_start
); }
190 /* The opcodes are listed in approximately alphabetical order. */
194 sfr = special function register - symbol, 0xFFF00 to 0xFFFFF
195 sfrp = special function register - symbol, 0xFFF00 to 0xFFFFE, even only
196 saddr = 0xFFE20 to 0xFFF1F
197 saddrp = 0xFFE20 to 0xFFF1E, even only
199 addr20 = 0x00000 to 0xFFFFF
200 addr16 = 0x00000 to 0x0FFFF, even only for 16-bit ops
201 addr5 = 0x00000 to 0x000BE, even only
204 /* ---------------------------------------------------------------------- */
206 /* addsub is ADD, ADDC, SUB, SUBC, AND, OR, XOR, and parts of CMP. */
208 | addsub A
',' '#' EXPR
209 { B1
(0x0c|
$1); O1
($5); }
211 | addsub EXPR
{SA
($2)} ',' '#' EXPR
212 { B1
(0x0a|
$1); SET_SA
($2); O1
($2); O1
($6); }
215 { B2
(0x61, 0x01|
$1); }
217 | addsub A
',' regb_na
218 { B2
(0x61, 0x08|
$1); F
($4, 13, 3); }
220 | addsub regb_na
',' A
221 { B2
(0x61, 0x00|
$1); F
($2, 13, 3); }
223 | addsub A
',' EXPR
{SA
($4)}
224 { B1
(0x0b|
$1); SET_SA
($4); O1
($4); }
226 | addsub A
',' opt_es
'!' EXPR
227 { B1
(0x0f|
$1); O2
($6); rl78_linkrelax_addr16
(); }
229 | addsub A
',' opt_es
'[' HL
']'
232 | addsub A
',' opt_es
'[' HL
'+' EXPR
']'
233 { B1
(0x0e|
$1); O1
($8); }
235 | addsub A
',' opt_es
'[' HL
'+' B
']'
236 { B2
(0x61, 0x80|
$1); }
238 | addsub A
',' opt_es
'[' HL
'+' C
']'
239 { B2
(0x61, 0x82|
$1); }
241 | addsub opt_es
'!' EXPR
',' '#' EXPR
243 { rl78_error
("Only CMP takes these operands"); }
245 { B1
(0x00|
$1); O2
($4); O1
($7); rl78_linkrelax_addr16
(); }
248 /* ---------------------------------------------------------------------- */
250 | addsubw AX
',' '#' EXPR
251 { B1
(0x04|
$1); O2
($5); }
253 | addsubw AX
',' regw
254 { B1
(0x01|
$1); F
($4, 5, 2); }
256 | addsubw AX
',' EXPR
{SA
($4)}
257 { B1
(0x06|
$1); SET_SA
($4); O1
($4); }
259 | addsubw AX
',' opt_es
'!' EXPR
260 { B1
(0x02|
$1); O2
($6); rl78_linkrelax_addr16
(); }
262 | addsubw AX
',' opt_es
'[' HL
'+' EXPR
']'
263 { B2
(0x61, 0x09|
$1); O1
($8); }
265 | addsubw AX
',' opt_es
'[' HL
']'
266 { B3
(0x61, 0x09|
$1, 0); }
268 | addsubw SP
',' '#' EXPR
269 { B1
($1 ?
0x20 : 0x10); O1
($5);
271 rl78_error
("CMPW SP,#imm not allowed");
274 /* ---------------------------------------------------------------------- */
276 | andor1 CY
',' sfr
'.' EXPR
{Bit
($6)}
277 { B3
(0x71, 0x08|
$1, $4); FE
($6, 9, 3); }
279 | andor1 CY
',' EXPR
'.' EXPR
{Bit
($6)}
280 { if
(expr_is_sfr
($4))
281 { B2
(0x71, 0x08|
$1); FE
($6, 9, 3); O1
($4); }
282 else if
(expr_is_saddr
($4))
283 { B2
(0x71, 0x00|
$1); FE
($6, 9, 3); SET_SA
($4); O1
($4); }
288 | andor1 CY
',' A
'.' EXPR
{Bit
($6)}
289 { B2
(0x71, 0x88|
$1); FE
($6, 9, 3); }
291 | andor1 CY
',' opt_es
'[' HL
']' '.' EXPR
{Bit
($9)}
292 { B2
(0x71, 0x80|
$1); FE
($9, 9, 3); }
294 /* ---------------------------------------------------------------------- */
297 { B1
(0xdc); PC1
($3); rl78_linkrelax_branch
(); }
300 { B1
(0xde); PC1
($3); rl78_linkrelax_branch
(); }
303 { B1
(0xdd); PC1
($3); rl78_linkrelax_branch
(); }
306 { B1
(0xdf); PC1
($3); rl78_linkrelax_branch
(); }
309 { B2
(0x61, 0xc3); PC1
($3); rl78_linkrelax_branch
(); }
312 { B2
(0x61, 0xd3); PC1
($3); rl78_linkrelax_branch
(); }
314 /* ---------------------------------------------------------------------- */
316 | bt_bf sfr
'.' EXPR
',' '$' EXPR
317 { B3
(0x31, 0x80|
$1, $2); FE
($4, 9, 3); PC1
($7); }
319 | bt_bf EXPR
'.' EXPR
',' '$' EXPR
320 { if
(expr_is_sfr
($2))
321 { B2
(0x31, 0x80|
$1); FE
($4, 9, 3); O1
($2); PC1
($7); }
322 else if
(expr_is_saddr
($2))
323 { B2
(0x31, 0x00|
$1); FE
($4, 9, 3); SET_SA
($2); O1
($2); PC1
($7); }
328 | bt_bf A
'.' EXPR
',' '$' EXPR
329 { B2
(0x31, 0x01|
$1); FE
($4, 9, 3); PC1
($7); }
331 | bt_bf opt_es
'[' HL
']' '.' EXPR
',' '$' EXPR
332 { B2
(0x31, 0x81|
$1); FE
($7, 9, 3); PC1
($10); }
334 /* ---------------------------------------------------------------------- */
340 { B1
(0xef); PC1
($3); rl78_linkrelax_branch
(); }
343 { B1
(0xee); PC2
($4); rl78_linkrelax_branch
(); }
346 { B1
(0xed); O2
($3); rl78_linkrelax_branch
(); }
349 { B1
(0xec); O3
($4); rl78_linkrelax_branch
(); }
351 /* ---------------------------------------------------------------------- */
359 /* ---------------------------------------------------------------------- */
362 { B2
(0x61, 0xca); F
($2, 10, 2); }
365 { B1
(0xfe); PC2
($4); }
368 { B1
(0xfd); O2
($3); }
371 { B1
(0xfc); O3
($4); rl78_linkrelax_branch
(); }
374 { if
($3.X_op
!= O_constant
)
375 rl78_error
("CALLT requires a numeric address");
378 int i
= $3.X_add_number
;
379 if
(i
< 0x80 || i
> 0xbe)
380 rl78_error
("CALLT address not 0x80..0xbe");
382 rl78_error
("CALLT address not even");
386 F
((i
>> 1) & 7, 9, 3);
387 F
((i
>> 4) & 7, 14, 2);
392 /* ---------------------------------------------------------------------- */
395 { B2
(0x71, $1 ?
0x88 : 0x80); }
397 | setclr1 sfr
'.' EXPR
398 { B3
(0x71, 0x0a|
$1, $2); FE
($4, 9, 3); }
400 | setclr1 EXPR
'.' EXPR
401 { if
(expr_is_sfr
($2))
402 { B2
(0x71, 0x0a|
$1); FE
($4, 9, 3); O1
($2); }
403 else if
(expr_is_saddr
($2))
404 { B2
(0x71, 0x02|
$1); FE
($4, 9, 3); SET_SA
($2); O1
($2); }
410 { B2
(0x71, 0x8a|
$1); FE
($4, 9, 3); }
412 | setclr1 opt_es
'!' EXPR
'.' EXPR
413 { B2
(0x71, 0x00+$1*0x08); FE
($6, 9, 3); O2
($4); rl78_linkrelax_addr16
(); }
415 | setclr1 opt_es
'[' HL
']' '.' EXPR
416 { B2
(0x71, 0x82|
$1); FE
($7, 9, 3); }
418 /* ---------------------------------------------------------------------- */
429 | oneclrb EXPR
{SA
($2)}
430 { B1
(0xe4|
$1); SET_SA
($2); O1
($2); }
432 | oneclrb opt_es
'!' EXPR
433 { B1
(0xe5|
$1); O2
($4); rl78_linkrelax_addr16
(); }
435 /* ---------------------------------------------------------------------- */
442 /* ---------------------------------------------------------------------- */
457 { B1
(0xd4); SET_SA
($2); O1
($2); }
459 | CMP0 opt_es
'!' EXPR
460 { B1
(0xd5); O2
($4); rl78_linkrelax_addr16
(); }
462 /* ---------------------------------------------------------------------- */
464 | CMPS X
',' opt_es
'[' HL
'+' EXPR
']'
465 { B2
(0x61, 0xde); O1
($8); }
467 /* ---------------------------------------------------------------------- */
470 { B1
(0x80|
$1); F
($2, 5, 3); }
472 | incdec EXPR
{SA
($2)}
473 { B1
(0xa4|
$1); SET_SA
($2); O1
($2); }
475 { B1
(0xa0|
$1); O2
($3); rl78_linkrelax_addr16
(); }
476 | incdec ES
':' '!' EXPR
477 { B2
(0x11, 0xa0|
$1); O2
($5); }
478 | incdec
'[' HL
'+' EXPR
']'
479 { B2
(0x61, 0x59+$1); O1
($5); }
480 | incdec ES
':' '[' HL
'+' EXPR
']'
481 { B3
(0x11, 0x61, 0x59+$1); O1
($7); }
483 /* ---------------------------------------------------------------------- */
486 { B1
(0xa1|
$1); F
($2, 5, 2); }
488 | incdecw EXPR
{SA
($2)}
489 { B1
(0xa6|
$1); SET_SA
($2); O1
($2); }
491 | incdecw opt_es
'!' EXPR
492 { B1
(0xa2|
$1); O2
($4); rl78_linkrelax_addr16
(); }
494 | incdecw opt_es
'[' HL
'+' EXPR
']'
495 { B2
(0x61, 0x79+$1); O1
($6); }
497 /* ---------------------------------------------------------------------- */
500 { B3
(0x71, 0x7b, 0xfa); }
503 { B3
(0x71, 0x7a, 0xfa); }
505 /* ---------------------------------------------------------------------- */
507 | MULHU
{ ISA_G14
("MULHU"); }
508 { B3
(0xce, 0xfb, 0x01); }
510 | MULH
{ ISA_G14
("MULH"); }
511 { B3
(0xce, 0xfb, 0x02); }
516 | DIVHU
{ ISA_G14
("DIVHU"); }
517 { B3
(0xce, 0xfb, 0x03); }
519 /* Note that the DIVWU encoding was changed from [0xce,0xfb,0x04] to
520 [0xce,0xfb,0x0b]. Different versions of the Software Manual exist
521 with the same version number, but varying encodings. The version
522 here matches the hardware. */
524 | DIVWU
{ ISA_G14
("DIVWU"); }
525 { B3
(0xce, 0xfb, 0x0b); }
527 | MACHU
{ ISA_G14
("MACHU"); }
528 { B3
(0xce, 0xfb, 0x05); }
530 | MACH
{ ISA_G14
("MACH"); }
531 { B3
(0xce, 0xfb, 0x06); }
533 /* ---------------------------------------------------------------------- */
538 /* ---------------------------------------------------------------------- */
539 /* Note that opt_es is included even when it's not an option, to avoid
540 shift/reduce conflicts. The NOT_ES macro produces an error if ES:
541 is given by the user. */
544 { B1
(0x51); O1
($5); }
545 | MOV regb_na
',' '#' EXPR
546 { B1
(0x50); F
($2, 5, 3); O1
($5); }
548 | MOV sfr
',' '#' EXPR
550 { B2
(0xce, $2); O1
($5); }
552 { B1
(0x41); O1
($5); }
555 | MOV opt_es EXPR
',' '#' EXPR
{NOT_ES
}
556 { if
(expr_is_sfr
($3))
557 { B1
(0xce); O1
($3); O1
($6); }
558 else if
(expr_is_saddr
($3))
559 { B1
(0xcd); SET_SA
($3); O1
($3); O1
($6); }
564 | MOV
'!' EXPR
',' '#' EXPR
565 { B1
(0xcf); O2
($3); O1
($6); rl78_linkrelax_addr16
(); }
567 | MOV ES
':' '!' EXPR
',' '#' EXPR
568 { B2
(0x11, 0xcf); O2
($5); O1
($8); }
571 { B1
(0x70); F
($2, 5, 3); }
574 { B1
(0x60); F
($4, 5, 3); }
576 | MOV opt_es EXPR
',' A
{NOT_ES
}
577 { if
(expr_is_sfr
($3))
578 { B1
(0x9e); O1
($3); }
579 else if
(expr_is_saddr
($3))
580 { B1
(0x9d); SET_SA
($3); O1
($3); }
585 | MOV A
',' opt_es
'!' EXPR
586 { B1
(0x8f); O2
($6); rl78_linkrelax_addr16
(); }
589 { B1
(0x9f); O2
($3); rl78_linkrelax_addr16
(); }
591 | MOV ES
':' '!' EXPR
',' A
592 { B2
(0x11, 0x9f); O2
($5); }
594 | MOV regb_na
',' opt_es
'!' EXPR
595 { B1
(0xc9|reg_xbc
($2)); O2
($6); rl78_linkrelax_addr16
(); }
597 | MOV A
',' opt_es EXPR
{NOT_ES
}
598 { if
(expr_is_saddr
($5))
599 { B1
(0x8d); SET_SA
($5); O1
($5); }
600 else if
(expr_is_sfr
($5))
601 { B1
(0x8e); O1
($5); }
606 | MOV regb_na
',' opt_es EXPR
{SA
($5)} {NOT_ES
}
607 { B1
(0xc8|reg_xbc
($2)); SET_SA
($5); O1
($5); }
614 rl78_error
("Only A allowed here");
619 | MOV sfr
',' opt_es EXPR
{SA
($5)} {NOT_ES
}
621 rl78_error
("Only ES allowed here");
623 { B2
(0x61, 0xb8); SET_SA
($5); O1
($5); }
626 | MOV A
',' opt_es
'[' DE
']'
629 | MOV opt_es
'[' DE
']' ',' A
632 | MOV opt_es
'[' DE
'+' EXPR
']' ',' '#' EXPR
633 { B1
(0xca); O1
($6); O1
($10); }
635 | MOV A
',' opt_es
'[' DE
'+' EXPR
']'
636 { B1
(0x8a); O1
($8); }
638 | MOV opt_es
'[' DE
'+' EXPR
']' ',' A
639 { B1
(0x9a); O1
($6); }
641 | MOV A
',' opt_es
'[' HL
']'
644 | MOV opt_es
'[' HL
']' ',' A
647 | MOV opt_es
'[' HL
'+' EXPR
']' ',' '#' EXPR
648 { B1
(0xcc); O1
($6); O1
($10); }
650 | MOV A
',' opt_es
'[' HL
'+' EXPR
']'
651 { B1
(0x8c); O1
($8); }
653 | MOV opt_es
'[' HL
'+' EXPR
']' ',' A
654 { B1
(0x9c); O1
($6); }
656 | MOV A
',' opt_es
'[' HL
'+' B
']'
659 | MOV opt_es
'[' HL
'+' B
']' ',' A
662 | MOV A
',' opt_es
'[' HL
'+' C
']'
665 | MOV opt_es
'[' HL
'+' C
']' ',' A
668 | MOV opt_es EXPR
'[' B
']' ',' '#' EXPR
669 { B1
(0x19); O2
($3); O1
($9); }
671 | MOV A
',' opt_es EXPR
'[' B
']'
672 { B1
(0x09); O2
($5); }
674 | MOV opt_es EXPR
'[' B
']' ',' A
675 { B1
(0x18); O2
($3); }
677 | MOV opt_es EXPR
'[' C
']' ',' '#' EXPR
678 { B1
(0x38); O2
($3); O1
($9); }
680 | MOV A
',' opt_es EXPR
'[' C
']'
681 { B1
(0x29); O2
($5); }
683 | MOV opt_es EXPR
'[' C
']' ',' A
684 { B1
(0x28); O2
($3); }
686 | MOV opt_es EXPR
'[' BC
']' ',' '#' EXPR
687 { B1
(0x39); O2
($3); O1
($9); }
689 | MOV opt_es
'[' BC
']' ',' '#' EXPR
690 { B3
(0x39, 0, 0); O1
($8); }
692 | MOV A
',' opt_es EXPR
'[' BC
']'
693 { B1
(0x49); O2
($5); }
695 | MOV A
',' opt_es
'[' BC
']'
698 | MOV opt_es EXPR
'[' BC
']' ',' A
699 { B1
(0x48); O2
($3); }
701 | MOV opt_es
'[' BC
']' ',' A
704 | MOV opt_es
'[' SP
'+' EXPR
']' ',' '#' EXPR
{NOT_ES
}
705 { B1
(0xc8); O1
($6); O1
($10); }
707 | MOV opt_es
'[' SP
']' ',' '#' EXPR
{NOT_ES
}
708 { B2
(0xc8, 0); O1
($8); }
710 | MOV A
',' opt_es
'[' SP
'+' EXPR
']' {NOT_ES
}
711 { B1
(0x88); O1
($8); }
713 | MOV A
',' opt_es
'[' SP
']' {NOT_ES
}
716 | MOV opt_es
'[' SP
'+' EXPR
']' ',' A
{NOT_ES
}
717 { B1
(0x98); O1
($6); }
719 | MOV opt_es
'[' SP
']' ',' A
{NOT_ES
}
722 /* ---------------------------------------------------------------------- */
724 | mov1 CY
',' EXPR
'.' EXPR
725 { if
(expr_is_saddr
($4))
726 { B2
(0x71, 0x04); FE
($6, 9, 3); SET_SA
($4); O1
($4); }
727 else if
(expr_is_sfr
($4))
728 { B2
(0x71, 0x0c); FE
($6, 9, 3); O1
($4); }
733 | mov1 CY
',' A
'.' EXPR
734 { B2
(0x71, 0x8c); FE
($6, 9, 3); }
736 | mov1 CY
',' sfr
'.' EXPR
737 { B3
(0x71, 0x0c, $4); FE
($6, 9, 3); }
739 | mov1 CY
',' opt_es
'[' HL
']' '.' EXPR
740 { B2
(0x71, 0x84); FE
($9, 9, 3); }
742 | mov1 EXPR
'.' EXPR
',' CY
743 { if
(expr_is_saddr
($2))
744 { B2
(0x71, 0x01); FE
($4, 9, 3); SET_SA
($2); O1
($2); }
745 else if
(expr_is_sfr
($2))
746 { B2
(0x71, 0x09); FE
($4, 9, 3); O1
($2); }
751 | mov1 A
'.' EXPR
',' CY
752 { B2
(0x71, 0x89); FE
($4, 9, 3); }
754 | mov1 sfr
'.' EXPR
',' CY
755 { B3
(0x71, 0x09, $2); FE
($4, 9, 3); }
757 | mov1 opt_es
'[' HL
']' '.' EXPR
',' CY
758 { B2
(0x71, 0x81); FE
($7, 9, 3); }
760 /* ---------------------------------------------------------------------- */
762 | MOVS opt_es
'[' HL
'+' EXPR
']' ',' X
763 { B2
(0x61, 0xce); O1
($6); }
765 /* ---------------------------------------------------------------------- */
767 | MOVW AX
',' '#' EXPR
768 { B1
(0x30); O2
($5); }
770 | MOVW regw_na
',' '#' EXPR
771 { B1
(0x30); F
($2, 5, 2); O2
($5); }
773 | MOVW opt_es EXPR
',' '#' EXPR
{NOT_ES
}
774 { if
(expr_is_saddr
($3))
775 { B1
(0xc9); SET_SA
($3); O1
($3); O2
($6); }
776 else if
(expr_is_sfr
($3))
777 { B1
(0xcb); O1
($3); O2
($6); }
782 | MOVW AX
',' opt_es EXPR
{NOT_ES
}
783 { if
(expr_is_saddr
($5))
784 { B1
(0xad); SET_SA
($5); O1
($5); WA
($5); }
785 else if
(expr_is_sfr
($5))
786 { B1
(0xae); O1
($5); WA
($5); }
791 | MOVW opt_es EXPR
',' AX
{NOT_ES
}
792 { if
(expr_is_saddr
($3))
793 { B1
(0xbd); SET_SA
($3); O1
($3); WA
($3); }
794 else if
(expr_is_sfr
($3))
795 { B1
(0xbe); O1
($3); WA
($3); }
800 | MOVW AX
',' regw_na
801 { B1
(0x11); F
($4, 5, 2); }
803 | MOVW regw_na
',' AX
804 { B1
(0x10); F
($2, 5, 2); }
806 | MOVW AX
',' opt_es
'!' EXPR
807 { B1
(0xaf); O2
($6); WA
($6); rl78_linkrelax_addr16
(); }
809 | MOVW opt_es
'!' EXPR
',' AX
810 { B1
(0xbf); O2
($4); WA
($4); rl78_linkrelax_addr16
(); }
812 | MOVW AX
',' opt_es
'[' DE
']'
815 | MOVW opt_es
'[' DE
']' ',' AX
818 | MOVW AX
',' opt_es
'[' DE
'+' EXPR
']'
819 { B1
(0xaa); O1
($8); }
821 | MOVW opt_es
'[' DE
'+' EXPR
']' ',' AX
822 { B1
(0xba); O1
($6); }
824 | MOVW AX
',' opt_es
'[' HL
']'
827 | MOVW opt_es
'[' HL
']' ',' AX
830 | MOVW AX
',' opt_es
'[' HL
'+' EXPR
']'
831 { B1
(0xac); O1
($8); }
833 | MOVW opt_es
'[' HL
'+' EXPR
']' ',' AX
834 { B1
(0xbc); O1
($6); }
836 | MOVW AX
',' opt_es EXPR
'[' B
']'
837 { B1
(0x59); O2
($5); }
839 | MOVW opt_es EXPR
'[' B
']' ',' AX
840 { B1
(0x58); O2
($3); }
842 | MOVW AX
',' opt_es EXPR
'[' C
']'
843 { B1
(0x69); O2
($5); }
845 | MOVW opt_es EXPR
'[' C
']' ',' AX
846 { B1
(0x68); O2
($3); }
848 | MOVW AX
',' opt_es EXPR
'[' BC
']'
849 { B1
(0x79); O2
($5); }
851 | MOVW AX
',' opt_es
'[' BC
']'
854 | MOVW opt_es EXPR
'[' BC
']' ',' AX
855 { B1
(0x78); O2
($3); }
857 | MOVW opt_es
'[' BC
']' ',' AX
860 | MOVW AX
',' opt_es
'[' SP
'+' EXPR
']' {NOT_ES
}
861 { B1
(0xa8); O1
($8); WA
($8);}
863 | MOVW AX
',' opt_es
'[' SP
']' {NOT_ES
}
866 | MOVW opt_es
'[' SP
'+' EXPR
']' ',' AX
{NOT_ES
}
867 { B1
(0xb8); O1
($6); WA
($6); }
869 | MOVW opt_es
'[' SP
']' ',' AX
{NOT_ES
}
872 | MOVW regw_na
',' EXPR
{SA
($4)}
873 { B1
(0xca); F
($2, 2, 2); SET_SA
($4); O1
($4); WA
($4); }
875 | MOVW regw_na
',' opt_es
'!' EXPR
876 { B1
(0xcb); F
($2, 2, 2); O2
($6); WA
($6); rl78_linkrelax_addr16
(); }
878 | MOVW SP
',' '#' EXPR
879 { B2
(0xcb, 0xf8); O2
($5); }
887 | MOVW regw_na
',' SP
888 { B3
(0xcb, 0xf8, 0xff); F
($2, 2, 2); }
890 /* ---------------------------------------------------------------------- */
895 /* ---------------------------------------------------------------------- */
900 /* ---------------------------------------------------------------------- */
903 { B1
(0xc0); F
($2, 5, 2); }
906 { B2
(0x61, 0xcd); };
909 { B1
(0xc1); F
($2, 5, 2); }
912 { B2
(0x61, 0xdd); };
914 /* ---------------------------------------------------------------------- */
925 /* ---------------------------------------------------------------------- */
928 { if
(check_expr_is_const
($4, 1, 1))
933 { if
(check_expr_is_const
($4, 1, 1))
938 { if
(check_expr_is_const
($4, 1, 1))
943 { if
(check_expr_is_const
($4, 1, 1))
948 { if
(check_expr_is_const
($4, 1, 1))
953 { if
(check_expr_is_const
($4, 1, 1))
957 /* ---------------------------------------------------------------------- */
960 { if
(check_expr_is_const
($4, 1, 7))
961 { B2
(0x31, 0x0b); FE
($4, 9, 3); }
965 { if
(check_expr_is_const
($4, 1, 15))
966 { B2
(0x31, 0x0f); FE
($4, 8, 4); }
969 /* ---------------------------------------------------------------------- */
983 /* ---------------------------------------------------------------------- */
986 { if
(check_expr_is_const
($4, 1, 7))
987 { B2
(0x31, 0x09); FE
($4, 9, 3); }
991 { if
(check_expr_is_const
($4, 1, 7))
992 { B2
(0x31, 0x08); FE
($4, 9, 3); }
996 { if
(check_expr_is_const
($4, 1, 7))
997 { B2
(0x31, 0x07); FE
($4, 9, 3); }
1001 { if
(check_expr_is_const
($4, 1, 15))
1002 { B2
(0x31, 0x0d); FE
($4, 8, 4); }
1006 { if
(check_expr_is_const
($4, 1, 15))
1007 { B2
(0x31, 0x0c); FE
($4, 8, 4); }
1010 /* ---------------------------------------------------------------------- */
1013 { if
(check_expr_is_const
($4, 1, 7))
1014 { B2
(0x31, 0x0a); FE
($4, 9, 3); }
1018 { if
(check_expr_is_const
($4, 1, 15))
1019 { B2
(0x31, 0x0e); FE
($4, 8, 4); }
1022 /* ---------------------------------------------------------------------- */
1025 { B2
(0x61, 0xc8); rl78_relax
(RL78_RELAX_BRANCH
, 0); }
1028 { B2
(0x61, 0xe3); rl78_relax
(RL78_RELAX_BRANCH
, 0); }
1031 { B2
(0x61, 0xd8); rl78_relax
(RL78_RELAX_BRANCH
, 0); }
1034 { B2
(0x61, 0xf3); rl78_relax
(RL78_RELAX_BRANCH
, 0); }
1037 { B2
(0x61, 0xf8); rl78_relax
(RL78_RELAX_BRANCH
, 0); }
1040 { B2
(0x61, 0xe8); rl78_relax
(RL78_RELAX_BRANCH
, 0); }
1042 /* ---------------------------------------------------------------------- */
1045 { B2
(0x61, 0xfd); }
1047 /* ---------------------------------------------------------------------- */
1050 { if
($4 == 0) /* X */
1053 { B2
(0x61, 0x88); F
($4, 13, 3); }
1056 | XCH A
',' opt_es
'!' EXPR
1057 { B2
(0x61, 0xaa); O2
($6); rl78_linkrelax_addr16
(); }
1059 | XCH A
',' opt_es
'[' DE
']'
1060 { B2
(0x61, 0xae); }
1062 | XCH A
',' opt_es
'[' DE
'+' EXPR
']'
1063 { B2
(0x61, 0xaf); O1
($8); }
1065 | XCH A
',' opt_es
'[' HL
']'
1066 { B2
(0x61, 0xac); }
1068 | XCH A
',' opt_es
'[' HL
'+' EXPR
']'
1069 { B2
(0x61, 0xad); O1
($8); }
1071 | XCH A
',' opt_es
'[' HL
'+' B
']'
1072 { B2
(0x61, 0xb9); }
1074 | XCH A
',' opt_es
'[' HL
'+' C
']'
1075 { B2
(0x61, 0xa9); }
1078 { if
(expr_is_sfr
($4))
1079 { B2
(0x61, 0xab); O1
($4); }
1080 else if
(expr_is_saddr
($4))
1081 { B2
(0x61, 0xa8); SET_SA
($4); O1
($4); }
1086 /* ---------------------------------------------------------------------- */
1088 | XCHW AX
',' regw_na
1089 { B1
(0x31); F
($4, 5, 2); }
1091 /* ---------------------------------------------------------------------- */
1093 ; /* end of statement */
1095 /* ---------------------------------------------------------------------- */
1097 opt_es
: /* nothing */
1099 { rl78_prefix
(0x11); }
1102 regb
: X
{ $$
= 0; }
1112 regb_na
: X
{ $$
= 0; }
1121 regw
: AX
{ $$
= 0; }
1127 regw_na
: BC
{ $$
= 1; }
1132 sfr
: SPL
{ $$
= 0xf8; }
1133 | SPH
{ $$
= 0xf9; }
1134 | PSW
{ $$
= 0xfa; }
1137 | PMC
{ $$
= 0xfe; }
1138 | MEM
{ $$
= 0xff; }
1141 /* ---------------------------------------------------------------------- */
1142 /* Shortcuts for groups of opcodes with common encodings. */
1144 addsub
: ADD
{ $$
= 0x00; }
1145 | ADDC
{ $$
= 0x10; }
1146 | SUB
{ $$
= 0x20; }
1147 | SUBC
{ $$
= 0x30; }
1148 | CMP
{ $$
= 0x40; }
1149 | AND_
{ $$
= 0x50; }
1151 | XOR
{ $$
= 0x70; }
1154 addsubw
: ADDW
{ $$
= 0x00; }
1155 | SUBW
{ $$
= 0x20; }
1156 | CMPW
{ $$
= 0x40; }
1159 andor1
: AND1
{ $$
= 0x05; rl78_bit_insn
= 1; }
1160 | OR1
{ $$
= 0x06; rl78_bit_insn
= 1; }
1161 | XOR1
{ $$
= 0x07; rl78_bit_insn
= 1; }
1164 bt_bf
: BT
{ $$
= 0x02; rl78_bit_insn
= 1; rl78_linkrelax_branch
(); }
1165 | BF
{ $$
= 0x04; rl78_bit_insn
= 1; rl78_linkrelax_branch
(); }
1166 | BTCLR
{ $$
= 0x00; rl78_bit_insn
= 1; }
1169 setclr1
: SET1
{ $$
= 0; rl78_bit_insn
= 1; }
1170 | CLR1
{ $$
= 1; rl78_bit_insn
= 1; }
1173 oneclrb
: ONEB
{ $$
= 0x00; }
1174 | CLRB
{ $$
= 0x10; }
1177 oneclrw
: ONEW
{ $$
= 0x00; }
1178 | CLRW
{ $$
= 0x10; }
1181 incdec
: INC
{ $$
= 0x00; }
1182 | DEC
{ $$
= 0x10; }
1185 incdecw
: INCW
{ $$
= 0x00; }
1186 | DECW
{ $$
= 0x10; }
1189 mov1
: MOV1
{ rl78_bit_insn
= 1; }
1193 /* ====================================================================== */
1197 const char * string;
1237 { "spl", SPL
, 0xf8 },
1238 { "sph", SPH
, 0xf9 },
1239 { "psw", PSW
, 0xfa },
1242 { "pmc", PMC
, 0xfe },
1243 { "mem", MEM
, 0xff },
1250 { ".ub", DOT_UB
, 0 },
1251 { ".uw", DOT_UW
, 0},
1260 #define OPC(x) { #x, x, IS_OPCODE }
1265 { "and", AND_
, IS_OPCODE
},
1346 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1349 rl78_lex_init
(char * beginning
, char * ending
)
1351 rl78_init_start
= beginning
;
1352 rl78_lex_start
= beginning
;
1353 rl78_lex_end
= ending
;
1354 rl78_in_brackets
= 0;
1355 rl78_last_token
= 0;
1362 /* Return a pointer to the '.' in a bit index expression (like
1363 foo.5), or NULL if none is found. */
1365 find_bit_index
(char *tok
)
1367 char *last_dot
= NULL
;
1368 char *last_digit
= NULL
;
1369 while
(*tok
&& *tok
!= ',')
1376 else if
(*tok
>= '0' && *tok
<= '7'
1378 && last_digit
== NULL
)
1382 else if
(ISSPACE
(*tok
))
1393 if
(last_dot
!= NULL
1394 && last_digit
!= NULL
)
1402 /*unsigned int ci;*/
1403 char * save_input_pointer
;
1406 while
(ISSPACE
(*rl78_lex_start
)
1407 && rl78_lex_start
!= rl78_lex_end
)
1410 rl78_last_exp_start
= rl78_lex_start
;
1412 if
(rl78_lex_start
== rl78_lex_end
)
1415 if
(ISALPHA
(*rl78_lex_start
)
1416 ||
(*rl78_lex_start
== '.' && ISALPHA
(rl78_lex_start
[1])))
1422 for
(e
= rl78_lex_start
+ 1;
1423 e
< rl78_lex_end
&& ISALNUM
(*e
);
1429 for
(i
= 0; i
< NUM_TOKENS
; i
++)
1430 if
(strcasecmp
(rl78_lex_start
, token_table
[i
].
string) == 0
1431 && !(token_table
[i
].val
== IS_OPCODE
&& rl78_last_token
!= 0)
1432 && !(token_table
[i
].token
== FLAG
&& !need_flag
))
1434 rl78_lval.regno
= token_table
[i
].val
;
1437 rl78_last_token
= token_table
[i
].token
;
1438 return token_table
[i
].token
;
1443 if
(rl78_last_token
== 0)
1445 rl78_last_token
= UNKNOWN_OPCODE
;
1446 return UNKNOWN_OPCODE
;
1449 if
(rl78_last_token
== UNKNOWN_OPCODE
)
1452 if
(*rl78_lex_start
== '[')
1453 rl78_in_brackets
= 1;
1454 if
(*rl78_lex_start
== ']')
1455 rl78_in_brackets
= 0;
1457 /* '.' is funny - the syntax includes it for bitfields, but only for
1458 bitfields. We check for it specially so we can allow labels
1459 with '.' in them. */
1462 && *rl78_lex_start
== '.'
1463 && find_bit_index
(rl78_lex_start
) == rl78_lex_start
)
1465 rl78_last_token
= *rl78_lex_start
;
1466 return
*rl78_lex_start
++;
1469 if
((rl78_in_brackets
&& *rl78_lex_start
== '+')
1470 || strchr
("[],#!$:", *rl78_lex_start
))
1472 rl78_last_token
= *rl78_lex_start
;
1473 return
*rl78_lex_start
++;
1476 /* Again, '.' is funny. Look for '.<digit>' at the end of the line
1477 or before a comma, which is a bitfield, not an expression. */
1481 bit
= find_bit_index
(rl78_lex_start
);
1488 save_input_pointer
= input_line_pointer
;
1489 input_line_pointer
= rl78_lex_start
;
1490 rl78_lval.exp.X_md
= 0;
1491 expression
(&rl78_lval.exp
);
1496 rl78_lex_start
= input_line_pointer
;
1497 input_line_pointer
= save_input_pointer
;
1498 rl78_last_token
= EXPR
;
1503 rl78_error
(const char * str
)
1507 len
= rl78_last_exp_start
- rl78_init_start
;
1509 as_bad
("%s", rl78_init_start
);
1510 as_bad
("%*s^ %s", len
, "", str
);
1515 expr_is_sfr
(expressionS exp
)
1519 if
(exp.X_op
!= O_constant
)
1522 v
= exp.X_add_number
;
1523 if
(0xFFF00 <= v
&& v
<= 0xFFFFF)
1529 expr_is_saddr
(expressionS exp
)
1533 if
(exp.X_op
!= O_constant
)
1536 v
= exp.X_add_number
;
1537 if
(0xFFE20 <= v
&& v
<= 0xFFF1F)
1543 expr_is_word_aligned
(expressionS exp
)
1547 if
(exp.X_op
!= O_constant
)
1550 v
= exp.X_add_number
;
1558 check_expr_is_bit_index
(expressionS exp
)
1562 if
(exp.X_op
!= O_constant
)
1564 rl78_error
(_
("bit index must be a constant"));
1567 val
= exp.X_add_number
;
1569 if
(val
< 0 || val
> 7)
1570 rl78_error
(_
("rtsd size must be 0..7"));
1574 exp_val
(expressionS exp
)
1576 if
(exp.X_op
!= O_constant
)
1578 rl78_error
(_
("constant expected"));
1581 return exp.X_add_number
;
1585 check_expr_is_const
(expressionS e
, int vmin
, int vmax
)
1587 static char buf
[100];
1588 if
(e.X_op
!= O_constant
1589 || e.X_add_number
< vmin
1590 || e.X_add_number
> vmax
)
1593 sprintf
(buf
, "%d expected here", vmin
);
1595 sprintf
(buf
, "%d..%d expected here", vmin
, vmax
);