view emu/iset.c @ 35:2e35be400012

took broken instructions out of the iset
author james <jb302@eecs.qmul.ac.uk>
date Thu, 17 Apr 2014 13:34:56 +0100
parents 4411dee34085
children 792da050d8c4
line wrap: on
line source
/* iset.c
 * IR functions */
#include <stdlib.h>
#include "iset.h"
#include "mem.h"

/* useful macros */
#define NNN (IR & 0x07)
#define MMM ((IR & 0x38) >> 3)

/* 0x00 - NOP */
void
NOP(void) {    
}

/* 0x08 - SET C
 * 0x0A - SET BS
 * 0x0C - SET IE */
void
SET(void) {
    switch (IR) {
        
        case 0x08:
            set_flag(C, 0x01);
            break;
        
        case 0x0A:
            set_flag(BS, 0x01);
            break;
        
        case 0x0C:
            set_flag(IE, 0x01);
            break;
        
        default:
            break;
    }
}

/* 0x09 - CLR C
 * 0x0B - CLR BS
 * 0x0D - CLR IE */
void
CLR(void) {
    switch (IR) {
        
        case 0x09:
            set_flag(C, 0x00);
            break;
        
        case 0x0B:
            set_flag(BS, 0x00);
            break;
        
        case 0x0D:
            set_flag(IE, 0x00);
            break;
        
        default:
            break;
    }    
}

/* 0x0E - CPL C
 * 0x0F - CPL A */
void
CPL(void) {
    switch (IR) {
        
        case 0x0E:
            if (get_flag(C) == 0) {
                set_flag(C, 0x01);
            }
            else {
                set_flag(C, 0x00);
            }
        
        case 0x0F:
            A = ~A;
            break;
        
        default:
            break;
    }
}

/* 0x10 - XCSD */
void
XCSD(void) {
    tmpw = get_wide(SP);
    set_wide(SP, get_wide(DPTR));
    set_wide(DPTR, tmpw);
}

/* 0x11 - SFA */
void
SFA(void) {
    A = flags;
}

/* 0x12 - LAF */
void
LAF(void) {
    flags = A;   
}

/* 0b00010XXX - special MOVs
 * 0b00011XXX - direct, indirect and indexed MOVs
 * 0b00100nnn - register-indirect MOVs - MOV @DPTR, Rn
 * 0b00101nnn - immediate movs - MOV Rn, #data8
 * 0b00110nnn - MOV Rn, A
 * 0b00111nnn - MOV A, Rn
 * 0b01mmmnnn - 64 register move instructions
 *
 * this is a mess */
