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