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