
#include "debug.h"

extern error;

char *mem_base;

initmem()
{
    register i;
    register long *ptr;    

    mem_base=(char *) Malloc(0x10000l);
    ptr=(long *) mem_base;
    for (i=0; i<16000; i++)
        *(ptr++)=0l;
}

swap(val)
register val;
{
    asm
    {
        rol #8,D7
    }
    return val;
}

word(adr)
unsigned adr;
{
    if (adr & 1)
    {
        error=4;
        return;
    }
    kbtst(adr);
    return swap(*((int *) (mem_base+adr)));
}

*wordptr(adr)
unsigned adr;
{
    if (adr & 1)
    {
        error=4;
        return;
    }
    kbtst(adr);
    return (int *) (mem_base+adr);
}

char byte(adr)
unsigned adr;
{
    kbtst(adr);
    return *((char *) (mem_base+adr));
}

short *byteptr(adr)
unsigned adr;
{
    kbtst(adr);
    return (short *) (mem_base+adr);
}

putword(adr,val)
unsigned adr;
int val;
{
    *((int *) (mem_base+adr))=swap(val);
}

#define CCR 0177776

setfl(cond,offs)
int cond,offs;
{
    if (cond)
        putword(CCR,word(CCR)|offs);
    else
        putword(CCR,word(CCR)&(~offs));
}

makefl(bits)
int bits;
{
    putword(CCR,(word(CCR) | 0xf) & (0xfff0 | bits));
}

flag(offs)
int offs;
{
    return word(CCR) & offs;
}
 
lfetch()
{
    extern unsigned lc;
    int val;
    
    val=word(lc);
    lc+=2;
    return val;
}

fetch()
{
    extern regs[];
    int val;
    
    val=word(regs[7]);
    regs[7]+=2;
    return val;
}

int regs[8] = {0,0,0,0,0,0,0,0};

showregs()
{
    printf("R0: %06o %06o %06o %06o  ",regs[0],regs[1],regs[2],regs[3]);
    printf("R4: %06o %06o %06o %06o   ",regs[4],regs[5],regs[6],regs[7]);
    putchar(flag(NEGA) ? 'N' : ' ');
    putchar(' ');
    putchar(flag(ZERO) ? 'Z' : ' ');
    putchar(' ');
    putchar(flag(OVER) ? 'V' : ' ');
    putchar(' ');
    putchar(flag(CARRY) ? 'C' : ' ');
    putchar('\n');
}    

wsource(field)
int field;
{
    register r,val;
    
    r=field & 7;
    switch ((field & 070) >> 3)
    {
        case 0:
            return regs[r];
        case 2:
            val=word(regs[r]);
            regs[r]+=2;
            return val;
        case 3:
            val=word(word(regs[r]));
            regs[r]+=2;
            return val;
        case 4:
            regs[r]-=2;
        case 1:
            return word(regs[r]);
        case 5:
            regs[r]-=2;
            return word(word(regs[r]));
        case 6:
            val=fetch();
            return word(val+regs[r]);
        case 7:
            val=fetch();
            return word(word(val+regs[r]));
    }
}

short bsource(field)
int field;
{
    register r,val;
    
    r=field & 7;
    switch ((field & 070) >> 3)
    {
        case 0:
            return regs[r];
        case 1:
            return byte(regs[r]);
        case 2:
            val=byte(regs[r]++);
            if (r == 6 || r == 7)
                regs[r]++;
            return val;
        case 3:
            val=byte(word(regs[r]));
            regs[r]+=2;
            return val;
        case 4:
            if (r == 6 || r == 7)
                regs[r]-=2;
            else
                regs[r]--;
            return byte(regs[r]);
        case 5:
            regs[r]-=2;
            return byte(word(regs[r]));
        case 6:
            val=fetch();
            return byte(val+regs[r]);
        case 7:
            val=fetch();
            return byte(word(val+regs[r]));
    }
}

*wdest(field)
int field;
{
    register r,val,*ptr;
    
    r=field & 7;
    switch ((field & 070) >> 3)
    {
        case 0:
            return &regs[r];
        case 2:
            ptr=wordptr(regs[r]);
            regs[r]+=2;
            break;
        case 3:
            ptr=wordptr(word(regs[r]));
            regs[r]+=2;
            break;
        case 4:
            regs[r]-=2;
        case 1:
            ptr=wordptr(regs[r]);
            break;
        case 5:
            regs[r]-=2;
            ptr=wordptr(word(regs[r]));
            break;
        case 6:
            val=fetch();
            ptr=wordptr(val+regs[r]);
            break;
        case 7:
            val=fetch();
            ptr=wordptr(word(val+regs[r]));
            break;
    }
    *ptr=swap(*ptr);
    return ptr;
}

short *bdest(field)
int field;
{
    register r,val;
    register short *ptr;
    
    r=field & 7;
    switch ((field & 070) >> 3)
    {
        case 0:
            return ((short *) &regs[r])+1;
        case 2:
            ptr=byteptr(regs[r]++);
            if (r == 6 || r == 7)
                regs[r]++;
            return ptr;
        case 3:
            ptr=byteptr(word(regs[r]));
            regs[r]+=2;
            return ptr;
        case 4:
            if (r == 7 || r == 6)
                regs[r]-=2;
            else
                regs[r]--;
        case 1:
            return byteptr(regs[r]);
        case 5:
            regs[r]-=2;
            return byteptr(word(regs[r]));
        case 6:
            val=fetch();
            return byteptr(val+regs[r]);
        case 7:
            val=fetch();
            return byteptr(word(val+regs[r]));
    }
}

wshow(ptr)
int *ptr;
{
    dirshow(ptr);
    reexch(ptr);
}

dirshow(ptr)
int *ptr;
{
    extern run;

    if (!run && (ptr < &regs[0] || ptr > &regs[7]))
        printf("%06o- %06o\n",(int) ((long) ptr - (long) mem_base),*ptr);
}

reexch(ptr)
int *ptr;
{
    if (ptr < &regs[0] || ptr > &regs[7])
        *ptr=swap(*ptr);
}

bshow(ptr)
short *ptr;
{
    extern run;
    
    if (!run && (ptr < (short *) &regs[0] || ptr > (short *) &regs[7]))
        printf("%06o- %03o\n",(int) ((long) ptr - (long) mem_base),*ptr & 0xff);
}

#define KBDATA 0177562

kbtst(adr)
{
    extern oldkbstat,run;

    if (adr==KBDATA && run)
        oldkbstat=0;
}
