Example #1
0
        // Seek to an absolute file position
        private uint swiSeek()
        {
            // Params:  file handle, absolute file position in bytes
            // Result:  r0 = -1 if error, 0 otherwise
            if (!fetchParams(2))
            {
                return(errorCode(Errno.EFAULT));
            }
            ARMSimStream astream = getStream(paramBlock[0]);

            if (astream == null)
            {
                return(uint.MaxValue);
            }
            InputARMSimFileStream iastream = astream as InputARMSimFileStream;

            if (iastream != null)
            {
                try {
                    Stream s = iastream.Stream.BaseStream;
                    if (s.CanSeek)
                    {
                        s.Position = (long)paramBlock[1];
                        return(0);
                    }
                } catch (Exception) {
                    return(errorCode(Errno.EIO));
                }
            }
            return(errorCode(Errno.ENOTSUP));
        }
        }//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
Example #3
0
        }//Execute

        // Open a file
        private uint swiOpen()
        {
            // Params:  filename, length of filename, mode
            // Result:  r0 = file handle
            if (!fetchParams(3))
            {
                return(errorCode(Errno.EFAULT));
            }

            try {
                string str    = ARMPluginInterfaces.Utils.loadStringFromMemory(mIhost, paramBlock[0], paramBlock[1]);
                uint   mode   = paramBlock[2];
                bool   binary = false;
                if ((mode & 1) != 0)
                {
                    binary = true;
                    mode  &= 0xffffffe;
                }
                if (binary)
                {
                    ARMPluginInterfaces.Utils.OutputDebugString("binary mode files unsupported");
                }

                mErrno = Errno.NONE;
                ARMSimStream astream = null;
                if (String.IsNullOrEmpty(str) || str == ":tt")
                {
                    // First three uses of this filename map to the standard streams
                    // stdin, stdout, & stderr which have already been opened
                    if (stdFileNum <= 2)
                    {
                        return(stdFileNum++);
                    }
                    // We want additional console windowss??
                    uint stdHandle = mIhost.CreateStandardConsole(str);
                    astream = new ARMSimConsoleStream(stdHandle, mIhost);
                }
                else
                {
                    string currDir = null;
                    if (mIhost.UserDirectory != null)
                    {
                        currDir = Directory.GetCurrentDirectory();
                        Directory.SetCurrentDirectory(mIhost.UserDirectory);
                    }
                    switch (mode)
                    {
                    case 0:      // read
                        astream = new InputARMSimFileStream(new StreamReader(File.OpenRead(str)));
                        break;

                    case 2:                     // read-write mode
                        mErrno = Errno.ENOTSUP; // unsupported mode
                        break;

                    case 4:      // write (with create or truncate)
                        astream = new OutputARMSimFileStream(new StreamWriter(File.Open(str, FileMode.OpenOrCreate)));
                        break;

                    case 8:      // write in append mode
                        astream = new OutputARMSimFileStream(new StreamWriter(File.Open(str, FileMode.Append)));
                        break;

                    default:
                        mErrno = Errno.EINVAL;      // invalid mode
                        break;
                    }
                    if (currDir != null)
                    {
                        Directory.SetCurrentDirectory(currDir);
                    }
                    if (mErrno != Errno.NONE)
                    {
                        return(uint.MaxValue);
                    }
                }
                int fileHandle = 0;
                // search for the first available handle
                while (fileHandle < mFiles.Count)
                {
                    if (mFiles[fileHandle] == null)
                    {
                        mFiles[fileHandle] = astream;
                        return((uint)fileHandle);
                    }
                    fileHandle++;
                }
                mFiles.Add(astream);
                return((uint)fileHandle);
            } catch (Exception) {
                return(errorCode(Errno.EIO));
            }
        }