void
MOV(void) {
    switch (IR & 0x40) {
       
        case 0x00:
            switch (IR & 0xF8) {
                
                /* 0b00010XXX - special MOVs*/
                case 0x10:
                    switch (NNN) {
                        
                        /* MOV DPTR, SP */
                        case 3:
                            set_wide(DPTR, get_wide(SP));
                            break;
                        
                        /* MOV SP, DPTR */
                        case 4:
                            set_wide(SP, get_wide(DPTR));
                            break;
                        
                        /* MOV A, #data8 */
                        case 5:
                            A = fetch();
                            break;
                        
                        /* MOV SP, #data16 */
                        case 6:
                            set_wide(SP, fetch_wide());
                            break;
                        
                        /* MOV DPTR, #data16 */
                        case 7:
                            set_wide(DPTR, fetch_wide());
                            break;
                        
                        default:
                            break;
                    }
                    break;
                
                /* 0b00011XXX - direct, indirect and indexed MOVs*/
                case 0x18:
                    switch (NNN) {
                        
                        /* MOV A, addr16 */
                        case 0:
                            set_wide(TMP, fetch_wide());
                            A = mem[get_wide(TMP)];
                            break;
                        
                        /* MOV addr16, A */
                        case 1:
                            set_wide(TMP, fetch_wide());
                            mem[get_wide(TMP)] = A;
                            break;
                        
                        /* MOV A, @A+DPTR */
                        case 2:
                            set_wide(TMP, A + get_wide(DPTR));
                            A = mem[get_wide(TMP)];
                            break;
                        
                        /* MOV A, @A+PC */
                        case 3:
                            set_wide(TMP, A + get_wide(PC));
                            A = mem[TMP];
                            break;
                        
                        /* MOV A, @addr16 */
                        case 4:
                            set_wide(TMP, fetch_wide());
                            A = mem[mem[get_wide(TMP)]];
                            break;
                        
                        /* MOV @addr16, A */ 
                        case 5:
                            set_wide(TMP, fetch_wide());
                            mem[mem[get_wide(TMP)]] = A;
                            break;
                        
                        /* MOV A, @DPTR */
                        case 6:
                            set_wide(TMP, get_wide(DPTR));
                            A = mem[get_wide(TMP)];
                            break;
                        
                        /* MOV @DPTR, A */
                        case 7:
                            set_wide(TMP, get_wide(DPTR));
                            mem[get_wide(TMP)] = A;
                            break;
                        
                        default:
                            break;
                    }
                    break;
                
                /* 0b00100nnn - MOV @DPTR, Rn*/
                case 0x20:
                    set_wide(TMP, get_wide(DPTR));
                    mem[get_wide(TMP)] = get_reg(NNN);
                    break;
                
                /* 0b00101nnn - immediate movs - MOV Rn, #data8*/
                case 0x28:
                    set_reg(NNN, fetch());
                    break;
                
                /* 0b00110nnn - MOV Rn, A */
                case 0x30:
                    set_reg(NNN, A);
                    break;
                
                /* 0b00111nnn MOV A, Rn */
                case 0x38:
                    A = get_reg(NNN);
                    break;
                
                default:
                    break;
                }
            break;;
        
        /* 0b01mmmnnn MOV Rm Rn
         *   if m == n: MOV Rm, @DPTR */
        case 0x40:
            if (NNN == MMM) {
                set_wide(TMP, get_wide(DPTR));
                set_reg(NNN, mem[get_wide(TMP)]);
            }
            else {
                set_reg(MMM, get_reg(NNN));
            }
            break;
        
        default:
            break;
    }
}


/* 0x80 - ANL A, R0
 * 0x81 - ANL A, R1
 * 0x82 - ANL A, R2
 * 0x83 - ANL A, R3
 * 0x84 - ANL A, DPH
 * 0x85 - ANL A, DPL
 * 0x86 - ANL A, #data8
 * 0x87 - ANL A, @DPTR */
void
ANL(void) {
    if (NNN < 6) {
        A = A & get_reg(NNN);
    }
    else {
        switch (NNN) {
            
            case 6:
                A = A & fetch();
                break;

            case 7:
                set_wide(TMP, get_wide(DPTR));
                A = A & mem[TMP];
                break;
        }
    }
    set_zp(A);
}

/* 0x88 - ORL A, R0
 * 0x89 - ORL A, R1
 * 0x8A - ORL A, R2
 * 0x8B - ORL A, R3
 * 0x8C - ORL A, DPH
 * 0x8D - ORL A, DPL
 * 0x8E - ORL A, #data8
 * 0x8F - ORL A, @DPTR */
void
ORL(void) {
    if (NNN < 6) {
        A = A | get_reg(NNN);
    }
    else {
        switch (NNN) {
            
            case 6:
                A = A | fetch();
                break;

            case 7:
                set_wide(TMP, get_wide(DPTR));
                A = A | mem[TMP];
                break;
        }
    }
    set_zp(A);
}

/* 0x90 - XRL A, R0
 * 0x91 - XRL A, R1
 * 0x92 - XRL A, R2
 * 0x93 - XRL A, R3
 * 0x94 - XRL A, DPH
 * 0x95 - XRL A, DPL
 * 0x96 - XRL A, #data8
 * 0x97 - XRL A, @DPTR */
void
XRL(void) {
    if (NNN < 6) {
        A = A ^ get_reg(NNN);
    }
    else {
        switch (NNN) {
            
            case 6:
                A = A ^ fetch();
                break;

            case 7:
                set_wide(TMP, get_wide(DPTR));
                A = A ^ mem[TMP];
                break;
        }
    }
    set_zp(A);
}

/* 0x98 - RL A */
void
RL(void) {
    A = (A << 1) | (A >> 7);
}

/* 0x99 - RLC A */
void
RLC(void) {
     tmpb = A;
     A = (A << 1) | get_flag(C);
     set_flag(C, tmpb >> 7);
}

/* 0x9A - RR A */
void
RR(void) {
    A = (A >> 1) | (A << 7);
}

