* device/include/pic16/pic18f*.h: add bit aliases in INTCONbits_t
[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 #else /* GAMEBOY */
553         case S_JR:
554                 if ((v1 = admode(CND)) != 0) {
555 #endif /* GAMEBOY */
556                         if ((v1 &= 0xFF) <= 0x18) {
557                                 op += (v1+1)<<3;
558                         } else {
559                                 aerr();
560                         }
561                         comma();
562                 }
563                 expr(&e2, 0);
564                 outab(op);
565                 if (e2.e_base.e_ap == NULL || e2.e_base.e_ap == dot.s_area) {
566                         v2 = e2.e_addr - dot.s_addr - 1;
567                         if (pass == 2 && ((v2 < -128) || (v2 > 127)))
568                                 aerr();
569                         outab(v2);
570                 } else {
571                         outrb(&e2, R_PCR);
572                 }
573                 if (e2.e_mode != S_USER)
574                         rerr();
575                 break;
576
577         case S_CALL:
578                 if ((v1 = admode(CND)) != 0) {
579                         op |= (v1&0xFF)<<3;
580                         comma();
581                 } else {
582                         op = 0xCD;
583                 }
584                 expr(&e1, 0);
585                 outab(op);
586                 outrw(&e1, 0);
587                 break;
588
589         case S_JP:
590                 if ((v1 = admode(CND)) != 0) {
591                         op |= (v1&0xFF)<<3;
592                         comma();
593                         expr(&e1, 0);
594                         outab(op);
595                         outrw(&e1, 0);
596                         break;
597                 }
598                 t1 = addr(&e1);
599                 if (t1 == S_USER) {
600                         outab(0xC3);
601                         outrw(&e1, 0);
602                         break;
603                 }
604                 if ((e1.e_addr == 0) && (gixiy(t1) == S_IDHL)) {
605                         outab(0xE9);
606                         break;
607                 }
608                 aerr();
609                 break;
610
611 #ifndef GAMEBOY
612         case X_HD64:
613                 ++hd64;
614                 break;
615
616         case X_INH2:
617                 outab(0xED);
618                 outab(op);
619                 break;
620
621         case X_IN:
622         case X_OUT:
623                 if (rf == X_IN) {
624                         t1 = addr(&e1);
625                         comma();
626                         t2 = addr(&e2);
627                 } else {
628                         t2 = addr(&e2);
629                         comma();
630                         t1 = addr(&e1);
631                 }
632                 if ((t1 == S_R8) && (t2 == S_INDM)) {
633                         outab(0xED);
634                         outab(op | e1.e_addr<<3);
635                         outrb(&e2, 0);
636                         break;
637                 }
638                 aerr();
639                 break;
640
641         case X_MLT:
642                 t1 = addr(&e1);
643                 if ((t1 == S_R16) && ((v1 = e1.e_addr) <= SP)) {
644                         outab(0xED);
645                         outab(op | v1<<4);
646                         break;
647                 }
648                 aerr();
649                 break;
650
651         case X_TST:
652                 t1 = addr(&e1);
653                 if (t1 == S_R8) {
654                         outab(0xED);
655                         outab(op | e1.e_addr<<3);
656                         break;
657                 }
658                 if (t1 == S_IDHL) {
659                         outab(0xED);
660                         outab(0x34);
661                         break;
662                 }
663                 if (t1 == S_IMMED) {
664                         outab(0xED);
665                         outab(0x64);
666                         outrb(&e1, 0);
667                         break;
668                 }
669                 aerr();
670                 break;
671
672         case X_TSTIO:
673                 t1 = addr(&e1);
674                 if (t1 == S_IMMED) {
675                         outab(0xED);
676                         outab(op);
677                         outrb(&e1, 0);
678                         break;
679                 }
680                 aerr();
681                 break;
682 #endif /* GAMEBOY */
683
684         default:
685                 err('o');
686         }
687 }
688
689 /*
690  * general addressing evaluation
691  * return(0) if general addressing mode output, else
692  * return(esp->e_mode)
693  */
694 int
695 genop(pop, op, esp, f)
696 register int pop, op;
697 register struct expr *esp;
698 int f;
699 {
700         register int t1;
701         if ((t1 = esp->e_mode) == S_R8) {
702                 if (pop)
703                         outab(pop);
704                 outab(op|esp->e_addr);
705                 return(0);
706         }
707         if (t1 == S_IDHL) {
708                 if (pop)
709                         outab(pop);
710                 outab(op|0x06);
711                 return(0);
712         }
713         if (gixiy(t1) == S_IDHL) {
714                 if (pop) {
715                         outab(pop);
716                         outrb(esp,0);
717                         outab(op|0x06);
718                 } else {
719                         outab(op|0x06);
720                         outrb(esp,0);
721                 }
722                 return(0);
723         }
724         if ((t1 == S_IMMED) && (f)) {
725                 if (pop)
726                         outab(pop);
727                 outab(op|0x46);
728                 outrb(esp,0);
729                 return(0);
730         }
731         return(t1);
732 }
733
734 /*
735  * IX and IY prebyte check
736  */
737 int
738 gixiy(v)
739 int v;
740 {
741 #ifndef GAMEBOY
742         if (v == IX) {
743                 v = HL;
744                 outab(0xDD);
745         } else if (v == IY) {
746                 v = HL;
747                 outab(0xFD);
748         } else if (v == S_IDIX) {
749                 v = S_IDHL;
750                 outab(0xDD);
751         } else if (v == S_IDIY) {
752                 v = S_IDHL;
753                 outab(0xFD);
754         }
755 #endif /* GAMEBOY */
756         return(v);
757 }
758
759 /*
760  * The next character must be a
761  * comma.
762  */
763 int
764 comma()
765 {
766         if (getnb() != ',')
767                 qerr();
768         return(1);
769 }
770
771 /*
772  * Machine dependent initialization
773  */
774 VOID
775 minit()
776 {
777 #ifndef GAMEBOY
778         hd64 = 0;
779 #endif /* GAMEBOY */
780 }