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