/* 0x9B - RRC A */
void
RRC(void) { 
    tmpb = A;
    A = (A >> 1) | (get_flag(C) << 7);
    set_flag(C, tmpb & 0x01);
}

/* 0x9C - INC DPTR
 * 0x9E - INC A */
void
INC(void) {
    switch (IR) {

        case 0x9C:
            tmpw = get_wide(DPTR);
            if ((tmpw + 1) > 0xFFFF) {
                set_flag(OV, 1);
            }
            set_wide(DPTR, tmpw + 1);
            set_zp(DPL);
            set_zp(DPH);
            break;

        case 0x9E:
            if ((A + 1) > 0xFF) {
                set_flag(OV, 1);
            }
            A++;
            set_zp(A);

    }
}

/* 0x9D - DEC DPTR
 * 0x9F - DEC A */
void
DEC(void) {
    switch (IR) {

        case 0x9D:
            tmpw = get_wide(DPTR);
            if ((tmpw - 1) < 0) {
                set_flag(OV, 1);
            }
            set_wide(DPTR, tmpw - 1);
            set_zp(DPL);
            set_zp(DPH);

        case 0x9F:
            if ((A - 1) < 0) {
                set_flag(OV, 1);
            }
            A--;
            set_zp(A);
    }    
}

/* 0xA0 - ADD A, R0
 * 0xA1 - ADD A, R1
 * 0xA2 - ADD A, R2
 * 0xA3 - ADD A, R3
 * 0xA4 - ADD A, DPH
 * 0xA5 - ADD A, DPL
 * 0xA6 - ADD A, #data8
 * 0xA7 - ADD A, @DPTR */
void
ADD(void) {
    if (NNN < 6) {
        if ((A + get_reg(NNN)) > 0xFF) {
            set_flag(OV, 1);
        }
        else {
            set_flag(OV, 0);
        }
        A = A + get_reg(NNN);
        set_zp(A);
    }
    else {
        switch (NNN) {
            
            case 6:
                tmpb = fetch();
                if ((A + tmpb) > 0xFF) {
                    set_flag(OV, 1);
                }
                else {
                    set_flag(OV, 0);
                }
                A = A + tmpb;
                set_zp(A);
                break;

            case 7:
                set_wide(TMP, get_wide(DPTR));
                if ((A + mem[TMP]) > 0xFF) {
                    set_flag(OV, 1);
                }
                else {
                    set_flag(OV, 0);
                }
                A = A + mem[TMP];
                set_zp(A);
                break;
        }
    }

}

/* 0xA8 - ADDC A, R0
 * 0xA9 - ADDC A, R1
 * 0xAA - ADDC A, R2
 * 0xAB - ADDC A, R3
 * 0xAC - ADDC A, DPH
 * 0xAD - ADDC A, DPL
 * 0xAE - ADDC A, #data8
 * 0xAF - ADDC A, @DPTR */
void
ADDC(void) {
    if (NNN < 6) {
        if ((A + get_reg(NNN) + get_flag(C)) > 0xFF) {
            set_flag(C, 1);
        }
        else {
            set_flag(C, 0);
        }
        A = A + get_reg(NNN) + get_flag(C);
        set_zp(A);
    }
    else {
        switch (NNN) {
            
            case 6:
                tmpb = fetch();
                if ((A + tmpb + get_flag(C)) > 0xFF) {
                    set_flag(C, 1);
                }
                else {
                    set_flag(C, 0);
                }
                A = A + tmpb + get_flag(C);
                set_zp(A);
                break;

            case 7:
                set_wide(TMP, get_wide(DPTR));
                if ((A + mem[TMP] + get_flag(C)) > 0xFF) {
                    set_flag(C, 1);
                }
                else {
                    set_flag(C, 0);
                }
                A = A + mem[TMP] + get_flag(C);
                set_zp(A);
                break;
        }
    }


}

/* 0xB0 - SUB A, R0
 * 0xB1 - SUB A, R1
 * 0xB2 - SUB A, R2
 * 0xB3 - SUB A, R3
 * 0xB4 - SB A, DPH
 * 0xB5 - SUB A, DPL
 * 0xB6 - SUB A, #data8
 * 0xB7 - SUB A, @DPTR */
