//called when our requested opcode(s) have been fetched and need executing public uint onExecute(uint opcode) { switch (opcode & 0x000001ff) { //set traffic light (r0 = light, 0 - main, 1 - side:r1 = state, 0-black,1-red,2-green,3-yellow) case 0x100: { UIControls.TrafficLight trafficLight; int light = (int)mHost.getReg(0); if (light == 0) { trafficLight = mTrafficIntersectionControl.MainTrafficLight; } else if (light == 1) { trafficLight = mTrafficIntersectionControl.SideTrafficLight; } else { mHost.OutputConsoleString("Bad traffic light code specified:{0}", light); return(1); } int code = (int)mHost.getReg(1); if (code < 0 || code > 3) { mHost.OutputConsoleString("Bad traffic light state specified:{0}", code); return(1); } trafficLight.State = (UIControls.TrafficLight.TrafficLightStates)code; } break; //check xwalk button (r0 = button to check 0-1) //returns:r0 , 0 not pushed, 1 pushed case 0x101: { int button = (int)mHost.getReg(0); bool pressed = false; if (button == 0) { pressed = mTrafficIntersectionControl.GetMainButtonPressed(); } else if (button == 1) { pressed = mTrafficIntersectionControl.GetSideButtonPressed(); } else { mHost.OutputConsoleString("Bad traffic light button specified:{0}", button); return(1); } mHost.setReg((uint)0, (uint)(pressed ? 1 : 0)); } break; //set xwalk sign (r0 - 0 walk, 1 dont walk, 2 hurry) case 0x102: { UIControls.WalkSignal walkSignal; int walk = (int)mHost.getReg(0); if (walk == 0) { walkSignal = mTrafficIntersectionControl.MainWalkSignal; } else if (walk == 1) { walkSignal = mTrafficIntersectionControl.SideWalkSignal; } else { mHost.OutputConsoleString("Bad walk code specified:{0}", walk); return(1); } int code = (int)mHost.getReg(1); if (code < 0 || code > 2) { mHost.OutputConsoleString("Bad walk code specified:{0}", code); return(1); } walkSignal.State = (UIControls.WalkSignal.XWalkStates)code; } break; default: break; } //return true indicating opcode was processed return(3); }//onExecute
}//onRestart //Execute an SWI instruction. /// <summary> /// Called when an swi 0x0000 to swi 0x00ff is executed /// </summary> /// <param name="op_code">opcode being executed</param> /// <returns>number of cycles executed. 0 if none</returns> public uint Execute(uint op_code) { //extract the bottom 8 bits to get swi code. uint swi_code = op_code & 0x000000ff; try { //and execute based on the swi code. switch (swi_code) { //write a character to Outputview //r0: character to output case 0x00: { char c = (char)mIhost.getReg(0); mIhost.OutputConsoleString(new string(c, 1)); } break; //write a character string to Outputview //r0: address of (null terminated) string to display case 0x02: { string s = ARMPluginInterfaces.Utils.loadStringFromMemory(mIhost, mIhost.getReg(0), 256); mIhost.OutputConsoleString(s); } break; //SWI_Exit case 0x11: mIhost.HaltSimulation(); mIhost.GPR[15] -= 4; //todo thumb mode? this.closeAllStreams(); break; //SWI_HeapMalloc //r0: size of block in bytes //Output: C set on error //r0: address of allocated block (or 0 if error) case 0x12: mIhost.setReg(0, mIhost.Malloc(mIhost.getReg(0))); mIhost.cf = (mIhost.getReg(0) == 0); break; //SWI_HeapClear case 0x13: mIhost.HeapClear(); break; //write a character to an open file //r0: file handle (value 1 == screen) //r1: character to output //Output: C flag set on error case 0x60: { string text = ARMPluginInterfaces.Utils.loadStringFromMemory(mIhost, mIhost.getReg(1), 1); uint fileHandle = mIhost.getReg(0); if (fileHandle < mFiles.Count) { mFiles[(int)fileHandle].Write(text); mIhost.cf = false; } else { mIhost.cf = true; } } break; //read one byte (an ASCII character?) from an open file //r0: file handle (value 0 == keyboard) //Output: C flag set on error //r0: the byte read from the file, or -1 if at EOF case 0x61: { uint fileHandle = mIhost.getReg(0); bool error = fileHandle >= mFiles.Count; if (!error) { int ch = (char)mFiles[(int)fileHandle].Read(); mIhost.setReg(0, (uint)ch); } mIhost.cf = error; } break; //read bytes from an open file //r0: file handle //r1: input buffer address //r2: buffer size (number of bytes to read) case 0x62: { uint fileHandle = mIhost.getReg(0); uint address = mIhost.getReg(1); uint maxbytes = mIhost.getReg(2); bool error = fileHandle >= mFiles.Count; //special case if maxbytes is 0. Just return a success. if (maxbytes == 0 || error) { mIhost.cf = error; mIhost.setReg(0, 0); break; } uint storedBytes = 0; while (storedBytes < maxbytes) { int ch = (int)mFiles[(int)fileHandle].Read(); if (ch < 0) { break; } mIhost.SetMemory(address++, ARMPluginInterfaces.MemorySize.Byte, (uint)ch); storedBytes++; } mIhost.cf = false; mIhost.setReg(0, storedBytes); } break; //write bytes to an open file //r0: file handle //r1: output buffer address //r2: buffer size (number of bytes to write) //Output: C flag set on error //r0: the number of bytes successfully written to the file case 0x63: { uint fileHandle = mIhost.getReg(0); uint address = mIhost.getReg(1); uint maxbytes = mIhost.getReg(2); bool error = fileHandle >= mFiles.Count; //special case if maxbytes is 0. Just return a success. if (maxbytes == 0 || error) { mIhost.cf = error; mIhost.setReg(0, 0); break; } uint copiedBytes = 0; while (copiedBytes < maxbytes) { uint ch = mIhost.GetMemory(address++, ARMPluginInterfaces.MemorySize.Byte); mFiles[(int)fileHandle].Write((char)ch); copiedBytes++; } mIhost.cf = false; mIhost.setReg(0, copiedBytes); } break; //open text file for input or output //r0: pointer to filename to open, null terminated //r1: mode -- 0 means input, 1 means output, 2 means append, 0x100 - stdconsole(filename used as title). //Output: C flag set on error //r0: file handle(-1 on error) case 0x66: { bool bError = true; string str = ARMPluginInterfaces.Utils.loadStringFromMemory(mIhost, mIhost.getReg(0), 256); string currDir = Directory.GetCurrentDirectory(); if (!string.IsNullOrEmpty(mIhost.UserDirectory)) { Directory.SetCurrentDirectory(mIhost.UserDirectory); } ARMSimStream astream = null; try { switch (mIhost.getReg(1)) { case 0: astream = new InputARMSimFileStream(new StreamReader(File.OpenRead(str))); break; case 1: astream = new OutputARMSimFileStream(new StreamWriter(File.Open(str, FileMode.Create))); break; case 2: astream = new OutputARMSimFileStream(new StreamWriter(File.Open(str, FileMode.Append))); break; case 0x100: { //create a new standardConsole uint stdHandle = mIhost.CreateStandardConsole(str); astream = new ARMSimConsoleStream(stdHandle, mIhost); } break; default: break; } //switch uint fileHandle = uint.MaxValue; if (astream != null) { fileHandle = mNextFileHandle++; mFiles.Add(astream); bError = false; } mIhost.setReg(0, fileHandle); } //try catch (Exception) { mIhost.setReg(0, uint.MaxValue); } Directory.SetCurrentDirectory(currDir); mIhost.cf = bError; } break; //case 0x66 //close an open file //r0: file handle //Output: C flag set on error case 0x68: { uint handle = mIhost.getReg(0); if (handle < mFiles.Count) { mFiles[(int)handle].Close(); mFiles[(int)handle] = null; mIhost.cf = false; } else { mIhost.cf = true; } } break; //write null-terminated string to screen or to open file //r0: file handle (value 1 == screen) //r1: address of string to read from memory //Output: C flag set on error case 0x69: { uint addr = mIhost.getReg(1); string text = ARMPluginInterfaces.Utils.loadStringFromMemory(mIhost, addr, 256); uint fileHandle = mIhost.getReg(0); if (fileHandle < mFiles.Count) { mFiles[(int)fileHandle].Write(text); mIhost.cf = false; } else { mIhost.cf = true; } } break; //read line of text from open file //r0: file handle //r1: location to put read data //r2: max number of bytes to read (including added null terminator) //Output: C flag set on error //r0: number of bytes stored (including added null terminator) case 0x6a: { uint fileHandle = mIhost.getReg(0); uint maxbytes = mIhost.getReg(2); bool error = fileHandle >= mFiles.Count; //special case if maxbytes is 0. Just return a success. if (maxbytes == 0) { mIhost.cf = error; mIhost.setReg(0, 0); break; } uint storedBytes = 0; string text = null; if (!error) { text = mFiles[(int)fileHandle].ReadLine(); error = text == null; } if (!error) { storedBytes = (uint)(text.Length + 1); if (maxbytes < text.Length) { storedBytes = maxbytes; } uint address = mIhost.getReg(1); for (uint i = 0; i < storedBytes - 1; i++) { uint data = (uint)(text[(int)i]); mIhost.SetMemory(address++, ARMPluginInterfaces.MemorySize.Byte, data); } mIhost.SetMemory(address++, ARMPluginInterfaces.MemorySize.Byte, 0); } mIhost.setReg(0, storedBytes); mIhost.cf = error; } break; //write signed integer to screen or to open file //r0: file handle (value 1 == screen) //r1: integer value to write //Output: C flag set on error case 0x6b: { uint fileHandle = mIhost.getReg(0); string text = ((int)mIhost.getReg(1)).ToString(); if (fileHandle < mFiles.Count) { mFiles[(int)fileHandle].Write(text); mIhost.cf = false; } else { mIhost.cf = true; } } break; //read signed integer from open file //r0: file handle //Output: C flag set on error //r0: value of the integer read from file case 0x6c: { int number = 0; uint fileHandle = mIhost.getReg(0); ARMSimStream sr = null; if (fileHandle < mFiles.Count) { sr = mFiles[(int)fileHandle]; } bool error = true; if (sr != null) { error = sr.GetInteger(ref number); } if (!error) { mIhost.setReg(0, (uint)number); } mIhost.cf = error; } break; case 0x6d: //return milliseconds in r0 mIhost.setReg(0, (uint)(DateTime.Now.Ticks / 10000)); break; //output a double FP number to the console //r0:register to output (0-15) //outputs in the same format as the registers view, uses the formatstring "0.###E+0" case 0x6e: { uint reg = mIhost.getReg(0); if (reg > 15) { reportBadRegister(reg, 0x6e); return(0); } double value = mIhost.getFPDoubleReg(reg); string str = ARMSim.Simulator.VFP.FloatingPointProcessor.DoubleToString(value); mIhost.OutputConsoleString(str); } break; //output a float FP number to the console //r0:register to output (0-31) //outputs in the same format as the registers view, uses the formatstring "0.###E+0" case 0x6f: { uint reg = mIhost.getReg(0); if (reg > 31) { reportBadRegister(reg, 0x6f); return(0); } float value = mIhost.getFPSingleReg(reg); string str = ARMSim.Simulator.VFP.FloatingPointProcessor.FloatToString(value); mIhost.OutputConsoleString(str); } break; //read double value from open file //r0: file handle //r1: register to read value into (0-15) case 0x7b: { double number = 0.0; uint fileHandle = mIhost.getReg(0); uint reg = mIhost.getReg(1); if (reg > 15) { reportBadRegister(reg, swi_code); return(0); } ARMSimStream sr = null; if (fileHandle < mFiles.Count) { sr = mFiles[(int)fileHandle]; } bool error = true; if (sr != null) { error = sr.GetDouble(ref number); } if (!error) { mIhost.setFPDoubleReg(0, number); } mIhost.cf = error; } break; //read float value from open file //r0: file handle //r1: register to read value into (0-31) case 0x7c: { double number = 0.0; uint fileHandle = mIhost.getReg(0); uint reg = mIhost.getReg(1); if (reg > 31) { reportBadRegister(reg, swi_code); return(0); } ARMSimStream sr = null; if (fileHandle < mFiles.Count) { sr = mFiles[(int)fileHandle]; } //else bool error = true; if (sr != null) { error = sr.GetDouble(ref number); } if (!error) { mIhost.setFPSingleReg(0, (float)number); } else { mIhost.cf = error; } } break; //output a double FP number to screen or to open file //r0: file handle (value 1 == screen) //r1:register to output (0-15) //outputs in the same format as the registers view, uses the formatstring "0.###E+0" case 0x7e: { uint reg = mIhost.getReg(1); if (reg > 15) { reportBadRegister(reg, swi_code); return(0); } double value = mIhost.getFPDoubleReg(reg); string text = ARMSim.Simulator.VFP.FloatingPointProcessor.DoubleToString(value); uint fileHandle = mIhost.getReg(0); if (fileHandle < mFiles.Count) { mFiles[(int)fileHandle].Write(text); mIhost.cf = false; } else { mIhost.cf = true; } } break; //output a float FP number to screen or to open file //r0: file handle (value 1 == screen) //r1:register to output (0-31) //outputs in the same format as the registers view, uses the formatstring "0.###E+0" case 0x7f: { uint reg = mIhost.getReg(1); if (reg > 31) { reportBadRegister(reg, swi_code); return(0); } float value = mIhost.getFPSingleReg(reg); string text = ARMSim.Simulator.VFP.FloatingPointProcessor.FloatToString(value); uint fileHandle = mIhost.getReg(0); if (fileHandle < mFiles.Count) { mFiles[(int)fileHandle].Write(text); mIhost.cf = false; } else { mIhost.cf = true; } } break; default: //if it is an unknown swi code then return 3 clock cycles executed but //do no actual work. This prevents the swi exception from being raised //for swi codes not handled here break; } //switch } //try catch (Exception ex) { ARMPluginInterfaces.Utils.OutputDebugString( "Exception caught while processing SWI call: 0x" + swi_code.ToString("X2") + " Message: " + ex.Message); return(0); } return(3); }//Execute
//called when our requested opcode(s) have been fetched and need executing //In our case, any swi 0x200 to swi 0x2ff public uint onExecute(uint opcode) { try { switch (opcode & 0x000002ff) { //set eight segment display (r0 - segment pattern) case 0x200: { //get code to display from R0 byte code = (byte)mIHost.getReg(0); mEmbestBoardControl.EightSegmentDisplay.Code = code; } break; case 0x201: { uint code = mIHost.getReg(0); mEmbestBoardControl.Leds.LeftLed = ((code & (uint)LedEnum.LeftLed) == (uint)LedEnum.LeftLed); mEmbestBoardControl.Leds.RightLed = ((code & (uint)LedEnum.RightLed) == (uint)LedEnum.RightLed); } break; //check black buttons //returns r0 : bit0:left button, bit1:right button case 0x202: { mIHost.setReg(0, mEmbestBoardControl.BlackButtons.CheckPressed()); } break; //check blue buttons //returns r0 : low 16 bits contains button(s) pressed case 0x203: { mIHost.setReg(0, mEmbestBoardControl.BlueButtons.CheckPressed()); } break; //SWI_DrawLcdString //R0:xpos //R1:ypos //R2:string to print(null terminated) case 0x204: { uint xpos = mIHost.getReg(0); uint ypos = mIHost.getReg(1); string str = Utils.loadStringFromMemory(mIHost, mIHost.getReg(2), 256); mEmbestBoardControl.Lcd.PrintString(xpos, ypos, str); mEmbestBoardControl.Lcd.Invalidate(); } break; //SWI_DrawLcdInt //R0:xpos //R1:ypos //R2:int to print case 0x205: { uint xpos = mIHost.getReg(0); uint ypos = mIHost.getReg(1); string str = mIHost.getReg(2).ToString(); mEmbestBoardControl.Lcd.PrintString(xpos, ypos, str); mEmbestBoardControl.Lcd.Invalidate(); } break; //ClearLCDDisplay case 0x206: { mEmbestBoardControl.Lcd.ClearScreen(); mEmbestBoardControl.Lcd.Invalidate(); } break; //DrawLCDCharacter //R0:xpos //R1:ypos //R2:char case 0x207: { uint xpos = mIHost.getReg(0); uint ypos = mIHost.getReg(1); char ch = (char)mIHost.getReg(2); mEmbestBoardControl.Lcd.PrintChar(xpos, ypos, ch); mEmbestBoardControl.Lcd.Invalidate(); } break; //ClearLCDLine //R0:line# case 0x208: { uint ypos = mIHost.getReg(0); mEmbestBoardControl.Lcd.ClearLine(ypos); mEmbestBoardControl.Lcd.Invalidate(); } break; ////Draw Pixel ////R0:xpos ////R1:ypos ////R2:0 - erase, 1 - draw //case 0x209: // { // int xpos = (int)mIHost.getReg(0); // int ypos = (int)mIHost.getReg(1); // bool erase = (mIHost.getReg(2) == 0); // mEmbestBoardControl.Lcd.DrawPixel(xpos, ypos, erase); // } break; //Return 15bit timer case 0x20a: { uint ticks = (uint)(DateTime.Now.Ticks / 10000); ticks = (ticks & 0x00007fff); mIHost.setReg(0, ticks); } break; default: break; } //switch } //try catch (Exception ex) { uint where = mIHost.getReg(15) - 0x04; mIHost.OutputConsoleString("An error occurred in {0} at 0x{1:X8}\nReason:{2}", this.PluginName, where, ex.Message); mIHost.setReg(15, where); } //catch return(3); } //onExecute