* as/mcs51/i51mch.c (machine): S_DJNZ fixed bug 1554318
[fw/sdcc] / as / mcs51 / i51mch.c
1 /* i85mch.c */
2
3 /*
4  * (C) Copyright 1989,1990
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  * 28-Oct-97 Ported from 8085 to 8051 by John Hartman
12  */
13
14 #include <stdio.h>
15 #include <setjmp.h>
16 #include "asm.h"
17 #include "i8051.h"
18
19 extern int addr(struct expr *);
20 /*
21  * Process machine ops.
22  */
23 VOID
24 machine(struct mne *mp)
25 {
26         register unsigned op;
27         register int t, t1, v1;
28         struct expr e, e1;
29
30         clrexpr(&e);
31         clrexpr(&e1);
32
33         op = mp->m_valu;
34         switch (mp->m_type) {
35
36         case S_INH:
37                 outab(op);
38                 break;
39
40         case S_JMP11:
41                 /* ACALL or AJMP. In Flat24 mode, this is a
42                  * 19 bit destination; in 8051 mode, this is a
43                  * 11 bit destination.
44                  *
45                  * The opcode is merged with the address in a
46                  * hack-o-matic fashion by the linker.
47                 */
48                 expr(&e, 0);
49                 if (flat24Mode)
50                 {
51                         outr19(&e, op, R_J19);
52                 }
53                 else
54                 {
55                 outr11(&e, op, R_J11);
56                 }
57                 break;
58
59         case S_JMP16:
60                 /* LCALl or LJMP. In Flat24 mode, this is a 24 bit
61                  * destination; in 8051 mode, this is a 16 bit
62                  * destination.
63                  */
64                 expr(&e, 0);
65                 outab(op);
66                 if (flat24Mode)
67                 {
68                         outr24(&e, 0);
69                 }
70                 else
71                 {
72                 outrw(&e, 0);
73                 }
74                 break;
75
76         case S_ACC:
77                 t = addr(&e);
78                 if (t != S_A)
79                         aerr();
80                 outab(op);
81                 break;
82
83         case S_TYP1:
84                 /* A, direct, @R0, @R1, R0 to R7.  "INC" also allows DPTR */
85                 t = addr(&e);
86
87                 switch (t) {
88                 case S_A:
89                         outab(op + 4);
90                         break;
91
92                 case S_DIR:
93                 case S_EXT:
94                         /* Direct is also legal */
95                         outab(op + 5);
96                         outrb(&e, R_PAG0);
97                         break;
98
99                 case S_AT_R:
100                         outab(op + 6 + e.e_addr);
101                         break;
102
103                 case S_REG:
104                         outab(op + 8 + e.e_addr);
105                         break;
106
107                 case S_DPTR:
108                         if (op != 0)
109                                 /* only INC (op=0) has DPTR mode */
110                                 aerr();
111                         else
112                                 outab( 0xA3);
113                         break;
114
115                 default:
116                         aerr();
117                 }
118                 break;
119
120         case S_TYP2:
121                 /* A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7 */
122                 t = addr(&e);
123                 if (t != S_A)
124                         aerr();
125                 comma();
126                 t1 = addr(&e1);
127
128                 switch (t1) {
129                 case S_IMMED:
130                         outab(op + 4);
131                         outrb(&e1, 0);
132                         break;
133
134                 case S_DIR:
135                 case S_EXT:
136                         outab(op + 5);
137                         outrb(&e1, R_PAG0);
138                         break;
139
140                 case S_AT_R:
141                         outab(op + 6 + e1.e_addr);
142                         break;
143
144                 case S_REG:
145                         outab(op + 8 + (e1.e_addr));
146                         break;
147
148                 default:
149                         aerr();
150                 }
151                 break;
152
153         case S_TYP3:
154                 /* dir,A; dir,#imm;
155                  * A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7
156                  * C,direct;  C,/direct
157                  */
158                 t = addr(&e);
159                 comma();
160                 t1 = addr(&e1);
161
162                 switch (t) {
163                 case S_DIR:
164                 case S_EXT:
165                         switch (t1) {
166                         case S_A:
167                                 outab(op + 2);
168                                 outrb(&e, R_PAG0);
169                                 break;
170
171                         case S_IMMED:
172                                 outab(op + 3);
173                                 outrb(&e, 0);
174                                 outrb(&e1, 0);
175                                 break;
176                         default:
177                                 aerr();
178                         }
179                         break;
180
181                 case S_A:
182                         switch (t1) {
183                         case S_IMMED:
184                                 outab(op + 4);
185                                 outrb(&e1, 0);
186                                 break;
187
188                         case S_DIR:
189                         case S_EXT:
190                                 outab(op + 5);
191                                 outrb(&e1, R_PAG0);
192                                 break;
193
194                         case S_AT_R:
195                                 outab(op + 6 + e1.e_addr);
196                                 break;
197
198                         case S_REG:
199                                 outab(op + 8 + e1.e_addr);
200                                 break;
201
202                         default:
203                                 aerr();
204                         }
205                         break;
206
207                 case S_C:
208                         /* XRL has no boolean version.  Trap it */
209                         if (op == 0x60)
210                                 aerr();
211
212                         switch (t1) {
213                         case S_DIR:
214                         case S_EXT:
215                                 outab(op + 0x32);
216                                 outrb(&e1, R_PAG0);
217                                 break;
218
219                         case S_NOT_BIT:
220                                 outab(op + 0x60);
221                                 outrb(&e1, 0);
222                                 break;
223
224                         default:
225                                 aerr();
226                         }
227                         break;
228
229                 default:
230                         aerr();
231                 }
232                 break;
233
234         case S_TYP4:
235                 /* A,direct; A,@R0; A,@R1; A,R0 to A,R7 */
236                 t = addr(&e);
237                 if (t != S_A)
238                         aerr();
239                 comma();
240                 t1 = addr(&e1);
241
242                 switch (t1) {
243                 case S_DIR:
244                 case S_EXT:
245                         outab(op + 5);
246                         outrb(&e1, R_PAG0);
247                         break;
248
249                 case S_AT_R:
250                         outab(op + 6 + e1.e_addr);
251                         break;
252
253                 case S_REG:
254                         outab(op + 8 + e1.e_addr);
255                         break;
256
257                 default:
258                         aerr();
259                 }
260                 break;
261
262         /* MOV instruction, all modes */
263         case S_MOV:
264                 t = addr(&e);
265                 comma();
266                 t1 = addr(&e1);
267
268                 switch (t) {
269                 case S_A:
270                         switch (t1) {
271                         case S_IMMED:
272                                 outab(0x74);
273                                 outrb(&e1, 0);
274                                 break;
275
276                         case S_DIR:
277                         case S_EXT:
278                                 outab(0xE5);
279                                 outrb(&e1, R_PAG0);
280                                 break;
281
282                         case S_AT_R:
283                                 outab(0xE6 + e1.e_addr);
284                                 break;
285
286                         case S_REG:
287                                 outab(0xE8 + e1.e_addr);
288                                 break;
289
290                         default:
291                                 aerr();
292                         }
293                         break;
294
295                 case S_REG:
296                         switch (t1) {
297                         case S_A:
298                                 outab(0xF8 + e.e_addr);
299                                 break;
300
301                         case S_IMMED:
302                                 outab(0x78 + e.e_addr);
303                                 outrb(&e1, 0);
304                                 break;
305
306                         case S_DIR:
307                         case S_EXT:
308                                 outab(0xA8 + e.e_addr);
309                                 outrb(&e1, R_PAG0);
310                                 break;
311
312                         default:
313                                 aerr();
314                         }
315                         break;
316
317                 case S_DIR:
318                 case S_EXT:
319                         switch (t1) {
320                         case S_A:
321                                 outab(0xF5);
322                                 outrb(&e, R_PAG0);
323                                 break;
324
325                         case S_IMMED:
326                                 outab(0x75);
327                                 outrb(&e, R_PAG0);
328                                 outrb(&e1, 0);
329                                 break;
330
331                         case S_DIR:
332                         case S_EXT:
333                                 outab(0x85);
334                                 outrb(&e1, R_PAG0);
335                                 outrb(&e, R_PAG0);
336                                 break;
337
338                         case S_AT_R:
339                                 outab(0x86 + e1.e_addr);
340                                 outrb(&e, R_PAG0);
341                                 break;
342
343                         case S_REG:
344                                 outab(0x88 + e1.e_addr);
345                                 outrb(&e, R_PAG0);
346                                 break;
347
348                         case S_C:
349                                 outab(0x92);
350                                 outrb(&e, R_PAG0);
351                                 break;
352
353                         default:
354                                 aerr();
355                         }
356                         break;
357
358                 case S_AT_R:
359                         switch (t1) {
360                         case S_IMMED:
361                                 outab(0x76 + e.e_addr);
362                                 outrb(&e1, 0);
363                                 break;
364
365                         case S_DIR:
366                         case S_EXT:
367                                 outab(0xA6 + e.e_addr);
368                                 outrb(&e1, R_PAG0);
369                                 break;
370
371                         case S_A:
372                                 outab(0xF6 + e.e_addr);
373                                 break;
374
375                         default:
376                                 aerr();
377                         }
378                         break;
379
380                 case S_C:
381                         if ((t1 != S_DIR) && (t1 != S_EXT))
382                                 aerr();
383                         outab(0xA2);
384                         outrb(&e1, R_PAG0);
385                         break;
386
387                 case S_DPTR:
388                         if (t1 != S_IMMED)
389                                 aerr();
390                         outab(0x90);
391
392                         /* mov DPTR, #immed: for Flat24 mode,
393                          * #immed is a 24 bit constant. For 8051,
394                          * it is a 16 bit constant.
395                          */
396                         if (flat24Mode)
397                         {
398                             outr24(&e1, 0);
399                         }
400                         else
401                         {
402                         outrw(&e1, 0);
403                         }
404                         break;
405
406                 default:
407                         aerr();
408                 }
409                 break;
410
411         case S_BITBR:
412                 /* Branch on bit set/clear */
413                 t = addr(&e);
414                 if ((t != S_DIR) && (t != S_EXT))
415                         aerr();
416                 outab(op);
417                 outrb(&e, R_PAG0);
418
419                 comma();
420                 expr(&e1, 0);
421                 if (e1.e_base.e_ap == NULL || e1.e_base.e_ap == dot.s_area) {
422                     if ( e1.e_addr == dot.s_addr)
423                         v1 = -3;
424                     else
425                         v1 = e1.e_addr - dot.s_addr - 1;
426                         if (pass==2 && ((v1 < -128) || (v1 > 127)))
427                                 aerr();
428                         outab(v1);
429                 } else {
430                         outrb(&e1, R_PCR);
431                 }
432                 if (e1.e_mode != S_USER)
433                         rerr();
434                 break;
435
436         case S_BR:
437                 /* Relative branch */
438                 outab(op);
439                 expr(&e1, 0);
440                 if (e1.e_base.e_ap == NULL || e1.e_base.e_ap == dot.s_area) {
441                     if ( e1.e_addr == dot.s_addr)
442                         v1 = -2;
443                     else
444                         v1 = e1.e_addr - dot.s_addr - 1;
445                         if (pass == 2 && ((v1 < -128) || (v1 > 127)))
446                                 aerr();
447                         outab(v1);
448                 } else {
449                         outrb(&e1, R_PCR);
450                 }
451                 if (e1.e_mode != S_USER)
452                         rerr();
453                 break;
454
455         case S_CJNE:
456                 /* A,#;  A,dir;  @R0,#;  @R1,#;  Rn,# */
457                 t = addr(&e);
458                 comma();
459                 t1 = addr(&e1);
460                 switch (t) {
461                 case S_A:
462                         if (t1 == S_IMMED) {
463                                 outab(op + 4);
464                                 outrb(&e1, 0);
465                         }
466                         else if ((t1 == S_DIR) || (t1 == S_EXT)) {
467                                 outab(op + 5);
468                                 outrb(&e1, R_PAG0);
469                         }
470                         else
471                                 aerr();
472                 break;
473
474                 case S_AT_R:
475                         outab(op + 6 + e.e_addr);
476                         if (t1 != S_IMMED)
477                                 aerr();
478                         outrb(&e1, 0);
479                         break;
480
481                 case S_REG:
482                         outab(op + 8 + e.e_addr);
483                         if (t1 != S_IMMED)
484                                 aerr();
485                         outrb(&e1, 0);
486                         break;
487
488                 default:
489                         aerr();
490                 }
491
492                 /* branch destination */
493                 comma();
494                 expr(&e1, 0);
495                 if (e1.e_base.e_ap == NULL || e1.e_base.e_ap == dot.s_area) {
496                         if ( e1.e_addr == dot.s_addr)
497                                 v1 = -3;
498                         else
499                                 v1 = e1.e_addr - dot.s_addr - 1;
500                         if (pass == 2 && ((v1 < -128) || (v1 > 127)))
501                                 aerr();
502                         outab(v1);
503                 } else {
504                         outrb(&e1, R_PCR);
505                 }
506                 if (e1.e_mode != S_USER)
507                         rerr();
508                 break;
509
510         case S_DJNZ:
511                 /* Dir,dest;  Reg,dest */
512                 t = addr(&e);
513                 switch (t) {
514
515                 case S_DIR:
516                 case S_EXT:
517                         outab(op + 5);
518                         outrb(&e, R_PAG0);
519                         v1 = -3;
520                         break;
521
522                 case S_REG:
523                         outab(op + 8 + e.e_addr);
524                         v1 = -2;
525                         break;
526
527                 default:
528                         aerr();
529                 }
530
531                 /* branch destination */
532                 comma();
533                 expr(&e1, 0);
534                 if (e1.e_base.e_ap == NULL || e1.e_base.e_ap == dot.s_area) {
535                         if ( e1.e_addr != dot.s_addr)
536                                 v1 = e1.e_addr - dot.s_addr - 1;
537                         if (pass == 2 && ((v1 < -128) || (v1 > 127)))
538                                 aerr();
539                         outab(v1);
540                 } else {
541                         outrb(&e1, R_PCR);
542                 }
543                 if (e1.e_mode != S_USER)
544                         rerr();
545                 break;
546
547         case S_JMP:
548                 /* @A+DPTR */
549                 t = addr(&e);
550                 if (t != S_AT_ADP)
551                         aerr();
552                 outab(op);
553                 break;
554
555         case S_MOVC:
556                 /* A,@A+DPTR  A,@A+PC */
557                 t = addr(&e);
558                 if (t != S_A)
559                         aerr();
560                 comma();
561                 t1 = addr(&e1);
562                 if (t1 == S_AT_ADP)
563                         outab(0x93);
564                 else if (t1 == S_AT_APC)
565                         outab(0x83);
566                 else
567                         aerr();
568                 break;
569
570         case S_MOVX:
571                 /* A,@DPTR  A,@R0  A,@R1  @DPTR,A  @R0,A  @R1,A */
572                 t = addr(&e);
573                 comma();
574                 t1 = addr(&e1);
575
576                 switch (t) {
577                 case S_A:
578                         switch (t1) {
579                         case S_AT_DP:
580                                 outab(0xE0);
581                                 break;
582                         case S_AT_R:
583                                 outab(0xE2 + e1.e_addr);
584                                 break;
585                         default:
586                                 aerr();
587                         }
588                         break;
589
590                 case S_AT_DP:
591                         if (t1 == S_A)
592                                 outab(0xF0);
593                         else
594                                 aerr();
595                         break;
596
597                 case S_AT_R:
598                         if (t1 == S_A)
599                                 outab(0xF2 + e.e_addr);
600                         else
601                                 aerr();
602                         break;
603
604                 default:
605                         aerr();
606                 }
607                 break;
608
609         /* MUL/DIV A,B */
610         case S_AB:
611                 t = addr(&e);
612                 if (t != S_RAB) aerr();
613                 outab(op);
614                 break;
615
616         /* CLR or CPL:  A, C, or bit */
617         case S_ACBIT:
618                 t = addr(&e);
619                 switch (t) {
620                 case S_A:
621                         if (op == 0xB2)
622                                 outab(0xF4);
623                         else
624                                 outab(0xE4);
625                         break;
626
627                 case S_C:
628                         outab(op+1);
629                         break;
630
631                 case S_DIR:
632                 case S_EXT:
633                         outab(op);
634                         outrb(&e, R_PAG0);
635                         break;
636
637                 default:
638                         aerr();
639                 }
640                 break;
641
642         /* SETB C or bit */
643         case S_SETB:
644                 t = addr(&e);
645                 switch (t) {
646                 case S_C:
647                         outab(op+1);
648                         break;
649
650                 case S_DIR:
651                 case S_EXT:
652                         outab(op);
653                         outrb(&e, R_PAG0);
654                         break;
655
656                 default:
657                         aerr();
658                 }
659                 break;
660
661         /* direct */
662         case S_DIRECT:
663                 t = addr(&e);
664                 if ((t != S_DIR) && (t != S_EXT)) {
665                         aerr();
666                         break;
667                 }
668                 outab(op);
669                 outrb(&e, R_PAG0);
670                 break;
671
672         /* XCHD A,@Rn */
673         case S_XCHD:
674                 t = addr(&e);
675                 if (t != S_A)
676                         aerr();
677                 comma();
678                 t1 = addr(&e1);
679                 switch (t1) {
680                 case S_AT_R:
681                         outab(op + e1.e_addr);
682                         break;
683                 default:
684                         aerr();
685                 }
686                 break;
687
688         default:
689                 err('o');
690         }
691 }
692
693 /*
694  * Is the next character a comma ?
695  */
696 int
697 comma()
698 {
699         if (getnb() != ',')
700                 qerr();
701         return(1);
702 }
703
704  /*
705   * Machine specific initialization
706   */
707  VOID
708  minit()
709  {
710          static int beenHere=0;      /* set non-zero if we have done that... */
711          struct sym    *sp;
712          struct PreDef *pd;
713
714          /*  First time only, add the pre-defined symbols to the symbol table*/
715          if (beenHere == 0) {
716                  pd = preDef;
717                  while (*pd->id) {
718                          sp = lookup(pd->id);
719                          if (sp->s_type == S_NEW) {
720                                  sp->s_addr = pd->value;
721                                  sp->s_type = S_DIR;
722                          }
723                          pd++;
724                 }
725                 beenHere = 1;
726         }
727 }