view emulator/iset.c @ 27:a542cd390efd

long overdue update
author james <jb302@eecs.qmul.ac.uk>
date Wed, 02 Apr 2014 14:11:50 +0100
parents 256d24488e3f
children
line wrap: on
line source
/* iset.c
 * op functions */
#include <stdlib.h>
#include "iset.h"
#include "mem.h"

/* useful macros */
#define BANK (registers.flags & 0x01)
#define CARRY ((registers.flags & 0x08) >> 3)
#define NNN (op & 0x07)
#define MMM ((op & 0x38) >> 3)

/* temp registers for various instructions */

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

/* 0x08 - SET C
 * 0x0A - SET BS
 * 0x0C - SET IE */
void
SET(void) {
    switch (op) {
        
        case 0x08:
            registers.flags = registers.flags | 0x80;
            break;
        
        case 0x0A:
            registers.flags = registers.flags | 0x01;
            break;
        
        case 0x0C:
            registers.flags = registers.flags | 0x02;
            break;
        
        default:
            break;
    }
}

/* 0x09 - CLR C
 * 0x0B - CLR BS
 * 0x0D - CLR IE */
void
CLR(void) {
    switch (op) {
        
        case 0x09:
            registers.flags = registers.flags & 0xF7;
            break;
        
        case 0x0B:
            registers.flags = registers.flags & 0xFE;
            break;
        
        case 0x0D:
            registers.flags = registers.flags & 0xFD;
            break;
        
        default:
            break;
    }    
}

/* 0x0E - CPL C
 * 0x0F - CPL A */
void
CPL(void) {
    switch (op) {
        
        case 0x0E:
            if (CARRY) {
                registers.flags = registers.flags | 0x80;
            }
            else {
                registers.flags = registers.flags & 0xF7;
            }
            break;
        
        case 0x0F:
            registers.A = ~registers.A;
            break;
        
        default:
            break;
    }
}

/* 0x10 - XCSD */
void
XCSD(void) {
    tmpw = get_SP();
    set_SP(get_DPTR());
    set_DPTR(tmpw);
}

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

/* 0x12 - LAF */
void
LAF(void) {
    registers.flags = registers.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 (op & 0x40) {
       
        case 0x00:
            switch (op & 0xF8) {
                
                /* 0b00010XXX */
                case 0x10:
                    switch (NNN) {
                        
                        /* MOV DPTR, SP */
                        case 3:
                            set_DPTR(get_SP());
                            break;
                        
                        /* MOV SP, DPTR */
                        case 4:
                            set_SP(get_DPTR());
                            break;
                        
                        /* MOV A, #data8 */
                        case 5:
                            PC++;
                            registers.A = fetch();
                            break;
                        
                        /* MOV SP, #data16 */
                        case 6:
                            PC++;
                            set_SP(fetch_wide());
                            PC++;
                            break;
                        
                        /* MOV DPTR, #data16 */
                        case 7:
                            PC++;
                            set_DPTR(fetch_wide());
                            PC++;
                            break;
                        
                        default:
                            break;
                    }
                    break;
                
                /* 0b00011XXX */
                case 0x18:
                    switch (NNN) {
                        
                        /* MOV A, addr16 */
                        case 0:
                            PC++;
                            registers.A = memory[fetch_wide()];
                            PC++;
                            break;
                        
                        /* MOV addr16, A */
                        case 1:
                            PC++;
                            memory[fetch_wide()] = registers.A;
                            PC++;
                            break;
                        
                        /* MOV A, @A+DPTR */
                        case 2:
                            registers.A = memory[registers.A + get_DPTR()];
                            break;
                        
                        /* MOV A, @A+PC */
                        case 3:
                            registers.A = memory[registers.A + PC];
                            break;
                        
                        /* MOV A, @addr16 */
                        case 4:
                            PC++;
                            registers.A = memory[memory[fetch_wide()]];
                            PC++;
                            break;
                        
                        /* MOV @addr16, A */ 
                        case 5:
                            PC++;
                            memory[memory[fetch_wide()]] = registers.A;
                            PC++;
                            break;
                        
                        /* MOV A, @DPTR */
                        case 6:
                            registers.A = memory[get_DPTR()];
                            break;
                        
                        /* MOV @DPTR, A */
                        case 7:
                            memory[get_DPTR()] = registers.A;
                            break;
                        
                        default:
                            break;
                    }
                    break;
                
                /* 0b00100nnn */
                case 0x20:
                    memory[get_DPTR()] = get_R(NNN, BANK);
                    break;
                
                /* 0b00101nnn */
                case 0x28:
                    /* store immediate data in op */
                    PC++;
                    set_R(NNN, BANK, fetch());
                    break;
                
                /* 0b00110nnn */
                case 0x30:
                    set_R(NNN, BANK, registers.A);
                    break;
                
                /* 0b00111nnn */
                case 0x38:
                    registers.A = get_R(NNN, BANK);
                    break;
                
                default:
                    break;
                }
            break;
        
        /* 0b01mmmnnn */
        case 0x40:
            /* if mmm == nnn: MOV Rm, @DPTR */
            if (MMM == NNN) {
                set_R(NNN, BANK, memory[get_DPTR()]);
            }
            /* else: MOV Rm, Rn */
            else {
                set_R(MMM, BANK, get_R(NNN, BANK));
            }
            break;
        
        default:
            break;
    }
}

