Hello everyone, here is the source code of the emulator introduced during my workshop concerning emulators. I waited almost two weeks to publish the code in order to let people to try to build it by themselves.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MP08ALib; namespace MP08AEmu { public enum STATUS_FLAGS { EQUAL = 0, GREATER = 1, LOWER = 2 }; public class MP08E : ICPU { byte[] memory = new byte[0x100]; protected byte AC; protected byte[] dataRegisters = new byte[0x10]; protected byte flags; protected byte PC; protected byte latch; public byte[] GetMemory() { return memory; } public void LoadMemory(byte[] buffer) { for (int i = 0; i < buffer.Length; i++) this.memory[i] = buffer[i]; } public void Reset() { this.AC = 0; this.flags = 0; this.PC = 0; this.latch = 0; dataRegisters = new byte[0x10]; } public void Step() { byte opcode = (byte)((memory[this.PC] >> 4) & 0xF); byte imm4 = (byte)(memory[this.PC] & 0xF); byte imm8 = (byte)(memory[(this.PC + 1) & 0xFF]); bool jmp = false; switch (opcode) { case 0x0: break; /* NOP */ case 0x1: this.AC = memory[++this.PC]; break; /* LOADLIT */ case 0x2: this.AC = dataRegisters[imm4]; break; /* LOADREG */ case 0x3: dataRegisters[imm4] = this.AC; break; /* STORE */ case 0x4: this.AC++; break; /* INC */ case 0x5: this.AC--; break; /* DEC */ case 0x6: this.AC = latch; break; /* IN */ case 0x7: this.latch = this.AC; break; /* OUT */ case 0x8: Compare(this.AC, imm8); this.PC++; break; /* COMPLIT */ case 0x9: Compare(this.AC, dataRegisters[imm4]); break; /* COMPREG */ case 0xA: if (GetBit(flags, STATUS_FLAGS.EQUAL)) { this.PC = imm8; jmp = true; } break; /* JE addr */ case 0xB: if (GetBit(flags, STATUS_FLAGS.GREATER)) { this.PC = imm8; jmp = true; } break; /* JG addr */ case 0xC: if (GetBit(flags, STATUS_FLAGS.LOWER)) { this.PC = imm8; jmp = true; } break; /* JL addr */ case 0xD: this.PC = imm8; jmp = true; break; /* JMP addr */ case 0xE: this.AC = (byte)(this.AC + dataRegisters[imm4]); break; /* ADD reg */ case 0xF: this.flags = 0; break; /* CLEAR */ } if (!jmp) this.PC++; } public bool GetBit(int value, int bit) { return (((value >> bit) & 0x1) == 1); } public bool GetBit(int value, STATUS_FLAGS bit) { return GetBit(value, (int)bit); } public int GetRegister(int reg, int datareg = 0) { switch (reg) { case 0: return this.PC; case 1: return this.AC; case 2: return this.flags; case 3: return this.latch; case 4: return this.dataRegisters[datareg]; default: return -1; } } public void Compare(int ac, int value) { MP08ALib.Utils.SetBit(ref flags, 0, ac == value); MP08ALib.Utils.SetBit(ref flags, 1, ac > value); MP08ALib.Utils.SetBit(ref flags, 2, ac < value); } } } |