private bool createLines() { if (linesCreated.HasValue) { return((bool)linesCreated); } linesCreated = false; // temporary result until work completed ArmAssembly.AssembledProgram ap = JM.AssembledProgram; if (ap == null) { return(false); // added by NH: 10-04-2015 } _codeViewList.SuspendLayout(); _codeViewList.Items.Clear(); Errors = false; // it is an object code or executable file ArmAssembly.ObjFromAsmFileInfo pi = _PI as ArmAssembly.ObjFromAsmFileInfo; if (pi != null) { ArmAssembly.SectionType sect = ArmAssembly.SectionType.Text; for (int i = 0; i < pi.SourceLines.Length; i++) { ListLine newLine = analyzeLine(pi, i, ref sect); _codeViewList.Items.Add(newLine); } } else { uint textAddress = (uint)(_PI.SectionAddress[(int)(ArmAssembly.SectionType.Text)]); uint dataAddress = (uint)(_PI.SectionAddress[(int)(ArmAssembly.SectionType.Data)]); uint bssAddress = (uint)(_PI.SectionAddress[(int)(ArmAssembly.SectionType.Bss)]); // get sorted list of code labels to intersperse in the code listing AddressLabelPair[] cl; int clLen; if (JM.CodeLabels == null) { cl = null; clLen = 0; } else { cl = JM.CodeLabels.CodeLabelList(); clLen = cl.Length; } ArmAssembly.DisassembleARM.CurrentLabels = cl; int clix = 0; while (clix < clLen && cl[clix].Address < textAddress) { clix++; } uint addrss = textAddress; uint endAddress = (uint)(textAddress + _PI.SectionSize[(int)(ArmAssembly.SectionType.Text)]); while (addrss < endAddress) { while (clix < clLen && cl[clix].Address <= addrss) { _codeViewList.Items.Add( new ListLine(_drawParameters, cl[clix].Label + ":", cl[clix].Address, this)); clix++; } string contents; uint opcode; if (ap != null) { opcode = ap.LoadWord((int)addrss); contents = " " + ArmAssembly.DisassembleARM.DisassembleARMInstruction(opcode, addrss); } else { opcode = 0; contents = " <<disassembly not available>>"; } _codeViewList.Items.Add(new ObjectCodeLine(_drawParameters, addrss, opcode, contents, this)); addrss += 4; } while (clix < clLen && cl[clix].Address < dataAddress) { clix++; } addrss = dataAddress; endAddress = (uint)(dataAddress + _PI.SectionSize[(int)(ArmAssembly.SectionType.Data)]); // Generate labels for the defined data area. We display up to 16 bytes per line. while (addrss < endAddress) { string hex; uint nextLabel = clix < clLen ? cl[clix].Address : (uint)ap.BssStart; int bytesToDisplay = (int)nextLabel - (int)addrss; if ((addrss & 0x3) != 0) { int oddBytes = 4 - (int)(addrss & 0x3); if (oddBytes > bytesToDisplay) { oddBytes = bytesToDisplay; } hex = convertBytes(oddBytes, addrss); _codeViewList.Items.Add( new ObjectCodeLine(_drawParameters, addrss, ".byte", hex, this)); bytesToDisplay -= oddBytes; addrss += (uint)oddBytes; } while (bytesToDisplay >= 16) { hex = String.Format( "0x{0,8:X8}, 0x{1,8:X8}, 0x{2,8:X8}, 0x{3,8:X8}", ap.LoadWord((int)addrss), ap.LoadWord((int)addrss + 4), ap.LoadWord((int)addrss + 8), ap.LoadWord((int)addrss + 12)); _codeViewList.Items.Add( new ObjectCodeLine(_drawParameters, addrss, ".word", hex, this)); addrss += 16; bytesToDisplay -= 16; } if (bytesToDisplay > 0) { if (bytesToDisplay >= 4) { hex = ""; string sep = ""; uint addr = addrss; while (bytesToDisplay >= 4) { hex += String.Format("{0} 0x{1,8:X8}", sep, ap.LoadWord((int)addrss)); sep = ","; addrss += 4; bytesToDisplay -= 4; } _codeViewList.Items.Add( new ObjectCodeLine(_drawParameters, addr, ".word", hex, this)); } if (bytesToDisplay > 0) { hex = convertBytes(bytesToDisplay, addrss); _codeViewList.Items.Add( new ObjectCodeLine(_drawParameters, addrss, ".byte", hex, this)); addrss += (uint)bytesToDisplay; } } if (clix < clLen) { _codeViewList.Items.Add( new ListLine(_drawParameters, cl[clix].Label + ":", cl[clix].Address, this)); clix++; } } while (clix < clLen && cl[clix].Address < bssAddress) { clix++; } addrss = bssAddress; endAddress = (uint)(bssAddress + _PI.SectionSize[(int)(ArmAssembly.SectionType.Bss)]); // Generate labels in the BSS region while (addrss < endAddress) { uint nextLabel = clix < clLen ? cl[clix].Address : (uint)ap.EndAddress; int bytesToDisplay = (int)nextLabel - (int)addrss; if (bytesToDisplay > 0) { _codeViewList.Items.Add( new ObjectCodeLine(_drawParameters, addrss, ".space", bytesToDisplay.ToString(), this)); addrss = nextLabel; } if (clix < clLen) { _codeViewList.Items.Add( new ListLine(_drawParameters, cl[clix].Label + ":", cl[clix].Address, this)); clix++; } } } computeMaxWidth(); _codeViewList.ResumeLayout(); linesCreated = true; return(true); }//init
/// <summary> /// Load a new program into the simulator. This function will compile it, load it and set up the /// simulator for a run. /// </summary> /// <param name="fileNames">list of filenames to load</param> /// <param name="preferences">ARMSim preferences</param> /// <returns>true if sucessful</returns> public bool Load(IList <string> fileNames) { this.ValidLoadedProgram = false; foreach (string str in fileNames) { if (str.EndsWith(".o") || str.EndsWith(".O")) { OutputConsoleString("Loading object code file {0}\n", str); } else if (str.EndsWith(".a") || str.EndsWith(".A")) { OutputConsoleString("Searching library archive {0}\n", str); } else { OutputConsoleString("Loading assembly language file {0}\n", str); } }//foreach mArmAssembler = new ArmAssembly.ArmAssembler(fileNames); try { //perform pass 1 on all the files mArmAssembler.PerformPass(); //ar.DumpInfo(); if (ArmAssembly.AssemblerErrors.ErrorReports.Count <= 0) { // now determine where everything will go in memory mArmAssembler.PlaceCode((int)this.ARMPreferences.SimulatorPreferences.MemoryStart); //ar.DumpInfo(); // allocate a block of memory for the assembled // and linked program mAssembledProgram = new ArmAssembly.AssembledProgram(mArmAssembler); // perform pass 2 on all the files mArmAssembler.PerformPass(mAssembledProgram); //ar.DumpInfo(); //ap.Hexdump(); // display all code } } catch (Exception ex) { OutputConsoleString("A fatal error occurred while assembling the program, Reason:{0}\n", ex.Message); OutputConsoleString("Please keep a copy of the ARM source code and report this ARMSim bug!\n"); return(false); }//catch if (ArmAssembly.AssemblerErrors.ErrorReports.Count > 0) { OutputConsoleString("The following assembler/loader errors occurred ...\n"); IDictionary <string, IList <ArmAssembly.ErrorReport> > xxx = ArmAssembly.AssemblerErrors.ErrorReports.ErrorLists; //display each reported error in the outputview foreach (string fileName in xxx.Keys) { OutputConsoleString("** File: {0}\n", fileName); IList <ArmAssembly.ErrorReport> ht = ArmAssembly.AssemblerErrors.ErrorReports.GetErrorsList(fileName); foreach (ArmAssembly.ErrorReport ce in ht) { string fmt; if (ce.Col == 0) { if (ce.Line == 0) { fmt = " Message = {0}\n"; } else { fmt = " Line {1}: Message = {0}\n"; } } else { fmt = " Line {1}, col {2}: Message = {0}\n"; } OutputConsoleString(fmt, ce.ErrorMsg, ce.Line, ce.Col); } } OutputConsoleString("End of assembler errors\n"); //all done for error case return(false); } //Construct the code labels data structure from the assembled program. mCodeLabels = new CodeLabels(mArmAssembler); //tell the simulator which directory to try for user files this.UserDirectory = System.IO.Path.GetDirectoryName(fileNames[0]); // set the program entry point to be the _start label if it exists; // otherwise set it to the address of main if it exists; // otherwise set it to the start of memory //save the entry point in case the user does a "Restart" but the preferences may have changed - dale if (!mCodeLabels.LabelToAddress("_start", ref mEntryPoint)) { if (!mCodeLabels.LabelToAddress("main", ref mEntryPoint)) { mEntryPoint = (uint)mAssembledProgram.StartAddress; } } //define the simulation memory //save the stack pointer in case the user does a "Restart" but the preferences may have changed - dale mStackPointer = this.DefineMemory(this.ARMPreferences.SimulatorPreferences, mAssembledProgram.Memory.Length); //create the caches based on the user preferences this.DefineCache(this.ARMPreferences.CachePreferences); //perform a restart - loads code into memory, zeros cpu registers, sets pc and sp //note sets the ValidLoadedProgram flag to true this.Restart(); return(true); }//Load