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