Mercurial > hg > ede
view emu/iset.c @ 42:792da050d8c4 tip
more dox
author | james <jb302@eecs.qmul.ac.uk> |
---|---|
date | Tue, 22 Apr 2014 14:25:14 +0100 |
parents | 2e35be400012 |
children |
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) { tmpw = regs[R0] * regs[R1]; regs[R0] = GHIGH(tmpw); regs[R1] = GLOW(tmpw); } /* 0xF9 - DIV R0, R1 */ void DIV(void) { tmpw = regs[R0] / regs[R1]; regs[R0] = GHIGH(tmpw); regs[R1] = GLOW(tmpw); } /* 0xFA - DA A */ void DA(void) { if (((A & 0xF) > 9) | get_flag(AC) == 1) { A = A + 6; } if (((A & 0xF0) > 9) | get_flag(C) == 1) { A = A + 0x60; } } /* 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) { exit(0); }