void
ANL(void) {
    /* 0x80 - ANL A, R0
     * 0x81 - ANL A, R1
     * 0x82 - ANL A, R2
     * 0x83 - ANL A, R3
     * 0x84 - ANL A, DPH
     * 0x85 - ANL A, DPL */
    if (NNN <= 5) {
        registers.A = registers.A & get_R(NNN, BANK);
    }
    else {
        switch (NNN) {
            
            /* 0x86 - ANL A, #data8 */
            case 6:
                PC++;
                registers.A = registers.A & fetch();
                break;
            
            /* 0x87 - ANL A, @DPTR */
            case 7:
                registers.A = registers.A & memory[get_DPTR()];
            
            default:
                break;
        }
    }
}

void
ORL(void) {
    /* 0x88 - ORL A, R0
     * 0x89 - ORL A, R1
     * 0x8A - ORL A, R2
     * 0x8B - ORL A, R3
     * 0x8C - ORL A, DPH
     * 0x8D - ORL A, DPL */
    if (NNN <= 5) {
        registers.A = registers.A | get_R(NNN, BANK);
    }
    else {
        switch (NNN) {
            
            /* 0x8E - ORL A, #data8 */
            case 6:
                PC++;
                registers.A = registers.A | fetch();
                break;
            
            /* 0x8F - ORL A, @DPTR */
            case 7:
                registers.A = registers.A | memory[get_DPTR()];
            
            default:
                break;
        }
    }
}

void
XRL(void) {
    /* 0x90 - XRL A, R0
     * 0x91 - XRL A, R1
     * 0x92 - XRL A, R2
     * 0x93 - XRL A, R3
     * 0x94 - XRL A, DPH
     * 0x95 - XRL A, DPL */
    if (NNN <= 5) {
        registers.A = registers.A ^ get_R(NNN, BANK);
    }
    else {
        switch (NNN) {
            
            /* 0x96 - XRL A, #data8 */
            case 6:
                PC++;
                registers.A = registers.A ^ fetch();
                break;
            
            /* 0x97 - XRL A, @DPTR */
            case 7:
                registers.A = registers.A ^ memory[get_DPTR()];
            
            default:
                break;
        }
    }
}

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

/* 0x99 - RLC A */
void
RLC(void) {
    /* implement me */
}

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

/* 0x9B - RRC A */
void
RRC(void) { 
    /* implement me */
}

/* 0x9C - INC DPTR
 * 0x9E - INC A */
void
INC(void) {    
    switch (op) {
        
        case 0x9C:
            tmpw = get_DPTR();
            set_DPTR(tmpw + 1);
            break;
        
        case 0x9E:
            registers.A++;
            break;
        
        default:
            break;
    }
}

/* 0x9D - DEC DPTR
 * 0x9F - DEC A */
