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