1 /* rl78-parse.y Renesas RL78 parser
2 Copyright (C) 2011-2014 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 NOT_SFR rl78_error ("Expression not 0xFFF00 to 0xFFFFF")
100 #define SFR(e) if (!expr_is_sfr (e)) NOT_SFR;
102 #define NOT_SFR_OR_SADDR rl78_error ("Expression not 0xFFE20 to 0xFFFFF")
104 #define NOT_ES if (rl78_has_prefix()) rl78_error ("ES: prefix not allowed here");
106 #define WA(x) if (!expr_is_word_aligned (x)) rl78_error ("Expression not word-aligned");
108 static void check_expr_is_bit_index (expressionS);
109 #define Bit(e) check_expr_is_bit_index (e);
111 /* Returns TRUE (non-zero) if the expression is a constant in the
113 static int check_expr_is_const (expressionS, int vmin, int vmax);
115 /* Convert a "regb" value to a "reg_xbc" value. Error if other
116 registers are passed. Needed to avoid reduce-reduce conflicts. */
129 rl78_error ("Only X, B, or C allowed here");
143 %type <regno> regb regb_na regw regw_na FLAG sfr
144 %type <regno> A X B C D E H L AX BC DE HL
147 %type <regno> addsub addsubw andor1 bt_bf setclr1 oneclrb oneclrw
148 %type <regno> incdec incdecw
150 %token A X B C D E H L AX BC DE HL
151 %token SPL SPH PSW CS ES PMC MEM
153 %token RB0 RB1 RB2 RB3
155 %token EXPR UNKNOWN_OPCODE IS_OPCODE
157 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
159 %token ADD ADDC ADDW AND_ AND1
160 /* BC is also a register pair */
161 %token BF BH BNC BNH BNZ BR BRK BRK1 BT BTCLR BZ
162 %token CALL CALLT CLR1 CLRB CLRW CMP CMP0 CMPS CMPW
163 %token DEC DECW DI DIVHU DIVWU
167 %token MACH MACHU MOV MOV1 MOVS MOVW MULH MULHU MULU
169 %token ONEB ONEW OR OR1
171 %token RET RETI RETB ROL ROLC ROLWC ROR RORC
172 %token SAR SARW SEL SET1 SHL SHLW SHR SHRW
173 %token SKC SKH SKNC SKNH SKNZ SKZ STOP SUB SUBC SUBW
174 %token XCH XCHW XOR XOR1
177 /* ====================================================================== */
182 { as_bad (_("Unknown opcode: %s"), rl78_init_start); }
184 /* The opcodes are listed in approximately alphabetical order. */
188 sfr = special function register - symbol, 0xFFF00 to 0xFFFFF
189 sfrp = special function register - symbol, 0xFFF00 to 0xFFFFE, even only
190 saddr = 0xFFE20 to 0xFFF1F
191 saddrp = 0xFFE20 to 0xFFF1E, even only
193 addr20 = 0x00000 to 0xFFFFF
194 addr16 = 0x00000 to 0x0FFFF, even only for 16-bit ops
195 addr5 = 0x00000 to 0x000BE, even only
198 /* ---------------------------------------------------------------------- */
200 /* addsub is ADD, ADDC, SUB, SUBC, AND, OR, XOR, and parts of CMP. */
202 | addsub A ',' '#' EXPR
203 { B1 (0x0c|$1); O1 ($5); }
205 | addsub EXPR {SA($2)} ',' '#' EXPR
206 { B1 (0x0a|$1); O1 ($2); O1 ($6); }
209 { B2 (0x61, 0x01|$1); }
211 | addsub A ',' regb_na
212 { B2 (0x61, 0x08|$1); F ($4, 13, 3); }
214 | addsub regb_na ',' A
215 { B2 (0x61, 0x00|$1); F ($2, 13, 3); }
217 | addsub A ',' EXPR {SA($4)}
218 { B1 (0x0b|$1); O1 ($4); }
220 | addsub A ',' opt_es '!' EXPR
221 { B1 (0x0f|$1); O2 ($6); rl78_linkrelax_addr16 (); }
223 | addsub A ',' opt_es '[' HL ']'
226 | addsub A ',' opt_es '[' HL '+' EXPR ']'
227 { B1 (0x0e|$1); O1 ($8); }
229 | addsub A ',' opt_es '[' HL '+' B ']'
230 { B2 (0x61, 0x80|$1); }
232 | addsub A ',' opt_es '[' HL '+' C ']'
233 { B2 (0x61, 0x82|$1); }
237 | addsub opt_es '!' EXPR ',' '#' EXPR
239 { rl78_error ("Only CMP takes these operands"); }
241 { B1 (0x00|$1); O2 ($4); O1 ($7); rl78_linkrelax_addr16 (); }
244 /* ---------------------------------------------------------------------- */
246 | addsubw AX ',' '#' EXPR
247 { B1 (0x04|$1); O2 ($5); }
249 | addsubw AX ',' regw
250 { B1 (0x01|$1); F ($4, 5, 2); }
252 | addsubw AX ',' EXPR {SA($4)}
253 { B1 (0x06|$1); O1 ($4); }
255 | addsubw AX ',' opt_es '!' EXPR
256 { B1 (0x02|$1); O2 ($6); rl78_linkrelax_addr16 (); }
258 | addsubw AX ',' opt_es '[' HL '+' EXPR ']'
259 { B2 (0x61, 0x09|$1); O1 ($8); }
261 | addsubw AX ',' opt_es '[' HL ']'
262 { B4 (0x61, 0x09|$1, 0, 0); }
264 | addsubw SP ',' '#' EXPR
265 { B1 ($1 ? 0x20 : 0x10); O1 ($5);
267 rl78_error ("CMPW SP,#imm not allowed");
270 /* ---------------------------------------------------------------------- */
272 | andor1 CY ',' sfr '.' EXPR {Bit($6)}
273 { B3 (0x71, 0x08|$1, $4); FE ($6, 9, 3); }
275 | andor1 CY ',' EXPR '.' EXPR {Bit($6)}
276 { if (expr_is_sfr ($4))
277 { B2 (0x71, 0x08|$1); FE ($6, 9, 3); O1 ($4); }
278 else if (expr_is_saddr ($4))
279 { B2 (0x71, 0x00|$1); FE ($6, 9, 3); O1 ($4); }
284 | andor1 CY ',' A '.' EXPR {Bit($6)}
285 { B2 (0x71, 0x88|$1); FE ($6, 9, 3); }
287 | andor1 CY ',' opt_es '[' HL ']' '.' EXPR {Bit($9)}
288 { B2 (0x71, 0x80|$1); FE ($9, 9, 3); }
290 /* ---------------------------------------------------------------------- */
293 { B1 (0xdc); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
296 { B1 (0xde); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
299 { B1 (0xdd); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
302 { B1 (0xdf); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
305 { B2 (0x61, 0xc3); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
308 { B2 (0x61, 0xd3); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
310 /* ---------------------------------------------------------------------- */
312 | bt_bf sfr '.' EXPR ',' '$' EXPR
313 { B3 (0x31, 0x80|$1, $2); FE ($4, 9, 3); PC1 ($7); }
315 | bt_bf EXPR '.' EXPR ',' '$' EXPR
316 { if (expr_is_sfr ($2))
317 { B2 (0x31, 0x80|$1); FE ($4, 9, 3); O1 ($2); PC1 ($7); }
318 else if (expr_is_saddr ($2))
319 { B2 (0x31, 0x00|$1); FE ($4, 9, 3); O1 ($2); PC1 ($7); }
324 | bt_bf A '.' EXPR ',' '$' EXPR
325 { B2 (0x31, 0x01|$1); FE ($4, 9, 3); PC1 ($7); }
327 | bt_bf opt_es '[' HL ']' '.' EXPR ',' '$' EXPR
328 { B2 (0x31, 0x81|$1); FE ($7, 9, 3); PC1 ($10); }
330 /* ---------------------------------------------------------------------- */
336 { B1 (0xef); PC1 ($3); }
339 { B1 (0xee); PC2 ($4); rl78_linkrelax_branch (); }
342 { B1 (0xed); O2 ($3); rl78_linkrelax_branch (); }
345 { B1 (0xec); O3 ($4); rl78_linkrelax_branch (); }
347 /* ---------------------------------------------------------------------- */
355 /* ---------------------------------------------------------------------- */
358 { B2 (0x61, 0xca); F ($2, 10, 2); }
361 { B1 (0xfe); PC2 ($4); }
364 { B1 (0xfd); O2 ($3); }
367 { B1 (0xfc); O3 ($4); rl78_linkrelax_branch (); }
370 { if ($3.X_op != O_constant)
371 rl78_error ("CALLT requires a numeric address");
374 int i = $3.X_add_number;
375 if (i < 0x80 || i > 0xbe)
376 rl78_error ("CALLT address not 0x80..0xbe");
378 rl78_error ("CALLT address not even");
382 F ((i >> 1) & 7, 9, 3);
383 F ((i >> 4) & 7, 14, 2);
388 /* ---------------------------------------------------------------------- */
391 { B2 (0x71, $1 ? 0x88 : 0x80); }
393 | setclr1 sfr '.' EXPR
394 { B3 (0x71, 0x0a|$1, $2); FE ($4, 9, 3); }
396 | setclr1 EXPR '.' EXPR
397 { if (expr_is_sfr ($2))
398 { B2 (0x71, 0x0a|$1); FE ($4, 9, 3); O1 ($2); }
399 else if (expr_is_saddr ($2))
400 { B2 (0x71, 0x02|$1); FE ($4, 9, 3); O1 ($2); }
406 { B2 (0x71, 0x8a|$1); FE ($4, 9, 3); }
408 | setclr1 opt_es '!' EXPR '.' EXPR
409 { B2 (0x71, 0x00+$1*0x08); FE ($6, 9, 3); O2 ($4); rl78_linkrelax_addr16 (); }
411 | setclr1 opt_es '[' HL ']' '.' EXPR
412 { B2 (0x71, 0x82|$1); FE ($7, 9, 3); }
414 /* ---------------------------------------------------------------------- */
425 | oneclrb EXPR {SA($2)}
426 { B1 (0xe4|$1); O1 ($2); }
428 | oneclrb opt_es '!' EXPR
429 { B1 (0xe5|$1); O2 ($4); rl78_linkrelax_addr16 (); }
431 /* ---------------------------------------------------------------------- */
438 /* ---------------------------------------------------------------------- */
453 { B1 (0xd4); O1 ($2); }
455 | CMP0 opt_es '!' EXPR
456 { B1 (0xd5); O2 ($4); rl78_linkrelax_addr16 (); }
458 /* ---------------------------------------------------------------------- */
460 | CMPS X ',' opt_es '[' HL '+' EXPR ']'
461 { B2 (0x61, 0xde); O1 ($8); }
463 /* ---------------------------------------------------------------------- */
466 { B1 (0x80|$1); F ($2, 5, 3); }
468 | incdec EXPR {SA($2)}
469 { B1 (0xa4|$1); O1 ($2); }
471 { B1 (0xa0|$1); O2 ($3); rl78_linkrelax_addr16 (); }
472 | incdec ES ':' '!' EXPR
473 { B2 (0x11, 0xa0|$1); O2 ($5); }
474 | incdec '[' HL '+' EXPR ']'
475 { B2 (0x61, 0x59+$1); O1 ($5); }
476 | incdec ES ':' '[' HL '+' EXPR ']'
477 { B3 (0x11, 0x61, 0x59+$1); O1 ($7); }
479 /* ---------------------------------------------------------------------- */
482 { B1 (0xa1|$1); F ($2, 5, 2); }
484 | incdecw EXPR {SA($2)}
485 { B1 (0xa6|$1); O1 ($2); }
487 | incdecw opt_es '!' EXPR
488 { B1 (0xa2|$1); O2 ($4); rl78_linkrelax_addr16 (); }
490 | incdecw opt_es '[' HL '+' EXPR ']'
491 { B2 (0x61, 0x79+$1); O1 ($6); }
493 /* ---------------------------------------------------------------------- */
496 { B3 (0x71, 0x7b, 0xfa); }
499 { B3 (0x71, 0x7a, 0xfa); }
501 /* ---------------------------------------------------------------------- */
504 { B3 (0xce, 0xfb, 0x01); }
507 { B3 (0xce, 0xfb, 0x02); }
513 { B3 (0xce, 0xfb, 0x03); }
515 /* Note that the DIVWU encoding was changed from [0xce,0xfb,0x04] to
516 [0xce,0xfb,0x0b]. Different versions of the Software Manual exist
517 with the same version number, but varying encodings. The version
518 here matches the hardware. */
521 { B3 (0xce, 0xfb, 0x0b); }
524 { B3 (0xce, 0xfb, 0x05); }
527 { B3 (0xce, 0xfb, 0x06); }
529 /* ---------------------------------------------------------------------- */
534 /* ---------------------------------------------------------------------- */
535 /* Note that opt_es is included even when it's not an option, to avoid
536 shift/reduce conflicts. The NOT_ES macro produces an error if ES:
537 is given by the user. */
540 { B1 (0x51); O1 ($5); }
541 | MOV regb_na ',' '#' EXPR
542 { B1 (0x50); F($2, 5, 3); O1 ($5); }
544 | MOV sfr ',' '#' EXPR
546 { B2 (0xce, $2); O1 ($5); }
548 { B1 (0x41); O1 ($5); }
551 | MOV opt_es EXPR ',' '#' EXPR {NOT_ES}
552 { if (expr_is_sfr ($3))
553 { B1 (0xce); O1 ($3); O1 ($6); }
554 else if (expr_is_saddr ($3))
555 { B1 (0xcd); O1 ($3); O1 ($6); }
560 | MOV '!' EXPR ',' '#' EXPR
561 { B1 (0xcf); O2 ($3); O1 ($6); rl78_linkrelax_addr16 (); }
563 | MOV ES ':' '!' EXPR ',' '#' EXPR
564 { B2 (0x11, 0xcf); O2 ($5); O1 ($8); }
567 { B1 (0x70); F ($2, 5, 3); }
570 { B1 (0x60); F ($4, 5, 3); }
572 | MOV opt_es EXPR ',' A {NOT_ES}
573 { if (expr_is_sfr ($3))
574 { B1 (0x9e); O1 ($3); }
575 else if (expr_is_saddr ($3))
576 { B1 (0x9d); O1 ($3); }
581 | MOV A ',' opt_es '!' EXPR
582 { B1 (0x8f); O2 ($6); rl78_linkrelax_addr16 (); }
585 { B1 (0x9f); O2 ($3); rl78_linkrelax_addr16 (); }
587 | MOV ES ':' '!' EXPR ',' A
588 { B2 (0x11, 0x9f); O2 ($5); }
590 | MOV regb_na ',' opt_es '!' EXPR
591 { B1 (0xc9|reg_xbc($2)); O2 ($6); rl78_linkrelax_addr16 (); }
593 | MOV A ',' opt_es EXPR {NOT_ES}
594 { if (expr_is_saddr ($5))
595 { B1 (0x8d); O1 ($5); }
596 else if (expr_is_sfr ($5))
597 { B1 (0x8e); O1 ($5); }
602 | MOV regb_na ',' opt_es EXPR {SA($5)} {NOT_ES}
603 { B1 (0xc8|reg_xbc($2)); O1 ($5); }
610 rl78_error ("Only A allowed here");
615 | MOV sfr ',' opt_es EXPR {SA($5)} {NOT_ES}
617 rl78_error ("Only ES allowed here");
619 { B2 (0x61, 0xb8); O1 ($5); }
622 | MOV A ',' opt_es '[' DE ']'
625 | MOV opt_es '[' DE ']' ',' A
628 | MOV opt_es '[' DE '+' EXPR ']' ',' '#' EXPR
629 { B1 (0xca); O1 ($6); O1 ($10); }
631 | MOV A ',' opt_es '[' DE '+' EXPR ']'
632 { B1 (0x8a); O1 ($8); }
634 | MOV opt_es '[' DE '+' EXPR ']' ',' A
635 { B1 (0x9a); O1 ($6); }
637 | MOV A ',' opt_es '[' HL ']'
640 | MOV opt_es '[' HL ']' ',' A
643 | MOV opt_es '[' HL '+' EXPR ']' ',' '#' EXPR
644 { B1 (0xcc); O1 ($6); O1 ($10); }
646 | MOV A ',' opt_es '[' HL '+' EXPR ']'
647 { B1 (0x8c); O1 ($8); }
649 | MOV opt_es '[' HL '+' EXPR ']' ',' A
650 { B1 (0x9c); O1 ($6); }
652 | MOV A ',' opt_es '[' HL '+' B ']'
655 | MOV opt_es '[' HL '+' B ']' ',' A
658 | MOV A ',' opt_es '[' HL '+' C ']'
661 | MOV opt_es '[' HL '+' C ']' ',' A
664 | MOV opt_es EXPR '[' B ']' ',' '#' EXPR
665 { B1 (0x19); O2 ($3); O1 ($9); }
667 | MOV A ',' opt_es EXPR '[' B ']'
668 { B1 (0x09); O2 ($5); }
670 | MOV opt_es EXPR '[' B ']' ',' A
671 { B1 (0x18); O2 ($3); }
673 | MOV opt_es EXPR '[' C ']' ',' '#' EXPR
674 { B1 (0x38); O2 ($3); O1 ($9); }
676 | MOV A ',' opt_es EXPR '[' C ']'
677 { B1 (0x29); O2 ($5); }
679 | MOV opt_es EXPR '[' C ']' ',' A
680 { B1 (0x28); O2 ($3); }
682 | MOV opt_es EXPR '[' BC ']' ',' '#' EXPR
683 { B1 (0x39); O2 ($3); O1 ($9); }
685 | MOV opt_es '[' BC ']' ',' '#' EXPR
686 { B3 (0x39, 0, 0); O1 ($8); }
688 | MOV A ',' opt_es EXPR '[' BC ']'
689 { B1 (0x49); O2 ($5); }
691 | MOV A ',' opt_es '[' BC ']'
694 | MOV opt_es EXPR '[' BC ']' ',' A
695 { B1 (0x48); O2 ($3); }
697 | MOV opt_es '[' BC ']' ',' A
700 | MOV opt_es '[' SP '+' EXPR ']' ',' '#' EXPR {NOT_ES}
701 { B1 (0xc8); O1 ($6); O1 ($10); }
703 | MOV opt_es '[' SP ']' ',' '#' EXPR {NOT_ES}
704 { B2 (0xc8, 0); O1 ($8); }
706 | MOV A ',' opt_es '[' SP '+' EXPR ']' {NOT_ES}
707 { B1 (0x88); O1 ($8); }
709 | MOV A ',' opt_es '[' SP ']' {NOT_ES}
712 | MOV opt_es '[' SP '+' EXPR ']' ',' A {NOT_ES}
713 { B1 (0x98); O1 ($6); }
715 | MOV opt_es '[' SP ']' ',' A {NOT_ES}
718 /* ---------------------------------------------------------------------- */
720 | mov1 CY ',' EXPR '.' EXPR
721 { if (expr_is_saddr ($4))
722 { B2 (0x71, 0x04); FE ($6, 9, 3); O1 ($4); }
723 else if (expr_is_sfr ($4))
724 { B2 (0x71, 0x0c); FE ($6, 9, 3); O1 ($4); }
729 | mov1 CY ',' A '.' EXPR
730 { B2 (0x71, 0x8c); FE ($6, 9, 3); }
732 | mov1 CY ',' sfr '.' EXPR
733 { B3 (0x71, 0x0c, $4); FE ($6, 9, 3); }
735 | mov1 CY ',' opt_es '[' HL ']' '.' EXPR
736 { B2 (0x71, 0x84); FE ($9, 9, 3); }
738 | mov1 EXPR '.' EXPR ',' CY
739 { if (expr_is_saddr ($2))
740 { B2 (0x71, 0x01); FE ($4, 9, 3); O1 ($2); }
741 else if (expr_is_sfr ($2))
742 { B2 (0x71, 0x09); FE ($4, 9, 3); O1 ($2); }
747 | mov1 A '.' EXPR ',' CY
748 { B2 (0x71, 0x89); FE ($4, 9, 3); }
750 | mov1 sfr '.' EXPR ',' CY
751 { B3 (0x71, 0x09, $2); FE ($4, 9, 3); }
753 | mov1 opt_es '[' HL ']' '.' EXPR ',' CY
754 { B2 (0x71, 0x81); FE ($7, 9, 3); }
756 /* ---------------------------------------------------------------------- */
758 | MOVS opt_es '[' HL '+' EXPR ']' ',' X
759 { B2 (0x61, 0xce); O1 ($6); }
761 /* ---------------------------------------------------------------------- */
763 | MOVW AX ',' '#' EXPR
764 { B1 (0x30); O2 ($5); }
766 | MOVW regw_na ',' '#' EXPR
767 { B1 (0x30); F ($2, 5, 2); O2 ($5); }
769 | MOVW opt_es EXPR ',' '#' EXPR {NOT_ES}
770 { if (expr_is_saddr ($3))
771 { B1 (0xc9); O1 ($3); O2 ($6); }
772 else if (expr_is_sfr ($3))
773 { B1 (0xcb); O1 ($3); O2 ($6); }
778 | MOVW AX ',' opt_es EXPR {NOT_ES}
779 { if (expr_is_saddr ($5))
780 { B1 (0xad); O1 ($5); WA($5); }
781 else if (expr_is_sfr ($5))
782 { B1 (0xae); O1 ($5); WA($5); }
787 | MOVW opt_es EXPR ',' AX {NOT_ES}
788 { if (expr_is_saddr ($3))
789 { B1 (0xbd); O1 ($3); WA($3); }
790 else if (expr_is_sfr ($3))
791 { B1 (0xbe); O1 ($3); WA($3); }
796 | MOVW AX ',' regw_na
797 { B1 (0x11); F ($4, 5, 2); }
799 | MOVW regw_na ',' AX
800 { B1 (0x10); F ($2, 5, 2); }
802 | MOVW AX ',' opt_es '!' EXPR
803 { B1 (0xaf); O2 ($6); WA($6); rl78_linkrelax_addr16 (); }
805 | MOVW opt_es '!' EXPR ',' AX
806 { B1 (0xbf); O2 ($4); WA($4); rl78_linkrelax_addr16 (); }
808 | MOVW AX ',' opt_es '[' DE ']'
811 | MOVW opt_es '[' DE ']' ',' AX
814 | MOVW AX ',' opt_es '[' DE '+' EXPR ']'
815 { B1 (0xaa); O1 ($8); }
817 | MOVW opt_es '[' DE '+' EXPR ']' ',' AX
818 { B1 (0xba); O1 ($6); }
820 | MOVW AX ',' opt_es '[' HL ']'
823 | MOVW opt_es '[' HL ']' ',' AX
826 | MOVW AX ',' opt_es '[' HL '+' EXPR ']'
827 { B1 (0xac); O1 ($8); }
829 | MOVW opt_es '[' HL '+' EXPR ']' ',' AX
830 { B1 (0xbc); O1 ($6); }
832 | MOVW AX ',' opt_es EXPR '[' B ']'
833 { B1 (0x59); O2 ($5); }
835 | MOVW opt_es EXPR '[' B ']' ',' AX
836 { B1 (0x58); O2 ($3); }
838 | MOVW AX ',' opt_es EXPR '[' C ']'
839 { B1 (0x69); O2 ($5); }
841 | MOVW opt_es EXPR '[' C ']' ',' AX
842 { B1 (0x68); O2 ($3); }
844 | MOVW AX ',' opt_es EXPR '[' BC ']'
845 { B1 (0x79); O2 ($5); }
847 | MOVW AX ',' opt_es '[' BC ']'
850 | MOVW opt_es EXPR '[' BC ']' ',' AX
851 { B1 (0x78); O2 ($3); }
853 | MOVW opt_es '[' BC ']' ',' AX
856 | MOVW AX ',' opt_es '[' SP '+' EXPR ']' {NOT_ES}
857 { B1 (0xa8); O1 ($8); WA($8);}
859 | MOVW AX ',' opt_es '[' SP ']' {NOT_ES}
862 | MOVW opt_es '[' SP '+' EXPR ']' ',' AX {NOT_ES}
863 { B1 (0xb8); O1 ($6); WA($6); }
865 | MOVW opt_es '[' SP ']' ',' AX {NOT_ES}
868 | MOVW regw_na ',' EXPR {SA($4)}
869 { B1 (0xca); F ($2, 2, 2); O1 ($4); WA($4); }
871 | MOVW regw_na ',' opt_es '!' EXPR
872 { B1 (0xcb); F ($2, 2, 2); O2 ($6); WA($6); rl78_linkrelax_addr16 (); }
874 | MOVW SP ',' '#' EXPR
875 { B2 (0xcb, 0xf8); O2 ($5); }
883 | MOVW regw_na ',' SP
884 { B3 (0xcb, 0xf8, 0xff); F ($2, 2, 2); }
886 /* ---------------------------------------------------------------------- */
891 /* ---------------------------------------------------------------------- */
896 /* ---------------------------------------------------------------------- */
899 { B1 (0xc0); F ($2, 5, 2); }
902 { B2 (0x61, 0xcd); };
905 { B1 (0xc1); F ($2, 5, 2); }
908 { B2 (0x61, 0xdd); };
910 /* ---------------------------------------------------------------------- */
921 /* ---------------------------------------------------------------------- */
924 { if (check_expr_is_const ($4, 1, 1))
929 { if (check_expr_is_const ($4, 1, 1))
934 { if (check_expr_is_const ($4, 1, 1))
939 { if (check_expr_is_const ($4, 1, 1))
944 { if (check_expr_is_const ($4, 1, 1))
949 { if (check_expr_is_const ($4, 1, 1))
953 /* ---------------------------------------------------------------------- */
956 { if (check_expr_is_const ($4, 1, 7))
957 { B2 (0x31, 0x0b); FE ($4, 9, 3); }
961 { if (check_expr_is_const ($4, 1, 15))
962 { B2 (0x31, 0x0f); FE ($4, 8, 4); }
965 /* ---------------------------------------------------------------------- */
979 /* ---------------------------------------------------------------------- */
982 { if (check_expr_is_const ($4, 1, 7))
983 { B2 (0x31, 0x09); FE ($4, 9, 3); }
987 { if (check_expr_is_const ($4, 1, 7))
988 { B2 (0x31, 0x08); FE ($4, 9, 3); }
992 { if (check_expr_is_const ($4, 1, 7))
993 { B2 (0x31, 0x07); FE ($4, 9, 3); }
997 { if (check_expr_is_const ($4, 1, 15))
998 { B2 (0x31, 0x0d); FE ($4, 8, 4); }
1002 { if (check_expr_is_const ($4, 1, 15))
1003 { B2 (0x31, 0x0c); FE ($4, 8, 4); }
1006 /* ---------------------------------------------------------------------- */
1009 { if (check_expr_is_const ($4, 1, 7))
1010 { B2 (0x31, 0x0a); FE ($4, 9, 3); }
1014 { if (check_expr_is_const ($4, 1, 15))
1015 { B2 (0x31, 0x0e); FE ($4, 8, 4); }
1018 /* ---------------------------------------------------------------------- */
1021 { B2 (0x61, 0xc8); rl78_linkrelax_branch (); }
1024 { B2 (0x61, 0xe3); rl78_linkrelax_branch (); }
1027 { B2 (0x61, 0xd8); rl78_linkrelax_branch (); }
1030 { B2 (0x61, 0xf3); rl78_linkrelax_branch (); }
1033 { B2 (0x61, 0xf8); rl78_linkrelax_branch (); }
1036 { B2 (0x61, 0xe8); rl78_linkrelax_branch (); }
1038 /* ---------------------------------------------------------------------- */
1041 { B2 (0x61, 0xfd); }
1043 /* ---------------------------------------------------------------------- */
1046 { if ($4 == 0) /* X */
1049 { B2 (0x61, 0x88); F ($4, 13, 3); }
1052 | XCH A ',' opt_es '!' EXPR
1053 { B2 (0x61, 0xaa); O2 ($6); rl78_linkrelax_addr16 (); }
1055 | XCH A ',' opt_es '[' DE ']'
1056 { B2 (0x61, 0xae); }
1058 | XCH A ',' opt_es '[' DE '+' EXPR ']'
1059 { B2 (0x61, 0xaf); O1 ($8); }
1061 | XCH A ',' opt_es '[' HL ']'
1062 { B2 (0x61, 0xac); }
1064 | XCH A ',' opt_es '[' HL '+' EXPR ']'
1065 { B2 (0x61, 0xad); O1 ($8); }
1067 | XCH A ',' opt_es '[' HL '+' B ']'
1068 { B2 (0x61, 0xb9); }
1070 | XCH A ',' opt_es '[' HL '+' C ']'
1071 { B2 (0x61, 0xa9); }
1074 { if (expr_is_sfr ($4))
1075 { B2 (0x61, 0xab); O1 ($4); }
1076 else if (expr_is_saddr ($4))
1077 { B2 (0x61, 0xa8); O1 ($4); }
1082 /* ---------------------------------------------------------------------- */
1084 | XCHW AX ',' regw_na
1085 { B1 (0x31); F ($4, 5, 2); }
1087 /* ---------------------------------------------------------------------- */
1089 ; /* end of statement */
1091 /* ---------------------------------------------------------------------- */
1093 opt_es : /* nothing */
1095 { rl78_prefix (0x11); }
1098 regb : X { $$ = 0; }
1108 regb_na : X { $$ = 0; }
1117 regw : AX { $$ = 0; }
1123 regw_na : BC { $$ = 1; }
1128 sfr : SPL { $$ = 0xf8; }
1129 | SPH { $$ = 0xf9; }
1130 | PSW { $$ = 0xfa; }
1133 | PMC { $$ = 0xfe; }
1134 | MEM { $$ = 0xff; }
1137 /* ---------------------------------------------------------------------- */
1138 /* Shortcuts for groups of opcodes with common encodings. */
1140 addsub : ADD { $$ = 0x00; }
1141 | ADDC { $$ = 0x10; }
1142 | SUB { $$ = 0x20; }
1143 | SUBC { $$ = 0x30; }
1144 | CMP { $$ = 0x40; }
1145 | AND_ { $$ = 0x50; }
1147 | XOR { $$ = 0x70; }
1150 addsubw : ADDW { $$ = 0x00; }
1151 | SUBW { $$ = 0x20; }
1152 | CMPW { $$ = 0x40; }
1155 andor1 : AND1 { $$ = 0x05; rl78_bit_insn = 1; }
1156 | OR1 { $$ = 0x06; rl78_bit_insn = 1; }
1157 | XOR1 { $$ = 0x07; rl78_bit_insn = 1; }
1160 bt_bf : BT { $$ = 0x02; rl78_bit_insn = 1; rl78_relax (RL78_RELAX_BRANCH, 0); }
1161 | BF { $$ = 0x04; rl78_bit_insn = 1; rl78_relax (RL78_RELAX_BRANCH, 0); }
1162 | BTCLR { $$ = 0x00; rl78_bit_insn = 1; }
1165 setclr1 : SET1 { $$ = 0; rl78_bit_insn = 1; }
1166 | CLR1 { $$ = 1; rl78_bit_insn = 1; }
1169 oneclrb : ONEB { $$ = 0x00; }
1170 | CLRB { $$ = 0x10; }
1173 oneclrw : ONEW { $$ = 0x00; }
1174 | CLRW { $$ = 0x10; }
1177 incdec : INC { $$ = 0x00; }
1178 | DEC { $$ = 0x10; }
1181 incdecw : INCW { $$ = 0x00; }
1182 | DECW { $$ = 0x10; }
1185 mov1 : MOV1 { rl78_bit_insn = 1; }
1189 /* ====================================================================== */
1193 const char * string;
1233 { "spl", SPL, 0xf8 },
1234 { "sph", SPH, 0xf9 },
1235 { "psw", PSW, 0xfa },
1238 { "pmc", PMC, 0xfe },
1239 { "mem", MEM, 0xff },
1246 { ".ub", DOT_UB, 0 },
1247 { ".uw", DOT_UW , 0},
1256 #define OPC(x) { #x, x, IS_OPCODE }
1261 { "and", AND_, IS_OPCODE },
1342 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1345 rl78_lex_init (char * beginning, char * ending)
1347 rl78_init_start = beginning;
1348 rl78_lex_start = beginning;
1349 rl78_lex_end = ending;
1350 rl78_in_brackets = 0;
1351 rl78_last_token = 0;
1358 /* Return a pointer to the '.' in a bit index expression (like
1359 foo.5), or NULL if none is found. */
1361 find_bit_index (char *tok)
1363 char *last_dot = NULL;
1364 char *last_digit = NULL;
1365 while (*tok && *tok != ',')
1372 else if (*tok >= '0' && *tok <= '7'
1374 && last_digit == NULL)
1378 else if (ISSPACE (*tok))
1389 if (last_dot != NULL
1390 && last_digit != NULL)
1398 /*unsigned int ci;*/
1399 char * save_input_pointer;
1402 while (ISSPACE (*rl78_lex_start)
1403 && rl78_lex_start != rl78_lex_end)
1406 rl78_last_exp_start = rl78_lex_start;
1408 if (rl78_lex_start == rl78_lex_end)
1411 if (ISALPHA (*rl78_lex_start)
1412 || (*rl78_lex_start == '.' && ISALPHA (rl78_lex_start[1])))
1418 for (e = rl78_lex_start + 1;
1419 e < rl78_lex_end && ISALNUM (*e);
1425 for (i = 0; i < NUM_TOKENS; i++)
1426 if (strcasecmp (rl78_lex_start, token_table[i].string) == 0
1427 && !(token_table[i].val == IS_OPCODE && rl78_last_token != 0)
1428 && !(token_table[i].token == FLAG && !need_flag))
1430 rl78_lval.regno = token_table[i].val;
1433 rl78_last_token = token_table[i].token;
1434 return token_table[i].token;
1439 if (rl78_last_token == 0)
1441 rl78_last_token = UNKNOWN_OPCODE;
1442 return UNKNOWN_OPCODE;
1445 if (rl78_last_token == UNKNOWN_OPCODE)
1448 if (*rl78_lex_start == '[')
1449 rl78_in_brackets = 1;
1450 if (*rl78_lex_start == ']')
1451 rl78_in_brackets = 0;
1453 /* '.' is funny - the syntax includes it for bitfields, but only for
1454 bitfields. We check for it specially so we can allow labels
1455 with '.' in them. */
1458 && *rl78_lex_start == '.'
1459 && find_bit_index (rl78_lex_start) == rl78_lex_start)
1461 rl78_last_token = *rl78_lex_start;
1462 return *rl78_lex_start ++;
1465 if ((rl78_in_brackets && *rl78_lex_start == '+')
1466 || strchr ("[],#!$:", *rl78_lex_start))
1468 rl78_last_token = *rl78_lex_start;
1469 return *rl78_lex_start ++;
1472 /* Again, '.' is funny. Look for '.<digit>' at the end of the line
1473 or before a comma, which is a bitfield, not an expression. */
1477 bit = find_bit_index (rl78_lex_start);
1484 save_input_pointer = input_line_pointer;
1485 input_line_pointer = rl78_lex_start;
1486 rl78_lval.exp.X_md = 0;
1487 expression (&rl78_lval.exp);
1492 rl78_lex_start = input_line_pointer;
1493 input_line_pointer = save_input_pointer;
1494 rl78_last_token = EXPR;
1499 rl78_error (const char * str)
1503 len = rl78_last_exp_start - rl78_init_start;
1505 as_bad ("%s", rl78_init_start);
1506 as_bad ("%*s^ %s", len, "", str);
1511 expr_is_sfr (expressionS exp)
1515 if (exp.X_op != O_constant)
1518 v = exp.X_add_number;
1519 if (0xFFF00 <= v && v <= 0xFFFFF)
1525 expr_is_saddr (expressionS exp)
1529 if (exp.X_op != O_constant)
1532 v = exp.X_add_number;
1533 if (0xFFE20 <= v && v <= 0xFFF1F)
1539 expr_is_word_aligned (expressionS exp)
1543 if (exp.X_op != O_constant)
1546 v = exp.X_add_number;
1554 check_expr_is_bit_index (expressionS exp)
1558 if (exp.X_op != O_constant)
1560 rl78_error (_("bit index must be a constant"));
1563 val = exp.X_add_number;
1565 if (val < 0 || val > 7)
1566 rl78_error (_("rtsd size must be 0..7"));
1570 exp_val (expressionS exp)
1572 if (exp.X_op != O_constant)
1574 rl78_error (_("constant expected"));
1577 return exp.X_add_number;
1581 check_expr_is_const (expressionS e, int vmin, int vmax)
1583 static char buf[100];
1584 if (e.X_op != O_constant
1585 || e.X_add_number < vmin
1586 || e.X_add_number > vmax)
1589 sprintf (buf, "%d expected here", vmin);
1591 sprintf (buf, "%d..%d expected here", vmin, vmax);