void
SUB(void) {
    if (NNN < 6) {
        if ((A - get_reg(NNN)) < 0){
            set_flag(S, 1);
        }
        else {
            set_flag(S, 0);
        }
        A = A - get_reg(NNN);
        set_zp(A);
    }
    else {
        switch (NNN) {
            
            case 6:
                tmpb = fetch();
                if ((A - tmpb) < 0) {
                    set_flag(S, 1);
                }
                else {
                    set_flag(S, 0);
                }
                A = A - tmpb;
                set_zp(A);
                break;

            case 7:
                set_wide(TMP, get_wide(DPTR));
                if ((A - mem[TMP]) < 0) {
                    set_flag(S, 1);
                }
                else {
                    set_flag(S, 0);
                }
                A = A - mem[TMP];
                set_zp(A);
                break;
        }
    }
}

/* 0xB8 - SUBB A, R0
 * 0xB9 - SUBB A, R1
 * 0xBA - SUBB A, R2
 * 0xBB - SUBB A, R3
 * 0xBC - SUBB A, DPH
 * 0xBD - SUBB A, DPL
 * 0xBE - SUBB A, #data8
 * 0xBF - SUBB A, @DPTR */
void
SUBB(void) {
    if (NNN < 6) {
        if ((A - get_reg(NNN) - get_flag(C)) < 0){
            set_flag(C, 1);
        }
        else {
            set_flag(C, 0);
        }
        A = A - get_reg(NNN) -get_flag(C);
        set_zp(A);
    }
    else {
        switch (NNN) {
            
            case 6:
                tmpb = fetch();
                if ((A - tmpb - get_flag(C)) < 0) {
                    set_flag(C, 1);
                }
                else {
                    set_flag(C, 0);
                }
                A = A - tmpb - get_flag(C);
                set_zp(A);
                break;

            case 7:
                set_wide(TMP, get_wide(DPTR));
                if ((A - mem[TMP] - get_flag(C)) < 0) {
                    set_flag(C, 1);
                }
                else {
                    set_flag(C, 0);
                }
                A = A - mem[TMP] - get_flag(C);
                set_zp(A);
                break;
        }
    }
}

void
PJMP(void) {
    /* implement me */
}

void
PCALL(void) {
    /* implement me */
}

/* 0xD0 - DJNZ R0, rel8
 * 0xD1 - DJNZ R1, rel8
 * 0xD2 - DJNZ R2, rel8
 * 0xD3 - DJNZ R3, rel8 */
void
DJNZ(void) {
    set_reg(NNN, get_reg(NNN) - 1);
    if (get_reg(NNN) == 0) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() - 1);
    }
    else {
        inc_pc(1);
    }
}

/* 0xD4 - CJNE R0, #data, rel8
 * 0xD5 - CJNE R1, #data, rel8
 * 0xD6 - CJNE R2, #data, rel8
 * 0xD7 - CJNE R3, #data, rel8 
 * 0xDF - CJNE A, #data8, rel8 */
void
CJNE(void) {
    switch(IR) {
        
        case 0xDF:
             tmpb = fetch();
            if (tmpb != A) {
                set_wide(PC, get_wide(PC) + (signed char)fetch() - 1);
            }
            else {
                inc_pc(1);
            }
            break;


        default:
            tmpb = fetch();
            if (tmpb != get_reg(NNN - 4)) {
                set_wide(PC, get_wide(PC) + (signed char)fetch() - 1);
            }
            else {
                inc_pc(1);
            }
            break;
    }
}

/* 0xD8 - LJMP addr16 */
void
LJMP(void) {
    set_wide(PC, fetch_wide());
}

/* 0xD9 - LCALL addr16 */
void
LCALL(void) {
    /* push PC to stack */
    mem[get_wide(SP)] = get_reg(PCL);
    set_wide(SP, get_wide(SP) + 1);
    mem[get_wide(SP)] = get_reg(PCH);
    set_wide(SP, get_wide(SP) + 1);
    /* jmp */
    set_wide(PC, fetch_wide());
}

/* 0xDA - RET */
void
RET(void) {
    /* get PC from stack */
    set_wide(SP, get_wide(SP) - 1);
    tmpb = mem[get_wide(SP)]; /* PCH */
    set_wide(SP, get_wide(SP) - 1);
    set_wide(PC, MWIDE(tmpb, mem[get_wide(SP)]));
}

