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 /* ---------------------------------------------------------------------- */
892 /* ---------------------------------------------------------------------- */
895 { B1
(0xc0); F
($2, 5, 2); }
898 { B2
(0x61, 0xcd); };
901 { B1
(0xc1); F
($2, 5, 2); }
904 { B2
(0x61, 0xdd); };
906 /* ---------------------------------------------------------------------- */
917 /* ---------------------------------------------------------------------- */
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))
945 { if
(check_expr_is_const
($4, 1, 1))
949 /* ---------------------------------------------------------------------- */
952 { if
(check_expr_is_const
($4, 1, 7))
953 { B2
(0x31, 0x0b); FE
($4, 9, 3); }
957 { if
(check_expr_is_const
($4, 1, 15))
958 { B2
(0x31, 0x0f); FE
($4, 8, 4); }
961 /* ---------------------------------------------------------------------- */
975 /* ---------------------------------------------------------------------- */
978 { if
(check_expr_is_const
($4, 1, 7))
979 { B2
(0x31, 0x09); FE
($4, 9, 3); }
983 { if
(check_expr_is_const
($4, 1, 7))
984 { B2
(0x31, 0x08); FE
($4, 9, 3); }
988 { if
(check_expr_is_const
($4, 1, 7))
989 { B2
(0x31, 0x07); FE
($4, 9, 3); }
993 { if
(check_expr_is_const
($4, 1, 15))
994 { B2
(0x31, 0x0d); FE
($4, 8, 4); }
998 { if
(check_expr_is_const
($4, 1, 15))
999 { B2
(0x31, 0x0c); FE
($4, 8, 4); }
1002 /* ---------------------------------------------------------------------- */
1005 { if
(check_expr_is_const
($4, 1, 7))
1006 { B2
(0x31, 0x0a); FE
($4, 9, 3); }
1010 { if
(check_expr_is_const
($4, 1, 15))
1011 { B2
(0x31, 0x0e); FE
($4, 8, 4); }
1014 /* ---------------------------------------------------------------------- */
1017 { B2
(0x61, 0xc8); rl78_linkrelax_branch
(); }
1020 { B2
(0x61, 0xe3); rl78_linkrelax_branch
(); }
1023 { B2
(0x61, 0xd8); rl78_linkrelax_branch
(); }
1026 { B2
(0x61, 0xf3); rl78_linkrelax_branch
(); }
1029 { B2
(0x61, 0xf8); rl78_linkrelax_branch
(); }
1032 { B2
(0x61, 0xe8); rl78_linkrelax_branch
(); }
1034 /* ---------------------------------------------------------------------- */
1037 { B2
(0x61, 0xfd); }
1039 /* ---------------------------------------------------------------------- */
1042 { if
($4 == 0) /* X */
1045 { B2
(0x61, 0x88); F
($4, 13, 3); }
1048 | XCH A
',' opt_es
'!' EXPR
1049 { B2
(0x61, 0xaa); O2
($6); rl78_linkrelax_addr16
(); }
1051 | XCH A
',' opt_es
'[' DE
']'
1052 { B2
(0x61, 0xae); }
1054 | XCH A
',' opt_es
'[' DE
'+' EXPR
']'
1055 { B2
(0x61, 0xaf); O1
($8); }
1057 | XCH A
',' opt_es
'[' HL
']'
1058 { B2
(0x61, 0xac); }
1060 | XCH A
',' opt_es
'[' HL
'+' EXPR
']'
1061 { B2
(0x61, 0xad); O1
($8); }
1063 | XCH A
',' opt_es
'[' HL
'+' B
']'
1064 { B2
(0x61, 0xb9); }
1066 | XCH A
',' opt_es
'[' HL
'+' C
']'
1067 { B2
(0x61, 0xa9); }
1070 { if
(expr_is_sfr
($4))
1071 { B2
(0x61, 0xab); O1
($4); }
1072 else if
(expr_is_saddr
($4))
1073 { B2
(0x61, 0xa8); O1
($4); }
1078 /* ---------------------------------------------------------------------- */
1080 | XCHW AX
',' regw_na
1081 { B1
(0x31); F
($4, 5, 2); }
1083 /* ---------------------------------------------------------------------- */
1085 ; /* end of statement */
1087 /* ---------------------------------------------------------------------- */
1089 opt_es
: /* nothing */
1091 { rl78_prefix
(0x11); }
1094 regb
: X
{ $$
= 0; }
1104 regb_na
: X
{ $$
= 0; }
1113 regw
: AX
{ $$
= 0; }
1119 regw_na
: BC
{ $$
= 1; }
1124 sfr
: SPL
{ $$
= 0xf8; }
1125 | SPH
{ $$
= 0xf9; }
1126 | PSW
{ $$
= 0xfa; }
1129 | PMC
{ $$
= 0xfe; }
1130 | MEM
{ $$
= 0xff; }
1133 /* ---------------------------------------------------------------------- */
1134 /* Shortcuts for groups of opcodes with common encodings. */
1136 addsub
: ADD
{ $$
= 0x00; }
1137 | ADDC
{ $$
= 0x10; }
1138 | SUB
{ $$
= 0x20; }
1139 | SUBC
{ $$
= 0x30; }
1140 | CMP
{ $$
= 0x40; }
1141 | AND_
{ $$
= 0x50; }
1143 | XOR
{ $$
= 0x70; }
1146 addsubw
: ADDW
{ $$
= 0x00; }
1147 | SUBW
{ $$
= 0x20; }
1148 | CMPW
{ $$
= 0x40; }
1151 andor1
: AND1
{ $$
= 0x05; rl78_bit_insn
= 1; }
1152 | OR1
{ $$
= 0x06; rl78_bit_insn
= 1;}
1153 | XOR1
{ $$
= 0x07; rl78_bit_insn
= 1; }
1156 bt_bf
: BT
{ $$
= 0x02; rl78_bit_insn
= 1;}
1157 | BF
{ $$
= 0x04; rl78_bit_insn
= 1; }
1158 | BTCLR
{ $$
= 0x00; rl78_bit_insn
= 1; }
1161 setclr1
: SET1
{ $$
= 0; rl78_bit_insn
= 1; }
1162 | CLR1
{ $$
= 1; rl78_bit_insn
= 1; }
1165 oneclrb
: ONEB
{ $$
= 0x00; }
1166 | CLRB
{ $$
= 0x10; }
1169 oneclrw
: ONEW
{ $$
= 0x00; }
1170 | CLRW
{ $$
= 0x10; }
1173 incdec
: INC
{ $$
= 0x00; }
1174 | DEC
{ $$
= 0x10; }
1177 incdecw
: INCW
{ $$
= 0x00; }
1178 | DECW
{ $$
= 0x10; }
1181 mov1
: MOV1
{ rl78_bit_insn
= 1; }
1185 /* ====================================================================== */
1189 const char * string;
1229 { "spl", SPL
, 0xf8 },
1230 { "sph", SPH
, 0xf9 },
1231 { "psw", PSW
, 0xfa },
1234 { "pmc", PMC
, 0xfe },
1235 { "mem", MEM
, 0xff },
1242 { ".ub", DOT_UB
, 0 },
1243 { ".uw", DOT_UW
, 0},
1252 #define OPC(x) { #x, x, IS_OPCODE }
1257 { "and", AND_
, IS_OPCODE
},
1338 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1341 rl78_lex_init
(char * beginning
, char * ending
)
1343 rl78_init_start
= beginning
;
1344 rl78_lex_start
= beginning
;
1345 rl78_lex_end
= ending
;
1346 rl78_in_brackets
= 0;
1347 rl78_last_token
= 0;
1354 /* Return a pointer to the '.' in a bit index expression (like
1355 foo.5), or NULL if none is found. */
1357 find_bit_index
(char *tok
)
1359 char *last_dot
= NULL
;
1360 char *last_digit
= NULL
;
1361 while
(*tok
&& *tok
!= ',')
1368 else if
(*tok
>= '0' && *tok
<= '7'
1370 && last_digit
== NULL
)
1374 else if
(ISSPACE
(*tok
))
1385 if
(last_dot
!= NULL
1386 && last_digit
!= NULL
)
1394 /*unsigned int ci;*/
1395 char * save_input_pointer
;
1398 while
(ISSPACE
(*rl78_lex_start
)
1399 && rl78_lex_start
!= rl78_lex_end
)
1402 rl78_last_exp_start
= rl78_lex_start
;
1404 if
(rl78_lex_start
== rl78_lex_end
)
1407 if
(ISALPHA
(*rl78_lex_start
)
1408 ||
(*rl78_lex_start
== '.' && ISALPHA
(rl78_lex_start
[1])))
1414 for
(e
= rl78_lex_start
+ 1;
1415 e
< rl78_lex_end
&& ISALNUM
(*e
);
1421 for
(i
= 0; i
< NUM_TOKENS
; i
++)
1422 if
(strcasecmp
(rl78_lex_start
, token_table
[i
].
string) == 0
1423 && !(token_table
[i
].val
== IS_OPCODE
&& rl78_last_token
!= 0)
1424 && !(token_table
[i
].token
== FLAG
&& !need_flag
))
1426 rl78_lval.regno
= token_table
[i
].val
;
1429 rl78_last_token
= token_table
[i
].token
;
1430 return token_table
[i
].token
;
1435 if
(rl78_last_token
== 0)
1437 rl78_last_token
= UNKNOWN_OPCODE
;
1438 return UNKNOWN_OPCODE
;
1441 if
(rl78_last_token
== UNKNOWN_OPCODE
)
1444 if
(*rl78_lex_start
== '[')
1445 rl78_in_brackets
= 1;
1446 if
(*rl78_lex_start
== ']')
1447 rl78_in_brackets
= 0;
1449 /* '.' is funny - the syntax includes it for bitfields, but only for
1450 bitfields. We check for it specially so we can allow labels
1451 with '.' in them. */
1454 && *rl78_lex_start
== '.'
1455 && find_bit_index
(rl78_lex_start
) == rl78_lex_start
)
1457 rl78_last_token
= *rl78_lex_start
;
1458 return
*rl78_lex_start
++;
1461 if
((rl78_in_brackets
&& *rl78_lex_start
== '+')
1462 || strchr
("[],#!$:", *rl78_lex_start
))
1464 rl78_last_token
= *rl78_lex_start
;
1465 return
*rl78_lex_start
++;
1468 /* Again, '.' is funny. Look for '.<digit>' at the end of the line
1469 or before a comma, which is a bitfield, not an expression. */
1473 bit
= find_bit_index
(rl78_lex_start
);
1480 save_input_pointer
= input_line_pointer
;
1481 input_line_pointer
= rl78_lex_start
;
1482 rl78_lval.exp.X_md
= 0;
1483 expression
(&rl78_lval.exp
);
1488 rl78_lex_start
= input_line_pointer
;
1489 input_line_pointer
= save_input_pointer
;
1490 rl78_last_token
= EXPR
;
1495 rl78_error
(const char * str
)
1499 len
= rl78_last_exp_start
- rl78_init_start
;
1501 as_bad
("%s", rl78_init_start
);
1502 as_bad
("%*s^ %s", len
, "", str
);
1507 expr_is_sfr
(expressionS exp
)
1511 if
(exp.X_op
!= O_constant
)
1514 v
= exp.X_add_number
;
1515 if
(0xFFF00 <= v
&& v
<= 0xFFFFF)
1521 expr_is_saddr
(expressionS exp
)
1525 if
(exp.X_op
!= O_constant
)
1528 v
= exp.X_add_number
;
1529 if
(0xFFE20 <= v
&& v
<= 0xFFF1F)
1535 expr_is_word_aligned
(expressionS exp
)
1539 if
(exp.X_op
!= O_constant
)
1542 v
= exp.X_add_number
;
1550 check_expr_is_bit_index
(expressionS exp
)
1554 if
(exp.X_op
!= O_constant
)
1556 rl78_error
(_
("bit index must be a constant"));
1559 val
= exp.X_add_number
;
1561 if
(val
< 0 || val
> 7)
1562 rl78_error
(_
("rtsd size must be 0..7"));
1566 exp_val
(expressionS exp
)
1568 if
(exp.X_op
!= O_constant
)
1570 rl78_error
(_
("constant expected"));
1573 return exp.X_add_number
;
1577 check_expr_is_const
(expressionS e
, int vmin
, int vmax
)
1579 static char buf
[100];
1580 if
(e.X_op
!= O_constant
1581 || e.X_add_number
< vmin
1582 || e.X_add_number
> vmax
)
1585 sprintf
(buf
, "%d expected here", vmin
);
1587 sprintf
(buf
, "%d..%d expected here", vmin
, vmax
);