7ee7c746fecdc1b90b35c20afeeb3664b2e42487
[fw/sdcc] / as / z80 / z80mch.c
1 /* z80mch.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  */
11
12 /*
13  * Extensions: P. Felber
14  */
15
16 #include <stdio.h>
17 #include <setjmp.h>
18 #include "asm.h"
19 #include "z80.h"
20
21 char    imtab[3] = { 0x46, 0x56, 0x5E };
22 #ifndef GAMEBOY
23 int     hd64;
24 #endif /* GAMEBOY */
25
26 /*
27  * Process a machine op.
28  */
29 VOID
30 machine(mp)
31 struct mne *mp;
32 {
33         register int op, t1, t2;
34         struct expr e1, e2;
35         int rf, v1, v2;
36
37         clrexpr(&e1);
38         clrexpr(&e2);
39         op = mp->m_valu;
40         rf = mp->m_type;
41 #ifndef GAMEBOY
42         if (!hd64 && rf>X_HD64)
43                 rf = 0;
44 #endif /* GAMEBOY */
45         switch (rf) {
46
47         case S_INH1:
48                 outab(op);
49                 break;
50
51 #ifndef GAMEBOY
52         case S_INH2:
53                 outab(0xED);
54                 outab(op);
55                 break;
56 #endif /* GAMEBOY */
57
58         case S_RET:
59                 if (more()) {
60                         if ((v1 = admode(CND)) != 0) {
61                                 outab(op | v1<<3);
62                         } else {
63                                 qerr();
64                         }
65                 } else {
66                         outab(0xC9);
67                 }
68                 break;
69
70         case S_PUSH:
71                 if (admode(R16X)) {
72                         outab(op+0x30);
73                         break;
74                 } else
75                 if ((v1 = admode(R16)) != 0 && (v1 &= 0xFF) != SP) {
76                         if (v1 != gixiy(v1)) {
77                                 outab(op+0x20);
78                                 break;
79                         }
80                         outab(op | v1<<4);
81                         break;
82                 }
83                 aerr();
84                 break;
85
86         case S_RST:
87                 v1 = absexpr();
88                 if (v1 & ~0x38) {
89                         aerr();
90                         v1 = 0;
91                 }
92                 outab(op|v1);
93                 break;
94
95         case S_IM:
96                 expr(&e1, 0);
97                 abscheck(&e1);
98                 if (e1.e_addr > 2) {
99                         aerr();
100                         e1.e_addr = 0;
101                 }
102                 outab(op);
103                 outab(imtab[e1.e_addr]);
104                 break;
105
106         case S_BIT:
107                 expr(&e1, 0);
108                 t1 = 0;
109                 v1 = e1.e_addr;
110                 if (v1 > 7) {
111                         ++t1;
112                         v1 &= 0x07;
113                 }
114                 op |= (v1<<3);
115                 comma();
116                 addr(&e2);
117                 abscheck(&e1);
118                 if (genop(0xCB, op, &e2, 0) || t1)
119                         aerr();
120                 break;
121
122         case S_RL:
123                 t1 = 0;
124                 t2 = addr(&e2);
125                 if (more()) {
126                         if ((t2 != S_R8) || (e2.e_addr != A))
127                                 ++t1;
128                         comma();
129                         t2 = addr(&e2);
130                 }
131                 if (genop(0xCB, op, &e2, 0) || t1)
132                         aerr();
133                 break;
134
135         case S_AND:
136         case S_SUB:
137                 t1 = 0;
138                 t2 = addr(&e2);
139                 if (more()) {
140                         if ((t2 != S_R8) || (e2.e_addr != A))
141                                 ++t1;
142                         comma();
143                         t2 = addr(&e2);
144                 }
145                 if (genop(0, op, &e2, 1) || t1)
146                         aerr();
147                 break;
148
149         case S_ADD:
150         case S_ADC:
151         case S_SBC:
152                 t1 = addr(&e1);
153                 t2 = 0;
154                 if (more()) {
155                         comma();
156                         t2 = addr(&e2);
157                 }
158                 if (t2 == 0) {
159                         if (genop(0, op, &e1, 1))
160                                 aerr();
161                         break;
162                 }
163                 if ((t1 == S_R8) && (e1.e_addr == A)) {
164                         if (genop(0, op, &e2, 1))
165                                 aerr();
166                         break;
167                 }
168                 if ((t1 == S_R16) && (t2 == S_R16)) {
169 #ifndef GAMEBOY
170                         if (rf == S_ADD)
171                                 op = 0x09;
172                         if (rf == S_ADC)
173                                 op = 0x4A;
174                         if (rf == S_SBC)
175                                 op = 0x42;
176                         v1 = e1.e_addr;
177                         v2 = e2.e_addr;
178                         if ((v1 == HL) && (v2 <= SP)) {
179                                 if (rf != S_ADD)
180                                         outab(0xED);
181                                 outab(op | (v2<<4));
182                                 break;
183                         }
184                         if (rf != S_ADD) {
185                                 aerr();
186                                 break;
187                         }
188                         if ((v1 == IX) && (v2 != HL) && (v2 != IY)) {
189                                 if (v2 == IX)
190                                         v2 = HL;
191                                 outab(0xDD);
192                                 outab(op | (v2<<4));
193                                 break;
194                         }
195                         if ((v1 == IY) && (v2 != HL) && (v2 != IX)) {
196                                 if (v2 == IY)
197                                         v2 = HL;
198                                 outab(0xFD);
199                                 outab(op | (v2<<4));
200                                 break;
201                         }
202                 }
203 #else /* GAMEBOY */
204                         v1 = e1.e_addr;
205                         v2 = e2.e_addr;
206                         if ((v1 == HL) && (v2 <= SP) && (rf == S_ADD)) {
207                                 outab(0x09 | (v2<<4));
208                                 break;
209                         }
210                 }
211                 /*
212                  * 0xE8 : ADD SP,#n
213                  */
214                 if ((rf == S_ADD) && (t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
215                         outab(0xE8);
216                         outrb(&e2,0);
217                         break;
218                 }
219 #endif /* GAMEBOY */
220                 aerr();
221                 break;
222
223         case S_LD:
224                 t1 = addr(&e1);
225                 comma();
226                 t2 = addr(&e2);
227                 if (t1 == S_R8) {
228                         v1 = op | e1.e_addr<<3;
229                         if (genop(0, v1, &e2, 0) == 0)
230                                 break;
231                         if (t2 == S_IMMED) {
232                                 outab(e1.e_addr<<3 | 0x06);
233                                 outrb(&e2,0);
234                                 break;
235                         }
236                 }
237                 v1 = e1.e_addr;
238                 v2 = e2.e_addr;
239                 if ((t1 == S_R16) && (t2 == S_IMMED)) {
240                         v1 = gixiy(v1);
241                         outab(0x01|v1<<4);
242                         outrw(&e2, 0);
243                         break;
244                 }
245 #ifndef GAMEBOY
246                 if ((t1 == S_R16) && (t2 == S_INDM)) {
247                         if (gixiy(v1) == HL) {
248                                 outab(0x2A);
249                         } else {
250                                 outab(0xED);
251                                 outab(0x4B | v1<<4);
252                         }
253                         outrw(&e2, 0);
254                         break;
255                 }
256                 if ((t1 == S_INDM) && (t2 == S_R16)) {
257                         if (gixiy(v2) == HL) {
258                                 outab(0x22);
259                         } else {
260                                 outab(0xED);
261                                 outab(0x43 | v2<<4);
262                         }
263                         outrw(&e1, 0);
264                         break;
265                 }
266                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_INDM)) {
267                         outab(0x3A);
268                         outrw(&e2, 0);
269                         break;
270                 }
271                 if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
272                         outab(0x32);
273                         outrw(&e1, 0);
274                         break;
275                 }
276 #endif /* GAMEBOY */
277                 if ((t2 == S_R8) && (gixiy(t1) == S_IDHL)) {
278                         outab(0x70|v2);
279                         if (t1 != S_IDHL)
280                                 outrb(&e1, 0);
281                         break;
282                 }
283                 if ((t2 == S_IMMED) && (gixiy(t1) == S_IDHL)) {
284                         outab(0x36);
285                         if (t1 != S_IDHL)
286                                 outrb(&e1, 0);
287                         outrb(&e2, 0);
288                         break;
289                 }
290 #ifndef GAMEBOY
291                 if ((t1 == S_R8X) && (t2 == S_R8) && (v2 == A)) {
292                         outab(0xED);
293                         outab(v1);
294                         break;
295                 }
296                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_R8X)) {
297                         outab(0xED);
298                         outab(v2|0x10);
299                         break;
300                 }
301 #endif /* GAMEBOY */
302                 if ((t1 == S_R16) && (v1 == SP)) {
303                         if ((t2 == S_R16) && (gixiy(v2) == HL)) {
304                                 outab(0xF9);
305                                 break;
306                         }
307                 }
308                 if ((t1 == S_R8) && (v1 == A)) {
309                         if ((t2 == S_IDBC) || (t2 == S_IDDE)) {
310                                 outab(0x0A | (t2-S_INDR)<<4);
311                                 break;
312                         }
313                 }
314                 if ((t2 == S_R8) && (v2 == A)) {
315                         if ((t1 == S_IDBC) || (t1 == S_IDDE)) {
316                                 outab(0x02 | (t1-S_INDR)<<4);
317                                 break;
318                         }
319                 }
320 #ifdef GAMEBOY
321                 /*
322                  * 0x08 : LD (nn),SP
323                  */
324                 if ((t1 == S_INDM) && (t2 == S_R16) && (v2 == SP)) {
325                         outab(0x08);
326                         outrw(&e1, 0);
327                         break;
328                 }
329                 /*
330                  * 0xEA : LD (nn),A
331                  * 0xFA : LD A,(nn)
332                  */
333                 if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
334                         outab(0xEA);
335                         outrw(&e1, 0);
336                         break;
337                 }
338                 if ((t2 == S_INDM) && (t1 == S_R8) && (v1 == A)) {
339                         outab(0xFA);
340                         outrw(&e2, 0);
341                         break;
342                 }
343                 /*
344                  * 0x32 : LD (HL-),A
345                  * 0x3A : LD A,(HL-)
346                  */
347                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLD)) {
348                         outab(0x3A);
349                         break;
350                 }
351                 if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLD)) {
352                         outab(0x32);
353                         break;
354                 }
355                 /*
356                  * 0x22 : LD (HL+),A
357                  * 0x2A : LD A,(HL+)
358                  */
359                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLI)) {
360                         outab(0x2A);
361                         break;
362                 }
363                 if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLI)) {
364                         outab(0x22);
365                         break;
366                 }
367 #endif /* GAMEBOY */
368                 aerr();
369                 break;
370
371
372 #ifdef GAMEBOY
373         case S_STOP:    /* 0x10 */
374                 /*
375                  * 0x10 : STOP
376                  */
377                 outab(op);
378                 outab(0x00);
379                 break;
380
381
382         case S_LDH:     /* 0xE0 */
383                 /*
384                  * 0xE0 : LDH (n),A = LD ($FF00+n),A
385                  * 0xE2 : LDH (C),A = LD ($FF00+C),A
386                  * 0xF0 : LDH A,(n) = LD A,($FF00+n)
387                  * 0xF2 : LDH A,(C) = LD A,($FF00+C)
388                  */
389                 t1 = addr(&e1);
390                 comma();
391                 t2 = addr(&e2);
392                 if ((t1 == S_INDM) && (t2 == S_R8) && (e2.e_addr == A)) {
393                         outab(0xE0);
394                         outrb(&e1, 0);
395                         break;
396                 }
397                 if ((t1 == S_IDC) && (t2 == S_R8) && (e2.e_addr == A)) {
398                         outab(0xE2);
399                         break;
400                 }
401                 if ((t2 == S_INDM) && (t1 == S_R8) && (e1.e_addr == A)) {
402                         outab(0xF0);
403                         outrb(&e2, 0);
404                         break;
405                 }
406                 if ((t2 == S_IDC) && (t1 == S_R8) && (e1.e_addr == A)) {
407                         outab(0xF2);
408                         break;
409                 }
410                 aerr();
411                 break;
412
413
414         case S_LDA:     /* 0xE8 */
415                 /*
416                  * 0xE8 : LDA SP,#n(SP)
417                  * 0xF8 : LDA HL,#n(SP)
418                  */
419                 t1 = addr(&e1);
420                 comma();
421                 t2 = addr(&e2);
422                 if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_INDR+SP)) {
423                         outab(0xE8);
424                         outrb(&e2,0);
425                         break;
426                 }
427                 if ((t1 == S_R16) && (e1.e_addr == HL) && (t2 == S_INDR+SP)) {
428                         outab(0xF8);
429                         outrb(&e2,0);
430                         break;
431                 }
432                 aerr();
433                 break;
434
435
436         case S_LDHL:    /* 0xF8 */
437                 /*
438                  * 0xF8 : LDHL SP,#n
439                  */
440                 t1 = addr(&e1);
441                 comma();
442                 t2 = addr(&e2);
443                 if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
444                         outab(0xF8);
445                         outrb(&e2,0);
446                         break;
447                 }
448                 aerr();
449                 break;
450 #endif /* GAMEBOY */
451
452
453 #ifndef GAMEBOY
454         case S_EX:
455                 t1 = addr(&e1);
456                 comma();
457                 t2 = addr(&e2);
458                 if (t2 == S_R16) {
459                         v1 = e1.e_addr;
460                         v2 = e2.e_addr;
461                         if ((t1 == S_IDSP) && (v1 == 0)) {
462                                 if (gixiy(v2) == HL) {
463                                         outab(op);
464                                         break;
465                                 }
466                         }
467                         if (t1 == S_R16) {
468                                 if ((v1 == DE) && (v2 == HL)) {
469                                         outab(0xEB);
470                                         break;
471                                 }
472                         }
473                 }
474                 if ((t1 == S_R16X) && (t2 == S_R16X)) {
475                         outab(0x08);
476                         break;
477                 }
478                 aerr();
479                 break;
480
481         case S_IN:
482         case S_OUT:
483                 if (rf == S_IN) {
484                         t1 = addr(&e1);
485                         comma();
486                         t2 = addr(&e2);
487                 } else {
488                         t2 = addr(&e2);
489                         comma();
490                         t1 = addr(&e1);
491                 }
492                 v1 = e1.e_addr;
493                 v2 = e2.e_addr;
494                 if (t1 == S_R8) {
495                         if ((v1 == A) && (t2 == S_INDM)) {
496                                 outab(op);
497                                 outab(v2);
498                                 break;
499                         }
500                         if (t2 == S_IDC) {
501                                 outab(0xED);
502                                 outab(((rf == S_IN) ? 0x40 : 0x41) + (v1<<3));
503                                 break;
504                         }
505                 }
506                 aerr();
507                 break;
508 #endif /* GAMEBOY */
509
510         case S_DEC:
511         case S_INC:
512                 t1 = addr(&e1);
513                 v1 = e1.e_addr;
514                 if (t1 == S_R8) {
515                         outab(op|(v1<<3));
516                         break;
517                 }
518                 if (t1 == S_IDHL) {
519                         outab(op|0x30);
520                         break;
521                 }
522                 if (t1 != gixiy(t1)) {
523                         outab(op|0x30);
524                         outrb(&e1,0);
525                         break;
526                 }
527                 if (t1 == S_R16) {
528                         v1 = gixiy(v1);
529                         if (rf == S_INC) {
530                                 outab(0x03|(v1<<4));
531                                 break;
532                         }
533                         if (rf == S_DEC) {
534                                 outab(0x0B|(v1<<4));
535                                 break;
536                         }
537                 }
538                 aerr();
539                 break;
540
541 #ifndef GAMEBOY
542         case S_DJNZ:
543         case S_JR:
544                 if ((v1 = admode(CND)) != 0 && rf != S_DJNZ) {
545 #else /* GAMEBOY */
546         case S_JR:
547                 if ((v1 = admode(CND)) != 0) {
548 #endif /* GAMEBOY */
549                         if ((v1 &= 0xFF) <= 0x18) {
550                                 op += (v1+1)<<3;
551                         } else {
552                                 aerr();
553                         }
554                         comma();
555                 }
556                 expr(&e2, 0);
557                 outab(op);
558                 if (e2.e_base.e_ap == NULL || e2.e_base.e_ap == dot.s_area) {
559                         v2 = e2.e_addr - dot.s_addr - 1;
560                         if (pass == 2 && ((v2 < -128) || (v2 > 127)))
561                                 aerr();
562                         outab(v2);
563                 } else {
564                         outrb(&e2, R_PCR);
565                 }
566                 if (e2.e_mode != S_USER)
567                         rerr();
568                 break;
569
570         case S_CALL:
571                 if ((v1 = admode(CND)) != 0) {
572                         op |= (v1&0xFF)<<3;
573                         comma();
574                 } else {
575                         op = 0xCD;
576                 }
577                 expr(&e1, 0);
578                 outab(op);
579                 outrw(&e1, 0);
580                 break;
581
582         case S_JP:
583                 if ((v1 = admode(CND)) != 0) {
584                         op |= (v1&0xFF)<<3;
585                         comma();
586                         expr(&e1, 0);
587                         outab(op);
588                         outrw(&e1, 0);
589                         break;
590                 }
591                 t1 = addr(&e1);
592                 if (t1 == S_USER) {
593                         outab(0xC3);
594                         outrw(&e1, 0);
595                         break;
596                 }
597                 if ((e1.e_addr == 0) && (gixiy(t1) == S_IDHL)) {
598                         outab(0xE9);
599                         break;
600                 }
601                 aerr();
602                 break;
603
604 #ifndef GAMEBOY
605         case X_HD64:
606                 ++hd64;
607                 break;
608
609         case X_INH2:
610                 outab(0xED);
611                 outab(op);
612                 break;
613
614         case X_IN:
615         case X_OUT:
616                 if (rf == X_IN) {
617                         t1 = addr(&e1);
618                         comma();
619                         t2 = addr(&e2);
620                 } else {
621                         t2 = addr(&e2);
622                         comma();
623                         t1 = addr(&e1);
624                 }
625                 if ((t1 == S_R8) && (t2 == S_INDM)) {
626                         outab(0xED);
627                         outab(op | e1.e_addr<<3);
628                         outrb(&e2, 0);
629                         break;
630                 }
631                 aerr();
632                 break;
633
634         case X_MLT:
635                 t1 = addr(&e1);
636                 if ((t1 == S_R16) && ((v1 = e1.e_addr) <= SP)) {
637                         outab(0xED);
638                         outab(op | v1<<4);
639                         break;
640                 }
641                 aerr();
642                 break;
643
644         case X_TST:
645                 t1 = addr(&e1);
646                 if (t1 == S_R8) {
647                         outab(0xED);
648                         outab(op | e1.e_addr<<3);
649                         break;
650                 }
651                 if (t1 == S_IDHL) {
652                         outab(0xED);
653                         outab(0x34);
654                         break;
655                 }
656                 if (t1 == S_IMMED) {
657                         outab(0xED);
658                         outab(0x64);
659                         outrb(&e1, 0);
660                         break;
661                 }
662                 aerr();
663                 break;
664
665         case X_TSTIO:
666                 t1 = addr(&e1);
667                 if (t1 == S_IMMED) {
668                         outab(0xED);
669                         outab(op);
670                         outrb(&e1, 0);
671                         break;
672                 }
673                 aerr();
674                 break;
675 #endif /* GAMEBOY */
676
677         default:
678                 err('o');
679         }
680 }
681
682 /*
683  * general addressing evaluation
684  * return(0) if general addressing mode output, else
685  * return(esp->e_mode)
686  */
687 int
688 genop(pop, op, esp, f)
689 register int pop, op;
690 register struct expr *esp;
691 int f;
692 {
693         register int t1;
694         if ((t1 = esp->e_mode) == S_R8) {
695                 if (pop)
696                         outab(pop);
697                 outab(op|esp->e_addr);
698                 return(0);
699         }
700         if (t1 == S_IDHL) {
701                 if (pop)
702                         outab(pop);
703                 outab(op|0x06);
704                 return(0);
705         }
706         if (gixiy(t1) == S_IDHL) {
707                 if (pop) {
708                         outab(pop);
709                         outrb(esp,0);
710                         outab(op|0x06);
711                 } else {
712                         outab(op|0x06);
713                         outrb(esp,0);
714                 }
715                 return(0);
716         }
717         if ((t1 == S_IMMED) && (f)) {
718                 if (pop)
719                         outab(pop);
720                 outab(op|0x46);
721                 outrb(esp,0);
722                 return(0);
723         }
724         return(t1);
725 }
726
727 /*
728  * IX and IY prebyte check
729  */
730 int
731 gixiy(v)
732 int v;
733 {
734 #ifndef GAMEBOY
735         if (v == IX) {
736                 v = HL;
737                 outab(0xDD);
738         } else if (v == IY) {
739                 v = HL;
740                 outab(0xFD);
741         } else if (v == S_IDIX) {
742                 v = S_IDHL;
743                 outab(0xDD);
744         } else if (v == S_IDIY) {
745                 v = S_IDHL;
746                 outab(0xFD);
747         }
748 #endif /* GAMEBOY */
749         return(v);
750 }
751
752 /*
753  * The next character must be a
754  * comma.
755  */
756 int
757 comma()
758 {
759         if (getnb() != ',')
760                 qerr();
761         return(1);
762 }
763
764 /*
765  * Machine dependent initialization
766  */
767 VOID
768 minit()
769 {
770 #ifndef GAMEBOY
771         hd64 = 0;
772 #endif /* GAMEBOY */
773 }