home *** CD-ROM | disk | FTP | other *** search
- /* z80mch.c */
-
- /*
- * (C) Copyright 1989
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
- #include <stdio.h>
- #include <setjmp.h>
- #include "asm.h"
- #include "z80.h"
-
- char imtab[3] = { 0x46, 0x56, 0x5E };
- int hd64;
-
- /*
- * Process a machine op.
- */
- VOID
- machine(mp)
- struct mne *mp;
- {
- register op, t1, t2;
- struct expr e1, e2;
- int rf, v1, v2;
-
- op = mp->m_valu;
- rf = mp->m_type;
- if (!hd64 && rf>X_HD64)
- rf = 0;
- switch (rf) {
-
- case S_INH1:
- outab(op);
- break;
-
- case S_INH2:
- outab(0xED);
- outab(op);
- break;
-
- case S_RET:
- if (more()) {
- if (v1 = admode(CND)) {
- outab(op | v1<<3);
- } else {
- qerr();
- }
- } else {
- outab(0xC9);
- }
- break;
-
- case S_PUSH:
- if (admode(R16X)) {
- outab(op+0x30);
- break;
- } else
- if ((v1=admode(R16)) && (v1&=0xFF)!=SP) {
- if (v1 != gixiy(v1)) {
- outab(op+0x20);
- break;
- }
- outab(op | v1<<4);
- break;
- }
- aerr();
- break;
-
- case S_RST:
- v1 = absexpr();
- if (v1 & ~0x38) {
- aerr();
- v1 = 0;
- }
- outab(op|v1);
- break;
-
- case S_IM:
- expr(&e1, 0);
- abscheck(&e1);
- if (e1.e_addr > 2) {
- aerr();
- e1.e_addr = 0;
- }
- outab(op);
- outab(imtab[e1.e_addr]);
- break;
-
- case S_BIT:
- expr(&e1, 0);
- t1 = 0;
- v1 = e1.e_addr;
- if (v1 > 7) {
- ++t1;
- v1 &= 0x07;
- }
- op |= (v1<<3);
- comma();
- addr(&e2);
- abscheck(&e1);
- if (genop(0xCB, op, &e2, 0) || t1)
- aerr();
- break;
-
- case S_RL:
- t1 = 0;
- t2 = addr(&e2);
- if (more()) {
- if ((t2 != S_R8) || (e2.e_addr != A))
- ++t1;
- comma();
- t2 = addr(&e2);
- }
- if (genop(0xCB, op, &e2, 0) || t1)
- aerr();
- break;
-
- case S_AND:
- case S_SUB:
- t1 = 0;
- t2 = addr(&e2);
- if (more()) {
- if ((t2 != S_R8) || (e2.e_addr != A))
- ++t1;
- comma();
- t2 = addr(&e2);
- }
- if (rf==S_SUB && t2!=S_IMMED) {
- if (genop(0xCB, op, &e2, 0) || t1)
- aerr();
- } else {
- if (genop(0, op, &e2, 1) || t1)
- aerr();
- }
- break;
-
- case S_ADD:
- case S_ADC:
- case S_SBC:
- t1 = addr(&e1);
- t2 = 0;
- if (more()) {
- comma();
- t2 = addr(&e2);
- }
- if (t2 == 0) {
- if (genop(0, op, &e1, 1))
- aerr();
- break;
- }
- if ((t1 == S_R8) && (e1.e_addr == A)) {
- if (genop(0, op, &e2, 1))
- aerr();
- break;
- }
- if ((t1 == S_R16) && (t2 == S_R16)) {
- if (rf == S_ADD)
- op = 0x09;
- if (rf == S_ADC)
- op = 0x4A;
- if (rf == S_SBC)
- op = 0x42;
- v1 = e1.e_addr;
- v2 = e2.e_addr;
- if ((v1 == HL) && (v2 <= SP)) {
- if (rf != S_ADD)
- outab(0xED);
- outab(op | (v2<<4));
- break;
- }
- if (rf != S_ADD) {
- aerr();
- break;
- }
- if ((v1 == IX) && (v2 != HL) && (v2 != IY)) {
- if (v2 == IX)
- v2 = HL;
- outab(0xDD);
- outab(op | (v2<<4));
- break;
- }
- if ((v1 == IY) && (v2 != HL) && (v2 != IX)) {
- if (v2 == IY)
- v2 = HL;
- outab(0xFD);
- outab(op | (v2<<4));
- break;
- }
- }
- aerr();
- break;
-
- case S_LD:
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- if (t1 == S_R8) {
- v1 = op | e1.e_addr<<3;
- if (genop(0, v1, &e2, 0) == 0)
- break;
- if (t2 == S_IMMED) {
- outab(e1.e_addr<<3 | 0x06);
- outrb(&e2,0);
- break;
- }
- }
- v1 = e1.e_addr;
- v2 = e2.e_addr;
- if ((t1 == S_R16) && (t2 == S_IMMED)) {
- v1 = gixiy(v1);
- outab(0x01|v1<<4);
- outrw(&e2, 0);
- break;
- }
- if ((t1 == S_R16) && (t2 == S_INDM)) {
- if (gixiy(v1) == HL) {
- outab(0x2A);
- } else {
- outab(0xED);
- outab(0x4B | v1<<4);
- }
- outrw(&e2, 0);
- break;
- }
- if ((t1 == S_INDM) && (t2 == S_R16)) {
- if (gixiy(v2) == HL) {
- outab(0x22);
- } else {
- outab(0xED);
- outab(0x43 | v2<<4);
- }
- outrw(&e1, 0);
- break;
- }
- if ((t1 == S_R8) && (v1 == A) && (t2 == S_INDM)) {
- outab(0x3A);
- outrw(&e2, 0);
- break;
- }
- if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
- outab(0x32);
- outrw(&e1, 0);
- break;
- }
- if ((t2 == S_R8) && (gixiy(t1) == S_IDHL)) {
- outab(0x70|v2);
- if (t1 != S_IDHL)
- outrb(&e1, 0);
- break;
- }
- if ((t2 == S_IMMED) && (gixiy(t1) == S_IDHL)) {
- outab(0x36);
- if (t1 != S_IDHL)
- outrb(&e1, 0);
- outrb(&e2, 0);
- break;
- }
- if ((t1 == S_R8X) && (t2 == S_R8) && (v2 == A)) {
- outab(0xED);
- outab(v1);
- break;
- }
- if ((t1 == S_R8) && (v1 == A) && (t2 == S_R8X)) {
- outab(0xED);
- outab(v2|0x10);
- break;
- }
- if ((t1 == S_R16) && (v1 == SP)) {
- if ((t2 == S_R16) && (gixiy(v2) == HL)) {
- outab(0xF9);
- break;
- }
- }
- if ((t1 == S_R8) && (v1 == A)) {
- if ((t2 == S_IDBC) || (t2 == S_IDDE)) {
- outab(0x0A | (t2-S_INDR)<<4);
- break;
- }
- }
- if ((t2 == S_R8) && (v2 == A)) {
- if ((t1 == S_IDBC) || (t1 == S_IDDE)) {
- outab(0x02 | (t1-S_INDR)<<4);
- break;
- }
- }
- aerr();
- break;
-
-
- case S_EX:
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- if (t2 == S_R16) {
- v1 = e1.e_addr;
- v2 = e2.e_addr;
- if ((t1 == S_IDSP) && (v1 == 0)) {
- if (gixiy(v2) == HL) {
- outab(op);
- break;
- }
- }
- if (t1 == S_R16) {
- if ((v1 == DE) && (v2 == HL)) {
- outab(0xEB);
- break;
- }
- }
- }
- if ((t1 == S_R16X) && (t2 == S_R16X)) {
- outab(0x08);
- break;
- }
- aerr();
- break;
-
- case S_IN:
- case S_OUT:
- if (rf == S_IN) {
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- } else {
- t2 = addr(&e2);
- comma();
- t1 = addr(&e1);
- }
- v1 = e1.e_addr;
- v2 = e2.e_addr;
- if (t1 == S_R8) {
- if ((v1 == A) && (t2 == S_INDM)) {
- outab(op);
- outab(v2);
- break;
- }
- if (t2 == S_IDC) {
- outab(0xED);
- outab(((rf == S_IN) ? 0x40 : 0x41) + (v1<<3));
- break;
- }
- }
- aerr();
- break;
-
- case S_DEC:
- case S_INC:
- t1 = addr(&e1);
- v1 = e1.e_addr;
- if (t1 == S_R8) {
- outab(op|(v1<<3));
- break;
- }
- if (t1 == S_IDHL) {
- outab(op|0x30);
- break;
- }
- if (t1 != gixiy(t1)) {
- outab(op|0x30);
- outrb(&e1,0);
- break;
- }
- if (t1 == S_R16) {
- v1 = gixiy(v1);
- if (rf == S_INC) {
- outab(0x03|(v1<<4));
- break;
- }
- if (rf == S_DEC) {
- outab(0x0B|(v1<<4));
- break;
- }
- }
- aerr();
- break;
-
- case S_DJNZ:
- case S_JR:
- if ((v1=admode(CND)) && (rf != S_DJNZ)) {
- if ((v1&=0xFF) <= 0x18) {
- op += (v1+1)<<3;
- } else {
- aerr();
- }
- comma();
- }
- expr(&e2, 0);
- v2 = e2.e_addr - dot->s_addr - 2;
- if ((v2 < -128) || (v2 > 127))
- aerr();
- if (e2.e_base.e_ap != dot->s_area)
- rerr();
- outab(op);
- outab(v2);
- break;
-
- case S_CALL:
- if (v1=admode(CND)) {
- op |= (v1&0xFF)<<3;
- comma();
- } else {
- op = 0xCD;
- }
- expr(&e1, 0);
- outab(op);
- outrw(&e1, 0);
- break;
-
- case S_JP:
- if (v1=admode(CND)) {
- op |= (v1&0xFF)<<3;
- comma();
- expr(&e1, 0);
- outab(op);
- outrw(&e1, 0);
- break;
- }
- t1 = addr(&e1);
- if (t1 == S_USER) {
- outab(0xC3);
- outrw(&e1, 0);
- break;
- }
- if ((e1.e_addr == 0) && (gixiy(t1) == S_IDHL)) {
- outab(0xE9);
- break;
- }
- aerr();
- break;
-
- case X_HD64:
- ++hd64;
- break;
-
- case X_INH2:
- outab(0xED);
- outab(op);
- break;
-
- case X_IN:
- case X_OUT:
- if (rf == X_IN) {
- t1 = addr(&e1);
- comma();
- t2 = addr(&e2);
- } else {
- t2 = addr(&e2);
- comma();
- t1 = addr(&e1);
- }
- if ((t1 == S_R8) && (t2 == S_INDM)) {
- outab(0xED);
- outab(op | e1.e_addr<<3);
- outrb(&e2, 0);
- break;
- }
- aerr();
- break;
-
- case X_MLT:
- t1 = addr(&e1);
- if ((t1 == S_R16) && ((v1 = e1.e_addr) <= SP)) {
- outab(0xED);
- outab(op | v1<<4);
- break;
- }
- aerr();
- break;
-
- case X_TST:
- t1 = addr(&e1);
- if (t1 == S_R8) {
- outab(0xED);
- outab(op | e1.e_addr<<3);
- break;
- }
- if (t1 == S_IDHL) {
- outab(0xED);
- outab(0x34);
- break;
- }
- if (t1 == S_IMMED) {
- outab(0xED);
- outab(0x64);
- outrb(&e1, 0);
- break;
- }
- aerr();
- break;
-
- case X_TSTIO:
- t1 = addr(&e1);
- if (t1 == S_IMMED) {
- outab(0xED);
- outab(op);
- outrb(&e1, 0);
- break;
- }
- aerr();
- break;
-
- default:
- err('o');
- }
- }
-
- /*
- * general addressing evaluation
- * return(0) if general addressing mode output, else
- * return(esp->e_mode)
- */
- int
- genop(pop, op, esp, f)
- register int pop, op;
- register struct expr *esp;
- int f;
- {
- register int t1;
- if ((t1 = esp->e_mode) == S_R8) {
- if (pop)
- outab(pop);
- outab(op|esp->e_addr);
- return(0);
- }
- if (t1 == S_IDHL) {
- if (pop)
- outab(pop);
- outab(op|0x06);
- return(0);
- }
- if (gixiy(t1) == S_IDHL) {
- if (pop) {
- outab(pop);
- outrb(esp,0);
- outab(op|0x06);
- } else {
- outab(op|0x06);
- outrb(esp,0);
- }
- return(0);
- }
- if ((t1 == S_IMMED) && (f)) {
- if (pop)
- outab(pop);
- outab(op|0x46);
- outrb(esp,0);
- return(0);
- }
- return(t1);
- }
-
- /*
- * IX and IY prebyte check
- */
- int
- gixiy(v)
- int v;
- {
- if (v == IX) {
- v = HL;
- outab(0xDD);
- } else if (v == IY) {
- v = HL;
- outab(0xFD);
- } else if (v == S_IDIX) {
- v = S_IDHL;
- outab(0xDD);
- } else if (v == S_IDIY) {
- v = S_IDHL;
- outab(0xFD);
- }
- return(v);
- }
-
- /*
- * The next character must be a
- * comma.
- */
- VOID
- comma()
- {
- if (getnb() != ',')
- qerr();
- }
-
- /*
- * Machine dependent initialization
- */
- VOID
- minit()
- {
- hd64 = 0;
- }
-