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