Imported Upstream version 2.9.0
[debian/cc1111] / 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                         clrexpr(&e2);
137                         t2 = addr(&e2);
138                 }
139                 if (genop(0xCB, op, &e2, 0) || t1)
140                         aerr();
141                 break;
142
143         case S_AND:
144         case S_SUB:
145                 t1 = 0;
146                 t2 = addr(&e2);
147                 if (more()) {
148                         if ((t2 != S_R8) || (e2.e_addr != A))
149                                 ++t1;
150                         comma();
151                         clrexpr(&e2);
152                         t2 = addr(&e2);
153                 }
154                 if (genop(0, op, &e2, 1) || t1)
155                         aerr();
156                 break;
157
158         case S_ADD:
159         case S_ADC:
160         case S_SBC:
161                 t1 = addr(&e1);
162                 t2 = 0;
163                 if (more()) {
164                         comma();
165                         t2 = addr(&e2);
166                 }
167                 if (t2 == 0) {
168                         if (genop(0, op, &e1, 1))
169                                 aerr();
170                         break;
171                 }
172                 if ((t1 == S_R8) && (e1.e_addr == A)) {
173                         if (genop(0, op, &e2, 1))
174                                 aerr();
175                         break;
176                 }
177                 if ((t1 == S_R16) && (t2 == S_R16)) {
178 #ifndef GAMEBOY
179                         if (rf == S_ADD)
180                                 op = 0x09;
181                         if (rf == S_ADC)
182                                 op = 0x4A;
183                         if (rf == S_SBC)
184                                 op = 0x42;
185                         v1 = e1.e_addr;
186                         v2 = e2.e_addr;
187                         if ((v1 == HL) && (v2 <= SP)) {
188                                 if (rf != S_ADD)
189                                         outab(0xED);
190                                 outab(op | (v2<<4));
191                                 break;
192                         }
193                         if (rf != S_ADD) {
194                                 aerr();
195                                 break;
196                         }
197                         if ((v1 == IX) && (v2 != HL) && (v2 != IY)) {
198                                 if (v2 == IX)
199                                         v2 = HL;
200                                 outab(0xDD);
201                                 outab(op | (v2<<4));
202                                 break;
203                         }
204                         if ((v1 == IY) && (v2 != HL) && (v2 != IX)) {
205                                 if (v2 == IY)
206                                         v2 = HL;
207                                 outab(0xFD);
208                                 outab(op | (v2<<4));
209                                 break;
210                         }
211                 }
212 #else /* GAMEBOY */
213                         v1 = e1.e_addr;
214                         v2 = e2.e_addr;
215                         if ((v1 == HL) && (v2 <= SP) && (rf == S_ADD)) {
216                                 outab(0x09 | (v2<<4));
217                                 break;
218                         }
219                 }
220                 /*
221                  * 0xE8 : ADD SP,#n
222                  */
223                 if ((rf == S_ADD) && (t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
224                         outab(0xE8);
225                         outrb(&e2,0);
226                         break;
227                 }
228 #endif /* GAMEBOY */
229                 aerr();
230                 break;
231
232         case S_LD:
233                 t1 = addr(&e1);
234                 comma();
235                 t2 = addr(&e2);
236                 if (t1 == S_R8) {
237                         v1 = op | e1.e_addr<<3;
238                         if (genop(0, v1, &e2, 0) == 0)
239                                 break;
240                         if (t2 == S_IMMED) {
241                                 outab(e1.e_addr<<3 | 0x06);
242                                 outrb(&e2,0);
243                                 break;
244                         }
245                 }
246                 v1 = e1.e_addr;
247                 v2 = e2.e_addr;
248                 if ((t1 == S_R16) && (t2 == S_IMMED)) {
249                         v1 = gixiy(v1);
250                         outab(0x01|v1<<4);
251                         outrw(&e2, 0);
252                         break;
253                 }
254 #ifndef GAMEBOY
255                 if ((t1 == S_R16) && (t2 == S_INDM)) {
256                         if (gixiy(v1) == HL) {
257                                 outab(0x2A);
258                         } else {
259                                 outab(0xED);
260                                 outab(0x4B | v1<<4);
261                         }
262                         outrw(&e2, 0);
263                         break;
264                 }
265                 if ((t1 == S_INDM) && (t2 == S_R16)) {
266                         if (gixiy(v2) == HL) {
267                                 outab(0x22);
268                         } else {
269                                 outab(0xED);
270                                 outab(0x43 | v2<<4);
271                         }
272                         outrw(&e1, 0);
273                         break;
274                 }
275                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_INDM)) {
276                         outab(0x3A);
277                         outrw(&e2, 0);
278                         break;
279                 }
280                 if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
281                         outab(0x32);
282                         outrw(&e1, 0);
283                         break;
284                 }
285 #endif /* GAMEBOY */
286                 if ((t2 == S_R8) && (gixiy(t1) == S_IDHL)) {
287                         outab(0x70|v2);
288                         if (t1 != S_IDHL)
289                                 outrb(&e1, 0);
290                         break;
291                 }
292                 if ((t2 == S_IMMED) && (gixiy(t1) == S_IDHL)) {
293                         outab(0x36);
294                         if (t1 != S_IDHL)
295                                 outrb(&e1, 0);
296                         outrb(&e2, 0);
297                         break;
298                 }
299 #ifndef GAMEBOY
300                 if ((t1 == S_R8X) && (t2 == S_R8) && (v2 == A)) {
301                         outab(0xED);
302                         outab(v1);
303                         break;
304                 }
305                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_R8X)) {
306                         outab(0xED);
307                         outab(v2|0x10);
308                         break;
309                 }
310 #endif /* GAMEBOY */
311                 if ((t1 == S_R16) && (v1 == SP)) {
312                         if ((t2 == S_R16) && (gixiy(v2) == HL)) {
313                                 outab(0xF9);
314                                 break;
315                         }
316                 }
317                 if ((t1 == S_R8) && (v1 == A)) {
318                         if ((t2 == S_IDBC) || (t2 == S_IDDE)) {
319                                 outab(0x0A | (t2-S_INDR)<<4);
320                                 break;
321                         }
322                 }
323                 if ((t2 == S_R8) && (v2 == A)) {
324                         if ((t1 == S_IDBC) || (t1 == S_IDDE)) {
325                                 outab(0x02 | (t1-S_INDR)<<4);
326                                 break;
327                         }
328                 }
329 #ifdef GAMEBOY
330                 /*
331                  * 0x08 : LD (nn),SP
332                  */
333                 if ((t1 == S_INDM) && (t2 == S_R16) && (v2 == SP)) {
334                         outab(0x08);
335                         outrw(&e1, 0);
336                         break;
337                 }
338                 /*
339                  * 0xEA : LD (nn),A
340                  * 0xFA : LD A,(nn)
341                  */
342                 if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
343                         outab(0xEA);
344                         outrw(&e1, 0);
345                         break;
346                 }
347                 if ((t2 == S_INDM) && (t1 == S_R8) && (v1 == A)) {
348                         outab(0xFA);
349                         outrw(&e2, 0);
350                         break;
351                 }
352                 /*
353                  * 0x32 : LD (HL-),A
354                  * 0x3A : LD A,(HL-)
355                  */
356                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLD)) {
357                         outab(0x3A);
358                         break;
359                 }
360                 if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLD)) {
361                         outab(0x32);
362                         break;
363                 }
364                 /*
365                  * 0x22 : LD (HL+),A
366                  * 0x2A : LD A,(HL+)
367                  */
368                 if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLI)) {
369                         outab(0x2A);
370                         break;
371                 }
372                 if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLI)) {
373                         outab(0x22);
374                         break;
375                 }
376 #endif /* GAMEBOY */
377                 aerr();
378                 break;
379
380
381 #ifdef GAMEBOY
382         case S_STOP:    /* 0x10 */
383                 /*
384                  * 0x10 : STOP
385                  */
386                 outab(op);
387                 outab(0x00);
388                 break;
389
390
391         case S_LDH:     /* 0xE0 */
392                 /*
393                  * 0xE0 : LDH (n),A = LD ($FF00+n),A
394                  * 0xE2 : LDH (C),A = LD ($FF00+C),A
395                  * 0xF0 : LDH A,(n) = LD A,($FF00+n)
396                  * 0xF2 : LDH A,(C) = LD A,($FF00+C)
397                  */
398                 t1 = addr(&e1);
399                 comma();
400                 t2 = addr(&e2);
401                 if ((t1 == S_INDM) && (t2 == S_R8) && (e2.e_addr == A)) {
402                         outab(0xE0);
403                         outrb(&e1, 0);
404                         break;
405                 }
406                 if ((t1 == S_IDC) && (t2 == S_R8) && (e2.e_addr == A)) {
407                         outab(0xE2);
408                         break;
409                 }
410                 if ((t2 == S_INDM) && (t1 == S_R8) && (e1.e_addr == A)) {
411                         outab(0xF0);
412                         outrb(&e2, 0);
413                         break;
414                 }
415                 if ((t2 == S_IDC) && (t1 == S_R8) && (e1.e_addr == A)) {
416                         outab(0xF2);
417                         break;
418                 }
419                 aerr();
420                 break;
421
422
423         case S_LDA:     /* 0xE8 */
424                 /*
425                  * 0xE8 : LDA SP,#n(SP)
426                  * 0xF8 : LDA HL,#n(SP)
427                  */
428                 t1 = addr(&e1);
429                 comma();
430                 t2 = addr(&e2);
431                 if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_INDR+SP)) {
432                         outab(0xE8);
433                         outrb(&e2,0);
434                         break;
435                 }
436                 if ((t1 == S_R16) && (e1.e_addr == HL) && (t2 == S_INDR+SP)) {
437                         outab(0xF8);
438                         outrb(&e2,0);
439                         break;
440                 }
441                 aerr();
442                 break;
443
444
445         case S_LDHL:    /* 0xF8 */
446                 /*
447                  * 0xF8 : LDHL SP,#n
448                  */
449                 t1 = addr(&e1);
450                 comma();
451                 t2 = addr(&e2);
452                 if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
453                         outab(0xF8);
454                         outrb(&e2,0);
455                         break;
456                 }
457                 aerr();
458                 break;
459 #endif /* GAMEBOY */
460
461
462 #ifndef GAMEBOY
463         case S_EX:
464                 t1 = addr(&e1);
465                 comma();
466                 t2 = addr(&e2);
467                 if (t2 == S_R16) {
468                         v1 = e1.e_addr;
469                         v2 = e2.e_addr;
470                         if ((t1 == S_IDSP) && (v1 == 0)) {
471                                 if (gixiy(v2) == HL) {
472                                         outab(op);
473                                         break;
474                                 }
475                         }
476                         if (t1 == S_R16) {
477                                 if ((v1 == DE) && (v2 == HL)) {
478                                         outab(0xEB);
479                                         break;
480                                 }
481                         }
482                 }
483                 if ((t1 == S_R16X) && (t2 == S_R16X)) {
484                         outab(0x08);
485                         break;
486                 }
487                 aerr();
488                 break;
489
490         case S_IN:
491         case S_OUT:
492                 if (rf == S_IN) {
493                         t1 = addr(&e1);
494                         comma();
495                         t2 = addr(&e2);
496                 } else {
497                         t2 = addr(&e2);
498                         comma();
499                         t1 = addr(&e1);
500                 }
501                 v1 = e1.e_addr;
502                 v2 = e2.e_addr;
503                 if (t1 == S_R8) {
504                         if ((v1 == A) && (t2 == S_INDM)) {
505                                 outab(op);
506                                 outab(v2);
507                                 break;
508                         }
509                         if (t2 == S_IDC) {
510                                 outab(0xED);
511                                 outab(((rf == S_IN) ? 0x40 : 0x41) + (v1<<3));
512                                 break;
513                         }
514                 }
515                 aerr();
516                 break;
517 #endif /* GAMEBOY */
518
519         case S_DEC:
520         case S_INC:
521                 t1 = addr(&e1);
522                 v1 = e1.e_addr;
523                 if (t1 == S_R8) {
524                         outab(op|(v1<<3));
525                         break;
526                 }
527                 if (t1 == S_IDHL) {
528                         outab(op|0x30);
529                         break;
530                 }
531                 if (t1 != gixiy(t1)) {
532                         outab(op|0x30);
533                         outrb(&e1,0);
534                         break;
535                 }
536                 if (t1 == S_R16) {
537                         v1 = gixiy(v1);
538                         if (rf == S_INC) {
539                                 outab(0x03|(v1<<4));
540                                 break;
541                         }
542                         if (rf == S_DEC) {
543                                 outab(0x0B|(v1<<4));
544                                 break;
545                         }
546                 }
547                 aerr();
548                 break;
549
550 #ifndef GAMEBOY
551         case S_DJNZ:
552         case S_JR:
553                 if ((v1 = admode(CND)) != 0 && rf != S_DJNZ) {
554                         if ((v1 &= 0xFF) <= 0x03) {
555                                 op += (v1+1)<<3;
556                         } else {
557                                 aerr();
558                         }
559                         comma();
560                 }
561 #else /* GAMEBOY */
562         case S_JR:
563                 if ((v1 = admode(CND)) != 0) {
564                         if ((v1 &= 0xFF) <= 0x18) {
565                                 op += (v1+1)<<3;
566                         } else {
567                                 aerr();
568                         }
569                         comma();
570                 }
571 #endif /* GAMEBOY */
572                 expr(&e2, 0);
573                 outab(op);
574                 if (e2.e_base.e_ap == NULL || e2.e_base.e_ap == dot.s_area) {
575                         v2 = e2.e_addr - dot.s_addr - 1;
576                         if (pass == 2 && ((v2 < -128) || (v2 > 127)))
577                                 aerr();
578                         outab(v2);
579                 } else {
580                         outrb(&e2, R_PCR);
581                 }
582                 if (e2.e_mode != S_USER)
583                         rerr();
584                 break;
585
586         case S_CALL:
587                 if ((v1 = admode(CND)) != 0) {
588                         op |= (v1&0xFF)<<3;
589                         comma();
590                 } else {
591                         op = 0xCD;
592                 }
593                 expr(&e1, 0);
594                 outab(op);
595                 outrw(&e1, 0);
596                 break;
597
598         case S_JP:
599                 if ((v1 = admode(CND)) != 0) {
600                         op |= (v1&0xFF)<<3;
601                         comma();
602                         expr(&e1, 0);
603                         outab(op);
604                         outrw(&e1, 0);
605                         break;
606                 }
607                 t1 = addr(&e1);
608                 if (t1 == S_USER) {
609                         outab(0xC3);
610                         outrw(&e1, 0);
611                         break;
612                 }
613                 if ((e1.e_addr == 0) && (gixiy(t1) == S_IDHL)) {
614                         outab(0xE9);
615                         break;
616                 }
617                 aerr();
618                 break;
619
620 #ifndef GAMEBOY
621         case X_HD64:
622                 ++hd64;
623                 break;
624
625         case X_INH2:
626                 outab(0xED);
627                 outab(op);
628                 break;
629
630         case X_IN:
631         case X_OUT:
632                 if (rf == X_IN) {
633                         t1 = addr(&e1);
634                         comma();
635                         t2 = addr(&e2);
636                 } else {
637                         t2 = addr(&e2);
638                         comma();
639                         t1 = addr(&e1);
640                 }
641                 if ((t1 == S_R8) && (t2 == S_INDM)) {
642                         outab(0xED);
643                         outab(op | e1.e_addr<<3);
644                         outrb(&e2, 0);
645                         break;
646                 }
647                 aerr();
648                 break;
649
650         case X_MLT:
651                 t1 = addr(&e1);
652                 if ((t1 == S_R16) && ((v1 = e1.e_addr) <= SP)) {
653                         outab(0xED);
654                         outab(op | v1<<4);
655                         break;
656                 }
657                 aerr();
658                 break;
659
660         case X_TST:
661                 t1 = addr(&e1);
662                 if (t1 == S_R8) {
663                         outab(0xED);
664                         outab(op | e1.e_addr<<3);
665                         break;
666                 }
667                 if (t1 == S_IDHL) {
668                         outab(0xED);
669                         outab(0x34);
670                         break;
671                 }
672                 if (t1 == S_IMMED) {
673                         outab(0xED);
674                         outab(0x64);
675                         outrb(&e1, 0);
676                         break;
677                 }
678                 aerr();
679                 break;
680
681         case X_TSTIO:
682                 t1 = addr(&e1);
683                 if (t1 == S_IMMED) {
684                         outab(0xED);
685                         outab(op);
686                         outrb(&e1, 0);
687                         break;
688                 }
689                 aerr();
690                 break;
691 #endif /* GAMEBOY */
692
693         default:
694                 err('o');
695         }
696 }
697
698 /*
699  * general addressing evaluation
700  * return(0) if general addressing mode output, else
701  * return(esp->e_mode)
702  */
703 int
704 genop(pop, op, esp, f)
705 register int pop, op;
706 register struct expr *esp;
707 int f;
708 {
709         register int t1;
710         if ((t1 = esp->e_mode) == S_R8) {
711                 if (pop)
712                         outab(pop);
713                 outab(op|esp->e_addr);
714                 return(0);
715         }
716         if (t1 == S_IDHL) {
717                 if (pop)
718                         outab(pop);
719                 outab(op|0x06);
720                 return(0);
721         }
722         if (gixiy(t1) == S_IDHL) {
723                 if (pop) {
724                         outab(pop);
725                         outrb(esp,0);
726                         outab(op|0x06);
727                 } else {
728                         outab(op|0x06);
729                         outrb(esp,0);
730                 }
731                 return(0);
732         }
733         if ((t1 == S_IMMED) && (f)) {
734                 if (pop)
735                         outab(pop);
736                 outab(op|0x46);
737                 outrb(esp,0);
738                 return(0);
739         }
740         return(t1);
741 }
742
743 /*
744  * IX and IY prebyte check
745  */
746 int
747 gixiy(v)
748 int v;
749 {
750 #ifndef GAMEBOY
751         if (v == IX) {
752                 v = HL;
753                 outab(0xDD);
754         } else if (v == IY) {
755                 v = HL;
756                 outab(0xFD);
757         } else if (v == S_IDIX) {
758                 v = S_IDHL;
759                 outab(0xDD);
760         } else if (v == S_IDIY) {
761                 v = S_IDHL;
762                 outab(0xFD);
763         }
764 #endif /* GAMEBOY */
765         return(v);
766 }
767
768 /*
769  * The next character must be a
770  * comma.
771  */
772 int
773 comma()
774 {
775         if (getnb() != ',')
776                 qerr();
777         return(1);
778 }
779
780 /*
781  * Machine dependent initialization
782  */
783 VOID
784 minit()
785 {
786 #ifndef GAMEBOY
787         hd64 = 0;
788 #endif /* GAMEBOY */
789 }