home *** CD-ROM | disk | FTP | other *** search
- /* m09mch.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 "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);
- }
-