void
DEC(void) {
    switch (op) {
        
        case 0x9D:
            tmpw = get_DPTR();
            set_DPTR(tmpw - 1);
            break;
        
        case 0x9F:
            registers.A--;
            break;
        
        default:
            break;
    }
}

void
ADD(void) {
    /* 0xA0 - ADD A, R0
     * 0xA1 - ADD A, R1
     * 0xA2 - ADD A, R2
     * 0xA3 - ADD A, R3
     * 0xA4 - ADD A, DPH
     * 0xA5 - ADD A, DPL */
    if (NNN <= 5) {
        registers.A = registers.A + get_R(NNN, BANK);
    }
    else {
        switch (NNN) {
            
            /* 0xA6 - ADD A, #data8 */
            case 6:
                PC++;
                registers.A = registers.A + fetch();
                break;
            
            /* 0xA7 - ADD A, @DPTR */
            case 7:
                registers.A = registers.A + memory[get_DPTR()];
            
            default:
                break;
        }
    }
}

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

void
SUB(void) {
    /* 0xB0 - SUB A, R0
     * 0xB1 - SUB A, R1
     * 0xB2 - SUB A, R2
     * 0xB3 - SUB A, R3
     * 0xB4 - SUB A, DPH
     * 0xB5 - SUB A, DPL */
    if (NNN <= 5) {
        registers.A = registers.A - get_R(NNN, BANK);
    }
    else {
        switch (NNN) {
            
            /* 0xB6 - SUB A, #data8 */
            case 6:
                PC++;
                registers.A = registers.A - fetch();
                break;
            
            /* 0xB7 - SUB A, @DPTR */
            case 7:
                registers.A = registers.A - memory[get_DPTR()];
            
            default:
                break;
        }
    }
}

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

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) {
    /* decrement reg */
    tmpb = get_R(op & 0x03, BANK);
    tmpb--;
    set_R(op & 0x03, BANK, tmpb);
    /* jump if not zero */
    PC++;
    if (tmpb != 0) {
        tmpb = fetch();
        PC = PC + (signed char)tmpb - 1;
    }

}

void
CJNE(void) {
    /* fetch data */
    PC++;
    tmpb = fetch();
    PC++;

    /* 0xD4 - CJNE R0, data8, rel8
     * 0xD5 - CJNE R1, data8, rel8
     * 0xD6 - CJNE R2, data8, rel8
     * 0xD7 - CJNE R3, data8, rel8 */
    if ((op & 0x0F) <= 7) {
        /* jump if not equal to reg */
        if (tmpb != get_R(op & 0x03, BANK)) {
            tmpb = fetch();
            PC = PC + (signed char)tmpb -1;
        }
    }
    /* 0xDF - CJNE A, data8, rel8  */
    else if ((op & 0x0F) == 0x0F) {
        /* jump if not equal to A */
        if (tmpb != registers.A) {
            tmpb = fetch();
            PC = PC + (signed char)tmpb -1;
        }
    }
}

/* 0xD8 - LJMP addr16 */
void
LJMP(void) {
    PC++;
    PC = fetch_wide() - 1;
}

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

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

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

/* 0xDC - SJMP rel8 */
void
SJMP(void) {
    PC++;
    tmpb = fetch();
    PC = PC + (signed char)tmpb - 1;
}

/* 0xDD - JMP @A+DPTR
 * 0xDE - JMP @DPTR */
void
JMP(void) {
    switch (op) {
        case 0xDD:
            PC = registers.A + get_DPTR() - 1;
            break;
        case 0xDE:
            PC = get_DPTR() - 1;
            break;
        default:
            break;
    } 
}

void
JZ(void) {   
}

void
JNZ(void) {
}

void
JC(void) {   
}

void
JNC(void) {   
}

void
JPO(void) {   
}

void
JPE(void) {
}

void
JS(void) {    
}

void
JNS(void) {
}

void
PUSH(void) {
}

void
POP(void) { 
}

void
MUL(void) {    
}

void
DIV(void) {   
}

void
DA(void) {    
}

void
IN(void) {   
}

void
OUT(void) {
}

void
INT(void) {    
}

/* 0xFF - HLT */
void
HLT(void) {
    exit(0);
}