void
RETI(void) {
    /* implement me */
}

/* 0xDC - SJMP rel8 */
void
SJMP(void) {
    /* -1 because the fetch() increments the PC */
    set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
}

/* 0xDD - JMP @A+DPTR
 * 0xDE - JMP @DPTR */
void
JMP(void) {
    switch(IR) {
        
        case 0xDD:
            set_wide(PC, A + get_wide(DPTR));
            break;
        
        case 0xDE:
            set_wide(PC, get_wide(DPTR));
            break;
    }
}

/* 0xE0 - JZ rel8 */
void
JZ(void) {
    if (get_flag(Z) == 1) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    /* skip rel8 if jump not needed */
    else {
        inc_pc(1);
    }
}

/* 0xE1 - JNZ rel8 */
void
JNZ(void) {
    if (get_flag(Z) == 0) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    else {
        inc_pc(1);
    }
}

/* 0xE2 - JC rel8 */
void
JC(void) {
    if (get_flag(C) == 1) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    else {
        inc_pc(1);
    }
}

/* 0xE3 - JNC rel8 */
void
JNC(void) {
    if (get_flag(C) == 0) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    else {
        inc_pc(1);
    }
}

/* 0xE4 - JPO rel8 */
void
JPO(void) {
    /* P = 1 when parity even */
    if (get_flag(P) == 0) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    else {
        inc_pc(1);
    }

}

/* 0xE5 - JPE rel8 */
void
JPE(void) {
    if (get_flag(P) == 1) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    else {
        inc_pc(1);
    }
}

/* 0xE6 - JS rel8 */
void
JS(void) {
    if (get_flag(S) == 1) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    else {
        inc_pc(1);
    }
}

/* 0xE7 - JNS rel8 */
void
JNS(void) {
    if (get_flag(S) == 0) {
        set_wide(PC, get_wide(PC) + (signed char)fetch() -1);
    }
    else {
        inc_pc(1);
    }
}

/* 0xE8 - PUSH R0
 * 0xE9 - PUSH R1
 * 0xEA - PUSH R2
 * 0xEB - PUSH R3
 * 0xEC - PUSH DPH
 * 0xED - PUSH DPL
 * 0xEE - PUSH A
 * 0xEF - PUSH FLAGS */
void
PUSH(void) {
    if (NNN < 6) {
        mem[get_wide(SP)] = get_reg(NNN);
        set_wide(SP, get_wide(SP) + 1);

    }
    else {
        switch(IR) {
            
            case 0xEE:
                mem[get_wide(SP)] = A;
                set_wide(SP, get_wide(SP) + 1);
                break;

            case 0xEF:
                mem[get_wide(SP)] = flags;
                set_wide(SP, get_wide(SP) + 1);
                break;

            default:
                break;
        }
    }
}

/* 0xF0 - POP R0
 * 0xF1 - POP R1
 * 0xF2 - POP R2
 * 0xF3 - POP R3
 * 0xF4 - POP DPH
 * 0xF5 - POP DPL
 * 0xF6 - POP A
 * 0xF7 - POP FLAGS */
void
POP(void) {
    if (NNN < 6) {
        set_wide(SP, get_wide(SP) - 1);
        set_reg(NNN, mem[get_wide(SP)]);
    }
    else {
        switch(IR) {
            
            case 0xF6:
                set_wide(SP, get_wide(SP) - 1);
                A = mem[get_wide(SP)];
                break;

            case 0xF7:
                set_wide(SP, get_wide(SP) - 1);
                flags = mem[get_wide(SP)];
                break;

            default:
                break;
        }
    }
}


/* 0xF8 - MUL R0, R1 */
void
MUL(void) {
 /* implement me */    
}

/* 0xF9 - DIV R0, R1 */
void
DIV(void) {
 /* implement me */   
}

/* 0xFA - DA A */
void
DA(void) {
 /* implement me */
}

/* 0xFC - IN port_addr */
void
IN(void) {
 /* implement me */   
}

/* 0xFD - OUT port_addr */
void
OUT(void) {
 /* implement me */
}

/* 0xFE INT vect8 */
void
INT(void) {
 /* implement me */    
}

/* 0xFF - HLT */
void
HLT(void) {
 /* implement me */
}