/* m09mch.c */ /* * (C) Copyright 1989 * All Rights Reserved * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 */ #include #include #include "asm.h" #include "6809.h" #define NB 256 int *bp; int bm; int bb[NB]; struct sdp sdp[] = { 0, NULL }; /* * Process a machine op. */ VOID machine(mp) struct mne *mp; { register op, rf, cpg, c; struct expr e1; int t1, v1, v2; struct area *amp; char id[NCPS]; cpg = 0; op = mp->m_valu; switch (rf = mp->m_type) { case S_INH2: cpg += 0x01; case S_INH1: cpg += 0x10; case S_INH: if (cpg) outab(cpg); outab(op); break; case S_BRA: expr(&e1, 0); v1 = e1.e_addr - dot->s_addr - 2; if ((v1 < -128) || (v1 > 127)) aerr(); if (e1.e_base.e_ap != dot->s_area) rerr(); outab(op); outab(v1); break; case S_LBRA: cpg += 0x10; case S_LBSR: expr(&e1, 0); if (cpg) outab(cpg); outab(op); if (e1.e_base.e_ap != dot->s_area) { outrw(&e1, 1); } else { v1 = e1.e_addr - dot->s_addr - 2; outaw(v1); } if (e1.e_mode != S_USER) aerr(); break; case S_PULS: v1 = 0; do { if ((t1 = admode(stks)) == 0 || v1 & t1) aerr(); v1 |= t1; } while (more() && comma()); outab(op); outab(v1); break; case S_PULU: v1 = 0; do { if ((t1 = admode(stku)) == 0 || v1 & t1) aerr(); v1 |= t1; } while (more() && comma()); outab(op); outab(v1); break; case S_EXG: v1 = admode(regs); comma(); v2 = admode(regs); if ((v1 & 0x08) != (v2 & 0x08)) aerr(); outab(op); outab((v1<<4)|v2); break; case S_ACC: t1 = addr(&e1); if (t1 == S_IMMED) e1.e_mode = S_IMB; genout(cpg, op, rf, &e1); break; case S_STR1: cpg += 0x10; case S_SOP: case S_STR: t1 = addr(&e1); if (t1 == S_IMMED) e1.e_mode = S_IMER; genout(cpg, op, rf, &e1); break; case S_LR2: cpg += 0x01; case S_LR1: cpg += 0x10; case S_LR: t1 = addr(&e1); if (t1 == S_IMMED) e1.e_mode = S_IMW; genout(cpg, op, rf, &e1); break; case S_LEA: t1 = addr(&e1); if (index) { genout(cpg, op, rf, &e1); break; } aerr(); break; case S_CC: t1 = addr(&e1); if (t1 == S_IMMED) { e1.e_mode = S_IMB; genout(cpg, op, rf, &e1); break; } aerr(); break; case S_6800: m68out(op); break; case S_SDP: expr(&e1, 0); amp = NULL; if ((c = getnb()) == ',') { getid(id, -1); amp = alookup(id); if ( amp == NULL) { err('u'); } } else { unget(c); } if (amp) { sdp->s_area = amp; } else { sdp->s_area = dot->s_area; } sdp->s_addr = e1.e_addr & ~0xFF; lmode = SLIST; break; default: err('o'); } } /* * General Output Routine */ VOID genout(cpg, op, rf, esp) register int cpg, op, rf; register struct expr *esp; { int espv; struct area *espa; int disp, flag; espv = esp->e_addr; espa = esp->e_base.e_ap; switch (esp->e_mode) { case S_IMB: if (cpg) outab(cpg); outab(op); outrb(esp, 0); break; case S_IMW: if (cpg) outab(cpg); outab(op); outrw(esp, 0); break; case S_DIR: if (cpg) outab(cpg); if (rf == S_SOP) { outab(op&0x0F); } else { outab(op|0x10); } if (espa && espa != sdp->s_area) rerr(); espv = espv - sdp->s_addr; if (espv & ~0xFF) aerr(); outab(espv); break; case S_EXT: if (cpg) outab(cpg); if (index) { outab(op|0x20); outab(index|0x0F); outrw(esp, 0); break; } outab(op|0x30); outrw(esp, 0); break; case S_IND: if (cpg) outab(cpg); outab(op|0x20); outab(index); break; case S_PC: if (espa) { aerr(); break; } if (cpg) outab(cpg); outab(op|0x20); if (pass == 0) { dot->s_addr += 3; } else if (pass == 1) { if (esp->e_addr >= dot->s_addr) esp->e_addr -= fuzz; dot->s_addr += 2; disp = esp->e_addr; flag = 0; if (disp<-128 || disp>127) ++flag; if (setbit(flag)) ++dot->s_addr; } else { if (getbit()) { outab(index|0x01); outaw(espv); } else { outab(index); outab(espv); } } break; case S_PCR: if (cpg) outab(cpg); outab(op|0x20); if (pass == 0) { dot->s_addr += 3; } else if (espa && espa != dot->s_area) { outab(index|0x01); outrw(esp, 1); } else if (pass == 1) { if (esp->e_addr >= dot->s_addr) esp->e_addr -= fuzz; dot->s_addr += 2; disp = esp->e_addr - dot->s_addr; flag = 0; if (disp<-128 || disp>127) ++flag; if (setbit(flag)) ++dot->s_addr; } else { if (getbit()) { outab(index|0x01); disp = espv - dot->s_addr - 2; outaw(disp); } else { outab(index); disp = espv - dot->s_addr - 1; outab(disp); } } break; case S_OFST: if (cpg) outab(cpg); outab(op|0x20); if (pass == 0) { dot->s_addr += 3; } else if (espa) { outab(index|0x09); outrw(esp, 0); } else if (pass == 1) { if (esp->e_addr >= dot->s_addr) esp->e_addr -= fuzz; dot->s_addr += 1; flag = 0; if (espv <- 128 || espv > 127) ++flag; if (setbit(flag)) { dot->s_addr += 2; } else { flag = index & 0x10; if (espv <- 16 || espv > 15) ++flag; if (setbit(flag)) ++dot->s_addr; } } else { if (getbit()) { outab(index|0x09); outaw(espv); } else { if (getbit()) { outab(index|0x08); outab(espv); } else { outab((index & 0x60) | (espv & 0x1F)); } } } break; case S_IMER: default: aerr(); } } /* * mc6800 compatibility output routine */ VOID m68out(i) int i; { register char *ptr; register int j; ptr = (char *) &mc6800[i].opcode; for (j=0; j<4 ; j++) { if (i = *ptr++) { outab(i); } else { break; } } } /* * Machine specific initialization. * Set up the bit table. * Reset direct page. */ VOID minit() { bp = bb; bm = 1; sdp->s_addr = 0; sdp->s_area = dot->s_area; } /* * Store `b' in the next slot of the bit table. * If no room, force the longer form of the offset. */ int setbit(b) { if (bp >= &bb[NB]) return(1); if (b) *bp |= bm; bm <<= 1; if (bm == 0) { bm = 1; ++bp; } return(b); } /* * Get the next bit from the bit table. * If none left, return a `1'. * This will force the longer form of the offset. */ int getbit() { register f; if (bp >= &bb[NB]) return (1); f = *bp & bm; bm <<= 1; if (bm == 0) { bm = 1; ++bp; } return (f); } /* * The next character must be a * comma. */ int comma() { if (getnb() != ',') qerr(); return(1); }