xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/rl78-parse.y (revision 6cd39ddb8550f6fa1bff3fed32053d7f19fd0453)
1 /* rl78-parse.y  Renesas RL78 parser
2    Copyright 2011
3    Free Software Foundation, Inc.
4 
5    This file is part of GAS, the GNU Assembler.
6 
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)
10    any later version.
11 
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.
16 
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
20    02110-1301, USA.  */
21 %{
22 
23 #include "as.h"
24 #include "safe-ctype.h"
25 #include "rl78-defs.h"
26 
27 static int rl78_lex (void);
28 
29 /* Ok, here are the rules for using these macros...
30 
31    B*() is used to specify the base opcode bytes.  Fields to be filled
32         in later, leave zero.  Call this first.
33 
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().
36 
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
41 
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.
46 
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
49    call them.
50 
51    Use "disp" for displacements whenever possible; this handles the
52    "0" case properly.  */
53 
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)
58 
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);
62 
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)
67 
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)
71 
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)
79 
80 #define id24(a,b2,b3)	   B3 (0xfb+a, b2, b3)
81 
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);
86 
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;
93 
94 #define YYDEBUG 1
95 #define YYERROR_VERBOSE 1
96 
97 #define NOT_SADDR  rl78_error ("Expression not 0xFFE20 to 0xFFF1F")
98 #define SA(e) if (!expr_is_saddr (e)) NOT_SADDR;
99 
100 #define NOT_SFR  rl78_error ("Expression not 0xFFF00 to 0xFFFFF")
101 #define SFR(e) if (!expr_is_sfr (e)) NOT_SFR;
102 
103 #define NOT_SFR_OR_SADDR  rl78_error ("Expression not 0xFFE20 to 0xFFFFF")
104 
105 #define NOT_ES if (rl78_has_prefix()) rl78_error ("ES: prefix not allowed here");
106 
107 #define WA(x) if (!expr_is_word_aligned (x)) rl78_error ("Expression not word-aligned");
108 
109 static void check_expr_is_bit_index (expressionS);
110 #define Bit(e) check_expr_is_bit_index (e);
111 
112 /* Returns TRUE (non-zero) if the expression is a constant in the
113    given range.  */
114 static int check_expr_is_const (expressionS, int vmin, int vmax);
115 
116 /* Convert a "regb" value to a "reg_xbc" value.  Error if other
117    registers are passed.  Needed to avoid reduce-reduce conflicts.  */
118 static int
119 reg_xbc (int reg)
120 {
121   switch (reg)
122     {
123       case 0: /* X */
124         return 0x10;
125       case 3: /* B */
126         return 0x20;
127       case 2: /* C */
128         return 0x30;
129       default:
130         rl78_error ("Only X, B, or C allowed here");
131 	return 0;
132     }
133 }
134 
135 %}
136 
137 %name-prefix="rl78_"
138 
139 %union {
140   int regno;
141   expressionS exp;
142 }
143 
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
146 %type <exp> EXPR
147 
148 %type <regno> addsub addsubw andor1 bt_bf setclr1 oneclrb oneclrw
149 %type <regno> incdec incdecw
150 
151 %token A X B C D E H L AX BC DE HL
152 %token SPL SPH PSW CS ES PMC MEM
153 %token FLAG SP CY
154 %token RB0 RB1 RB2 RB3
155 
156 %token EXPR UNKNOWN_OPCODE IS_OPCODE
157 
158 %token DOT_S DOT_B DOT_W DOT_L DOT_A DOT_UB DOT_UW
159 
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
165 %token EI
166 %token HALT
167 %token INC INCW
168 %token MACH MACHU MOV MOV1 MOVS MOVW MULH MULHU MULU
169 %token NOP NOT1
170 %token ONEB ONEW OR OR1
171 %token POP PUSH
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
176 
177 %%
178 /* ====================================================================== */
179 
180 statement :
181 
182 	  UNKNOWN_OPCODE
183 	  { as_bad (_("Unknown opcode: %s"), rl78_init_start); }
184 
185 /* The opcodes are listed in approximately alphabetical order.  */
186 
187 /* For reference:
188 
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
193 
194   addr20 = 0x00000 to 0xFFFFF
195   addr16 = 0x00000 to 0x0FFFF, even only for 16-bit ops
196   addr5  = 0x00000 to 0x000BE, even only
197 */
198 
199 /* ---------------------------------------------------------------------- */
200 
201 /* addsub is ADD, ADDC, SUB, SUBC, AND, OR, XOR, and parts of CMP.  */
202 
203 	| addsub A ',' '#' EXPR
204 	  { B1 (0x0c|$1); O1 ($5); }
205 
206 	| addsub EXPR {SA($2)} ',' '#' EXPR
207 	  { B1 (0x0a|$1); O1 ($2); O1 ($6); }
208 
209 	| addsub A ',' A
210 	  { B2 (0x61, 0x01|$1); }
211 
212 	| addsub A ',' regb_na
213 	  { B2 (0x61, 0x08|$1); F ($4, 13, 3); }
214 
215 	| addsub regb_na ',' A
216 	  { B2 (0x61, 0x00|$1); F ($2, 13, 3); }
217 
218 	| addsub A ',' EXPR {SA($4)}
219 	  { B1 (0x0b|$1); O1 ($4); }
220 
221 	| addsub A ',' opt_es '!' EXPR
222 	  { B1 (0x0f|$1); O2 ($6); rl78_linkrelax_addr16 (); }
223 
224 	| addsub A ',' opt_es '[' HL ']'
225 	  { B1 (0x0d|$1); }
226 
227 	| addsub A ',' opt_es '[' HL '+' EXPR ']'
228 	  { B1 (0x0e|$1); O1 ($8); }
229 
230 	| addsub A ',' opt_es '[' HL '+' B ']'
231 	  { B2 (0x61, 0x80|$1); }
232 
233 	| addsub A ',' opt_es '[' HL '+' C ']'
234 	  { B2 (0x61, 0x82|$1); }
235 
236 
237 
238 	| addsub opt_es '!' EXPR ',' '#' EXPR
239 	  { if ($1 != 0x40)
240 	      { rl78_error ("Only CMP takes these operands"); }
241 	    else
242 	      { B1 (0x00|$1); O2 ($4); O1 ($7); rl78_linkrelax_addr16 (); }
243 	  }
244 
245 /* ---------------------------------------------------------------------- */
246 
247 	| addsubw AX ',' '#' EXPR
248 	  { B1 (0x04|$1); O2 ($5); }
249 
250 	| addsubw AX ',' regw
251 	  { B1 (0x01|$1); F ($4, 5, 2); }
252 
253 	| addsubw AX ',' EXPR {SA($4)}
254 	  { B1 (0x06|$1); O1 ($4); }
255 
256 	| addsubw AX ',' opt_es '!' EXPR
257 	  { B1 (0x02|$1); O2 ($6); rl78_linkrelax_addr16 (); }
258 
259 	| addsubw AX ',' opt_es '[' HL '+' EXPR ']'
260 	  { B2 (0x61, 0x09|$1); O1 ($8); }
261 
262 	| addsubw AX ',' opt_es '[' HL ']'
263 	  { B4 (0x61, 0x09|$1, 0, 0); }
264 
265 	| addsubw SP ',' '#' EXPR
266 	  { B1 ($1 ? 0x20 : 0x10); O1 ($5);
267 	    if ($1 == 0x40)
268 	      rl78_error ("CMPW SP,#imm not allowed");
269 	  }
270 
271 /* ---------------------------------------------------------------------- */
272 
273 	| andor1 CY ',' sfr '.' EXPR {Bit($6)}
274 	  { B3 (0x71, 0x08|$1, $4); FE ($6, 9, 3); }
275 
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); }
281 	    else
282 	      NOT_SFR_OR_SADDR;
283 	  }
284 
285 	| andor1 CY ',' A '.' EXPR {Bit($6)}
286 	  { B2 (0x71, 0x88|$1);  FE ($6, 9, 3); }
287 
288 	| andor1 CY ',' opt_es '[' HL ']' '.' EXPR {Bit($9)}
289 	  { B2 (0x71, 0x80|$1);  FE ($9, 9, 3); }
290 
291 /* ---------------------------------------------------------------------- */
292 
293 	| BC '$' EXPR
294 	  { B1 (0xdc); PC1 ($3); }
295 
296 	| BNC '$' EXPR
297 	  { B1 (0xde); PC1 ($3); }
298 
299 	| BZ '$' EXPR
300 	  { B1 (0xdd); PC1 ($3); }
301 
302 	| BNZ '$' EXPR
303 	  { B1 (0xdf); PC1 ($3); }
304 
305 	| BH '$' EXPR
306 	  { B2 (0x61, 0xc3); PC1 ($3); }
307 
308 	| BNH '$' EXPR
309 	  { B2 (0x61, 0xd3); PC1 ($3); }
310 
311 /* ---------------------------------------------------------------------- */
312 
313 	| bt_bf sfr '.' EXPR ',' '$' EXPR
314 	  { B3 (0x31, 0x80|$1, $2); FE ($4, 9, 3); PC1 ($7); }
315 
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); }
321 	    else
322 	      NOT_SFR_OR_SADDR;
323 	  }
324 
325 	| bt_bf A '.' EXPR ',' '$' EXPR
326 	  { B2 (0x31, 0x01|$1); FE ($4, 9, 3); PC1 ($7); }
327 
328 	| bt_bf opt_es '[' HL ']' '.' EXPR ',' '$' EXPR
329 	  { B2 (0x31, 0x81|$1); FE ($7, 9, 3); PC1 ($10); }
330 
331 /* ---------------------------------------------------------------------- */
332 
333 	| BR AX
334 	  { B2 (0x61, 0xcb); }
335 
336 	| BR '$' EXPR
337 	  { B1 (0xef); PC1 ($3); }
338 
339 	| BR '$' '!' EXPR
340 	  { B1 (0xee); PC2 ($4); rl78_linkrelax_branch (); }
341 
342 	| BR '!' EXPR
343 	  { B1 (0xed); O2 ($3); rl78_linkrelax_branch (); }
344 
345 	| BR '!' '!' EXPR
346 	  { B1 (0xec); O3 ($4); rl78_linkrelax_branch (); }
347 
348 /* ---------------------------------------------------------------------- */
349 
350 	| BRK
351 	  { B2 (0x61, 0xcc); }
352 
353 	| BRK1
354 	  { B1 (0xff); }
355 
356 /* ---------------------------------------------------------------------- */
357 
358 	| CALL regw
359 	  { B2 (0x61, 0xca); F ($2, 10, 2); }
360 
361 	| CALL '$' '!' EXPR
362 	  { B1 (0xfe); PC2 ($4); }
363 
364 	| CALL '!' EXPR
365 	  { B1 (0xfd); O2 ($3); }
366 
367 	| CALL '!' '!' EXPR
368 	  { B1 (0xfc); O3 ($4); rl78_linkrelax_branch (); }
369 
370 	| CALLT '[' EXPR ']'
371 	  { if ($3.X_op != O_constant)
372 	      rl78_error ("CALLT requires a numeric address");
373 	    else
374 	      {
375 	        int i = $3.X_add_number;
376 		if (i < 0x80 || i > 0xbe)
377 		  rl78_error ("CALLT address not 0x80..0xbe");
378 		else if (i & 1)
379 		  rl78_error ("CALLT address not even");
380 		else
381 		  {
382 		    B2 (0x61, 0x84);
383 	    	    F ((i >> 1) & 7, 9, 3);
384 	    	    F ((i >> 4) & 7, 14, 2);
385 		  }
386 	      }
387 	  }
388 
389 /* ---------------------------------------------------------------------- */
390 
391 	| setclr1 CY
392 	  { B2 (0x71, $1 ? 0x88 : 0x80); }
393 
394 	| setclr1 sfr '.' EXPR
395 	  { B3 (0x71, 0x0a|$1, $2); FE ($4, 9, 3); }
396 
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); }
402 	    else
403 	      NOT_SFR_OR_SADDR;
404 	  }
405 
406 	| setclr1 A '.' EXPR
407 	  { B2 (0x71, 0x8a|$1);  FE ($4, 9, 3); }
408 
409 	| setclr1 opt_es '!' EXPR '.' EXPR
410 	  { B2 (0x71, 0x00+$1*0x08); FE ($6, 9, 3); O2 ($4); rl78_linkrelax_addr16 (); }
411 
412 	| setclr1 opt_es '[' HL ']' '.' EXPR
413 	  { B2 (0x71, 0x82|$1); FE ($7, 9, 3); }
414 
415 /* ---------------------------------------------------------------------- */
416 
417 	| oneclrb A
418 	  { B1 (0xe1|$1); }
419 	| oneclrb X
420 	  { B1 (0xe0|$1); }
421 	| oneclrb B
422 	  { B1 (0xe3|$1); }
423 	| oneclrb C
424 	  { B1 (0xe2|$1); }
425 
426 	| oneclrb EXPR {SA($2)}
427 	  { B1 (0xe4|$1); O1 ($2); }
428 
429 	| oneclrb opt_es '!' EXPR
430 	  { B1 (0xe5|$1); O2 ($4); rl78_linkrelax_addr16 (); }
431 
432 /* ---------------------------------------------------------------------- */
433 
434 	| oneclrw AX
435 	  { B1 (0xe6|$1); }
436 	| oneclrw BC
437 	  { B1 (0xe7|$1); }
438 
439 /* ---------------------------------------------------------------------- */
440 
441 	| CMP0 A
442 	  { B1 (0xd1); }
443 
444 	| CMP0 X
445 	  { B1 (0xd0); }
446 
447 	| CMP0 B
448 	  { B1 (0xd3); }
449 
450 	| CMP0 C
451 	  { B1 (0xd2); }
452 
453 	| CMP0 EXPR {SA($2)}
454 	  { B1 (0xd4); O1 ($2); }
455 
456 	| CMP0 opt_es '!' EXPR
457 	  { B1 (0xd5); O2 ($4); rl78_linkrelax_addr16 (); }
458 
459 /* ---------------------------------------------------------------------- */
460 
461 	| CMPS X ',' opt_es '[' HL '+' EXPR ']'
462 	  { B2 (0x61, 0xde); O1 ($8); }
463 
464 /* ---------------------------------------------------------------------- */
465 
466 	| incdec regb
467 	  { B1 (0x80|$1); F ($2, 5, 3); }
468 
469 	| incdec EXPR {SA($2)}
470 	  { B1 (0xa4|$1); O1 ($2); }
471 	| incdec '!' EXPR
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); }
479 
480 /* ---------------------------------------------------------------------- */
481 
482 	| incdecw regw
483 	  { B1 (0xa1|$1); F ($2, 5, 2); }
484 
485 	| incdecw EXPR {SA($2)}
486 	  { B1 (0xa6|$1); O1 ($2); }
487 
488 	| incdecw opt_es '!' EXPR
489 	  { B1 (0xa2|$1); O2 ($4); rl78_linkrelax_addr16 (); }
490 
491 	| incdecw opt_es '[' HL '+' EXPR ']'
492 	  { B2 (0x61, 0x79+$1); O1 ($6); }
493 
494 /* ---------------------------------------------------------------------- */
495 
496 	| DI
497 	  { B3 (0x71, 0x7b, 0xfa); }
498 
499 	| EI
500 	  { B3 (0x71, 0x7a, 0xfa); }
501 
502 /* ---------------------------------------------------------------------- */
503 
504 	| MULHU
505 	  { B3 (0xce, 0xfb, 0x01); }
506 
507 	| MULH
508 	  { B3 (0xce, 0xfb, 0x02); }
509 
510 	| MULU X
511 	  { B1 (0xd6); }
512 
513 	| DIVHU
514 	  { B3 (0xce, 0xfb, 0x03); }
515 
516 	| DIVWU
517 	  { B3 (0xce, 0xfb, 0x04); }
518 
519 	| MACHU
520 	  { B3 (0xce, 0xfb, 0x05); }
521 
522 	| MACH
523 	  { B3 (0xce, 0xfb, 0x06); }
524 
525 /* ---------------------------------------------------------------------- */
526 
527 	| HALT
528 	  { B2 (0x61, 0xed); }
529 
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.  */
534 
535 	| MOV A ',' '#' EXPR
536 	  { B1 (0x51); O1 ($5); }
537 	| MOV regb_na ',' '#' EXPR
538 	  { B1 (0x50); F($2, 5, 3); O1 ($5); }
539 
540 	| MOV sfr ',' '#' EXPR
541 	  { if ($2 != 0xfd)
542 	      { B2 (0xce, $2); O1 ($5); }
543 	    else
544 	      { B1 (0x41); O1 ($5); }
545 	  }
546 
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); }
552 	    else
553 	      NOT_SFR_OR_SADDR;
554 	  }
555 
556 	| MOV '!' EXPR ',' '#' EXPR
557 	  { B1 (0xcf); O2 ($3); O1 ($6); rl78_linkrelax_addr16 (); }
558 
559 	| MOV ES ':' '!' EXPR ',' '#' EXPR
560 	  { B2 (0x11, 0xcf); O2 ($5); O1 ($8); }
561 
562 	| MOV regb_na ',' A
563 	  { B1 (0x70); F ($2, 5, 3); }
564 
565 	| MOV A ',' regb_na
566 	  { B1 (0x60); F ($4, 5, 3); }
567 
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); }
573 	    else
574 	      NOT_SFR_OR_SADDR;
575 	  }
576 
577 	| MOV A ',' opt_es '!' EXPR
578 	  { B1 (0x8f); O2 ($6); rl78_linkrelax_addr16 (); }
579 
580 	| MOV '!' EXPR ',' A
581 	  { B1 (0x9f); O2 ($3); rl78_linkrelax_addr16 (); }
582 
583 	| MOV ES ':' '!' EXPR ',' A
584 	  { B2 (0x11, 0x9f); O2 ($5); }
585 
586 	| MOV regb_na ',' opt_es '!' EXPR
587 	  { B1 (0xc9|reg_xbc($2)); O2 ($6); rl78_linkrelax_addr16 (); }
588 
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); }
594 	    else
595 	      NOT_SFR_OR_SADDR;
596 	  }
597 
598 	| MOV regb_na ',' opt_es EXPR {SA($5)} {NOT_ES}
599 	  { B1 (0xc8|reg_xbc($2)); O1 ($5); }
600 
601 	| MOV A ',' sfr
602 	  { B2 (0x8e, $4); }
603 
604 	| MOV sfr ',' regb
605 	  { if ($4 != 1)
606 	      rl78_error ("Only A allowed here");
607 	    else
608 	      { B2 (0x9e, $2); }
609 	  }
610 
611 	| MOV sfr ',' opt_es EXPR {SA($5)} {NOT_ES}
612 	  { if ($2 != 0xfd)
613 	      rl78_error ("Only ES allowed here");
614 	    else
615 	      { B2 (0x61, 0xb8); O1 ($5); }
616 	  }
617 
618 	| MOV A ',' opt_es '[' DE ']'
619 	  { B1 (0x89); }
620 
621 	| MOV opt_es '[' DE ']' ',' A
622 	  { B1 (0x99); }
623 
624 	| MOV opt_es '[' DE '+' EXPR ']' ',' '#' EXPR
625 	  { B1 (0xca); O1 ($6); O1 ($10); }
626 
627 	| MOV A ',' opt_es '[' DE '+' EXPR ']'
628 	  { B1 (0x8a); O1 ($8); }
629 
630 	| MOV opt_es '[' DE '+' EXPR ']' ',' A
631 	  { B1 (0x9a); O1 ($6); }
632 
633 	| MOV A ',' opt_es '[' HL ']'
634 	  { B1 (0x8b); }
635 
636 	| MOV opt_es '[' HL ']' ',' A
637 	  { B1 (0x9b); }
638 
639 	| MOV opt_es '[' HL '+' EXPR ']' ',' '#' EXPR
640 	  { B1 (0xcc); O1 ($6); O1 ($10); }
641 
642 	| MOV A ',' opt_es '[' HL '+' EXPR ']'
643 	  { B1 (0x8c); O1 ($8); }
644 
645 	| MOV opt_es '[' HL '+' EXPR ']' ',' A
646 	  { B1 (0x9c); O1 ($6); }
647 
648 	| MOV A ',' opt_es '[' HL '+' B ']'
649 	  { B2 (0x61, 0xc9); }
650 
651 	| MOV opt_es '[' HL '+' B ']' ',' A
652 	  { B2 (0x61, 0xd9); }
653 
654 	| MOV A ',' opt_es '[' HL '+' C ']'
655 	  { B2 (0x61, 0xe9); }
656 
657 	| MOV opt_es '[' HL '+' C ']' ',' A
658 	  { B2 (0x61, 0xf9); }
659 
660 	| MOV opt_es EXPR '[' B ']' ',' '#' EXPR
661 	  { B1 (0x19); O2 ($3); O1 ($9); }
662 
663 	| MOV A ',' opt_es EXPR '[' B ']'
664 	  { B1 (0x09); O2 ($5); }
665 
666 	| MOV opt_es EXPR '[' B ']' ',' A
667 	  { B1 (0x18); O2 ($3); }
668 
669 	| MOV opt_es EXPR '[' C ']' ',' '#' EXPR
670 	  { B1 (0x38); O2 ($3); O1 ($9); }
671 
672 	| MOV A ',' opt_es EXPR '[' C ']'
673 	  { B1 (0x29); O2 ($5); }
674 
675 	| MOV opt_es EXPR '[' C ']' ',' A
676 	  { B1 (0x28); O2 ($3); }
677 
678 	| MOV opt_es EXPR '[' BC ']' ',' '#' EXPR
679 	  { B1 (0x39); O2 ($3); O1 ($9); }
680 
681 	| MOV opt_es '[' BC ']' ',' '#' EXPR
682 	  { B3 (0x39, 0, 0); O1 ($8); }
683 
684 	| MOV A ',' opt_es EXPR '[' BC ']'
685 	  { B1 (0x49); O2 ($5); }
686 
687 	| MOV A ',' opt_es '[' BC ']'
688 	  { B3 (0x49, 0, 0); }
689 
690 	| MOV opt_es EXPR '[' BC ']' ',' A
691 	  { B1 (0x48); O2 ($3); }
692 
693 	| MOV opt_es '[' BC ']' ',' A
694 	  { B3 (0x48, 0, 0); }
695 
696 	| MOV opt_es '[' SP '+' EXPR ']' ',' '#' EXPR  {NOT_ES}
697 	  { B1 (0xc8); O1 ($6); O1 ($10); }
698 
699 	| MOV opt_es '[' SP ']' ',' '#' EXPR  {NOT_ES}
700 	  { B2 (0xc8, 0); O1 ($8); }
701 
702 	| MOV A ',' opt_es '[' SP '+' EXPR ']'  {NOT_ES}
703 	  { B1 (0x88); O1 ($8); }
704 
705 	| MOV A ',' opt_es '[' SP ']'  {NOT_ES}
706 	  { B2 (0x88, 0); }
707 
708 	| MOV opt_es '[' SP '+' EXPR ']' ',' A  {NOT_ES}
709 	  { B1 (0x98); O1 ($6); }
710 
711 	| MOV opt_es '[' SP ']' ',' A  {NOT_ES}
712 	  { B2 (0x98, 0); }
713 
714 /* ---------------------------------------------------------------------- */
715 
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); }
721 	    else
722 	      NOT_SFR_OR_SADDR;
723 	  }
724 
725 	| mov1 CY ',' A '.' EXPR
726 	  { B2 (0x71, 0x8c); FE ($6, 9, 3); }
727 
728 	| mov1 CY ',' sfr '.' EXPR
729 	  { B3 (0x71, 0x0c, $4); FE ($6, 9, 3); }
730 
731 	| mov1 CY ',' opt_es '[' HL ']' '.' EXPR
732 	  { B2 (0x71, 0x84); FE ($9, 9, 3); }
733 
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); }
739 	    else
740 	      NOT_SFR_OR_SADDR;
741 	  }
742 
743 	| mov1 A '.' EXPR ',' CY
744 	  { B2 (0x71, 0x89); FE ($4, 9, 3); }
745 
746 	| mov1 sfr '.' EXPR ',' CY
747 	  { B3 (0x71, 0x09, $2); FE ($4, 9, 3); }
748 
749 	| mov1 opt_es '[' HL ']' '.' EXPR ',' CY
750 	  { B2 (0x71, 0x81); FE ($7, 9, 3); }
751 
752 /* ---------------------------------------------------------------------- */
753 
754 	| MOVS opt_es '[' HL '+' EXPR ']' ',' X
755 	  { B2 (0x61, 0xce); O1 ($6); }
756 
757 /* ---------------------------------------------------------------------- */
758 
759 	| MOVW AX ',' '#' EXPR
760 	  { B1 (0x30); O2 ($5); }
761 
762 	| MOVW regw_na ',' '#' EXPR
763 	  { B1 (0x30); F ($2, 5, 2); O2 ($5); }
764 
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); }
770 	    else
771 	      NOT_SFR_OR_SADDR;
772 	  }
773 
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); }
779 	    else
780 	      NOT_SFR_OR_SADDR;
781 	  }
782 
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); }
788 	    else
789 	      NOT_SFR_OR_SADDR;
790 	  }
791 
792 	| MOVW AX ',' regw_na
793 	  { B1 (0x11); F ($4, 5, 2); }
794 
795 	| MOVW regw_na ',' AX
796 	  { B1 (0x10); F ($2, 5, 2); }
797 
798 	| MOVW AX ',' opt_es '!' EXPR
799 	  { B1 (0xaf); O2 ($6); WA($6); rl78_linkrelax_addr16 (); }
800 
801 	| MOVW opt_es '!' EXPR ',' AX
802 	  { B1 (0xbf); O2 ($4); WA($4); rl78_linkrelax_addr16 (); }
803 
804 	| MOVW AX ',' opt_es '[' DE ']'
805 	  { B1 (0xa9); }
806 
807 	| MOVW opt_es '[' DE ']' ',' AX
808 	  { B1 (0xb9); }
809 
810 	| MOVW AX ',' opt_es '[' DE '+' EXPR ']'
811 	  { B1 (0xaa); O1 ($8); }
812 
813 	| MOVW opt_es '[' DE '+' EXPR ']' ',' AX
814 	  { B1 (0xba); O1 ($6); }
815 
816 	| MOVW AX ',' opt_es '[' HL ']'
817 	  { B1 (0xab); }
818 
819 	| MOVW opt_es '[' HL ']' ',' AX
820 	  { B1 (0xbb); }
821 
822 	| MOVW AX ',' opt_es '[' HL '+' EXPR ']'
823 	  { B1 (0xac); O1 ($8); }
824 
825 	| MOVW opt_es '[' HL '+' EXPR ']' ',' AX
826 	  { B1 (0xbc); O1 ($6); }
827 
828 	| MOVW AX ',' opt_es EXPR '[' B ']'
829 	  { B1 (0x59); O2 ($5); }
830 
831 	| MOVW opt_es EXPR '[' B ']' ',' AX
832 	  { B1 (0x58); O2 ($3); }
833 
834 	| MOVW AX ',' opt_es EXPR '[' C ']'
835 	  { B1 (0x69); O2 ($5); }
836 
837 	| MOVW opt_es EXPR '[' C ']' ',' AX
838 	  { B1 (0x68); O2 ($3); }
839 
840 	| MOVW AX ',' opt_es EXPR '[' BC ']'
841 	  { B1 (0x79); O2 ($5); }
842 
843 	| MOVW AX ',' opt_es '[' BC ']'
844 	  { B3 (0x79, 0, 0); }
845 
846 	| MOVW opt_es EXPR '[' BC ']' ',' AX
847 	  { B1 (0x78); O2 ($3); }
848 
849 	| MOVW opt_es '[' BC ']' ',' AX
850 	  { B3 (0x78, 0, 0); }
851 
852 	| MOVW AX ',' opt_es '[' SP '+' EXPR ']' {NOT_ES}
853 	  { B1 (0xa8); O1 ($8);  WA($8);}
854 
855 	| MOVW AX ',' opt_es '[' SP ']' {NOT_ES}
856 	  { B2 (0xa8, 0); }
857 
858 	| MOVW opt_es '[' SP '+' EXPR ']' ',' AX {NOT_ES}
859 	  { B1 (0xb8); O1 ($6); WA($6); }
860 
861 	| MOVW opt_es '[' SP ']' ',' AX {NOT_ES}
862 	  { B2 (0xb8, 0); }
863 
864 	| MOVW regw_na ',' EXPR {SA($4)}
865 	  { B1 (0xca); F ($2, 2, 2); O1 ($4); WA($4); }
866 
867 	| MOVW regw_na ',' opt_es '!' EXPR
868 	  { B1 (0xcb); F ($2, 2, 2); O2 ($6); WA($6); rl78_linkrelax_addr16 (); }
869 
870 	| MOVW SP ',' '#' EXPR
871 	  { B2 (0xcb, 0xf8); O2 ($5); }
872 
873 	| MOVW SP ',' AX
874 	  { B2 (0xbe, 0xf8); }
875 
876 	| MOVW AX ',' SP
877 	  { B2 (0xae, 0xf8); }
878 
879 	| MOVW regw_na ',' SP
880 	  { B3 (0xcb, 0xf8, 0xff); F ($2, 2, 2); }
881 
882 /* ---------------------------------------------------------------------- */
883 
884 	| NOP
885 	  { B1 (0x00); }
886 
887 /* ---------------------------------------------------------------------- */
888 
889 	| NOT1 CY
890 	  { B2 (0x71, 0xc0); }
891 
892 /* ---------------------------------------------------------------------- */
893 
894 	| POP regw
895 	  { B1 (0xc0); F ($2, 5, 2); }
896 
897 	| POP PSW
898 	  { B2 (0x61, 0xcd); };
899 
900 	| PUSH regw
901 	  { B1 (0xc1); F ($2, 5, 2); }
902 
903 	| PUSH PSW
904 	  { B2 (0x61, 0xdd); };
905 
906 /* ---------------------------------------------------------------------- */
907 
908 	| RET
909 	  { B1 (0xd7); }
910 
911 	| RETI
912 	  { B2 (0x61, 0xfc); }
913 
914 	| RETB
915 	  { B2 (0x61, 0xec); }
916 
917 /* ---------------------------------------------------------------------- */
918 
919 	| ROL A ',' EXPR
920 	  { if (check_expr_is_const ($4, 1, 1))
921 	      { B2 (0x61, 0xeb); }
922 	  }
923 
924 	| ROLC A ',' EXPR
925 	  { if (check_expr_is_const ($4, 1, 1))
926 	      { B2 (0x61, 0xdc); }
927 	  }
928 
929 	| ROLWC AX ',' EXPR
930 	  { if (check_expr_is_const ($4, 1, 1))
931 	      { B2 (0x61, 0xee); }
932 	  }
933 
934 	| ROLWC BC ',' EXPR
935 	  { if (check_expr_is_const ($4, 1, 1))
936 	      { B2 (0x61, 0xfe); }
937 	  }
938 
939 	| ROR A ',' EXPR
940 	  { if (check_expr_is_const ($4, 1, 1))
941 	      { B2 (0x61, 0xdb); }
942 	  }
943 
944 	| RORC A ',' EXPR
945 	  { if (check_expr_is_const ($4, 1, 1))
946 	      { B2 (0x61, 0xfb);}
947 	  }
948 
949 /* ---------------------------------------------------------------------- */
950 
951 	| SAR A ',' EXPR
952 	  { if (check_expr_is_const ($4, 1, 7))
953 	      { B2 (0x31, 0x0b); FE ($4, 9, 3); }
954 	  }
955 
956 	| SARW AX ',' EXPR
957 	  { if (check_expr_is_const ($4, 1, 15))
958 	      { B2 (0x31, 0x0f); FE ($4, 8, 4); }
959 	  }
960 
961 /* ---------------------------------------------------------------------- */
962 
963 	| SEL RB0
964 	  { B2 (0x61, 0xcf); }
965 
966 	| SEL RB1
967 	  { B2 (0x61, 0xdf); }
968 
969 	| SEL RB2
970 	  { B2 (0x61, 0xef); }
971 
972 	| SEL RB3
973 	  { B2 (0x61, 0xff); }
974 
975 /* ---------------------------------------------------------------------- */
976 
977 	| SHL A ',' EXPR
978 	  { if (check_expr_is_const ($4, 1, 7))
979 	      { B2 (0x31, 0x09); FE ($4, 9, 3); }
980 	  }
981 
982 	| SHL B ',' EXPR
983 	  { if (check_expr_is_const ($4, 1, 7))
984 	      { B2 (0x31, 0x08); FE ($4, 9, 3); }
985 	  }
986 
987 	| SHL C ',' EXPR
988 	  { if (check_expr_is_const ($4, 1, 7))
989 	      { B2 (0x31, 0x07); FE ($4, 9, 3); }
990 	  }
991 
992 	| SHLW AX ',' EXPR
993 	  { if (check_expr_is_const ($4, 1, 15))
994 	      { B2 (0x31, 0x0d); FE ($4, 8, 4); }
995 	  }
996 
997 	| SHLW BC ',' EXPR
998 	  { if (check_expr_is_const ($4, 1, 15))
999 	      { B2 (0x31, 0x0c); FE ($4, 8, 4); }
1000 	  }
1001 
1002 /* ---------------------------------------------------------------------- */
1003 
1004 	| SHR A ',' EXPR
1005 	  { if (check_expr_is_const ($4, 1, 7))
1006 	      { B2 (0x31, 0x0a); FE ($4, 9, 3); }
1007 	  }
1008 
1009 	| SHRW AX ',' EXPR
1010 	  { if (check_expr_is_const ($4, 1, 15))
1011 	      { B2 (0x31, 0x0e); FE ($4, 8, 4); }
1012 	  }
1013 
1014 /* ---------------------------------------------------------------------- */
1015 
1016 	| SKC
1017 	  { B2 (0x61, 0xc8); rl78_linkrelax_branch (); }
1018 
1019 	| SKH
1020 	  { B2 (0x61, 0xe3); rl78_linkrelax_branch (); }
1021 
1022 	| SKNC
1023 	  { B2 (0x61, 0xd8); rl78_linkrelax_branch (); }
1024 
1025 	| SKNH
1026 	  { B2 (0x61, 0xf3); rl78_linkrelax_branch (); }
1027 
1028 	| SKNZ
1029 	  { B2 (0x61, 0xf8); rl78_linkrelax_branch (); }
1030 
1031 	| SKZ
1032 	  { B2 (0x61, 0xe8); rl78_linkrelax_branch (); }
1033 
1034 /* ---------------------------------------------------------------------- */
1035 
1036 	| STOP
1037 	  { B2 (0x61, 0xfd); }
1038 
1039 /* ---------------------------------------------------------------------- */
1040 
1041 	| XCH A ',' regb_na
1042 	  { if ($4 == 0) /* X */
1043 	      { B1 (0x08); }
1044 	    else
1045 	      { B2 (0x61, 0x88); F ($4, 13, 3); }
1046 	  }
1047 
1048 	| XCH A ',' opt_es '!' EXPR
1049 	  { B2 (0x61, 0xaa); O2 ($6); rl78_linkrelax_addr16 (); }
1050 
1051 	| XCH A ',' opt_es '[' DE ']'
1052 	  { B2 (0x61, 0xae); }
1053 
1054 	| XCH A ',' opt_es '[' DE '+' EXPR ']'
1055 	  { B2 (0x61, 0xaf); O1 ($8); }
1056 
1057 	| XCH A ',' opt_es '[' HL ']'
1058 	  { B2 (0x61, 0xac); }
1059 
1060 	| XCH A ',' opt_es '[' HL '+' EXPR ']'
1061 	  { B2 (0x61, 0xad); O1 ($8); }
1062 
1063 	| XCH A ',' opt_es '[' HL '+' B ']'
1064 	  { B2 (0x61, 0xb9); }
1065 
1066 	| XCH A ',' opt_es '[' HL '+' C ']'
1067 	  { B2 (0x61, 0xa9); }
1068 
1069 	| XCH A ',' EXPR
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); }
1074 	    else
1075 	      NOT_SFR_OR_SADDR;
1076 	  }
1077 
1078 /* ---------------------------------------------------------------------- */
1079 
1080 	| XCHW AX ',' regw_na
1081 	  { B1 (0x31); F ($4, 5, 2); }
1082 
1083 /* ---------------------------------------------------------------------- */
1084 
1085 	; /* end of statement */
1086 
1087 /* ---------------------------------------------------------------------- */
1088 
1089 opt_es	: /* nothing */
1090 	| ES ':'
1091 	  { rl78_prefix (0x11); }
1092 	;
1093 
1094 regb	: X { $$ = 0; }
1095 	| A { $$ = 1; }
1096 	| C { $$ = 2; }
1097 	| B { $$ = 3; }
1098 	| E { $$ = 4; }
1099 	| D { $$ = 5; }
1100 	| L { $$ = 6; }
1101 	| H { $$ = 7; }
1102 	;
1103 
1104 regb_na	: X { $$ = 0; }
1105 	| C { $$ = 2; }
1106 	| B { $$ = 3; }
1107 	| E { $$ = 4; }
1108 	| D { $$ = 5; }
1109 	| L { $$ = 6; }
1110 	| H { $$ = 7; }
1111 	;
1112 
1113 regw	: AX { $$ = 0; }
1114 	| BC { $$ = 1; }
1115 	| DE { $$ = 2; }
1116 	| HL { $$ = 3; }
1117 	;
1118 
1119 regw_na	: BC { $$ = 1; }
1120 	| DE { $$ = 2; }
1121 	| HL { $$ = 3; }
1122 	;
1123 
1124 sfr	: SPL { $$ = 0xf8; }
1125 	| SPH { $$ = 0xf9; }
1126 	| PSW { $$ = 0xfa; }
1127 	| CS  { $$ = 0xfc; }
1128 	| ES  { $$ = 0xfd; }
1129 	| PMC { $$ = 0xfe; }
1130 	| MEM { $$ = 0xff; }
1131 	;
1132 
1133 /* ---------------------------------------------------------------------- */
1134 /* Shortcuts for groups of opcodes with common encodings.                 */
1135 
1136 addsub	: ADD  { $$ = 0x00; }
1137 	| ADDC { $$ = 0x10; }
1138 	| SUB  { $$ = 0x20; }
1139 	| SUBC { $$ = 0x30; }
1140 	| CMP  { $$ = 0x40; }
1141 	| AND_ { $$ = 0x50; }
1142 	| OR   { $$ = 0x60; }
1143 	| XOR  { $$ = 0x70; }
1144 	;
1145 
1146 addsubw	: ADDW  { $$ = 0x00; }
1147 	| SUBW  { $$ = 0x20; }
1148 	| CMPW  { $$ = 0x40; }
1149 	;
1150 
1151 andor1	: AND1 { $$ = 0x05; rl78_bit_insn = 1; }
1152 	| OR1  { $$ = 0x06; rl78_bit_insn = 1;}
1153 	| XOR1 { $$ = 0x07; rl78_bit_insn = 1; }
1154 	;
1155 
1156 bt_bf	: BT { $$ = 0x02;    rl78_bit_insn = 1;}
1157 	| BF { $$ = 0x04;    rl78_bit_insn = 1; }
1158 	| BTCLR { $$ = 0x00; rl78_bit_insn = 1; }
1159 	;
1160 
1161 setclr1	: SET1 { $$ = 0; rl78_bit_insn = 1; }
1162 	| CLR1 { $$ = 1; rl78_bit_insn = 1; }
1163 	;
1164 
1165 oneclrb	: ONEB { $$ = 0x00; }
1166 	| CLRB { $$ = 0x10; }
1167 	;
1168 
1169 oneclrw	: ONEW { $$ = 0x00; }
1170 	| CLRW { $$ = 0x10; }
1171 	;
1172 
1173 incdec	: INC { $$ = 0x00; }
1174 	| DEC { $$ = 0x10; }
1175 	;
1176 
1177 incdecw	: INCW { $$ = 0x00; }
1178 	| DECW { $$ = 0x10; }
1179 	;
1180 
1181 mov1	: MOV1 { rl78_bit_insn = 1; }
1182 	;
1183 
1184 %%
1185 /* ====================================================================== */
1186 
1187 static struct
1188 {
1189   const char * string;
1190   int          token;
1191   int          val;
1192 }
1193 token_table[] =
1194 {
1195   { "r0", X, 0 },
1196   { "r1", A, 1 },
1197   { "r2", C, 2 },
1198   { "r3", B, 3 },
1199   { "r4", E, 4 },
1200   { "r5", D, 5 },
1201   { "r6", L, 6 },
1202   { "r7", H, 7 },
1203   { "x", X, 0 },
1204   { "a", A, 1 },
1205   { "c", C, 2 },
1206   { "b", B, 3 },
1207   { "e", E, 4 },
1208   { "d", D, 5 },
1209   { "l", L, 6 },
1210   { "h", H, 7 },
1211 
1212   { "rp0", AX, 0 },
1213   { "rp1", BC, 1 },
1214   { "rp2", DE, 2 },
1215   { "rp3", HL, 3 },
1216   { "ax", AX, 0 },
1217   { "bc", BC, 1 },
1218   { "de", DE, 2 },
1219   { "hl", HL, 3 },
1220 
1221   { "RB0", RB0, 0 },
1222   { "RB1", RB1, 1 },
1223   { "RB2", RB2, 2 },
1224   { "RB3", RB3, 3 },
1225 
1226   { "sp", SP, 0 },
1227   { "cy", CY, 0 },
1228 
1229   { "spl", SPL, 0xf8 },
1230   { "sph", SPH, 0xf9 },
1231   { "psw", PSW, 0xfa },
1232   { "cs", CS, 0xfc },
1233   { "es", ES, 0xfd },
1234   { "pmc", PMC, 0xfe },
1235   { "mem", MEM, 0xff },
1236 
1237   { ".s", DOT_S, 0 },
1238   { ".b", DOT_B, 0 },
1239   { ".w", DOT_W, 0 },
1240   { ".l", DOT_L, 0 },
1241   { ".a", DOT_A , 0},
1242   { ".ub", DOT_UB, 0 },
1243   { ".uw", DOT_UW , 0},
1244 
1245   { "c", FLAG, 0 },
1246   { "z", FLAG, 1 },
1247   { "s", FLAG, 2 },
1248   { "o", FLAG, 3 },
1249   { "i", FLAG, 8 },
1250   { "u", FLAG, 9 },
1251 
1252 #define OPC(x) { #x, x, IS_OPCODE }
1253 
1254   OPC(ADD),
1255   OPC(ADDC),
1256   OPC(ADDW),
1257   { "and", AND_, IS_OPCODE },
1258   OPC(AND1),
1259   OPC(BC),
1260   OPC(BF),
1261   OPC(BH),
1262   OPC(BNC),
1263   OPC(BNH),
1264   OPC(BNZ),
1265   OPC(BR),
1266   OPC(BRK),
1267   OPC(BRK1),
1268   OPC(BT),
1269   OPC(BTCLR),
1270   OPC(BZ),
1271   OPC(CALL),
1272   OPC(CALLT),
1273   OPC(CLR1),
1274   OPC(CLRB),
1275   OPC(CLRW),
1276   OPC(CMP),
1277   OPC(CMP0),
1278   OPC(CMPS),
1279   OPC(CMPW),
1280   OPC(DEC),
1281   OPC(DECW),
1282   OPC(DI),
1283   OPC(DIVHU),
1284   OPC(DIVWU),
1285   OPC(EI),
1286   OPC(HALT),
1287   OPC(INC),
1288   OPC(INCW),
1289   OPC(MACH),
1290   OPC(MACHU),
1291   OPC(MOV),
1292   OPC(MOV1),
1293   OPC(MOVS),
1294   OPC(MOVW),
1295   OPC(MULH),
1296   OPC(MULHU),
1297   OPC(MULU),
1298   OPC(NOP),
1299   OPC(NOT1),
1300   OPC(ONEB),
1301   OPC(ONEW),
1302   OPC(OR),
1303   OPC(OR1),
1304   OPC(POP),
1305   OPC(PUSH),
1306   OPC(RET),
1307   OPC(RETI),
1308   OPC(RETB),
1309   OPC(ROL),
1310   OPC(ROLC),
1311   OPC(ROLWC),
1312   OPC(ROR),
1313   OPC(RORC),
1314   OPC(SAR),
1315   OPC(SARW),
1316   OPC(SEL),
1317   OPC(SET1),
1318   OPC(SHL),
1319   OPC(SHLW),
1320   OPC(SHR),
1321   OPC(SHRW),
1322   OPC(SKC),
1323   OPC(SKH),
1324   OPC(SKNC),
1325   OPC(SKNH),
1326   OPC(SKNZ),
1327   OPC(SKZ),
1328   OPC(STOP),
1329   OPC(SUB),
1330   OPC(SUBC),
1331   OPC(SUBW),
1332   OPC(XCH),
1333   OPC(XCHW),
1334   OPC(XOR),
1335   OPC(XOR1),
1336 };
1337 
1338 #define NUM_TOKENS (sizeof (token_table) / sizeof (token_table[0]))
1339 
1340 void
1341 rl78_lex_init (char * beginning, char * ending)
1342 {
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;
1348 
1349   rl78_bit_insn = 0;
1350 
1351   setbuf (stdout, 0);
1352 }
1353 
1354 /* Return a pointer to the '.' in a bit index expression (like
1355    foo.5), or NULL if none is found.  */
1356 static char *
1357 find_bit_index (char *tok)
1358 {
1359   char *last_dot = NULL;
1360   char *last_digit = NULL;
1361   while (*tok && *tok != ',')
1362     {
1363       if (*tok == '.')
1364 	{
1365 	  last_dot = tok;
1366 	  last_digit = NULL;
1367 	}
1368       else if (*tok >= '0' && *tok <= '7'
1369 	       && last_dot != NULL
1370 	       && last_digit == NULL)
1371 	{
1372 	  last_digit = tok;
1373 	}
1374       else if (ISSPACE (*tok))
1375 	{
1376 	  /* skip */
1377 	}
1378       else
1379 	{
1380 	  last_dot = NULL;
1381 	  last_digit = NULL;
1382 	}
1383       tok ++;
1384     }
1385   if (last_dot != NULL
1386       && last_digit != NULL)
1387     return last_dot;
1388   return NULL;
1389 }
1390 
1391 static int
1392 rl78_lex (void)
1393 {
1394   /*unsigned int ci;*/
1395   char * save_input_pointer;
1396   char * bit = NULL;
1397 
1398   while (ISSPACE (*rl78_lex_start)
1399 	 && rl78_lex_start != rl78_lex_end)
1400     rl78_lex_start ++;
1401 
1402   rl78_last_exp_start = rl78_lex_start;
1403 
1404   if (rl78_lex_start == rl78_lex_end)
1405     return 0;
1406 
1407   if (ISALPHA (*rl78_lex_start)
1408       || (*rl78_lex_start == '.' && ISALPHA (rl78_lex_start[1])))
1409     {
1410       unsigned int i;
1411       char * e;
1412       char save;
1413 
1414       for (e = rl78_lex_start + 1;
1415 	   e < rl78_lex_end && ISALNUM (*e);
1416 	   e ++)
1417 	;
1418       save = *e;
1419       *e = 0;
1420 
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))
1425 	  {
1426 	    rl78_lval.regno = token_table[i].val;
1427 	    *e = save;
1428 	    rl78_lex_start = e;
1429 	    rl78_last_token = token_table[i].token;
1430 	    return token_table[i].token;
1431 	  }
1432       *e = save;
1433     }
1434 
1435   if (rl78_last_token == 0)
1436     {
1437       rl78_last_token = UNKNOWN_OPCODE;
1438       return UNKNOWN_OPCODE;
1439     }
1440 
1441   if (rl78_last_token == UNKNOWN_OPCODE)
1442     return 0;
1443 
1444   if (*rl78_lex_start == '[')
1445     rl78_in_brackets = 1;
1446   if (*rl78_lex_start == ']')
1447     rl78_in_brackets = 0;
1448 
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.  */
1452 
1453   if (rl78_bit_insn
1454       && *rl78_lex_start == '.'
1455       && find_bit_index (rl78_lex_start) == rl78_lex_start)
1456     {
1457       rl78_last_token = *rl78_lex_start;
1458       return *rl78_lex_start ++;
1459     }
1460 
1461   if ((rl78_in_brackets && *rl78_lex_start == '+')
1462       || strchr ("[],#!$:", *rl78_lex_start))
1463     {
1464       rl78_last_token = *rl78_lex_start;
1465       return *rl78_lex_start ++;
1466     }
1467 
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.  */
1470 
1471   if (rl78_bit_insn)
1472     {
1473       bit = find_bit_index (rl78_lex_start);
1474       if (bit)
1475 	*bit = 0;
1476       else
1477 	bit = NULL;
1478     }
1479 
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);
1484 
1485   if (bit)
1486     *bit = '.';
1487 
1488   rl78_lex_start = input_line_pointer;
1489   input_line_pointer = save_input_pointer;
1490   rl78_last_token = EXPR;
1491   return EXPR;
1492 }
1493 
1494 int
1495 rl78_error (const char * str)
1496 {
1497   int len;
1498 
1499   len = rl78_last_exp_start - rl78_init_start;
1500 
1501   as_bad ("%s", rl78_init_start);
1502   as_bad ("%*s^ %s", len, "", str);
1503   return 0;
1504 }
1505 
1506 static int
1507 expr_is_sfr (expressionS exp)
1508 {
1509   unsigned long v;
1510 
1511   if (exp.X_op != O_constant)
1512     return 0;
1513 
1514   v = exp.X_add_number;
1515   if (0xFFF00 <= v && v <= 0xFFFFF)
1516     return 1;
1517   return 0;
1518 }
1519 
1520 static int
1521 expr_is_saddr (expressionS exp)
1522 {
1523   unsigned long v;
1524 
1525   if (exp.X_op != O_constant)
1526     return 0;
1527 
1528   v = exp.X_add_number;
1529   if (0xFFE20 <= v && v <= 0xFFF1F)
1530     return 1;
1531   return 0;
1532 }
1533 
1534 static int
1535 expr_is_word_aligned (expressionS exp)
1536 {
1537   unsigned long v;
1538 
1539   if (exp.X_op != O_constant)
1540     return 1;
1541 
1542   v = exp.X_add_number;
1543   if (v & 1)
1544     return 0;
1545   return 1;
1546 
1547 }
1548 
1549 static void
1550 check_expr_is_bit_index (expressionS exp)
1551 {
1552   int val;
1553 
1554   if (exp.X_op != O_constant)
1555     {
1556       rl78_error (_("bit index must be a constant"));
1557       return;
1558     }
1559   val = exp.X_add_number;
1560 
1561   if (val < 0 || val > 7)
1562     rl78_error (_("rtsd size must be 0..7"));
1563 }
1564 
1565 static int
1566 exp_val (expressionS exp)
1567 {
1568   if (exp.X_op != O_constant)
1569   {
1570     rl78_error (_("constant expected"));
1571     return 0;
1572   }
1573   return exp.X_add_number;
1574 }
1575 
1576 static int
1577 check_expr_is_const (expressionS e, int vmin, int vmax)
1578 {
1579   static char buf[100];
1580   if (e.X_op != O_constant
1581       || e.X_add_number < vmin
1582       || e.X_add_number > vmax)
1583     {
1584       if (vmin == vmax)
1585 	sprintf (buf, "%d expected here", vmin);
1586       else
1587 	sprintf (buf, "%d..%d expected here", vmin, vmax);
1588       rl78_error(buf);
1589       return 0;
1590     }
1591   return 1;
1592 }
1593 
1594 
1595