1 /* rl78-parse.y Renesas RL78 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"
25 #include "rl78-defs.h"
27 static int rl78_lex (void);
29 /* Ok, here are the rules for using these macros...
31 B*() is used to specify the base opcode bytes. Fields to be filled
32 in later, leave zero. Call this first.
34 F() and FE() are used to fill in fields within the base opcode bytes. You MUST
35 call B*() before any F() or FE().
37 [UN]*O*(), PC*() appends operands to the end of the opcode. You
38 must call P() and B*() before any of these, so that the fixups
39 have the right byte location.
40 O = signed, UO = unsigned, NO = negated, PC = pcrel
42 IMM() adds an immediate and fills in the field for it.
43 NIMM() same, but negates the immediate.
44 NBIMM() same, but negates the immediate, for sbb.
45 DSP() adds a displacement, and fills in the field for it.
47 Note that order is significant for the O, IMM, and DSP macros, as
48 they append their data to the operand buffer in the order that you
51 Use "disp" for displacements whenever possible; this handles the
54 #define B1(b1) rl78_base1 (b1)
55 #define B2(b1, b2) rl78_base2 (b1, b2)
56 #define B3(b1, b2, b3) rl78_base3 (b1, b2, b3)
57 #define B4(b1, b2, b3, b4) rl78_base4 (b1, b2, b3, b4)
59 /* POS is bits from the MSB of the first byte to the LSB of the last byte. */
60 #define F(val,pos,sz) rl78_field (val, pos, sz)
61 #define FE(exp,pos,sz) rl78_field (exp_val (exp), pos, sz);
63 #define O1(v) rl78_op (v, 1, RL78REL_DATA)
64 #define O2(v) rl78_op (v, 2, RL78REL_DATA)
65 #define O3(v) rl78_op (v, 3, RL78REL_DATA)
66 #define O4(v) rl78_op (v, 4, RL78REL_DATA)
68 #define PC1(v) rl78_op (v, 1, RL78REL_PCREL)
69 #define PC2(v) rl78_op (v, 2, RL78REL_PCREL)
70 #define PC3(v) rl78_op (v, 3, RL78REL_PCREL)
72 #define IMM(v,pos) F (immediate (v, RL78REL_SIGNED, pos), pos, 2); \
73 if (v.X_op != O_constant && v.X_op != O_big) rl78_linkrelax_imm (pos)
74 #define NIMM(v,pos) F (immediate (v, RL78REL_NEGATIVE, pos), pos, 2)
75 #define NBIMM(v,pos) F (immediate (v, RL78REL_NEGATIVE_BORROW, pos), pos, 2)
76 #define DSP(v,pos,msz) if (!v.X_md) rl78_relax (RL78_RELAX_DISP, pos); \
77 else rl78_linkrelax_dsp (pos); \
78 F (displacement (v, msz), pos, 2)
80 #define id24(a,b2,b3) B3 (0xfb+a, b2, b3)
82 static int expr_is_sfr (expressionS);
83 static int expr_is_saddr (expressionS);
84 static int expr_is_word_aligned (expressionS);
85 static int exp_val (expressionS exp);
87 static int need_flag = 0;
88 static int rl78_in_brackets = 0;
89 static int rl78_last_token = 0;
90 static char * rl78_init_start;
91 static char * rl78_last_exp_start = 0;
92 static int rl78_bit_insn = 0;
95 #define YYERROR_VERBOSE 1
97 #define NOT_SADDR rl78_error ("Expression not 0xFFE20 to 0xFFF1F")
98 #define SA(e) if (!expr_is_saddr (e)) NOT_SADDR;
100 #define NOT_SFR rl78_error ("Expression not 0xFFF00 to 0xFFFFF")
101 #define SFR(e) if (!expr_is_sfr (e)) NOT_SFR;
103 #define NOT_SFR_OR_SADDR rl78_error ("Expression not 0xFFE20 to 0xFFFFF")
105 #define NOT_ES if (rl78_has_prefix()) rl78_error ("ES: prefix not allowed here");
107 #define WA(x) if (!expr_is_word_aligned (x)) rl78_error ("Expression not word-aligned");
109 static void check_expr_is_bit_index (expressionS);
110 #define Bit(e) check_expr_is_bit_index (e);
112 /* Returns TRUE (non-zero) if the expression is a constant in the
114 static int check_expr_is_const (expressionS, int vmin, int vmax);
116 /* Convert a "regb" value to a "reg_xbc" value. Error if other
117 registers are passed. Needed to avoid reduce-reduce conflicts. */
130 rl78_error ("Only X, B, or C allowed here");
144 %type <regno> regb regb_na regw regw_na FLAG sfr
145 %type <regno> A X B C D E H L AX BC DE HL
148 %type <regno> addsub addsubw andor1 bt_bf setclr1 oneclrb oneclrw
149 %type <regno> incdec incdecw
151 %token A X B C D E H L AX BC DE HL
152 %token SPL SPH PSW CS ES PMC MEM
154 %token RB0 RB1 RB2 RB3
156 %token EXPR UNKNOWN_OPCODE IS_OPCODE
158 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
160 %token ADD ADDC ADDW AND_ AND1
161 /* BC is also a register pair */
162 %token BF BH BNC BNH BNZ BR BRK BRK1 BT BTCLR BZ
163 %token CALL CALLT CLR1 CLRB CLRW CMP CMP0 CMPS CMPW
164 %token DEC DECW DI DIVHU DIVWU
168 %token MACH MACHU MOV MOV1 MOVS MOVW MULH MULHU MULU
170 %token ONEB ONEW OR OR1
172 %token RET RETI RETB ROL ROLC ROLWC ROR RORC
173 %token SAR SARW SEL SET1 SHL SHLW SHR SHRW
174 %token SKC SKH SKNC SKNH SKNZ SKZ STOP SUB SUBC SUBW
175 %token XCH XCHW XOR XOR1
178 /* ====================================================================== */
183 { as_bad (_("Unknown opcode: %s"), rl78_init_start); }
185 /* The opcodes are listed in approximately alphabetical order. */
189 sfr = special function register - symbol, 0xFFF00 to 0xFFFFF
190 sfrp = special function register - symbol, 0xFFF00 to 0xFFFFE, even only
191 saddr = 0xFFE20 to 0xFFF1F
192 saddrp = 0xFFE20 to 0xFFF1E, even only
194 addr20 = 0x00000 to 0xFFFFF
195 addr16 = 0x00000 to 0x0FFFF, even only for 16-bit ops
196 addr5 = 0x00000 to 0x000BE, even only
199 /* ---------------------------------------------------------------------- */
201 /* addsub is ADD, ADDC, SUB, SUBC, AND, OR, XOR, and parts of CMP. */
203 | addsub A ',' '#' EXPR
204 { B1 (0x0c|$1); O1 ($5); }
206 | addsub EXPR {SA($2)} ',' '#' EXPR
207 { B1 (0x0a|$1); O1 ($2); O1 ($6); }
210 { B2 (0x61, 0x01|$1); }
212 | addsub A ',' regb_na
213 { B2 (0x61, 0x08|$1); F ($4, 13, 3); }
215 | addsub regb_na ',' A
216 { B2 (0x61, 0x00|$1); F ($2, 13, 3); }
218 | addsub A ',' EXPR {SA($4)}
219 { B1 (0x0b|$1); O1 ($4); }
221 | addsub A ',' opt_es '!' EXPR
222 { B1 (0x0f|$1); O2 ($6); rl78_linkrelax_addr16 (); }
224 | addsub A ',' opt_es '[' HL ']'
227 | addsub A ',' opt_es '[' HL '+' EXPR ']'
228 { B1 (0x0e|$1); O1 ($8); }
230 | addsub A ',' opt_es '[' HL '+' B ']'
231 { B2 (0x61, 0x80|$1); }
233 | addsub A ',' opt_es '[' HL '+' C ']'
234 { B2 (0x61, 0x82|$1); }
238 | addsub opt_es '!' EXPR ',' '#' EXPR
240 { rl78_error ("Only CMP takes these operands"); }
242 { B1 (0x00|$1); O2 ($4); O1 ($7); rl78_linkrelax_addr16 (); }
245 /* ---------------------------------------------------------------------- */
247 | addsubw AX ',' '#' EXPR
248 { B1 (0x04|$1); O2 ($5); }
250 | addsubw AX ',' regw
251 { B1 (0x01|$1); F ($4, 5, 2); }
253 | addsubw AX ',' EXPR {SA($4)}
254 { B1 (0x06|$1); O1 ($4); }
256 | addsubw AX ',' opt_es '!' EXPR
257 { B1 (0x02|$1); O2 ($6); rl78_linkrelax_addr16 (); }
259 | addsubw AX ',' opt_es '[' HL '+' EXPR ']'
260 { B2 (0x61, 0x09|$1); O1 ($8); }
262 | addsubw AX ',' opt_es '[' HL ']'
263 { B4 (0x61, 0x09|$1, 0, 0); }
265 | addsubw SP ',' '#' EXPR
266 { B1 ($1 ? 0x20 : 0x10); O1 ($5);
268 rl78_error ("CMPW SP,#imm not allowed");
271 /* ---------------------------------------------------------------------- */
273 | andor1 CY ',' sfr '.' EXPR {Bit($6)}
274 { B3 (0x71, 0x08|$1, $4); FE ($6, 9, 3); }
276 | andor1 CY ',' EXPR '.' EXPR {Bit($6)}
277 { if (expr_is_sfr ($4))
278 { B2 (0x71, 0x08|$1); FE ($6, 9, 3); O1 ($4); }
279 else if (expr_is_saddr ($4))
280 { B2 (0x71, 0x00|$1); FE ($6, 9, 3); O1 ($4); }
285 | andor1 CY ',' A '.' EXPR {Bit($6)}
286 { B2 (0x71, 0x88|$1); FE ($6, 9, 3); }
288 | andor1 CY ',' opt_es '[' HL ']' '.' EXPR {Bit($9)}
289 { B2 (0x71, 0x80|$1); FE ($9, 9, 3); }
291 /* ---------------------------------------------------------------------- */
294 { B1 (0xdc); PC1 ($3); }
297 { B1 (0xde); PC1 ($3); }
300 { B1 (0xdd); PC1 ($3); }
303 { B1 (0xdf); PC1 ($3); }
306 { B2 (0x61, 0xc3); PC1 ($3); }
309 { B2 (0x61, 0xd3); PC1 ($3); }
311 /* ---------------------------------------------------------------------- */
313 | bt_bf sfr '.' EXPR ',' '$' EXPR
314 { B3 (0x31, 0x80|$1, $2); FE ($4, 9, 3); PC1 ($7); }
316 | bt_bf EXPR '.' EXPR ',' '$' EXPR
317 { if (expr_is_sfr ($2))
318 { B2 (0x31, 0x80|$1); FE ($4, 9, 3); O1 ($2); PC1 ($7); }
319 else if (expr_is_saddr ($2))
320 { B2 (0x31, 0x00|$1); FE ($4, 9, 3); O1 ($2); PC1 ($7); }
325 | bt_bf A '.' EXPR ',' '$' EXPR
326 { B2 (0x31, 0x01|$1); FE ($4, 9, 3); PC1 ($7); }
328 | bt_bf opt_es '[' HL ']' '.' EXPR ',' '$' EXPR
329 { B2 (0x31, 0x81|$1); FE ($7, 9, 3); PC1 ($10); }
331 /* ---------------------------------------------------------------------- */
337 { B1 (0xef); PC1 ($3); }
340 { B1 (0xee); PC2 ($4); rl78_linkrelax_branch (); }
343 { B1 (0xed); O2 ($3); rl78_linkrelax_branch (); }
346 { B1 (0xec); O3 ($4); rl78_linkrelax_branch (); }
348 /* ---------------------------------------------------------------------- */
356 /* ---------------------------------------------------------------------- */
359 { B2 (0x61, 0xca); F ($2, 10, 2); }
362 { B1 (0xfe); PC2 ($4); }
365 { B1 (0xfd); O2 ($3); }
368 { B1 (0xfc); O3 ($4); rl78_linkrelax_branch (); }
371 { if ($3.X_op != O_constant)
372 rl78_error ("CALLT requires a numeric address");
375 int i = $3.X_add_number;
376 if (i < 0x80 || i > 0xbe)
377 rl78_error ("CALLT address not 0x80..0xbe");
379 rl78_error ("CALLT address not even");
383 F ((i >> 1) & 7, 9, 3);
384 F ((i >> 4) & 7, 14, 2);
389 /* ---------------------------------------------------------------------- */
392 { B2 (0x71, $1 ? 0x88 : 0x80); }
394 | setclr1 sfr '.' EXPR
395 { B3 (0x71, 0x0a|$1, $2); FE ($4, 9, 3); }
397 | setclr1 EXPR '.' EXPR
398 { if (expr_is_sfr ($2))
399 { B2 (0x71, 0x0a|$1); FE ($4, 9, 3); O1 ($2); }
400 else if (expr_is_saddr ($2))
401 { B2 (0x71, 0x02|$1); FE ($4, 9, 3); O1 ($2); }
407 { B2 (0x71, 0x8a|$1); FE ($4, 9, 3); }
409 | setclr1 opt_es '!' EXPR '.' EXPR
410 { B2 (0x71, 0x00+$1*0x08); FE ($6, 9, 3); O2 ($4); rl78_linkrelax_addr16 (); }
412 | setclr1 opt_es '[' HL ']' '.' EXPR
413 { B2 (0x71, 0x82|$1); FE ($7, 9, 3); }
415 /* ---------------------------------------------------------------------- */
426 | oneclrb EXPR {SA($2)}
427 { B1 (0xe4|$1); O1 ($2); }
429 | oneclrb opt_es '!' EXPR
430 { B1 (0xe5|$1); O2 ($4); rl78_linkrelax_addr16 (); }
432 /* ---------------------------------------------------------------------- */
439 /* ---------------------------------------------------------------------- */
454 { B1 (0xd4); O1 ($2); }
456 | CMP0 opt_es '!' EXPR
457 { B1 (0xd5); O2 ($4); rl78_linkrelax_addr16 (); }
459 /* ---------------------------------------------------------------------- */
461 | CMPS X ',' opt_es '[' HL '+' EXPR ']'
462 { B2 (0x61, 0xde); O1 ($8); }
464 /* ---------------------------------------------------------------------- */
467 { B1 (0x80|$1); F ($2, 5, 3); }
469 | incdec EXPR {SA($2)}
470 { B1 (0xa4|$1); O1 ($2); }
472 { B1 (0xa0|$1); O2 ($3); rl78_linkrelax_addr16 (); }
473 | incdec ES ':' '!' EXPR
474 { B2 (0x11, 0xa0|$1); O2 ($5); }
475 | incdec '[' HL '+' EXPR ']'
476 { B2 (0x61, 0x59+$1); O1 ($5); }
477 | incdec ES ':' '[' HL '+' EXPR ']'
478 { B3 (0x11, 0x61, 0x59+$1); O1 ($7); }
480 /* ---------------------------------------------------------------------- */
483 { B1 (0xa1|$1); F ($2, 5, 2); }
485 | incdecw EXPR {SA($2)}
486 { B1 (0xa6|$1); O1 ($2); }
488 | incdecw opt_es '!' EXPR
489 { B1 (0xa2|$1); O2 ($4); rl78_linkrelax_addr16 (); }
491 | incdecw opt_es '[' HL '+' EXPR ']'
492 { B2 (0x61, 0x79+$1); O1 ($6); }
494 /* ---------------------------------------------------------------------- */
497 { B3 (0x71, 0x7b, 0xfa); }
500 { B3 (0x71, 0x7a, 0xfa); }
502 /* ---------------------------------------------------------------------- */
505 { B3 (0xce, 0xfb, 0x01); }
508 { B3 (0xce, 0xfb, 0x02); }
514 { B3 (0xce, 0xfb, 0x03); }
517 { B3 (0xce, 0xfb, 0x04); }
520 { B3 (0xce, 0xfb, 0x05); }
523 { B3 (0xce, 0xfb, 0x06); }
525 /* ---------------------------------------------------------------------- */
530 /* ---------------------------------------------------------------------- */
531 /* Note that opt_es is included even when it's not an option, to avoid
532 shift/reduce conflicts. The NOT_ES macro produces an error if ES:
533 is given by the user. */
536 { B1 (0x51); O1 ($5); }
537 | MOV regb_na ',' '#' EXPR
538 { B1 (0x50); F($2, 5, 3); O1 ($5); }
540 | MOV sfr ',' '#' EXPR
542 { B2 (0xce, $2); O1 ($5); }
544 { B1 (0x41); O1 ($5); }
547 | MOV opt_es EXPR ',' '#' EXPR {NOT_ES}
548 { if (expr_is_sfr ($3))
549 { B1 (0xce); O1 ($3); O1 ($6); }
550 else if (expr_is_saddr ($3))
551 { B1 (0xcd); O1 ($3); O1 ($6); }
556 | MOV '!' EXPR ',' '#' EXPR
557 { B1 (0xcf); O2 ($3); O1 ($6); rl78_linkrelax_addr16 (); }
559 | MOV ES ':' '!' EXPR ',' '#' EXPR
560 { B2 (0x11, 0xcf); O2 ($5); O1 ($8); }
563 { B1 (0x70); F ($2, 5, 3); }
566 { B1 (0x60); F ($4, 5, 3); }
568 | MOV opt_es EXPR ',' A {NOT_ES}
569 { if (expr_is_sfr ($3))
570 { B1 (0x9e); O1 ($3); }
571 else if (expr_is_saddr ($3))
572 { B1 (0x9d); O1 ($3); }
577 | MOV A ',' opt_es '!' EXPR
578 { B1 (0x8f); O2 ($6); rl78_linkrelax_addr16 (); }
581 { B1 (0x9f); O2 ($3); rl78_linkrelax_addr16 (); }
583 | MOV ES ':' '!' EXPR ',' A
584 { B2 (0x11, 0x9f); O2 ($5); }
586 | MOV regb_na ',' opt_es '!' EXPR
587 { B1 (0xc9|reg_xbc($2)); O2 ($6); rl78_linkrelax_addr16 (); }
589 | MOV A ',' opt_es EXPR {NOT_ES}
590 { if (expr_is_saddr ($5))
591 { B1 (0x8d); O1 ($5); }
592 else if (expr_is_sfr ($5))
593 { B1 (0x8e); O1 ($5); }
598 | MOV regb_na ',' opt_es EXPR {SA($5)} {NOT_ES}
599 { B1 (0xc8|reg_xbc($2)); O1 ($5); }
606 rl78_error ("Only A allowed here");
611 | MOV sfr ',' opt_es EXPR {SA($5)} {NOT_ES}
613 rl78_error ("Only ES allowed here");
615 { B2 (0x61, 0xb8); O1 ($5); }
618 | MOV A ',' opt_es '[' DE ']'
621 | MOV opt_es '[' DE ']' ',' A
624 | MOV opt_es '[' DE '+' EXPR ']' ',' '#' EXPR
625 { B1 (0xca); O1 ($6); O1 ($10); }
627 | MOV A ',' opt_es '[' DE '+' EXPR ']'
628 { B1 (0x8a); O1 ($8); }
630 | MOV opt_es '[' DE '+' EXPR ']' ',' A
631 { B1 (0x9a); O1 ($6); }
633 | MOV A ',' opt_es '[' HL ']'
636 | MOV opt_es '[' HL ']' ',' A
639 | MOV opt_es '[' HL '+' EXPR ']' ',' '#' EXPR
640 { B1 (0xcc); O1 ($6); O1 ($10); }
642 | MOV A ',' opt_es '[' HL '+' EXPR ']'
643 { B1 (0x8c); O1 ($8); }
645 | MOV opt_es '[' HL '+' EXPR ']' ',' A
646 { B1 (0x9c); O1 ($6); }
648 | MOV A ',' opt_es '[' HL '+' B ']'
651 | MOV opt_es '[' HL '+' B ']' ',' A
654 | MOV A ',' opt_es '[' HL '+' C ']'
657 | MOV opt_es '[' HL '+' C ']' ',' A
660 | MOV opt_es EXPR '[' B ']' ',' '#' EXPR
661 { B1 (0x19); O2 ($3); O1 ($9); }
663 | MOV A ',' opt_es EXPR '[' B ']'
664 { B1 (0x09); O2 ($5); }
666 | MOV opt_es EXPR '[' B ']' ',' A
667 { B1 (0x18); O2 ($3); }
669 | MOV opt_es EXPR '[' C ']' ',' '#' EXPR
670 { B1 (0x38); O2 ($3); O1 ($9); }
672 | MOV A ',' opt_es EXPR '[' C ']'
673 { B1 (0x29); O2 ($5); }
675 | MOV opt_es EXPR '[' C ']' ',' A
676 { B1 (0x28); O2 ($3); }
678 | MOV opt_es EXPR '[' BC ']' ',' '#' EXPR
679 { B1 (0x39); O2 ($3); O1 ($9); }
681 | MOV opt_es '[' BC ']' ',' '#' EXPR
682 { B3 (0x39, 0, 0); O1 ($8); }
684 | MOV A ',' opt_es EXPR '[' BC ']'
685 { B1 (0x49); O2 ($5); }
687 | MOV A ',' opt_es '[' BC ']'
690 | MOV opt_es EXPR '[' BC ']' ',' A
691 { B1 (0x48); O2 ($3); }
693 | MOV opt_es '[' BC ']' ',' A
696 | MOV opt_es '[' SP '+' EXPR ']' ',' '#' EXPR {NOT_ES}
697 { B1 (0xc8); O1 ($6); O1 ($10); }
699 | MOV opt_es '[' SP ']' ',' '#' EXPR {NOT_ES}
700 { B2 (0xc8, 0); O1 ($8); }
702 | MOV A ',' opt_es '[' SP '+' EXPR ']' {NOT_ES}
703 { B1 (0x88); O1 ($8); }
705 | MOV A ',' opt_es '[' SP ']' {NOT_ES}
708 | MOV opt_es '[' SP '+' EXPR ']' ',' A {NOT_ES}
709 { B1 (0x98); O1 ($6); }
711 | MOV opt_es '[' SP ']' ',' A {NOT_ES}
714 /* ---------------------------------------------------------------------- */
716 | mov1 CY ',' EXPR '.' EXPR
717 { if (expr_is_saddr ($4))
718 { B2 (0x71, 0x04); FE ($6, 9, 3); O1 ($4); }
719 else if (expr_is_sfr ($4))
720 { B2 (0x71, 0x0c); FE ($6, 9, 3); O1 ($4); }
725 | mov1 CY ',' A '.' EXPR
726 { B2 (0x71, 0x8c); FE ($6, 9, 3); }
728 | mov1 CY ',' sfr '.' EXPR
729 { B3 (0x71, 0x0c, $4); FE ($6, 9, 3); }
731 | mov1 CY ',' opt_es '[' HL ']' '.' EXPR
732 { B2 (0x71, 0x84); FE ($9, 9, 3); }
734 | mov1 EXPR '.' EXPR ',' CY
735 { if (expr_is_saddr ($2))
736 { B2 (0x71, 0x01); FE ($4, 9, 3); O1 ($2); }
737 else if (expr_is_sfr ($2))
738 { B2 (0x71, 0x09); FE ($4, 9, 3); O1 ($2); }
743 | mov1 A '.' EXPR ',' CY
744 { B2 (0x71, 0x89); FE ($4, 9, 3); }
746 | mov1 sfr '.' EXPR ',' CY
747 { B3 (0x71, 0x09, $2); FE ($4, 9, 3); }
749 | mov1 opt_es '[' HL ']' '.' EXPR ',' CY
750 { B2 (0x71, 0x81); FE ($7, 9, 3); }
752 /* ---------------------------------------------------------------------- */
754 | MOVS opt_es '[' HL '+' EXPR ']' ',' X
755 { B2 (0x61, 0xce); O1 ($6); }
757 /* ---------------------------------------------------------------------- */
759 | MOVW AX ',' '#' EXPR
760 { B1 (0x30); O2 ($5); }
762 | MOVW regw_na ',' '#' EXPR
763 { B1 (0x30); F ($2, 5, 2); O2 ($5); }
765 | MOVW opt_es EXPR ',' '#' EXPR {NOT_ES}
766 { if (expr_is_saddr ($3))
767 { B1 (0xc9); O1 ($3); O2 ($6); }
768 else if (expr_is_sfr ($3))
769 { B1 (0xcb); O1 ($3); O2 ($6); }
774 | MOVW AX ',' opt_es EXPR {NOT_ES}
775 { if (expr_is_saddr ($5))
776 { B1 (0xad); O1 ($5); WA($5); }
777 else if (expr_is_sfr ($5))
778 { B1 (0xae); O1 ($5); WA($5); }
783 | MOVW opt_es EXPR ',' AX {NOT_ES}
784 { if (expr_is_saddr ($3))
785 { B1 (0xbd); O1 ($3); WA($3); }
786 else if (expr_is_sfr ($3))
787 { B1 (0xbe); O1 ($3); WA($3); }
792 | MOVW AX ',' regw_na
793 { B1 (0x11); F ($4, 5, 2); }
795 | MOVW regw_na ',' AX
796 { B1 (0x10); F ($2, 5, 2); }
798 | MOVW AX ',' opt_es '!' EXPR
799 { B1 (0xaf); O2 ($6); WA($6); rl78_linkrelax_addr16 (); }
801 | MOVW opt_es '!' EXPR ',' AX
802 { B1 (0xbf); O2 ($4); WA($4); rl78_linkrelax_addr16 (); }
804 | MOVW AX ',' opt_es '[' DE ']'
807 | MOVW opt_es '[' DE ']' ',' AX
810 | MOVW AX ',' opt_es '[' DE '+' EXPR ']'
811 { B1 (0xaa); O1 ($8); }
813 | MOVW opt_es '[' DE '+' EXPR ']' ',' AX
814 { B1 (0xba); O1 ($6); }
816 | MOVW AX ',' opt_es '[' HL ']'
819 | MOVW opt_es '[' HL ']' ',' AX
822 | MOVW AX ',' opt_es '[' HL '+' EXPR ']'
823 { B1 (0xac); O1 ($8); }
825 | MOVW opt_es '[' HL '+' EXPR ']' ',' AX
826 { B1 (0xbc); O1 ($6); }
828 | MOVW AX ',' opt_es EXPR '[' B ']'
829 { B1 (0x59); O2 ($5); }
831 | MOVW opt_es EXPR '[' B ']' ',' AX
832 { B1 (0x58); O2 ($3); }
834 | MOVW AX ',' opt_es EXPR '[' C ']'
835 { B1 (0x69); O2 ($5); }
837 | MOVW opt_es EXPR '[' C ']' ',' AX
838 { B1 (0x68); O2 ($3); }
840 | MOVW AX ',' opt_es EXPR '[' BC ']'
841 { B1 (0x79); O2 ($5); }
843 | MOVW AX ',' opt_es '[' BC ']'
846 | MOVW opt_es EXPR '[' BC ']' ',' AX
847 { B1 (0x78); O2 ($3); }
849 | MOVW opt_es '[' BC ']' ',' AX
852 | MOVW AX ',' opt_es '[' SP '+' EXPR ']' {NOT_ES}
853 { B1 (0xa8); O1 ($8); WA($8);}
855 | MOVW AX ',' opt_es '[' SP ']' {NOT_ES}
858 | MOVW opt_es '[' SP '+' EXPR ']' ',' AX {NOT_ES}
859 { B1 (0xb8); O1 ($6); WA($6); }
861 | MOVW opt_es '[' SP ']' ',' AX {NOT_ES}
864 | MOVW regw_na ',' EXPR {SA($4)}
865 { B1 (0xca); F ($2, 2, 2); O1 ($4); WA($4); }
867 | MOVW regw_na ',' opt_es '!' EXPR
868 { B1 (0xcb); F ($2, 2, 2); O2 ($6); WA($6); rl78_linkrelax_addr16 (); }
870 | MOVW SP ',' '#' EXPR
871 { B2 (0xcb, 0xf8); O2 ($5); }
879 | MOVW regw_na ',' SP
880 { B3 (0xcb, 0xf8, 0xff); F ($2, 2, 2); }
882 /* ---------------------------------------------------------------------- */
887 /* ---------------------------------------------------------------------- */
890 { B1 (0xc0); F ($2, 5, 2); }
893 { B2 (0x61, 0xcd); };
896 { B1 (0xc1); F ($2, 5, 2); }
899 { B2 (0x61, 0xdd); };
901 /* ---------------------------------------------------------------------- */
912 /* ---------------------------------------------------------------------- */
915 { if (check_expr_is_const ($4, 1, 1))
920 { if (check_expr_is_const ($4, 1, 1))
925 { if (check_expr_is_const ($4, 1, 1))
930 { if (check_expr_is_const ($4, 1, 1))
935 { if (check_expr_is_const ($4, 1, 1))
940 { if (check_expr_is_const ($4, 1, 1))
944 /* ---------------------------------------------------------------------- */
947 { if (check_expr_is_const ($4, 1, 7))
948 { B2 (0x31, 0x0b); FE ($4, 9, 3); }
952 { if (check_expr_is_const ($4, 1, 15))
953 { B2 (0x31, 0x0f); FE ($4, 8, 4); }
956 /* ---------------------------------------------------------------------- */
970 /* ---------------------------------------------------------------------- */
973 { if (check_expr_is_const ($4, 1, 7))
974 { B2 (0x31, 0x09); FE ($4, 9, 3); }
978 { if (check_expr_is_const ($4, 1, 7))
979 { B2 (0x31, 0x08); FE ($4, 9, 3); }
983 { if (check_expr_is_const ($4, 1, 7))
984 { B2 (0x31, 0x07); FE ($4, 9, 3); }
988 { if (check_expr_is_const ($4, 1, 15))
989 { B2 (0x31, 0x0d); FE ($4, 8, 4); }
993 { if (check_expr_is_const ($4, 1, 15))
994 { B2 (0x31, 0x0c); FE ($4, 8, 4); }
997 /* ---------------------------------------------------------------------- */
1000 { if (check_expr_is_const ($4, 1, 7))
1001 { B2 (0x31, 0x0a); FE ($4, 9, 3); }
1005 { if (check_expr_is_const ($4, 1, 15))
1006 { B2 (0x31, 0x0e); FE ($4, 8, 4); }
1009 /* ---------------------------------------------------------------------- */
1012 { B2 (0x61, 0xc8); rl78_linkrelax_branch (); }
1015 { B2 (0x61, 0xe3); rl78_linkrelax_branch (); }
1018 { B2 (0x61, 0xd8); rl78_linkrelax_branch (); }
1021 { B2 (0x61, 0xf3); rl78_linkrelax_branch (); }
1024 { B2 (0x61, 0xf8); rl78_linkrelax_branch (); }
1027 { B2 (0x61, 0xe8); rl78_linkrelax_branch (); }
1029 /* ---------------------------------------------------------------------- */
1032 { B2 (0x61, 0xfd); }
1034 /* ---------------------------------------------------------------------- */
1037 { if ($4 == 0) /* X */
1040 { B2 (0x61, 0x88); F ($4, 13, 3); }
1043 | XCH A ',' opt_es '!' EXPR
1044 { B2 (0x61, 0xaa); O2 ($6); rl78_linkrelax_addr16 (); }
1046 | XCH A ',' opt_es '[' DE ']'
1047 { B2 (0x61, 0xae); }
1049 | XCH A ',' opt_es '[' DE '+' EXPR ']'
1050 { B2 (0x61, 0xaf); O1 ($8); }
1052 | XCH A ',' opt_es '[' HL ']'
1053 { B2 (0x61, 0xac); }
1055 | XCH A ',' opt_es '[' HL '+' EXPR ']'
1056 { B2 (0x61, 0xad); O1 ($8); }
1058 | XCH A ',' opt_es '[' HL '+' B ']'
1059 { B2 (0x61, 0xb9); }
1061 | XCH A ',' opt_es '[' HL '+' C ']'
1062 { B2 (0x61, 0xa9); }
1065 { if (expr_is_sfr ($4))
1066 { B2 (0x61, 0xab); O1 ($4); }
1067 else if (expr_is_saddr ($4))
1068 { B2 (0x61, 0xa8); O1 ($4); }
1073 /* ---------------------------------------------------------------------- */
1075 | XCHW AX ',' regw_na
1076 { B1 (0x31); F ($4, 5, 2); }
1078 /* ---------------------------------------------------------------------- */
1080 ; /* end of statement */
1082 /* ---------------------------------------------------------------------- */
1084 opt_es : /* nothing */
1086 { rl78_prefix (0x11); }
1089 regb : X { $$ = 0; }
1099 regb_na : X { $$ = 0; }
1108 regw : AX { $$ = 0; }
1114 regw_na : BC { $$ = 1; }
1119 sfr : SPL { $$ = 0xf8; }
1120 | SPH { $$ = 0xf9; }
1121 | PSW { $$ = 0xfa; }
1124 | PMC { $$ = 0xfe; }
1125 | MEM { $$ = 0xff; }
1128 /* ---------------------------------------------------------------------- */
1129 /* Shortcuts for groups of opcodes with common encodings. */
1131 addsub : ADD { $$ = 0x00; }
1132 | ADDC { $$ = 0x10; }
1133 | SUB { $$ = 0x20; }
1134 | SUBC { $$ = 0x30; }
1135 | CMP { $$ = 0x40; }
1136 | AND_ { $$ = 0x50; }
1138 | XOR { $$ = 0x70; }
1141 addsubw : ADDW { $$ = 0x00; }
1142 | SUBW { $$ = 0x20; }
1143 | CMPW { $$ = 0x40; }
1146 andor1 : AND1 { $$ = 0x05; rl78_bit_insn = 1; }
1147 | OR1 { $$ = 0x06; rl78_bit_insn = 1;}
1148 | XOR1 { $$ = 0x07; rl78_bit_insn = 1; }
1151 bt_bf : BT { $$ = 0x02; rl78_bit_insn = 1;}
1152 | BF { $$ = 0x04; rl78_bit_insn = 1; }
1153 | BTCLR { $$ = 0x00; rl78_bit_insn = 1; }
1156 setclr1 : SET1 { $$ = 0; rl78_bit_insn = 1; }
1157 | CLR1 { $$ = 1; rl78_bit_insn = 1; }
1160 oneclrb : ONEB { $$ = 0x00; }
1161 | CLRB { $$ = 0x10; }
1164 oneclrw : ONEW { $$ = 0x00; }
1165 | CLRW { $$ = 0x10; }
1168 incdec : INC { $$ = 0x00; }
1169 | DEC { $$ = 0x10; }
1172 incdecw : INCW { $$ = 0x00; }
1173 | DECW { $$ = 0x10; }
1176 mov1 : MOV1 { rl78_bit_insn = 1; }
1180 /* ====================================================================== */
1184 const char * string;
1224 { "spl", SPL, 0xf8 },
1225 { "sph", SPH, 0xf9 },
1226 { "psw", PSW, 0xfa },
1229 { "pmc", PMC, 0xfe },
1230 { "mem", MEM, 0xff },
1237 { ".ub", DOT_UB, 0 },
1238 { ".uw", DOT_UW , 0},
1247 #define OPC(x) { #x, x, IS_OPCODE }
1252 { "and", AND_, IS_OPCODE },
1332 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1335 rl78_lex_init (char * beginning, char * ending)
1337 rl78_init_start = beginning;
1338 rl78_lex_start = beginning;
1339 rl78_lex_end = ending;
1340 rl78_in_brackets = 0;
1341 rl78_last_token = 0;
1348 /* Return a pointer to the '.' in a bit index expression (like
1349 foo.5), or NULL if none is found. */
1351 find_bit_index (char *tok)
1353 char *last_dot = NULL;
1354 char *last_digit = NULL;
1355 while (*tok && *tok != ',')
1362 else if (*tok >= '0' && *tok <= '7'
1364 && last_digit == NULL)
1368 else if (ISSPACE (*tok))
1379 if (last_dot != NULL
1380 && last_digit != NULL)
1388 /*unsigned int ci;*/
1389 char * save_input_pointer;
1392 while (ISSPACE (*rl78_lex_start)
1393 && rl78_lex_start != rl78_lex_end)
1396 rl78_last_exp_start = rl78_lex_start;
1398 if (rl78_lex_start == rl78_lex_end)
1401 if (ISALPHA (*rl78_lex_start)
1402 || (*rl78_lex_start == '.' && ISALPHA (rl78_lex_start[1])))
1408 for (e = rl78_lex_start + 1;
1409 e < rl78_lex_end && ISALNUM (*e);
1415 for (i = 0; i < NUM_TOKENS; i++)
1416 if (strcasecmp (rl78_lex_start, token_table[i].string) == 0
1417 && !(token_table[i].val == IS_OPCODE && rl78_last_token != 0)
1418 && !(token_table[i].token == FLAG && !need_flag))
1420 rl78_lval.regno = token_table[i].val;
1423 rl78_last_token = token_table[i].token;
1424 return token_table[i].token;
1429 if (rl78_last_token == 0)
1431 rl78_last_token = UNKNOWN_OPCODE;
1432 return UNKNOWN_OPCODE;
1435 if (rl78_last_token == UNKNOWN_OPCODE)
1438 if (*rl78_lex_start == '[')
1439 rl78_in_brackets = 1;
1440 if (*rl78_lex_start == ']')
1441 rl78_in_brackets = 0;
1443 /* '.' is funny - the syntax includes it for bitfields, but only for
1444 bitfields. We check for it specially so we can allow labels
1445 with '.' in them. */
1448 && *rl78_lex_start == '.'
1449 && find_bit_index (rl78_lex_start) == rl78_lex_start)
1451 rl78_last_token = *rl78_lex_start;
1452 return *rl78_lex_start ++;
1455 if ((rl78_in_brackets && *rl78_lex_start == '+')
1456 || strchr ("[],#!$:", *rl78_lex_start))
1458 rl78_last_token = *rl78_lex_start;
1459 return *rl78_lex_start ++;
1462 /* Again, '.' is funny. Look for '.<digit>' at the end of the line
1463 or before a comma, which is a bitfield, not an expression. */
1467 bit = find_bit_index (rl78_lex_start);
1474 save_input_pointer = input_line_pointer;
1475 input_line_pointer = rl78_lex_start;
1476 rl78_lval.exp.X_md = 0;
1477 expression (&rl78_lval.exp);
1482 rl78_lex_start = input_line_pointer;
1483 input_line_pointer = save_input_pointer;
1484 rl78_last_token = EXPR;
1489 rl78_error (const char * str)
1493 len = rl78_last_exp_start - rl78_init_start;
1495 as_bad ("%s", rl78_init_start);
1496 as_bad ("%*s^ %s", len, "", str);
1501 expr_is_sfr (expressionS exp)
1505 if (exp.X_op != O_constant)
1508 v = exp.X_add_number;
1509 if (0xFFF00 <= v && v <= 0xFFFFF)
1515 expr_is_saddr (expressionS exp)
1519 if (exp.X_op != O_constant)
1522 v = exp.X_add_number;
1523 if (0xFFE20 <= v && v <= 0xFFF1F)
1529 expr_is_word_aligned (expressionS exp)
1533 if (exp.X_op != O_constant)
1536 v = exp.X_add_number;
1544 check_expr_is_bit_index (expressionS exp)
1548 if (exp.X_op != O_constant)
1550 rl78_error (_("bit index must be a constant"));
1553 val = exp.X_add_number;
1555 if (val < 0 || val > 7)
1556 rl78_error (_("rtsd size must be 0..7"));
1560 exp_val (expressionS exp)
1562 if (exp.X_op != O_constant)
1564 rl78_error (_("constant expected"));
1567 return exp.X_add_number;
1571 check_expr_is_const (expressionS e, int vmin, int vmax)
1573 static char buf[100];
1574 if (e.X_op != O_constant
1575 || e.X_add_number < vmin
1576 || e.X_add_number > vmax)
1579 sprintf (buf, "%d expected here", vmin);
1581 sprintf (buf, "%d..%d expected here", vmin, vmax);