work in progress
[fw/sdcc] / as / xa51 / xa_rasm.y
1 %{
2 /* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
3  *
4  * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2.
7  *
8  * Paul's XA51 Assembler is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with Foobar; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17
18 /* Author contact: paul@pjrc.com */
19
20 /* parser for the 51-XA assembler, Paul Stoffregen, July 1997 */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "xa_main.h"
26   
27 int op[MAX_DB];
28 int size;
29 int inst_size;
30 int arith_opcode, short_opcode, num_op, opcode0, opcode1;
31 int shift_imm_opcode, shift_reg_opcode, rotate_opcode;
32 int stack_addr_opcode, stack_reg_opcode, branch_opcode;
33 int rlist_reg_bank, rlist_bitmask, rlist_size;
34 int db_count, dw_count, i;
35 char symbol_name[MAX_SYMBOL], base_symbol_name[MAX_SYMBOL]={'\0'};
36 char expr_var[2][MAX_SYMBOL]={{'\0'},{'\0'}};
37
38 extern char lex_sym_name[];
39 extern int yylex();
40
41 extern void yyrestart(FILE *new_file);
42 extern char * disasm(int byte, int memory_location);
43 void error(char *s);
44
45
46 void RELOC_FF(unsigned pc, unsigned short offset, short rl) {
47   struct symbol *sym;
48   if ((sym=findSymbol(yytext))) {
49     if (sym->mode=='X') {
50       sprintf (rel_line[rl], "R %d REL_FF 0x%04x %s", offset, pc,
51                sym->name);
52     }
53   }
54 }
55  
56 void RELOC_FFFF(unsigned pc, unsigned short offset, short rl) {
57   struct symbol *sym;
58   if ((sym=findSymbol(yytext))) {
59     if (sym->mode=='X') {
60       sprintf (rel_line[rl], "R %d REL_FFFF 0x%04x %s", offset, pc,
61                sym->name);
62     }
63   }
64 }
65  
66 void RELOC_ABS_0F(unsigned short offset, int expr) {
67   struct symbol *sym;
68   if ((sym=findSymbol(expr_var[expr]))) {
69     if (sym->mode=='X') {
70       sprintf (rel_line[expr], "R %d ABS_0F %s", offset, sym->name);
71     }
72   }
73 }
74
75 void RELOC_ABS_FF(unsigned short offset, int expr) {
76   struct symbol *sym;
77   if ((sym=findSymbol(expr_var[expr]))) {
78     if (sym->mode=='X') {
79       sprintf (rel_line[expr], "R %d ABS_FF %s", offset, sym->name);
80     }
81   }
82 }
83
84 void RELOC_ABS_03FF(unsigned short offset, int expr) {
85   struct symbol *sym;
86   if (expr_var[0]) {
87     if ((sym=findSymbol(expr_var[expr]))) {
88       if (sym->mode=='X') {
89         sprintf (rel_line[expr], "R %d ABS_03FF %s", offset, sym->name);
90       }
91     }
92   }
93 }
94
95 void RELOC_ABS_07ff(unsigned short offset, int expr) {
96   struct symbol *sym;
97   if (expr_var[0]) {
98     if ((sym=findSymbol(expr_var[expr]))) {
99       if (sym->mode=='X') {
100         sprintf (rel_line[expr], "R %d ABS_07ff %s", offset, sym->name);
101       }
102     }
103   }
104 }
105
106 void RELOC_ABS_F0FF(unsigned short offset, int expr) {
107   struct symbol *sym;
108   if (expr_var[0]) {
109     if ((sym=findSymbol(expr_var[expr]))) {
110       if (sym->mode=='X') {
111         sprintf (rel_line[expr], "R %d ABS_F0FF %s", offset, sym->name);
112       }
113     }
114   }
115 }
116  
117 void RELOC_ABS_FFFF(unsigned short offset, int expr) {
118   struct symbol *sym;
119   if (expr_var[0]) {
120     if ((sym=findSymbol(expr_var[expr]))) {
121       if (sym->mode=='X') {
122 #if 1
123         sprintf (rel_line[expr], "R %d ABS_FFFF %s", offset, sym->name);
124 #else
125         sprintf (rel_line[expr], "R 0 0 00 %02x 02 %02x %02x", current_area, 
126                  (sym->lk_index>>8)&0xff, sym->lk_index&&0xff);
127 #endif
128       }
129     }
130   }
131 }
132  
133 void RELOC_ABS_0F00FF(unsigned short offset, int expr) {
134   struct symbol *sym;
135   if (expr_var[0]) {
136     if ((sym=findSymbol(expr_var[expr]))) {
137       if (sym->mode=='X') {
138         sprintf (rel_line[expr], "R %d ABS_0F00FF %s", offset, sym->name);
139       }
140     }
141   }
142 }
143  
144 %}
145
146 %token ADD ADDC ADDS AND ANL ASL ASR BCC BCS BEQ BG BGE BGT
147 %token BKPT BL BLE BLT BMI BNE BNV BOV BPL BR CALL CJNE CLR
148 %token CMP CPL DA DIV DIVU DJNZ FCALL FJMP JB JBC JMP JNB JNZ
149 %token JZ LEA LSR MOV MOVC MOVS MOVX MUL MULU NEG NOP NORM
150 %token OR ORL POP POPU PUSH PUSHU RESET RET RETI RL RLC RR RRC
151 %token SETB SEXT SUB SUBB TRAP XCH XOR
152 %token REG DPTR PC A C USP
153 %token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
154 %token ORG EQU SFR DB DW BITDEF REGDEF LOW HIGH
155 %token RSHIFT LSHIFT
156 %token AREA AREA_NAME AREA_DESC DS
157 %token MODULE GLOBL 
158
159 %left '&' '|' '^'
160 %left RSHIFT LSHIFT
161 %left '+' '-'
162 %left '*' '/'
163 %nonassoc UNARY
164
165 %%
166
167 all:           line
168              | line all;
169
170 line:          linesymbol ':' linenosym {
171                         if (p1) {
172                                 build_sym_list(symbol_name);
173                                 if (current_area == AREA_BSEG) {
174                                         mk_bit(symbol_name, current_area);
175                                 }
176                         }
177                         if (p1 || p2) assign_value(symbol_name, MEM_POS, 'R');
178                         MEM_POS += $3;
179                 }
180              | linenosym {
181                         MEM_POS += $1;
182                 }
183
184 linenosym:     directive EOL {
185                         if (p3) out(op, $1);
186                         $$ = $1;
187                 }
188              | instruction EOL {
189                         if (p3) out(op, $1);
190                         $$ = $1;
191                 }
192              | EOL {
193                         if (p3) out(NULL, 0);
194                         $$ = 0;
195                 }
196              | error EOL        /* try to recover from any parse error */
197
198
199 directive:     '.' ORG expr {
200                         MEM_POS = $3;
201                         $$ = 0;
202                 }
203              | ORG expr {
204                         MEM_POS = $2;
205                         $$ = 0;
206                 }
207              | '.' EQU symbol ',' expr { 
208                         if (p1) build_sym_list(symbol_name);
209                         if (p1 || p2) assign_value(symbol_name, $5, '?');
210                         $$ = 0;
211                 }
212              | normal_or_bit_symbol '=' expr {
213                         if (p1) build_sym_list(symbol_name);
214                         if (p1 || p2) assign_value(symbol_name, $3, '?');
215                 }
216              | symbol SFR expr {
217                         if (p1) build_sym_list(symbol_name);
218                         if (p1 || p2) assign_value(symbol_name, $3, 'A');
219                         if (p1 || p2) mk_sfr(symbol_name);
220                         $$ = 0;
221                 }
222              | '.' BITDEF bitsymbol ',' bit {
223                         if (p1) {
224                                 build_sym_list(symbol_name);
225                                 mk_bit(symbol_name, 0);
226                         }
227                         if (p1 || p2) assign_value(symbol_name, $5, '?');
228                         $$ = 0;
229                 }
230              | bitsymbol BITDEF bit {
231                         if (p1) {
232                                 build_sym_list(symbol_name);
233                                 mk_bit(symbol_name, 0);
234                         }
235                         if (p1 || p2) assign_value(symbol_name, $3, '?');
236                         $$ = 0;
237                 }
238              | bitsymbol BITDEF expr {
239                         if (p1) {
240                                 build_sym_list(symbol_name);
241                                 mk_bit(symbol_name, 0);
242                         }
243                         if (p1 || p2) assign_value(symbol_name, $3, 'A');
244                         $$ = 0;
245                 }
246              | '.' REGDEF regsymbol ',' REG {
247                         if (p1) {
248                                 build_sym_list(symbol_name);
249                                 mk_reg(symbol_name);
250                         }
251                         if (p1 || p2) assign_value(symbol_name, $5, '?');
252                         $$ = 0;
253                 }
254              | regsymbol REGDEF REG {
255                         if (p1) {
256                                 build_sym_list(symbol_name);
257                                 mk_reg(symbol_name);
258                         }
259                         if (p1 || p2) assign_value(symbol_name, $3, '?');
260                         $$ = 0;
261                 }
262
263              | '.' db_directive bytes {
264                         $$ = db_count;
265                 }
266              | '.' dw_directive words {
267                         $$ = dw_count;
268                 }
269              | '.' AREA AREA_NAME AREA_DESC {
270                         if ($3 < 0 || $3 > NUM_AREAS) {
271                                 error("Illegal Area Directive");
272                         }
273                         symbol_name[0] = '\0';
274                         current_area = $3;
275                         $$ = 0;
276                 }
277              | '.' MODULE WORD {
278                         /* ignore module definition */
279                         $$ = 0;
280                 }
281              | '.' GLOBL WORD {
282                         /* ignore global symbol declaration */
283                         $$ = 0;
284                 }
285              | '.' GLOBL bit {
286                         /* ignore bit symbol declaration */
287                         $$ = 0;
288                 }
289              | '.' DS expr {
290                         /* todo: if CSEG, emit some filler bytes */
291                         $$ = $3;
292                 }
293
294 db_directive:   DB {db_count = 0;}
295
296
297 linesymbol:    normal_or_bit_symbol  { 
298                         strcpy(symbol_name, lex_sym_name);
299                         if (!strchr(lex_sym_name, ':')) {
300                                 /* non-local label, remember base name */
301                                 strcpy(base_symbol_name, lex_sym_name);
302                         }
303                         if (is_target(symbol_name)) pad_with_nop();
304                 }
305
306 normal_or_bit_symbol: WORD {$$ = $1;}
307                 | BIT {$$ = $1;}
308
309 bytes:            byte_element
310                 | bytes ',' byte_element
311
312 byte_element:   expr {
313                         op[db_count] = $1 & 255;
314                         if (++db_count >= MAX_DB) {
315                                 error("too many bytes, use two DB");
316                                 db_count--;
317                         }
318                 }
319                 | STRING {
320                         for(i=1; i < strlen(yytext)-1; i++) {
321                                 op[db_count++] = yytext[i];
322                                 if (db_count >= MAX_DB) {
323                                         error("too many bytes, use two DB");
324                                         db_count--;
325                                 }
326                         }
327                 }
328
329 dw_directive:   DW {dw_count = 0;}
330
331 words:            words ',' word_element
332                 | word_element
333
334 word_element:   expr {
335                         op[dw_count] = $1 & 255;
336                         op[dw_count+1] = ($1 >> 8) & 255;
337                         dw_count += 2;
338                         if (dw_count >= MAX_DB) {
339                                 error("too many bytes, use two DW");
340                                 db_count -= 2;
341                         }
342                 }
343
344
345
346 symbol:     WORD  {
347                 strcpy(symbol_name, lex_sym_name);
348                 }
349
350 bitsymbol:    WORD { strcpy(symbol_name, lex_sym_name); }
351             | BIT  { strcpy(symbol_name, lex_sym_name); }
352
353
354 regsymbol:    WORD { strcpy(symbol_name, lex_sym_name); }
355             | REG  { strcpy(symbol_name, lex_sym_name); }
356
357 bit:    expr '.' expr {
358                 if ($3 < 0 || $3 > 7) {
359                         /* only 8 bits in a byte */
360                         error("Only eight bits in a byte");
361                 }
362                 $$ = 100000;    /* should really check $1 is valid */
363                 if ($1 >= 0x20 && $1 <= 0x3F) {
364                         $$ = $1 * 8 + $3;
365                 }
366                 if ($1 >= 0x400 && $1 <= 0x43F) {
367                         $$ = ($1 - 0x400) * 8 + $3 + 0x200;
368                 }
369         }
370         | REG '.' expr {
371                 $$ = 100000;
372                 if (find_size_reg($1) == SIZE8) {
373                         if ($3 < 0 || $3 > 7)
374                                 error("byte reg has only 8 bits");
375                         $$ = reg($1) * 8 + $3;
376                 }
377                 if (find_size_reg($1) == SIZE16) {
378                         if ($3 < 0 || $3 > 15)
379                                 error("word reg has only 16 bits");
380                         $$ = reg($1) * 16 + $3;
381                 }
382         }
383         | BIT {$$ = $1;}
384
385 jmpaddr:        WORD {
386                         $$ = $1;
387                         if (p1) build_target_list(lex_sym_name);
388                 }
389               | NUMBER {
390                         if ($1 & 1) error("Jump target must be aligned");
391                         $$ = $1;
392                 }
393
394
395 expr:   value   {$$ = $1;}
396         | expr '+' expr {$$ = $1 + $3;}
397         | expr '-' expr {$$ = $1 - $3;}
398         | expr '*' expr {$$ = $1 * $3;}
399         | expr '/' expr {$$ = $1 / $3;}
400         | expr '&' expr {$$ = $1 & $3;}
401         | expr '|' expr {$$ = $1 | $3;}
402         | expr '^' expr {$$ = $1 ^ $3;}
403         | expr RSHIFT expr {$$ = $1 >> $3;}
404         | expr LSHIFT expr {$$ = $1 << $3;}
405         | '-' expr %prec UNARY {$$ = $2 * -1;}
406         | '+' expr %prec UNARY {$$ = $2;}
407         | '(' expr ')' {$$ = $2;}
408         | LOW expr %prec UNARY {$$ = $2 & 255;}
409         | HIGH expr %prec UNARY {$$ = ($2 >> 8) & 255;}
410
411
412 value:    NUMBER {$$ = $1;}
413         | CHAR {$$ = $1;}
414         | WORD {
415           $$ = $1; 
416           if (expr_var[0][0]=='\0') {
417             strcpy(expr_var[0], yytext);
418           } else {
419             strcpy(expr_var[1], yytext);
420           }
421         }
422
423
424 rlist:  REG {
425                 rlist_bitmask = 1<<(reg($1) % 8);
426                 rlist_reg_bank = (reg($1) / 8) ? 1 : 0;
427                 rlist_size = find_size_reg($1);
428         }
429         | REG ',' rlist {
430                 rlist_bitmask |= 1<<(reg($1) % 8);
431                 if (rlist_reg_bank != ((reg($1) / 8) ? 1 : 0))
432                         error("register list may not mix 0-7/8-15 regs");
433                 if (rlist_size != find_size_reg($1))
434                         error("register list may not mix 8/16 bit registers");
435         }
436
437
438
439
440
441 instruction:
442
443   arith_inst REG ',' REG {
444         $$ = 2;
445         size = find_size2(inst_size, $2, $4);
446         op[0] = arith_opcode * 16 + size * 8 + 1;
447         op[1] = reg($2) * 16 + reg($4);
448   }
449 | arith_inst REG ',' '[' REG ']' {
450         $$ = 2;
451         size = find_size1(inst_size, $2);
452         op[0] = arith_opcode * 16 + size * 8 + 2;
453         op[1] = reg($2) * 16 + reg_indirect($5);
454   }
455 | arith_inst '[' REG ']' ',' REG {
456         $$ = 2;
457         size = find_size1(inst_size, $6);
458         op[0] = arith_opcode * 16 + size * 8 + 2;
459         op[1] = reg($6) * 16 + 8 + reg_indirect($3);
460   }
461 | arith_inst REG ',' '[' REG '+' expr ']' {
462         size = find_size1(inst_size, $2);
463         if ($7 >= -128 && $7 <= 127) {
464                 $$ = 3;
465                 op[0] = arith_opcode * 16 + size * 8 + 4;
466                 op[1] = reg($2) * 16 + reg_indirect($5);
467                 op[2] = ($7 >= 0) ? $7 : 256 + $7;
468                 RELOC_ABS_FF(2,0);
469         } else {
470                 $$ = 4;
471                 op[0] = arith_opcode * 16 + size * 8 + 5;
472                 op[1] = reg($2) * 16 + reg_indirect($5);
473                 op[2] = ($7 >= 0) ? msb($7) : msb(65536 + $7);
474                 op[3] = ($7 >= 0) ? lsb($7) : lsb(65536 + $7);
475                 RELOC_ABS_FFFF(2,0);
476         }
477   }
478 | arith_inst '[' REG '+' expr ']' ',' REG {
479         size = find_size1(inst_size, $8);
480         if ($5 >= -128 && $5 <= 127) {
481                 $$ = 3;
482                 op[0] = arith_opcode * 16 + size * 8 + 4;
483                 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
484                 op[2] = ($5 >= 0) ? $5 : 256 + $5;
485                 RELOC_ABS_FF(2,0);
486         } else {
487                 $$ = 4;
488                 op[0] = arith_opcode * 16 + size * 8 + 5;
489                 op[1] = reg($8) * 16 + 8 + reg_indirect($3);
490                 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
491                 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
492                 RELOC_ABS_FFFF(2,0);
493         }
494   }
495 | arith_inst REG ',' '[' REG '+' ']' {
496         $$ = 2;
497         size = find_size1(inst_size, $2);
498         op[0] = arith_opcode * 16 + size * 8 + 3;
499         op[1] = reg($2) * 16 + reg_indirect($5);
500   }
501 | arith_inst '[' REG '+' ']' ',' REG {
502         $$ = 2;
503         size = find_size1(inst_size, $7);
504         op[0] = arith_opcode * 16 + size * 8 + 3;
505         op[1] = reg($7) * 16 + 8 + reg_indirect($3);
506   }
507 | arith_inst WORD ',' REG {
508         $$ = 3;
509         size = find_size1(inst_size, $4);
510         op[0] = arith_opcode * 16 + size * 8 + 6;
511         op[1] = reg($4) * 16 + 8 + msb(direct_addr($2));
512         op[2] = lsb(direct_addr($2));
513         RELOC_ABS_07ff(1, 0);
514   }
515 | arith_inst REG ',' WORD {
516         $$ = 3;
517         size = find_size1(inst_size, $2);
518         op[0] = arith_opcode * 16 + size * 8 + 6;
519         op[1] = reg($2) * 16 + msb(direct_addr($4));
520         op[2] = lsb(direct_addr($4));
521         RELOC_ABS_07ff(1, 0);
522   }
523 | arith_inst REG ',' '#' expr {
524         size = find_size1(inst_size, $2);
525         if (size == SIZE8) {
526                 $$ = 3;
527                 op[0] = 0x91;
528                 op[1] = reg($2) * 16 + arith_opcode;
529                 op[2] = imm_data8($5);
530                 RELOC_ABS_FF(2, 0);
531         } else {
532                 $$ = 4;
533                 op[0] = 0x99;
534                 op[1] = reg($2) * 16 + arith_opcode;
535                 op[2] = msb(imm_data16($5));
536                 op[3] = lsb(imm_data16($5));
537                 RELOC_ABS_FFFF (2, 0);
538         }
539   }
540 | arith_inst '[' REG ']' ',' '#' expr {
541         size = find_size0(inst_size);
542         if (size == SIZE8) {
543                 $$ = 3;
544                 op[0] = 0x92;
545                 op[1] = reg_indirect($3) * 16 + arith_opcode;
546                 op[2] = imm_data8($7);
547                 RELOC_ABS_FF(2, 0);
548         } else {
549                 $$ = 4;
550                 op[0] = 0x9A;
551                 op[1] = reg_indirect($3) * 16 + arith_opcode;
552                 op[2] = msb(imm_data16($7));
553                 op[3] = lsb(imm_data16($7));
554                 RELOC_ABS_FFFF (2, 0);
555         }
556   }
557 | arith_inst '[' REG '+' ']' ',' '#' expr {
558         size = find_size0(inst_size);
559         if (size == SIZE8) {
560                 $$ = 3;
561                 op[0] = 0x93;
562                 op[1] = reg_indirect($3) * 16 + arith_opcode;
563                 op[2] = imm_data8($8);
564                 RELOC_ABS_FF(2, 0);
565         } else {
566                 $$ = 4;
567                 op[0] = 0x9B;
568                 op[1] = reg_indirect($3) * 16 + arith_opcode;
569                 op[2] = msb(imm_data16($8));
570                 op[3] = lsb(imm_data16($8));
571                 RELOC_ABS_FFFF (2, 0);
572         }
573   }
574 | arith_inst '[' REG '+' expr ']' ',' '#' expr {
575         size = find_size0(inst_size);
576         if ($5 >= -128 && $5 <= 127) {
577                 if (size == SIZE8) {
578                         $$ = 4;
579                         op[0] = 0x94;
580                         op[1] = reg_indirect($3) * 16 + arith_opcode;
581                         op[2] = ($5 >= 0) ? $5 : 256 + $5;
582                         op[3] = imm_data8($9);
583                         RELOC_ABS_FF(2, 0);
584                         RELOC_ABS_FF(3, 1);
585                 } else {
586                         $$ = 5;
587                         op[0] = 0x9C;
588                         op[1] = reg_indirect($3) * 16 + arith_opcode;
589                         op[2] = ($5 >= 0) ? $5 : 256 + $5;
590                         op[3] = msb(imm_data16($9));
591                         op[4] = lsb(imm_data16($9));
592                         RELOC_ABS_FF(2, 0);
593                         RELOC_ABS_FFFF(3, 1);
594                 }
595         } else {
596                 if (size == SIZE8) {
597                         $$ = 5;
598                         op[0] = 0x95;
599                         op[1] = reg_indirect($3) * 16 + arith_opcode;
600                         op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
601                         op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
602                         op[4] = imm_data8($9);
603                         RELOC_ABS_FFFF(2,0);
604                         RELOC_ABS_FF(4,1);
605                 } else {
606                         $$ = 6;
607                         op[0] = 0x9D;
608                         op[1] = reg_indirect($3) * 16 + arith_opcode;
609                         op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
610                         op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
611                         op[4] = msb(imm_data16($9));
612                         op[5] = lsb(imm_data16($9));
613                         RELOC_ABS_FFFF(2, 0);
614                         RELOC_ABS_FFFF(4, 1);
615                 }
616         }
617   }
618 | arith_inst WORD ',' '#' expr {
619         size = find_size0(inst_size);
620         if (size == SIZE8) {
621                 $$ = 4;
622                 op[0] = 0x96;
623                 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
624                 op[2] = lsb(direct_addr($2));
625                 op[3] = imm_data8($5);
626                 RELOC_ABS_F0FF(1,0);
627                 RELOC_ABS_FF(3,1);
628         } else {
629                 $$ = 5;
630                 op[0] = 0x9E;
631                 op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
632                 op[2] = lsb(direct_addr($2));
633                 op[3] = msb(imm_data16($5));
634                 op[4] = lsb(imm_data16($5));
635                 RELOC_ABS_F0FF(1,0);
636                 RELOC_ABS_FFFF (3,1);
637         }
638   }
639
640 /* the next 8 instructions are MOV, but because MOV was used in the */
641 /* arith_inst group, it will cause a shift/reduce conflict if used */
642 /* directly below... so we're forced to use arith_inst and then */
643 /* add a bit of code to make sure it was MOV and not the other ones */
644
645 | arith_inst '[' REG '+' ']' ',' '[' REG '+' ']' {
646         /* this addr mode is only valid for MOV */
647         if (arith_opcode != 8) error("Addr mode only valid for MOV (1)");
648         size = find_size0(inst_size);
649         $$ = 2;
650         op[0] = 0x90 + size * 8;
651         op[1] = reg_indirect($3) * 16 + reg_indirect($8);
652   }
653 | arith_inst WORD ',' '[' REG ']' {
654         /* this addr mode is only valid for MOV */
655         if (arith_opcode != 8) error("Addr mode only valid for MOV (2)");
656         size = find_size0(inst_size);
657         $$ = 3;
658         op[0] = 0xA0 + size * 8;
659         op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2));
660         op[2] = lsb(direct_addr($2));
661         RELOC_ABS_07ff(1, 0);
662   }
663 | arith_inst '[' REG ']' ',' WORD {
664         /* this addr mode is only valid for MOV */
665         if (arith_opcode != 8) error("Addr mode only valid for MOV (3)");
666         size = find_size0(inst_size);
667         $$ = 3;
668         op[0] = 0xA0 + size * 8;
669         op[1] = reg_indirect($3) * 16 + msb(direct_addr($6));
670         op[2] = lsb(direct_addr($6));
671         RELOC_ABS_07ff(1, 0);
672   }
673 | arith_inst WORD ',' WORD {
674         /* this addr mode is only valid for MOV */
675         if (arith_opcode != 8) error("Addr mode only valid for MOV (4)");
676         size = find_size0(inst_size);
677         $$ = 4;
678         op[0] = 0x97 + size * 8;
679         op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4));
680         op[2] = lsb(direct_addr($2));
681         op[3] = lsb(direct_addr($4));
682         RELOC_ABS_F0FF(1, 0);
683         RELOC_ABS_0F00FF(1, 1);
684   }
685 | arith_inst REG ',' USP {
686         /* this addr mode is only valid for MOV */
687         if (arith_opcode != 8) error("Addr mode only valid for MOV (5)");
688         $$ = 2;
689         op[0] = 0x90;
690         op[1] = reg($2) * 16 + 15;
691   }
692 | arith_inst USP ',' REG {
693         /* this addr mode is only valid for MOV */
694         if (arith_opcode != 8) error("Addr mode only valid for MOV (6)");
695         $$ = 2;
696         op[0] = 0x98;
697         op[1] = reg($4) * 16 + 15;
698   }
699 | arith_inst C ',' bit {
700         /* this addr mode is only valid for MOV */
701         if (arith_opcode != 8) error("Addr mode only valid for MOV (7)");
702         $$ = 3;
703         op[0] = 0x08;
704         op[1] = 0x20 + msb(bit_addr($4));
705         op[2] = lsb(bit_addr($4));
706         RELOC_ABS_03FF(1, 0);
707   }
708 | arith_inst bit ',' C {
709         /* this addr mode is only valid for MOV */
710         if (arith_opcode != 8) error("Addr mode only valid for MOV (8)");
711         $$ = 3;
712         op[0] = 0x08;
713         op[1] = 0x30 + msb(bit_addr($2));
714         op[2] = lsb(bit_addr($2));
715         RELOC_ABS_03FF(1, 0);
716   }
717
718 | MOVC REG ',' '[' REG '+' ']' {
719         size = find_size1(inst_size, $2);
720         $$ = 2;
721         op[0] = 0x80 + size * 8;
722         op[1] = reg($2) * 16 + reg_indirect($5);
723   }
724 | MOVC A ',' '[' A '+' DPTR ']' {
725         $$ = 2;
726         op[0] = 0x90;
727         op[1] = 0x4E;
728   }
729 | MOVC A ',' '[' A '+' PC ']' {
730         $$ = 2;
731         op[0] = 0x90;
732         op[1] = 0x4C;
733   }
734 | MOVX REG ',' '[' REG ']' {
735         $$ = 2;
736         size = find_size1(inst_size, $2);
737         op[0] = 0xA7 + size * 8;
738         op[1] = reg($2) * 16 + reg_indirect($5);
739   }
740 | MOVX '[' REG ']' ',' REG {
741         $$ = 2;
742         size = find_size1(inst_size, $6);
743         op[0] = 0xA7 + size * 8;
744         op[1] = reg($6) * 16 + 8 + reg_indirect($3);
745   }
746 | XCH REG ',' REG {
747         $$ = 2;
748         size = find_size2(inst_size, $2, $4);
749         op[0] = 0x60 + size * 8;
750         op[1] = reg($2) * 16 + reg($4);
751   }
752 | XCH REG ',' '[' REG ']' {
753         $$ = 2;
754         size = find_size1(inst_size, $2);
755         op[0] = 0x50 + size * 8;
756         op[1] = reg($2) * 16 + reg_indirect($5);
757   }
758 | XCH REG ',' WORD {
759         $$ = 3;
760         size = find_size1(inst_size, $2);
761         op[0] = 0xA0 + size * 8;
762         op[1] = reg($2) * 16 + msb(direct_addr($4));
763         op[2] = lsb(direct_addr($4));
764         RELOC_ABS_07ff(1, 0);
765   }
766 | short_data_inst REG ',' '#' expr {
767         $$ = 2;
768         size = find_size1(inst_size, $2);
769         op[0] = short_opcode + size * 8 + 1;
770         op[1] = reg($2) * 16 + imm_data4_signed($5);
771         RELOC_ABS_0F(1, 0);
772   }
773 | short_data_inst '[' REG ']' ',' '#' expr {
774         $$ = 2;
775         size = find_size0(inst_size);
776         op[0] = short_opcode + size * 8 + 2;
777         op[1] = reg_indirect($3) * 16 + imm_data4_signed($7);
778         RELOC_ABS_0F(1, 0);
779   }
780 | short_data_inst '[' REG '+' ']' ',' '#' expr {
781         $$ = 2;
782         size = find_size0(inst_size);
783         op[0] = short_opcode + size * 8 + 3;
784         op[1] = reg_indirect($3) * 16 + imm_data4_signed($8);
785         RELOC_ABS_0F(1, 0);
786   }
787 | short_data_inst '[' REG '+' expr ']' ',' '#' expr {
788         size = find_size0(inst_size);
789         if ($5 >= -128 && $5 <= 127) {
790                 $$ = 3;
791                 op[0] = short_opcode + size * 8 + 4;
792                 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
793                 op[2] = op[2] = ($5 >= 0) ? $5 : 256 + $5;
794                 RELOC_ABS_0F(1, 1);
795                 RELOC_ABS_FF(2, 0);
796         } else {
797                 $$ = 4;
798                 op[0] = short_opcode + size * 8 + 5;
799                 op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
800                 op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
801                 op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
802                 RELOC_ABS_0F(1, 1);
803                 RELOC_ABS_FFFF(2, 0);
804         }
805   }
806 | short_data_inst expr ',' '#' expr {
807         $$ = 3;
808         size = find_size0(inst_size);
809         op[0] = short_opcode + size * 8 + 6;
810         op[1] = msb(direct_addr($2)) * 16 + imm_data4_signed($5);
811         op[2] = lsb(direct_addr($2));
812         RELOC_ABS_0F(1, 0);
813   }
814 | ANL C ',' bit {
815         $$ = 3;
816         op[0] = 0x08;
817         op[1] = 0x40 + msb(bit_addr($4));
818         op[2] = lsb(bit_addr($4));
819         RELOC_ABS_03FF(1, 0);
820   }
821 | ANL C ',' '/' bit {
822         $$ = 3;
823         op[0] = 0x08;
824         op[1] = 0x50 + msb(bit_addr($5));
825         op[2] = lsb(bit_addr($5));
826         RELOC_ABS_03FF(1, 0);
827   }
828
829 | ORL C ',' bit {
830         $$ = 3;
831         op[0] = 0x08;
832         op[1] = 0x60 + msb(bit_addr($4));
833         op[2] = lsb(bit_addr($4));
834         RELOC_ABS_03FF(1, 0);
835   }
836 | ORL C ',' '/' bit {
837         $$ = 3;
838         op[0] = 0x08;
839         op[1] = 0x70 + msb(bit_addr($5));
840         op[2] = lsb(bit_addr($5));
841         RELOC_ABS_03FF(1, 0);
842   }
843 | CLR bit {
844         $$ = 3;
845         op[0] = 0x08;
846         op[1] = msb(bit_addr($2));
847         op[2] = lsb(bit_addr($2));
848         RELOC_ABS_03FF(1, 0);
849   }
850 | SETB bit {
851         $$ = 3;
852         op[0] = 0x08;
853         op[1] = 0x10 + msb(bit_addr($2));
854         op[2] = lsb(bit_addr($2));
855         RELOC_ABS_03FF(1, 0);
856   }
857 | logical_shift_inst REG ',' REG {
858         size = find_size1(inst_size, $2);
859         if (find_size_reg($4) != SIZE8)
860                 error("Second register in logical shift must be byte size");
861         $$ = 2;
862         op[0] = shift_reg_opcode;
863         switch (size) {
864                 case SIZE8:  op[0] += 0; break;
865                 case SIZE16: op[0] += 8; break;
866                 case SIZE32: op[0] += 12; break;
867         }
868         op[1] = reg($2) * 16 + reg($4);
869   }
870 | logical_shift_inst REG ',' '#' NUMBER {
871         size = find_size1(inst_size, $2);
872         $$ = 2;
873         if (shift_imm_opcode == -1)
874                 error("NORM may not use a constant");
875         op[0] = shift_imm_opcode;
876         switch (size) {
877                 case SIZE8:  op[0] += 0; break;
878                 case SIZE16: op[0] += 8; break;
879                 case SIZE32: op[0] += 12; break;
880         }
881         switch (size) {
882                 case SIZE8:
883                 case SIZE16:
884                         op[1] = reg($2) * 16 + imm_data4_unsigned($5);
885                         break;
886                 case SIZE32:
887                         op[1] = (reg($2) / 2) * 32 + imm_data5_unsigned($5);
888                         break;
889         }
890   }
891 | no_opperand_inst {
892         $$ = num_op;
893         op[0] = opcode0;
894         op[1] = opcode1;
895   }
896
897 | TRAP '#' NUMBER {
898         $$ = 2;
899         op[0] = 0xD6;
900         op[1] = 0x30 + imm_data4_unsigned($3);
901   }
902 | CPL REG {
903         $$ = 2;
904         size = find_size1(inst_size, $2);
905         op[0] = 0x90 + size * 8;
906         op[1] = reg($2) * 16 + 10;
907   }
908 | DA REG {
909         $$ = 2;
910         op[0] = 0x90;
911         op[1] = reg($2) * 16 + 8;
912   }
913 | NEG REG {
914         $$ = 2;
915         size = find_size1(inst_size, $2);
916         op[0] = 0x90 + size * 8;
917         op[1] = reg($2) * 16 + 11;
918   }
919 | SEXT REG {
920         $$ = 2;
921         size = find_size1(inst_size, $2);
922         op[0] = 0x90 + size * 8;
923         op[1] = reg($2) * 16 + 9;
924   }
925
926 | rotate_inst REG ',' '#' NUMBER {
927         $$ = 2;
928         size = find_size1(inst_size, $2);
929         op[0] = rotate_opcode + size * 8;
930         op[1] = reg($2) * 16 + imm_data4_unsigned($5);
931   }
932
933
934 | LEA REG ',' REG '+' expr {
935         if ($6 >= -128 && $6 <= 127) {
936                 $$ = 3;
937                 op[0] = 0x40;
938                 op[1] = reg($2) * 16 + reg_indirect($4);
939                 op[2] = ($6 >= 0) ? $6 : 256 + $6;
940                 RELOC_ABS_FF(2, 0);
941         } else {
942                 op[0] = 0x48;
943                 op[1] = reg($2) * 16 + reg_indirect($4);
944                 op[2] = ($6 >= 0) ? msb($6) : msb(65536 + $6);
945                 op[3] = ($6 >= 0) ? lsb($6) : lsb(65536 + $6);
946                 RELOC_ABS_FFFF(2, 0);
947         }
948   }
949 | stack_inst WORD {
950         $$ = 3;
951         size = find_size0(inst_size);
952         op[0] = msb(stack_addr_opcode) + size * 8;
953         op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2));
954         op[2] = lsb(direct_addr($2));
955         RELOC_ABS_07ff(1, 0);
956   }
957 | stack_inst rlist {
958         $$ = 2;
959         if (inst_size != UNKNOWN && find_size0(inst_size) != rlist_size)
960                 error("inst specifies different size than registers used");
961         op[0] = stack_reg_opcode + rlist_reg_bank * 64 + rlist_size * 8;
962         op[1] = rlist_bitmask;
963   }
964
965
966 | MUL REG ',' REG {
967         $$ = 2;
968         size = find_size2(inst_size, $2, $4);
969         op[0] = 0xE6;
970         op[1] = reg($2) * 16 + reg($4);
971   }
972 | MULU REG ',' REG {
973         $$ = 2;
974         size = find_size2(inst_size, $2, $4);
975         if (size == SIZE8) {
976                 op[0] = 0xE0;
977                 op[1] = reg($2) * 16 + reg($4);
978         } else {
979                 op[0] = 0xE4;
980                 op[1] = reg($2) * 16 + reg($4);
981         }
982   }
983 | MUL REG ',' '#' expr {
984         $$ = 2;
985         size = find_size1(inst_size, $2);
986         op[0] = 0xE9;
987         op[1] = reg($2) + 8;
988         op[2] = msb(imm_data16($5));
989         op[3] = lsb(imm_data16($5));
990         RELOC_ABS_FFFF(2, 0);
991   }
992 | MULU REG ',' '#' expr {
993         size = find_size2(inst_size, $2, $4);
994         if (size == SIZE8) {
995                 $$ = 3;
996                 op[0] = 0xE8;
997                 op[1] = reg($2) * 16;
998                 op[2] = imm_data8($5);
999                 RELOC_ABS_FF(2, 0);
1000         } else {
1001                 $$ = 4;
1002                 op[0] = 0xE9;
1003                 op[1] = reg($2) * 16;
1004                 op[2] = msb(imm_data16($5));
1005                 op[3] = lsb(imm_data16($5));
1006                 RELOC_ABS_FFFF(2, 0);
1007         }
1008   }
1009 | DIV REG ',' REG {
1010         $$ = 2;
1011         size = find_size2(inst_size, $2, $4);
1012         switch (size) {
1013         case SIZE8:
1014                 error("Singed DIV can't be 8 bit size"); break;
1015         case SIZE16:
1016                 op[0] = 0xE7;
1017                 op[1] = reg($2) * 16 + reg($4);
1018                 break;
1019         case SIZE32:
1020                 op[0] = 0xEF;
1021                 op[1] = (reg($2) / 2) * 32 + reg($4);
1022                 break;
1023         }
1024   }
1025 | DIVU REG ',' REG {
1026         $$ = 2;
1027         size = find_size2(inst_size, $2, $4);
1028         switch (size) {
1029         case SIZE8:
1030                 op[0] = 0xE1;
1031                 op[1] = reg($2) * 16 + reg($4);
1032                 break;
1033         case SIZE16:
1034                 op[0] = 0xE5;
1035                 op[1] = reg($2) * 16 + reg($4);
1036                 break;
1037         case SIZE32:
1038                 op[0] = 0xED;
1039                 op[1] = (reg($2) / 2) * 32 + reg($4);
1040                 break;
1041         }
1042   }
1043 | DIV REG ',' '#' expr { 
1044         size = find_size1(inst_size, $2);
1045         switch (size) {
1046         case SIZE8:
1047                 error("Singed DIV can't be 8 bit size"); break;
1048         case SIZE16:
1049                 $$ = 3;
1050                 op[0] = 0xE8;
1051                 op[1] = reg($2) * 16 + 11;
1052                 op[2] = imm_data8($5);
1053                 RELOC_ABS_FF(2, 0);
1054                 break;
1055         case SIZE32:
1056                 $$ = 4;
1057                 op[0] = 0xE9;
1058                 op[1] = (reg($2) / 2) * 32 + 9;
1059                 op[2] = msb(imm_data16($5));
1060                 op[3] = lsb(imm_data16($5));
1061                 RELOC_ABS_FFFF(2, 0);
1062                 break;
1063         }
1064   }
1065 | DIVU REG ',' '#' expr { 
1066         size = find_size1(inst_size, $2);
1067         switch (size) {
1068         case SIZE8:
1069                 $$ = 3;
1070                 op[0] = 0xE8;
1071                 op[1] = reg($2) * 16 + 1;
1072                 op[2] = imm_data8($5);
1073                 RELOC_ABS_FF(2, 0);
1074                 break;
1075         case SIZE16:
1076                 $$ = 3;
1077                 op[0] = 0xE8;
1078                 op[1] = reg($2) * 16 + 3;
1079                 op[2] = imm_data8($5);
1080                 RELOC_ABS_FF(2, 0);
1081                 break;
1082         case SIZE32:
1083                 $$ = 4;
1084                 op[0] = 0xE9;
1085                 op[1] = (reg($2) / 2) * 32 + 1;
1086                 op[2] = msb(imm_data16($5));
1087                 op[3] = lsb(imm_data16($5));
1088                 RELOC_ABS_FFFF(2, 0);
1089                 break;
1090         }
1091   }
1092 | CALL '[' REG ']' {
1093         $$ = 2;
1094         op[0] = 0xC6;
1095         op[1] = reg($3);
1096   }
1097 | FCALL jmpaddr {
1098         $$ = 4;
1099         op[0] = 0xC4;
1100         op[1] = ($2 >> 8) & 255;
1101         op[2] = $2 & 255;
1102         op[3] = ($2 >> 16) & 255;
1103   }
1104 | FJMP jmpaddr {
1105         $$ = 4;
1106         op[0] = 0xD4;
1107         op[1] = ($2 >> 8) & 255;
1108         op[2] = $2 & 255;
1109         op[3] = ($2 >> 16) & 255;
1110   }
1111 | JMP '[' REG ']' {
1112         $$ = 2;
1113         op[0] = 0xD6;
1114         op[1] = 0x70 + reg_indirect($3);
1115   }
1116 | JMP '[' A '+' DPTR ']' {
1117         $$ = 2;
1118         op[0] = 0xD6;
1119         op[1] = 0x46;
1120   }
1121 | JMP '[' '[' REG '+' ']' ']' {
1122         $$ = 2;
1123         op[0] = 0xD6;
1124         op[1] = 0x60 + reg_indirect($4);
1125   }
1126
1127 | JMP jmpaddr {
1128         $$ = 3;
1129         op[0] = 0xD5;
1130         op[1] = msb(rel16(MEM_POS + $$, $2));
1131         op[2] = lsb(rel16(MEM_POS + $$, $2));
1132         RELOC_FFFF(MEM_POS+$$,1,0);
1133   }
1134
1135 | CALL jmpaddr {
1136         $$ = 3;
1137         op[0] = 0xC5;
1138         op[1] = msb(rel16(MEM_POS + $$, $2));
1139         op[2] = lsb(rel16(MEM_POS + $$, $2));
1140         RELOC_FFFF(MEM_POS+$$,1,0);
1141   }
1142 | branch_inst jmpaddr {
1143         $$ = 2;
1144         op[0] = branch_opcode;
1145         op[1] = rel8(MEM_POS + $$, $2);
1146         RELOC_FF(MEM_POS + $$, 1,0);
1147   }
1148 | CJNE REG ',' expr ',' jmpaddr {
1149         $$ = 4;
1150         size = find_size1(inst_size, $2);
1151         op[0] = 0xE2 + size * 8;
1152         op[1] = reg($2) * 16 + msb(direct_addr($4));
1153         op[2] = lsb(direct_addr($4));
1154         op[3] = rel8(MEM_POS + $$, $6);
1155         RELOC_ABS_07ff(1, 0);
1156         RELOC_FF(MEM_POS + $$, 3,1);
1157   }
1158 | CJNE REG ',' '#' expr ',' jmpaddr {
1159         size  = find_size1(inst_size, $2);
1160         if (size == SIZE8) {
1161                 $$ = 4;
1162                 op[0] = 0xE3;
1163                 op[1] = reg($2) * 16;
1164                 op[2] = rel8(MEM_POS + $$, $7);
1165                 op[3] = imm_data8($5);
1166                 RELOC_ABS_FF(3, 0);
1167         } else {
1168                 $$ = 5;
1169                 op[0] = 0xEB;
1170                 op[1] = reg($2) * 16;
1171                 op[2] = rel8(MEM_POS + $$, $7);
1172                 op[3] = msb(imm_data16($5));
1173                 op[4] = lsb(imm_data16($5));
1174                 RELOC_ABS_FFFF(3, 0);
1175         }
1176   }
1177 | CJNE '[' REG ']' ',' '#' expr ',' jmpaddr {
1178         size  = find_size0(inst_size);
1179         if (size == SIZE8) {
1180                 $$ = 4;
1181                 op[0] = 0xE3;
1182                 op[1] = reg_indirect($3) * 16 + 8;
1183                 op[2] = rel8(MEM_POS + $$, $9);
1184                 op[3] = imm_data8($7);
1185                 RELOC_ABS_FF(3, 0);
1186         } else {
1187                 $$ = 5;
1188                 op[0] = 0xEB;
1189                 op[1] = reg_indirect($3) * 16 + 8;
1190                 op[2] = rel8(MEM_POS + $$, $9);
1191                 op[3] = msb(imm_data16($7));
1192                 op[4] = lsb(imm_data16($7));
1193                 RELOC_ABS_FFFF(3, 0);
1194         }
1195   }
1196 | DJNZ REG ',' jmpaddr {
1197         $$ = 3;
1198         size  = find_size1(inst_size, $2);
1199         op[0] = 0x87 + size * 8;
1200         op[1] = reg($2) * 16 + 8;
1201         op[2] = rel8(MEM_POS + $$, $4);
1202         RELOC_FF(MEM_POS+$$, 2, 0);
1203   }
1204
1205
1206 | DJNZ WORD ',' jmpaddr {
1207         $$ = 4;
1208         size  = find_size0(inst_size);
1209         op[0] = 0xE2 + size * 8;
1210         op[1] = msb(direct_addr($2)) + 8;
1211         op[2] = lsb(direct_addr($2));
1212         op[3] = rel8(MEM_POS + $$, $4);
1213         RELOC_ABS_07ff(1, 0);
1214         RELOC_FF(MEM_POS + $$, 3, 1)
1215   }
1216
1217 | JB bit ',' jmpaddr {
1218         $$ = 4;
1219         op[0] = 0x97;
1220         op[1] = 0x80 + msb(bit_addr($2));
1221         op[2] = lsb(bit_addr($2));
1222         op[3] = rel8(MEM_POS + $$, $4);
1223         RELOC_ABS_03FF(1, 0);
1224         RELOC_FF(MEM_POS + $$, 3, 1);
1225   }
1226
1227 | JBC bit ',' jmpaddr {
1228         $$ = 4;
1229         op[0] = 0x97;
1230         op[1] = 0xC0 + msb(bit_addr($2));
1231         op[2] = lsb(bit_addr($2));
1232         op[3] = rel8(MEM_POS + $$, $4);
1233         RELOC_ABS_03FF(1, 0);
1234         RELOC_FF(MEM_POS + $$, 3, 1);
1235   }
1236
1237 | JNB bit ',' jmpaddr {
1238         $$ = 4;
1239         op[0] = 0x97;
1240         op[1] = 0xA0 + msb(bit_addr($2));
1241         op[2] = lsb(bit_addr($2));
1242         op[3] = rel8(MEM_POS + $$, $4);
1243         RELOC_ABS_03FF(1, 0);
1244         RELOC_FF(MEM_POS + $$, 3, 1);
1245   }
1246
1247
1248 arith_inst:
1249           ADD   {arith_opcode = 0;}
1250         | ADDC  {arith_opcode = 1;}
1251         | AND   {arith_opcode = 5;}
1252         | CMP   {arith_opcode = 4;}
1253         | MOV   {arith_opcode = 8;}
1254         | OR    {arith_opcode = 6;}
1255         | SUB   {arith_opcode = 2;}
1256         | SUBB  {arith_opcode = 3;}
1257         | XOR   {arith_opcode = 7;}
1258
1259 short_data_inst:
1260           ADDS {short_opcode = 0xA0;}
1261         | MOVS {short_opcode = 0xB0;}
1262
1263 logical_shift_inst:
1264           ASL  {shift_reg_opcode = 0xC1; shift_imm_opcode = 0xD1;}
1265         | ASR  {shift_reg_opcode = 0xC2; shift_imm_opcode = 0xD2;}
1266         | LSR  {shift_reg_opcode = 0xC0; shift_imm_opcode = 0xD0;}
1267         | NORM {shift_reg_opcode = 0xC3; shift_imm_opcode = -1;}
1268
1269 rotate_inst:
1270           RL    {rotate_opcode = 0xD3;}
1271         | RLC   {rotate_opcode = 0xD7;}
1272         | RR    {rotate_opcode = 0xD0;}
1273         | RRC   {rotate_opcode = 0xD7;}
1274
1275 stack_inst:
1276           POP   {stack_addr_opcode = 0x8710; stack_reg_opcode = 0x27;}
1277         | POPU  {stack_addr_opcode = 0x8700; stack_reg_opcode = 0x37;}
1278         | PUSH  {stack_addr_opcode = 0x8730; stack_reg_opcode = 0x07;}
1279         | PUSHU {stack_addr_opcode = 0x8720; stack_reg_opcode = 0x17;}
1280
1281 no_opperand_inst:
1282           BKPT  {num_op = 1; opcode0 = 255; opcode1 = 0;}
1283         | NOP   {num_op = 1; opcode0 = 0; opcode1 = 0;}
1284         | RESET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x10;}
1285         | RET   {num_op = 2; opcode0 = 0xD6; opcode1 = 0x80;}
1286         | RETI  {num_op = 2; opcode0 = 0xD6; opcode1 = 0x90;}
1287
1288 branch_inst:
1289           BCC   {branch_opcode = 0xF0;}
1290         | BCS   {branch_opcode = 0xF1;}
1291         | BEQ   {branch_opcode = 0xF3;}
1292         | BG    {branch_opcode = 0xF8;}
1293         | BGE   {branch_opcode = 0xFA;}
1294         | BGT   {branch_opcode = 0xFC;}
1295         | BL    {branch_opcode = 0xF9;}
1296         | BLE   {branch_opcode = 0xFD;}
1297         | BLT   {branch_opcode = 0xFB;}
1298         | BMI   {branch_opcode = 0xF7;}
1299         | BNE   {branch_opcode = 0xF2;}
1300         | BNV   {branch_opcode = 0xF4;}
1301         | BOV   {branch_opcode = 0xF5;}
1302         | BPL   {branch_opcode = 0xF6;}
1303         | BR    {branch_opcode = 0xFE;}
1304         | JZ    {branch_opcode = 0xEC;}
1305         | JNZ   {branch_opcode = 0xEE;}
1306
1307
1308
1309 %%
1310
1311
1312 int reg(int reg_spec)
1313 {
1314         return reg_spec & 15;
1315 }
1316
1317 int reg_indirect(int reg_spec)
1318 {
1319         if (reg_spec & BYTE_REG)
1320                 error("Indirect addressing may not use byte registers");
1321         if ((reg_spec & 15) > 7)
1322                 error("Only R0 through R7 may be used for indirect addr");
1323         return reg_spec & 7;
1324 }
1325
1326 int rel16(int pos, int dest)
1327 {
1328         int rel;
1329
1330         if (!p3) return 0;      /* don't bother unless writing code */
1331         if (dest & (BRANCH_SPACING - 1))
1332                 error("Attempt to jump to unaligned location");
1333         pos &= ~(BRANCH_SPACING - 1);
1334         rel = (dest - pos) / BRANCH_SPACING;
1335         if (rel < -32768 || rel > 32767)
1336                 error("Attempt to jump out of 16 bit relative range");
1337         if (rel < 0) rel += 65536;
1338         return rel;
1339 }
1340
1341 int rel8(int pos, int dest)
1342 {
1343         int rel;
1344
1345         if (!p3) return 0;      /* don't bother unless writing code */
1346         if (dest & (BRANCH_SPACING - 1))
1347                 error("Attempt to jump to unaligned location");
1348         pos &= ~(BRANCH_SPACING - 1);
1349         rel = (dest - pos) / BRANCH_SPACING;
1350         if (rel < -128 || rel > 127)
1351                 error("Attempt to jump out of 16 bit relative range");
1352         if (rel < 0) rel += 256;
1353         return rel;
1354 }
1355
1356 int msb(int value)
1357 {
1358         return (value >> 8) & 255;
1359 }
1360
1361 int lsb(int value)
1362 {
1363         return value & 255;
1364 }
1365
1366 int direct_addr(int value)
1367 {
1368         char buf[250];
1369
1370         if (value < 0 || value > 2047) {
1371                 sprintf(buf, "illegal value (%d) for direct address", value);
1372                 error(buf);
1373         }
1374         return value;
1375 }
1376
1377 int imm_data4_signed(int value)
1378 {
1379         if (value < -8 || value > 7)
1380                 error("illegal 4 bit (signed) value");
1381         if (value >= 0) return value;
1382         else return (16 + value);
1383 }
1384
1385 int imm_data4_unsigned(int value)
1386 {
1387         if (value < 0 || value > 15)
1388                 error("illegal 4 bit (unsigned) value");
1389         return value;
1390 }
1391
1392 int imm_data5_unsigned(int value)
1393 {
1394         if (value < 0 || value > 31)
1395                 error("illegal 5 bit (unsigned) value");
1396         return value;
1397 }
1398
1399 int imm_data8(int value)
1400 {
1401         if (value < -128 || value > 255)
1402                 error("illegal 8 bit value");
1403         if (value >= 0) return value;
1404         else return (256 + value);
1405 }
1406
1407 int imm_data16(int value)
1408 {
1409         if (value < -32728 || value > 65535)
1410                 error("illegal 16 bit value");
1411         if (value >= 0) return value;
1412         else return (65536 + value);
1413 }
1414
1415 int bit_addr(int value)
1416 {
1417         if (value < 0 || value > 1023) {
1418                 fprintf(stderr, "bad bit addr of 0x%04X (%d dec)\n",
1419                         value, value);
1420                 error("illegal bit address");
1421         }
1422         return value;
1423 }
1424
1425
1426 int find_size_reg(int op1spec)
1427 {
1428         int op1size=UNKNOWN;
1429
1430         if (op1spec & BYTE_REG) op1size = SIZE8;
1431         if (op1spec & WORD_REG) op1size = SIZE16;
1432         if (op1size == UNKNOWN)
1433                 error("Register without implied size");
1434         return op1size;
1435 }
1436
1437 int find_size0(int isize)
1438 {
1439         if (isize == UNKNOWN)
1440                 error("Can't determine data size from instruction");
1441         return isize;
1442 }
1443
1444 int find_size1(int isize, int op1spec)
1445 {
1446         int op1size=UNKNOWN;
1447
1448         if (op1spec & BYTE_REG) op1size = SIZE8;
1449         if (op1spec & WORD_REG) op1size = SIZE16;
1450         if (op1size == UNKNOWN)
1451                 error("Register without implied size");
1452
1453         if (isize == SIZE32 && op1size == SIZE16) return SIZE32;
1454         if (isize == UNKNOWN) return op1size;
1455         else {
1456                 if (isize != op1size)
1457                         error("data size of register and inst don't agree");
1458                 return isize;
1459         }
1460 }
1461
1462 int find_size2(int isize, int op1spec, int op2spec)
1463 {
1464         int op1size=UNKNOWN, op2size=UNKNOWN;
1465
1466         if (op1spec & BYTE_REG) op1size = SIZE8;
1467         if (op1spec & WORD_REG) op1size = SIZE16;
1468         if (op1size == UNKNOWN)
1469                 error("Register without implied size");
1470         if (op2spec & BYTE_REG) op2size = SIZE8;
1471         if (op2spec & WORD_REG) op2size = SIZE16;
1472         if (op1size == UNKNOWN)
1473                 error("Register without implied size");
1474
1475         if (op1size != op2size)
1476                 error("data sizes of two registers don't agree");
1477         if (isize == UNKNOWN) return op1size;
1478         else {
1479                 if (isize != op1size)
1480                         error("data size of registers and inst don't agree");
1481                 return isize;
1482         }
1483 }
1484
1485 int yyerror(char *s)
1486 {
1487         if (yytext[0] >= 32) {
1488                 fprintf(stderr, "%s near '%s', line %d\n",
1489                         s, yytext, lineno);
1490         } else {
1491                 fprintf(stderr, "%s, line %d\n", s, lineno - 1);
1492         }
1493         return 0;
1494 }
1495
1496 void error(char *s)
1497 {
1498         yyerror(s);
1499         exit(1);
1500 }
1501
1502 int yywrap()
1503 {
1504         return 1;
1505 }