public TestSimulator() { e = new ELFReader(); mem = new Memory(32768); comp = new Computer(); reg = new Register[16]; resultHash = ""; hash = ""; }
/// <summary> /// The run method for Load Store. /// Overwrites parent's method /// </summary> /// <param name="ra"></param> /// <param name="mem"></param> public override void Run(ref Register[] ra, ref Memory mem) { Logger.Instance.writeLog(string.Format("Command Type: Data Movement : 0x{0}", Convert.ToString(this.initialBytes, 16))); // Gather information about registers uint RdVal = ra[this.Rd].ReadWord(0, true); uint RnVal = ra[this.Rn].ReadWord(0, true); uint RmVal = ra[this.Rm].ReadWord(0, true); this.shifter = HandleShift(this.b25, this.shifter, RmVal, ra); //addressing mode uint addr = FindAddressingMode(ref ra); string cmd = ""; // Check for Load / Store if (this.L) { cmd = "ldr"; if (this.B) { ra[this.Rd].WriteWord(0, 0); ra[this.Rd].WriteByte(0, mem.ReadByte(addr)); } else { ra[this.Rd].WriteWord(0, mem.ReadWord(addr)); } } // If not load then store else { cmd = "str"; if (this.B) { mem.WriteByte(addr, ra[this.Rd].ReadByte(0)); } else { mem.WriteWord(addr, RdVal); } } Logger.Instance.writeLog(string.Format("Specific Command: {0} {1}, 0x{2} : 0x{3} ", cmd, RdVal, Convert.ToString(addr, 16), Convert.ToString(this.initialBytes, 16))); }
public override void Run(ref Register[] ra, ref Memory mem) { uint addressToWhichWeBranch = 0; if (imm) { uint initialAddress = ra[15].ReadWord(0, true); if (this.L) { //store return address for post-branch ra[14].WriteWord(0, initialAddress - 4); } addressToWhichWeBranch = (uint)(initialAddress + this.offset); } else { addressToWhichWeBranch = (ra[this.regnum].ReadWord(0, true) & 0xFFFFFFFE); } addressToWhichWeBranch -= 4; ra[15].WriteWord(0, addressToWhichWeBranch); Logger.Instance.writeLog(string.Format("Assembly: BX 0x{0} : 0x{1}", Convert.ToString(addressToWhichWeBranch + 4,16), Convert.ToString(this.initialBytes, 16))); }
public void IFTHISTHINGWORKS() { this.Output("_____Beginning Tests_____"); this.Output("Console Running in Verbatim Mode for Unit Tests"); this.Output("Beginning Hash Test"); this.Output("Testing hash of test1.exe"); try { comp.load("test1.exe", 32768); resultHash = comp.getRAM().getHash(); hash = "3500a8bef72dfed358b25b61b7602cf1"; if (hash.ToUpper() == resultHash) { this.TestPass("test1.exe hash passed"); } else { this.TestFail("ERROR: test1.exe hash failed"); } } catch (FileNotFoundException) { this.TestWarn("WARNING: test1.exe not found. Test bypassed"); } comp.CLEAR(); // this.Output("Testing hash of test2.exe"); try { comp.load("test2.exe", 32768); resultHash = comp.getRAM().getHash(); hash = "0a81d8b63d44a192e5f9f52980f2792e"; if (hash.ToUpper() == resultHash) { this.TestPass("test2.exe hash passed"); } else { this.TestFail("ERROR: test2.exe hash failed"); } } catch (Exception) { this.TestWarn("WARNING: test2.exe not found. Test bypassed"); } comp.CLEAR(); // this.Output("Testing hash of test3.exe"); try { comp.load("test3.exe", 32768); resultHash = comp.getRAM().getHash(); hash = "977159b662ac4e450ed62063fba27029"; if (hash.ToUpper() == resultHash) { this.TestPass("test2.exe hash passed"); } else { this.TestFail("ERROR: test3.exe hash failed"); } } catch (Exception) { this.TestWarn("WARNING: test3.exe not found. Test bypassed"); } comp.CLEAR(); this.Output("End hash test"); this.Output("Beginning RAM tests"); this.Output("Testing Read/Write Byte"); byte bytetest = mem.ReadByte(0); if (!(bytetest == 0)) { this.TestFail("ERROR: Read/Write Byte fail"); } mem.WriteByte(0, 0xfd); bytetest = mem.ReadByte(0); if (!(bytetest == 0xfd)) { this.TestFail("ERROR: Read/Write Byte fail"); } else { this.TestPass("Read/Write Byte passed"); } mem.CLEAR(); this.Output("Testing Read/Write HalfWord"); ushort shorttest = mem.ReadHalfWord(0); if (!(shorttest == 0)) { this.TestFail("ERROR: Read/Write HalfWord fail"); } mem.WriteHalfWord(0, 0xabc); shorttest = mem.ReadHalfWord(0); if (!(shorttest == 0xabc)) { this.TestFail("ERROR: Read/Write HalfWord fail"); } else { this.TestPass("Read/Write HalfWord passed"); } mem.CLEAR(); this.Output("Testing Read/Write Word"); uint inttest = mem.ReadWord(0); if (!(inttest == 0)) { this.TestFail("ERROR: Read/Write Word fail"); } mem.WriteWord(0, 0xabc123); inttest = mem.ReadWord(0); if (!(inttest == 0xabc123)) { this.TestFail("ERROR: Read/Write Word fail"); } else { this.TestPass("Read/Write Word passed"); } mem.CLEAR(); this.Output("Testing Set/Test Flag"); bool flagtest = mem.TestFlag(0, 4); if (!(flagtest == false)) { this.TestFail("ERROR: Flag test failed"); } else { this.TestPass("Flag test test passed"); } //false >> true mem.SetFlag(0, 4, true); flagtest = mem.TestFlag(0, 4); if (!(flagtest == true)) { this.TestFail("ERROR: Flag test failed"); } else { this.TestPass("Flag test test passed"); } // true >> true mem.SetFlag(0, 4, true); flagtest = mem.TestFlag(0, 4); if (!(flagtest == true)) { this.TestFail("ERROR: Flag test failed"); } else { this.TestPass("Flag test test passed"); } // true >> false mem.SetFlag(0, 4, false); flagtest = mem.TestFlag(0, 4); if (!(flagtest == false)) { this.TestFail("ERROR: Flag test failed"); } else { this.TestPass("Flag test test passed"); } // false >> false mem.SetFlag(0, 4, false); flagtest = mem.TestFlag(0, 4); if (!(flagtest == false)) { this.TestFail("ERROR: Flag test failed"); } else { this.TestPass("Flag test test passed"); } this.Output("All Ram Tests completed"); Logger.Instance.closeTrace(); mem.CLEAR(); this.Output("Starting CPU unit tests"); //0xe3a02030 mov r2, #48 //defines 16 registers, 0 - 15 for (int i = 0; i < 16; i++) { reg[i] = new Register(); } // create cpu cpu = new CPU(mem, reg); // build instruction this.Output("Test Command: MOV R1,4016 : 0xe3a01efb"); this.TestCommand(0xe3a01efb); if (!(reg[1].ReadWord(0) == 4016)) { this.TestFail("ERROR: MOV Execution failed"); } else { this.TestPass("MOV Execution passed"); } this.Output("Test Command: ADD r10, r3, #9 : 0xe283A009"); reg[3].WriteWord(0, 1); this.TestCommand(0xe283A009); if (!(reg[10].ReadWord(0) == 10)) { this.TestFail("ERROR: ADD Execution failed"); } else { this.TestPass("ADD Execution passed"); } this.Output("Test Command: SUB r1, r10, #3 : 0xe24A1003"); this.TestCommand(0xe24A1003); if (!(reg[1].ReadWord(0) == 7)) { this.TestFail("ERROR: SUB Execution failed"); } else { this.TestPass("SUB Execution passed"); } this.Output("All Decode/Execute Tests Finished"); }
/// <summary> /// Run the commands that are given /// </summary> /// <param name="ra"></param> /// <param name="mem"></param> public override void Run(ref Register[] ra, ref Memory mem) { string tempHexString = Convert.ToString(this.initialBytes, 16); Logger.Instance.writeLog(string.Format("Command Type: Data Manipulation 0x{0}", tempHexString)); // Try to discover what type of command we have switch (this.opcode) { case 0: // Logical AND this.CommonWork(ref ra, ref mem,"and"); Logger.Instance.writeLog(string.Format("Specific Command: Logical AND 0x{0}", tempHexString)); break; case 1: // Logical Exclusive OR this.CommonWork(ref ra, ref mem,"eor"); Logger.Instance.writeLog(string.Format("Specific Command: Logical Exclusive OR 0x{0}", tempHexString)); break; case 2: // Subtract this.CommonWork(ref ra, ref mem,"sub"); Logger.Instance.writeLog(string.Format("Specific Command: Subtrac 0x{0}", tempHexString)); break; case 3: // Reverse Subtract this.CommonWork(ref ra, ref mem,"rsb"); Logger.Instance.writeLog(string.Format("Specific Command: Reverse Subtract 0x{0}", tempHexString)); break; case 4: // Add this.CommonWork(ref ra, ref mem, "add"); Logger.Instance.writeLog(string.Format("Specific Command: Addition 0x{0}", tempHexString)); break; case 5: // Add with Carry (unimplemented) case 6: // Subtract with Carry (unimplemented) case 7: // Reverse Subtract with Carry (unimplemented) case 8: // Test (unimplemented) case 9: // Test Equivalence (unimplemented) break; case 10: // Compare this.cmp(ref ra, ref mem); Logger.Instance.writeLog(string.Format("Specific Command: Compare 0x{0}", tempHexString)); break; case 11: // Compare Negated (unimplemented) break; case 12: // Logical (inclusive) OR this.CommonWork(ref ra, ref mem, "oor"); Logger.Instance.writeLog(string.Format("Specific Command: Logical (inclusive) OR 0x{0}", tempHexString)); break; case 13: // Move this.CommonWork(ref ra, ref mem,"mov"); Logger.Instance.writeLog(string.Format("Specific Command: Move 0x{0}", tempHexString)); break; case 14: // Bit Clear this.CommonWork(ref ra, ref mem,"bic"); Logger.Instance.writeLog(string.Format("Specific Command: Bit Clear 0x{0}", tempHexString)); break; case 15: // Move Not this.CommonWork(ref ra, ref mem,"mvn"); Logger.Instance.writeLog(string.Format("Specific Command: Move Not 0x{0}", tempHexString)); break; case 0x1F: // Multiply this.mul(ref ra, ref mem); Logger.Instance.writeLog(string.Format("Specific Command: Multiply 0x{0}", tempHexString)); break; default: break; } }
private void mul(ref Register[] reg, ref Memory RAM) { uint rmOp = reg[this.shifter.Rm].ReadWord(0, true); uint rsOp = reg[this.shifter.regShiftLength].ReadWord(0, true); uint product = rmOp * rsOp; if (product > 0xFFFFFFFF) { Logger.Instance.writeLog("Error: Multiply Overflow"); } reg[this.Rn].WriteWord(0, product); Logger.Instance.writeLog(String.Format("Assembly: MUL R{0},R{1},R{2} : 0x{3}", this.Rd, this.shifter.Rm, this.shifter.regShiftLength, Convert.ToString(this.initialBytes, 16))); }
private void cmp(ref Register[] ra, ref Memory mem) { this.shifter = Shift(this.b25, this.shifter, ra[this.shifter.Rm].ReadWord(0, true), ra); uint source = ra[this.Rn].ReadWord(0, true); uint comparer = source - this.shifter.offset; Memory m = new Memory(4); m.WriteWord(0, comparer); //set N flag N = m.TestFlag(0, 31); //set Z Z = m.ReadWord(0, true) == 0; //set C C = (this.shifter.offset <= source) ? true : false; //set O (which somehow I though was F...) int RnTest = (int)source; int opTest = (int)this.shifter.offset; bool case1 = ((RnTest >= 0) && (opTest < 0) && ((RnTest - opTest) < 0)); bool case2 = ((RnTest < 0) && (opTest >= 0) && ((RnTest - opTest) >= 0)); F = (case1 || case2) ? true : false; Logger.Instance.writeLog(String.Format("Assembly: CMP R{0}, {1} : 0x{2}", this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); }
/// <summary> /// Method to handle the common work for data processing /// Each of the operations are similar so this method /// reduces the amount of copy/paste /// </summary> /// <param name="ra"></param> /// <param name="mem"></param> /// <param name="cmd"></param> private void CommonWork(ref Register[] ra, ref Memory mem, string cmd) { this.shifter = Shift(this.b25, this.shifter, ra[this.shifter.Rm].ReadWord(0, true), ra); uint source = ra[this.Rn].ReadWord(0, true); switch (cmd) { case "add": ra[this.Rd].WriteWord(0, (source + this.shifter.offset)); Logger.Instance.writeLog(String.Format("Assembly: ADD R{0},R{1},{2} : 0x{3}", this.Rd, this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); break; case "and": ra[this.Rd].WriteWord(0, (source & this.shifter.offset)); Logger.Instance.writeLog(String.Format("Assembly: AND R{0},R{1},{2} : 0x{3}", this.Rd, this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); break; case "bic": ra[this.Rd].WriteWord(0, (source & (~this.shifter.offset))); Logger.Instance.writeLog(String.Format("Assembly: BIC R{0},R{1},{2} : 0x{3}", this.Rd, this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); break; case "eor": ra[this.Rd].WriteWord(0, (source ^ this.shifter.offset)); Logger.Instance.writeLog(String.Format("Assembly: EOR R{0},R{1},{2} : 0x{3}", this.Rd, this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); break; case "mov": ra[this.Rd].WriteWord(0, this.shifter.offset); Logger.Instance.writeLog(String.Format("Assembly: MOV R{0},{1} : 0x{2}", this.Rd, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); if (this.S) { flagWork(this.initialBytes, ra[this.Rd].ReadWord(0)); } break; case "mvn": ra[this.Rd].WriteWord(0, ~this.shifter.offset); Logger.Instance.writeLog(String.Format("Assembly: MVN R{0},{1} : 0x{2}", this.Rd, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); flagWork(this.initialBytes, ra[this.Rd].ReadWord(0)); break; case "oor": ra[this.Rd].WriteWord(0, (source | this.shifter.offset)); Logger.Instance.writeLog(String.Format("Assembly: OOR R{0},R{1},{2} : 0x{3}", this.Rd, this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); break; case "rsb": ra[this.Rd].WriteWord(0, (this.shifter.offset - source)); Logger.Instance.writeLog(String.Format("Assembly: RSB R{0},R{1},{2} : 0x{3}", this.Rd, this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); break; case "sub": ra[this.Rd].WriteWord(0, (source - this.shifter.offset)); Logger.Instance.writeLog(String.Format("Assembly: sub R{0},R{1},{2} : 0x{3}", this.Rd, this.Rn, this.shifter.offset, Convert.ToString(this.initialBytes, 16))); break; default: break; } }
/// <summary> /// This is responsible for the shifts that have /// to take place at times in the operand2 /// </summary> /// <param name="S"></param> /// <param name="shifter"></param> /// <param name="RmVal"></param> /// <param name="reg"></param> /// <returns></returns> public Operand2 Shift(bool S, Operand2 shifter, uint RmVal, Register[] reg) { // Look at our magic bit to see what to do if (!S) { // Check to see if shift is done on a register if (shifter.b4 && !shifter.b7) { shifter.shiftRM(RmVal, reg[shifter.regShiftLength].ReadWord(0, true));} // otherwise the shift is an immediate value else {shifter.shiftRM(RmVal, shifter.regShiftImm);} } return shifter; }
/// <summary> /// Parent Run /// Shouldn't ever be needed /// </summary> /// <param name="reg"></param> /// <param name="RAM"></param> public virtual void Run(ref Register[] reg, ref Memory RAM) { Logger.Instance.writeLog("Warning: Unkown Command"); }
/// <summary> /// Finds out addressing specifics about the instruction /// </summary> /// <param name="reg"></param> /// <returns></returns> private uint FindAddressingMode(ref Register[] reg) { uint RdVal = reg[this.Rd].ReadWord(0, true); uint RnVal = reg[this.Rn].ReadWord(0, true); uint addr = 0; // if pre-indexed.... if (this.P) { // ... and positively offset add offset to value // otherwise we need to subtract addr = (this.U) ? RnVal + this.shifter.offset : RnVal - this.shifter.offset; // check for writeback if (this.W) { reg[this.Rn].WriteWord(0, addr); } } // otherwise post-indexed else { addr = RnVal; uint val = (this.U) ? RnVal + this.shifter.offset : RnVal - this.shifter.offset; reg[this.Rn].WriteWord(0, val); } return addr; }
/// <summary> /// Deal with some of the knitty gritty that happens /// when we deal with operand2 /// </summary> /// <param name="b25"></param> /// <param name="shifter"></param> /// <param name="RmVal"></param> /// <param name="ra"></param> /// <returns></returns> public Operand2 HandleShift(bool b25, Operand2 shifter, uint RmVal, Register[] ra) { // if this bit is set then we are dealing with a register if (b25) {shifter = Shift(!b25, shifter, RmVal, ra);} // otherwise it is an immediate value else {shifter.offset = shifter.imm12;} return shifter; }
/// <summary> /// CPU constructor /// </summary> /// <param name="RAM"></param> /// <param name="reg"></param> public CPU(Memory RAM, Register[] reg) { _ram = RAM; _reg = reg; }
public override void Run(ref Register[] ra, ref Memory mem) { Logger.Instance.writeLog(string.Format("Command Type: Data Move Multiple : 0x{0}", Convert.ToString(this.initialBytes, 16))); int RnVal = (int)ra[this.Rn].ReadWord(0, true); uint reg = 0; string cmd = ""; string registers = ""; // Check to see if we traverse up or down in memory if (this.U) { if (this.P) { RnVal += 4; } for (int i = 0; i < 16; ++i) { if (this.registers[i]) { // Check for load / store multiple if (this.L) { ra[i].WriteWord(0, mem.ReadWord((uint)RnVal)); cmd = "ldm"; } else { mem.WriteWord((uint)RnVal, ra[i].ReadWord(0, true)); cmd = "stm"; } // continue incrementing RnVal += 4; registers += string.Format(", r{0}", i); reg++; } } } // Pretty much same as above, but we are subtracting this time else { if (this.P) { RnVal -= 4; } for (int i = 15; i > -1; --i) { if (this.registers[i]) { // Check for load / store multiple if (this.L) { ra[i].WriteWord(0, mem.ReadWord((uint)RnVal)); cmd = "ldm"; } else { mem.WriteWord((uint)RnVal, ra[i].ReadWord(0, true)); cmd = "stm"; } RnVal -= 4; registers += string.Format(", r{0}", i); ++reg; } } } // Handles the writeback if needed if (this.W) { uint n = (this.U) ? ra[this.Rn].ReadWord(0, true) + (4 * reg) : ra[this.Rn].ReadWord(0, true) - (4 * reg); ra[this.Rn].WriteWord(0, n); } Logger.Instance.writeLog(string.Format("Specific Command: {0} r{1}{2}", cmd, this.Rn, registers)); }