4 Commits

Author SHA1 Message Date
Hykilpikonna d6dab423cc Update README.md 2022-11-12 18:27:33 -05:00
Hykilpikonna ed74f3355a [+] 4.7rc2 2022-11-12 18:26:09 -05:00
Hykilpikonna 2c8c4f51a5 [O] Optimize a lot of things 2022-11-12 17:06:02 -05:00
Hykilpikonna 18750d7595 [+] Gradle version settings 2022-11-11 22:30:57 -05:00
25 changed files with 434 additions and 589 deletions
+31
View File
@@ -12,12 +12,24 @@
* Added `--open` command-line option to open a file on start
* Added **Keyboard++**: Enhanced keyboard events
* Refactored many classes in Kotlin
* A LOT of [optimizations](https://github.com/hykilpikonna/EMARS#optimizations)
## FAQ
**How to run:** Install Java JDK >11 and double-click on the jar.
**How to compile:** `gradle shadowJar`
## Modifications needed
1. To use **Bitmap Display++**, please add the following code at the end of each render loop:
```asm
# Tell the display to update
lw $t8, ADDR_DISPLAY
li $t9, 1
sw $t9, 0($t8)
```
## Keyboard++
![Demo](img/bitmap_display_plus_plus.png)
@@ -393,6 +405,25 @@ UNDEFINED = 0x0
</details>
## Optimizations
In MARS, the BitmapDisplay [re-draws the entire canvas](https://github.com/thomasrussellmurphy/MARS_Assembler/blob/c21dd72e8d2e4a51eb24e276c3f39ef1789148f2/mars/tools/BitmapDisplay.java#L496) instead of only the updated pixels whenever any memory address is updated. This makes updating the display very very very slow, taking 12% of all run time.
![image](https://user-images.githubusercontent.com/22280294/201498543-02a74fb4-9f55-45c8-8eaf-6f1531ab02bd.png)
For example, if I loop through the display and change every pixel in my assembly code, the original running time of hw will now take h2w2, making it take around one second for each update.
Since I cant easily draw one pixel on update without manual manipulation of AWT Graphics, I changed it so that it treats bit 0 of the memory display as an “update bit,” and only re-draw the screen when the MIPS program sets bit 0 to 1.
After optimizing for this, it runs faster but still not enough for the animation to be smooth. Then, I discovered that most of the running time is used by the backstepper and notifying observers for changes in registers and memory:
![image](https://user-images.githubusercontent.com/22280294/201498548-1e8712ef-79d6-45e9-9d22-096148185c64.png)
By default, MARS will store backstep register file copies each time a register is updated, which takes a lot of time since registers are updated very frequently. So I removed backstepping when the execution speed limit is not set. MARS also notifies all memory observers when a program statement instruction is read from memory, which I also removed because nothing uses the notification from reading program statements.
## License
[MIT][2]. Chech the [LICENSE][3] file. All the credits go to the original developers.
+2
View File
@@ -6,6 +6,8 @@ plugins {
id "com.github.johnrengelman.shadow" version "7.1.2"
}
version="4.7rc2"
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
+1 -1
View File
@@ -1 +1 @@
rootProject.name = 'MARS'
rootProject.name = 'EMARS'
+2 -2
View File
@@ -410,7 +410,7 @@ public class MIPSprogram
{
steppedExecution = false;
Simulator sim = Simulator.getInstance();
return sim.simulate(this, RegisterFile.getProgramCounter(), maxSteps, breakPoints, a);
return sim.simulate(this, RegisterFile.getPc(), maxSteps, breakPoints, a);
}
@@ -426,7 +426,7 @@ public class MIPSprogram
{
steppedExecution = true;
Simulator sim = Simulator.getInstance();
boolean done = sim.simulate(this, RegisterFile.getProgramCounter(), 1, null, a);
boolean done = sim.simulate(this, RegisterFile.getPc(), 1, null, a);
return done;
}
+1 -1
View File
@@ -669,7 +669,7 @@ class MarsLaunch(var args: Array<String>)
{
out.print(reg + "\t")
}
value = RegisterFile.getUserRegister(reg).value
value = RegisterFile.getUserRegister(reg)!!.value
out.println(formatIntForDisplay(value))
} else
{
+1 -1
View File
@@ -79,7 +79,7 @@ public class ProcessingException extends Exception
{
errs = new ErrorList();
errs.add(new ErrorMessage(ps, "Runtime exception at " +
Binary.intToHexString(RegisterFile.getProgramCounter() - Instruction.INSTRUCTION_LENGTH) +
Binary.intToHexString(RegisterFile.getPc() - Instruction.INSTRUCTION_LENGTH) +
": " + m));
// Stopped using ps.getAddress() because of pseudo-instructions. All instructions in
// the macro expansion point to the same ProgramStatement, and thus all will return the
+2 -1
View File
@@ -2,6 +2,7 @@ package mars;
import mars.util.Binary;
import mars.util.EditorFont;
import mars.venus.RunSpeedPanel;
import mars.venus.editors.jeditsyntax.SyntaxStyle;
import mars.venus.editors.jeditsyntax.SyntaxUtilities;
@@ -448,7 +449,7 @@ public class Settings extends Observable
*/
public boolean getBackSteppingEnabled()
{
return (Globals.program != null && Globals.program.getBackStepper() != null && Globals.program.getBackStepper().enabled());
return RunSpeedPanel.getInstance().getRunSpeed() != RunSpeedPanel.UNLIMITED_SPEED;
}
/**
+11 -80
View File
@@ -3,7 +3,6 @@ package mars.mips.hardware;
import mars.Globals;
import mars.ProgramStatement;
import mars.Settings;
import mars.mips.instructions.Instruction;
import mars.simulator.Exceptions;
import mars.util.Binary;
@@ -571,7 +570,7 @@ public class Memory extends Observable
if (Globals.getSettings().getBooleanSetting(Settings.SELF_MODIFYING_CODE_ENABLED))
{
ProgramStatement oldStatement = getStatementNoNotify(address);
ProgramStatement oldStatement = getStatement(address);
if (oldStatement != null)
{
oldValue = oldStatement.getBinaryStatement();
@@ -650,7 +649,7 @@ public class Memory extends Observable
// DPS adaptation 5-Jul-2013: either throw or call, depending on setting
if (Globals.getSettings().getBooleanSetting(Settings.SELF_MODIFYING_CODE_ENABLED))
{
ProgramStatement oldStatement = getStatementNoNotify(address);
ProgramStatement oldStatement = getStatement(address);
if (oldStatement != null)
{
oldValue = oldStatement.getBinaryStatement();
@@ -861,11 +860,11 @@ public class Memory extends Observable
}
else if (inTextSegment(address))
{
// Burch Mod (Jan 2013): replace throw with calls to getStatementNoNotify & getBinaryStatement
// Burch Mod (Jan 2013): replace throw with calls to getStatement & getBinaryStatement
// DPS adaptation 5-Jul-2013: either throw or call, depending on setting
if (Globals.getSettings().getBooleanSetting(Settings.SELF_MODIFYING_CODE_ENABLED))
{
ProgramStatement stmt = getStatementNoNotify(address);
ProgramStatement stmt = getStatement(address);
value = stmt == null ? 0 : stmt.getBinaryStatement();
}
else
@@ -947,11 +946,11 @@ public class Memory extends Observable
}
else if (inTextSegment(address))
{
// Burch Mod (Jan 2013): replace throw with calls to getStatementNoNotify & getBinaryStatement
// Burch Mod (Jan 2013): replace throw with calls to getStatement & getBinaryStatement
// DPS adaptation 5-Jul-2013: either throw or call, depending on setting
if (Globals.getSettings().getBooleanSetting(Settings.SELF_MODIFYING_CODE_ENABLED))
{
ProgramStatement stmt = getStatementNoNotify(address);
ProgramStatement stmt = getStatement(address);
value = stmt == null ? 0 : stmt.getBinaryStatement();
}
else
@@ -1028,7 +1027,7 @@ public class Memory extends Observable
{
try
{
value = (getStatementNoNotify(address) == null) ? null : getStatementNoNotify(address).getBinaryStatement();
value = (getStatement(address) == null) ? null : getStatement(address).getBinaryStatement();
}
catch (AddressErrorException aee)
{
@@ -1139,68 +1138,12 @@ public class Memory extends Observable
return get(address, 1);
}
/**
* Gets ProgramStatement from Text Segment.
*
* @param address Starting address of Memory address to be read. Must be word boundary.
* @return reference to ProgramStatement object associated with that address, or null if none.
* @throws AddressErrorException If address is not on word boundary or is outside Text Segment.
* @see ProgramStatement
**/
public ProgramStatement getStatement(int address) throws AddressErrorException
{
return getStatement(address, true);
/*
if (address % 4 != 0 || !(inTextSegment(address) || inKernelTextSegment(address))) {
throw new AddressErrorException(
"fetch address for text segment out of range or not aligned to word boundary ",
Exceptions.ADDRESS_EXCEPTION_LOAD, address);
}
if (inTextSegment(address)) {
return readProgramStatement(address, textBaseAddress, textBlockTable, true);
}
else {
return readProgramStatement(address, kernelTextBaseAddress, kernelTextBlockTable,true);
}
*/
}
///////////////////////////////////////////////////////////////////////////
// ALL THE OBSERVABLE STUFF GOES HERE. FOR COMPATIBILITY, Memory IS STILL
// EXTENDING OBSERVABLE, BUT WILL NOT USE INHERITED METHODS. WILL INSTEAD
// USE A COLLECTION OF MemoryObserver OBJECTS, EACH OF WHICH IS COMBINATION
// OF AN OBSERVER WITH AN ADDRESS RANGE.
/**
* Gets ProgramStatement from Text Segment without notifying observers.
*
* @param address Starting address of Memory address to be read. Must be word boundary.
* @return reference to ProgramStatement object associated with that address, or null if none.
* @throws AddressErrorException If address is not on word boundary or is outside Text Segment.
* @see ProgramStatement
**/
public ProgramStatement getStatementNoNotify(int address) throws AddressErrorException
{
return getStatement(address, false);
/*
if (address % 4 != 0 || !(inTextSegment(address) || inKernelTextSegment(address))) {
throw new AddressErrorException(
"fetch address for text segment out of range or not aligned to word boundary ",
Exceptions.ADDRESS_EXCEPTION_LOAD, address);
}
if (inTextSegment(address)) {
return readProgramStatement(address, textBaseAddress, textBlockTable, false);
}
else {
return readProgramStatement(address, kernelTextBaseAddress, kernelTextBlockTable, false);
}
*/
}
private ProgramStatement getStatement(int address, boolean notify) throws AddressErrorException
public ProgramStatement getStatement(int address) throws AddressErrorException
{
if (!wordAligned(address))
{
@@ -1217,11 +1160,11 @@ public class Memory extends Observable
}
if (inTextSegment(address))
{
return readProgramStatement(address, textBaseAddress, textBlockTable, notify);
return readProgramStatement(address, textBaseAddress, textBlockTable);
}
else if (inKernelTextSegment(address))
{
return readProgramStatement(address, kernelTextBaseAddress, kernelTextBlockTable, notify);
return readProgramStatement(address, kernelTextBaseAddress, kernelTextBlockTable);
}
else
{
@@ -1601,7 +1544,7 @@ public class Memory extends Observable
// as valid. It may be either in user or kernel text segment, as specified by arguments.
// Returns associated ProgramStatement or null if none.
// Last parameter controls whether or not observers will be notified.
private ProgramStatement readProgramStatement(int address, int baseAddress, ProgramStatement[][] blockTable, boolean notify)
private ProgramStatement readProgramStatement(int address, int baseAddress, ProgramStatement[][] blockTable)
{
int relative = (address - baseAddress) >> 2; // convert byte address to words
int block = relative / TEXT_BLOCK_LENGTH_WORDS;
@@ -1611,25 +1554,13 @@ public class Memory extends Observable
if (blockTable[block] == null || blockTable[block][offset] == null)
{
// No instructions are stored in this block or offset.
if (notify)
{
notifyAnyObservers(AccessNotice.READ, address, Instruction.INSTRUCTION_LENGTH, 0);
}
return null;
}
else
{
if (notify)
{
notifyAnyObservers(AccessNotice.READ, address, Instruction.INSTRUCTION_LENGTH, blockTable[block][offset].getBinaryStatement());
}
return blockTable[block][offset];
}
}
if (notify)
{
notifyAnyObservers(AccessNotice.READ, address, Instruction.INSTRUCTION_LENGTH, 0);
}
return null;
}
+1 -29
View File
@@ -45,7 +45,7 @@ public class Register extends Observable
private int resetValue;
// volatile should be enough to allow safe multi-threaded access
// volatile should be enough to allow safe multithreaded access
// w/o the use of synchronized methods. getValue and setValue
// are the only methods here used by the register collection
// (RegisterFile, Coprocessor0, Coprocessor1) methods.
@@ -85,19 +85,6 @@ public class Register extends Observable
*/
public synchronized int getValue()
{
notifyAnyObservers(AccessNotice.READ);
return value;
}
/**
* Returns the value of the Register. Observers are not notified. Added for release 3.8.
*
* @return value The value of the Register.
*/
public synchronized int getValueNoNotify()
{
return value;
}
@@ -136,7 +123,6 @@ public class Register extends Observable
{
int old = value;
value = val;
notifyAnyObservers(AccessNotice.WRITE);
return old;
}
@@ -157,18 +143,4 @@ public class Register extends Observable
{
resetValue = reset;
}
//
// Method to notify any observers of register operation that has just occurred.
//
private void notifyAnyObservers(int type)
{
if (this.countObservers() > 0)
{// && Globals.program != null) && Globals.program.inSteppedExecution()) {
this.setChanged();
this.notifyObservers(new RegisterAccessNotice(type, this.name));
}
}
}
@@ -1,395 +0,0 @@
package mars.mips.hardware;
import mars.Globals;
import mars.assembler.SymbolTable;
import mars.mips.instructions.Instruction;
import mars.util.Binary;
import java.util.Observer;
/*
Copyright (c) 2003-2008, Pete Sanderson and Kenneth Vollmar
Developed by Pete Sanderson (psanderson@otterbein.edu)
and Kenneth Vollmar (kenvollmar@missouristate.edu)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(MIT license, http://www.opensource.org/licenses/mit-license.html)
*/
/**
* Represents the collection of MIPS registers.
*
* @author Jason Bumgarner, Jason Shrewsbury
* @version June 2003
**/
public class RegisterFile
{
public static final int GLOBAL_POINTER_REGISTER = 28;
public static final int STACK_POINTER_REGISTER = 29;
private static final Register[] regFile =
{new Register("$zero", 0, 0), new Register("$at", 1, 0),
new Register("$v0", 2, 0), new Register("$v1", 3, 0),
new Register("$a0", 4, 0), new Register("$a1", 5, 0),
new Register("$a2", 6, 0), new Register("$a3", 7, 0),
new Register("$t0", 8, 0), new Register("$t1", 9, 0),
new Register("$t2", 10, 0), new Register("$t3", 11, 0),
new Register("$t4", 12, 0), new Register("$t5", 13, 0),
new Register("$t6", 14, 0), new Register("$t7", 15, 0),
new Register("$s0", 16, 0), new Register("$s1", 17, 0),
new Register("$s2", 18, 0), new Register("$s3", 19, 0),
new Register("$s4", 20, 0), new Register("$s5", 21, 0),
new Register("$s6", 22, 0), new Register("$s7", 23, 0),
new Register("$t8", 24, 0), new Register("$t9", 25, 0),
new Register("$k0", 26, 0), new Register("$k1", 27, 0),
new Register("$gp", GLOBAL_POINTER_REGISTER, Memory.globalPointer),
new Register("$sp", STACK_POINTER_REGISTER, Memory.stackPointer),
new Register("$fp", 30, 0), new Register("$ra", 31, 0)
};
private static final Register programCounter = new Register("pc", 32, Memory.textBaseAddress);
private static final Register hi = new Register("hi", 33, 0);//this is an internal register with arbitrary number
private static final Register lo = new Register("lo", 34, 0);// this is an internal register with arbitrary number
/**
* Method for displaying the register values for debugging.
**/
public static void showRegisters()
{
for (int i = 0; i < regFile.length; i++)
{
System.out.println("Name: " + regFile[i].getName());
System.out.println("Number: " + regFile[i].getNumber());
System.out.println("Value: " + regFile[i].getValue());
System.out.println();
}
}
/**
* This method updates the register value who's number is num. Also handles the lo and hi registers
*
* @param num Register to set the value of.
* @param val The desired value for the register.
**/
public static int updateRegister(int num, int val)
{
int old = 0;
if (num == 0)
{
//System.out.println("You can not change the value of the zero register.");
}
else
{
for (int i = 0; i < regFile.length; i++)
{
if (regFile[i].getNumber() == num)
{
old = (Globals.getSettings().getBackSteppingEnabled())
? Globals.program.getBackStepper().addRegisterFileRestore(num, regFile[i].setValue(val))
: regFile[i].setValue(val);
break;
}
}
}
if (num == 33)
{//updates the hi register
old = (Globals.getSettings().getBackSteppingEnabled())
? Globals.program.getBackStepper().addRegisterFileRestore(num, hi.setValue(val))
: hi.setValue(val);
}
else if (num == 34)
{// updates the low register
old = (Globals.getSettings().getBackSteppingEnabled())
? Globals.program.getBackStepper().addRegisterFileRestore(num, lo.setValue(val))
: lo.setValue(val);
}
return old;
}
/**
* Sets the value of the register given to the value given.
*
* @param reg Name of register to set the value of.
* @param val The desired value for the register.
**/
public static void updateRegister(String reg, int val)
{
if (reg.equals("zero"))
{
//System.out.println("You can not change the value of the zero register.");
}
else
{
for (int i = 0; i < regFile.length; i++)
{
if (regFile[i].getName().equals(reg))
{
updateRegister(i, val);
break;
}
}
}
}
/**
* Returns the value of the register who's number is num.
*
* @param num The register number.
* @return The value of the given register.
**/
public static int getValue(int num)
{
if (num == 33)
{
return hi.getValue();
}
else if (num == 34)
{
return lo.getValue();
}
else
{
return regFile[num].getValue();
}
}
/**
* For getting the number representation of the register.
*
* @param n The string formatted register name to look for.
* @return The number of the register represented by the string or -1 if no match.
**/
public static int getNumber(String n)
{
int j = -1;
for (int i = 0; i < regFile.length; i++)
{
if (regFile[i].getName().equals(n))
{
j = regFile[i].getNumber();
break;
}
}
return j;
}
/**
* For returning the set of registers.
*
* @return The set of registers.
**/
public static Register[] getRegisters()
{
return regFile;
}
/**
* Get register object corresponding to given name. If no match, return null.
*
* @param Rname The register name, either in $0 or $zero format.
* @return The register object,or null if not found.
**/
public static Register getUserRegister(String Rname)
{
Register reg = null;
if (Rname.charAt(0) == '$')
{
try
{
// check for register number 0-31.
reg = regFile[Binary.stringToInt(Rname.substring(1))]; // KENV 1/6/05
}
catch (Exception e)
{
// handles both NumberFormat and ArrayIndexOutOfBounds
// check for register mnemonic $zero thru $ra
reg = null; // just to be sure
// just do linear search; there aren't that many registers
for (int i = 0; i < regFile.length; i++)
{
if (Rname.equals(regFile[i].getName()))
{
reg = regFile[i];
break;
}
}
}
}
return reg;
}
/**
* For initializing the Program Counter. Do not use this to implement jumps and branches, as it will NOT record a
* backstep entry with the restore value. If you need backstepping capability, use setProgramCounter instead.
*
* @param value The value to set the Program Counter to.
**/
public static void initializeProgramCounter(int value)
{
programCounter.setValue(value);
}
/**
* Will initialize the Program Counter to either the default reset value, or the address associated with source
* program global label "main", if it exists as a text segment label and the global setting is set.
*
* @param startAtMain If true, will set program counter to address of statement labeled 'main' (or other defined
* start label) if defined. If not defined, or if parameter false, will set program counter to default reset
* value.
**/
public static void initializeProgramCounter(boolean startAtMain)
{
int mainAddr = Globals.symbolTable.getAddress(SymbolTable.getStartLabel());
if (startAtMain && mainAddr != SymbolTable.NOT_FOUND && (Memory.inTextSegment(mainAddr) || Memory.inKernelTextSegment(mainAddr)))
{
initializeProgramCounter(mainAddr);
}
else
{
initializeProgramCounter(programCounter.getResetValue());
}
}
/**
* For setting the Program Counter. Note that ordinary PC update should be done using incrementPC() method. Use
* this only when processing jumps and branches.
*
* @param value The value to set the Program Counter to.
* @return previous PC value
**/
public static int setProgramCounter(int value)
{
int old = programCounter.getValue();
programCounter.setValue(value);
if (Globals.getSettings().getBackSteppingEnabled())
{
Globals.program.getBackStepper().addPCRestore(old);
}
return old;
}
/**
* For returning the program counters value.
*
* @return The program counters value as an int.
**/
public static int getProgramCounter()
{
return programCounter.getValue();
}
/**
* Returns Register object for program counter. Use with caution.
*
* @return program counter's Register object.
*/
public static Register getProgramCounterRegister()
{
return programCounter;
}
/**
* For returning the program counter's initial (reset) value.
*
* @return The program counter's initial value
**/
public static int getInitialProgramCounter()
{
return programCounter.getResetValue();
}
/**
* Method to reinitialize the values of the registers.
* <b>NOTE:</b> Should <i>not</i> be called from command-mode MARS because this
* this method uses global settings from the registry. Command-mode must operate using only the command switches,
* not registry settings. It can be called from tools running stand-alone, and this is done in
* <code>AbstractMarsToolAndApplication</code>.
**/
public static void resetRegisters()
{
for (int i = 0; i < regFile.length; i++)
{
regFile[i].resetValue();
}
initializeProgramCounter(Globals.getSettings().getStartAtMain());// replaces "programCounter.resetValue()", DPS 3/3/09
hi.resetValue();
lo.resetValue();
}
/**
* Method to increment the Program counter in the general case (not a jump or branch).
**/
public static void incrementPC()
{
programCounter.setValue(programCounter.getValue() + Instruction.INSTRUCTION_LENGTH);
}
/**
* Each individual register is a separate object and Observable. This handy method will add the given Observer to
* each one. Currently does not apply to Program Counter.
*/
public static void addRegistersObserver(Observer observer)
{
for (int i = 0; i < regFile.length; i++)
{
regFile[i].addObserver(observer);
}
hi.addObserver(observer);
lo.addObserver(observer);
}
/**
* Each individual register is a separate object and Observable. This handy method will delete the given Observer
* from each one. Currently does not apply to Program Counter.
*/
public static void deleteRegistersObserver(Observer observer)
{
for (int i = 0; i < regFile.length; i++)
{
regFile[i].deleteObserver(observer);
}
hi.deleteObserver(observer);
lo.deleteObserver(observer);
}
}
@@ -0,0 +1,310 @@
package mars.mips.hardware
import mars.Globals
import mars.assembler.SymbolTable
import mars.mips.instructions.Instruction
import mars.util.Binary
import java.util.*
/*
Copyright (c) 2003-2008, Pete Sanderson and Kenneth Vollmar
Developed by Pete Sanderson (psanderson@otterbein.edu)
and Kenneth Vollmar (kenvollmar@missouristate.edu)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject
to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(MIT license, http://www.opensource.org/licenses/mit-license.html)
*/
/**
* Represents the collection of MIPS registers.
*
* @author Jason Bumgarner, Jason Shrewsbury
* @version June 2003
*/
object RegisterFile
{
const val GLOBAL_POINTER_REGISTER = 28
const val STACK_POINTER_REGISTER = 29
/**
* For returning the set of registers.
*
* @return The set of registers.
*/
@JvmStatic
val registers = arrayOf(
Register("\$zero", 0, 0), Register("\$at", 1, 0),
Register("\$v0", 2, 0), Register("\$v1", 3, 0),
Register("\$a0", 4, 0), Register("\$a1", 5, 0),
Register("\$a2", 6, 0), Register("\$a3", 7, 0),
Register("\$t0", 8, 0), Register("\$t1", 9, 0),
Register("\$t2", 10, 0), Register("\$t3", 11, 0),
Register("\$t4", 12, 0), Register("\$t5", 13, 0),
Register("\$t6", 14, 0), Register("\$t7", 15, 0),
Register("\$s0", 16, 0), Register("\$s1", 17, 0),
Register("\$s2", 18, 0), Register("\$s3", 19, 0),
Register("\$s4", 20, 0), Register("\$s5", 21, 0),
Register("\$s6", 22, 0), Register("\$s7", 23, 0),
Register("\$t8", 24, 0), Register("\$t9", 25, 0),
Register("\$k0", 26, 0), Register("\$k1", 27, 0),
Register("\$gp", GLOBAL_POINTER_REGISTER, Memory.globalPointer),
Register("\$sp", STACK_POINTER_REGISTER, Memory.stackPointer),
Register("\$fp", 30, 0), Register("\$ra", 31, 0), // Internal registers
Register("pc", 32, Memory.textBaseAddress),
Register("hi", 33, 0),
Register("lo", 34, 0)
)
val registerNameIndex = registers.associateBy { it.name }
@JvmStatic
val programCounterRegister = registers[32]
@JvmStatic
private val HI = registers[33]
@JvmStatic
private val LO = registers[34]
val backstep by lazy { Globals.getSettings().backSteppingEnabled }
/**
* Method for displaying the register values for debugging.
*/
@JvmStatic
fun showRegisters()
{
for (register in registers)
{
println("Name: " + register.name)
println("Number: " + register.number)
println("Value: " + register.value)
println()
}
}
/**
* This method updates the register value who's number is num. Also handles the lo and hi registers
*
* @param num Register to set the value of.
* @param value The desired value for the register.
*/
@JvmStatic
fun updateRegister(num: Int, value: Int): Int
{
val old = 0
if (num == 0)
{
println("You can not change the value of the zero register.")
}
else
{
registers[num].value = value
}
return old
}
/**
* Sets the value of the register given to the value given.
*
* @param reg Name of register to set the value of.
* @param value The desired value for the register.
*/
@JvmStatic
fun updateRegister(reg: String, value: Int)
{
registerNameIndex[reg]?.let {
updateRegister(it.number, value)
}
}
/**
* Returns the value of the register who's number is num.
*
* @param num The register number.
* @return The value of the given register.
*/
@JvmStatic
fun getValue(num: Int) = registers[num].value
/**
* For getting the number representation of the register.
*
* @param n The string formatted register name to look for.
* @return The number of the register represented by the string or -1 if no match.
*/
@JvmStatic
fun getNumber(n: String) = registerNameIndex[n]?.number ?: -1
/**
* Get register object corresponding to given name. If no match, return null.
*
* @param Rname The register name, either in $0 or $zero format.
* @return The register object,or null if not found.
*/
@JvmStatic
fun getUserRegister(Rname: String): Register?
{
var reg: Register? = null
if (Rname[0] == '$')
{
try
{
// check for register number 0-31.
reg = registers[Binary.stringToInt(Rname.substring(1))] // KENV 1/6/05
} catch (e: Exception)
{
// handles both NumberFormat and ArrayIndexOutOfBounds
// check for register mnemonic $zero thru $ra
reg = null // just to be sure
// just do linear search; there aren't that many registers
var i = 0
while (i < registers.size)
{
if (Rname == registers[i].name)
{
reg = registers[i]
break
}
i++
}
}
}
return reg
}
/**
* For initializing the Program Counter. Do not use this to implement jumps and branches, as it will NOT record a
* backstep entry with the restore value. If you need backstepping capability, use setProgramCounter instead.
*
* @param value The value to set the Program Counter to.
*/
@JvmStatic
fun initializeProgramCounter(value: Int)
{
programCounterRegister.value = value
}
/**
* Will initialize the Program Counter to either the default reset value, or the address associated with source
* program global label "main", if it exists as a text segment label and the global setting is set.
*
* @param startAtMain If true, will set program counter to address of statement labeled 'main' (or other defined
* start label) if defined. If not defined, or if parameter false, will set program counter to default reset
* value.
*/
fun initializeProgramCounter(startAtMain: Boolean)
{
val mainAddr = Globals.symbolTable.getAddress(SymbolTable.getStartLabel())
if (startAtMain && mainAddr != SymbolTable.NOT_FOUND && (Memory.inTextSegment(mainAddr) || Memory.inKernelTextSegment(
mainAddr
))
)
{
initializeProgramCounter(mainAddr)
} else
{
initializeProgramCounter(programCounterRegister.resetValue)
}
}
/**
* For setting the Program Counter. Note that ordinary PC update should be done using incrementPC() method. Use
* this only when processing jumps and branches.
*
* @param value The value to set the Program Counter to.
* @return previous PC value
*/
@JvmStatic
fun setProgramCounter(value: Int): Int
{
val old = programCounterRegister.value
programCounterRegister.value = value
if (Globals.getSettings().backSteppingEnabled)
{
Globals.program.backStepper.addPCRestore(old)
}
return old
}
/**
* For returning the program counters value.
*
* @return The program counters value as an int.
*/
@JvmStatic
val pc: Int
get() = programCounterRegister.value
/**
* For returning the program counter's initial (reset) value.
*
* @return The program counter's initial value
*/
val initialProgramCounter: Int
get() = programCounterRegister.resetValue
/**
* Method to reinitialize the values of the registers.
* **NOTE:** Should *not* be called from command-mode MARS because this
* this method uses global settings from the registry. Command-mode must operate using only the command switches,
* not registry settings. It can be called from tools running stand-alone, and this is done in
* `AbstractMarsToolAndApplication`.
*/
@JvmStatic
fun resetRegisters()
{
for (i in registers.indices)
{
registers[i].resetValue()
}
initializeProgramCounter(Globals.getSettings().startAtMain) // replaces "programCounter.resetValue()", DPS 3/3/09
HI.resetValue()
LO.resetValue()
}
/**
* Method to increment the Program counter in the general case (not a jump or branch).
*/
@JvmStatic
fun incrementPC()
{
programCounterRegister.value += Instruction.INSTRUCTION_LENGTH
}
/**
* Each individual register is a separate object and Observable. This handy method will add the given Observer to
* each one. Currently does not apply to Program Counter.
*/
@JvmStatic
fun addRegistersObserver(observer: Observer?)
{
registers.filter { it.number != 32 }.forEach { it.addObserver(observer) }
}
/**
* Each individual register is a separate object and Observable. This handy method will delete the given Observer
* from each one. Currently does not apply to Program Counter.
*/
@JvmStatic
fun deleteRegistersObserver(observer: Observer?)
{
registers.filter { it.number != 32 }.forEach { it.deleteObserver(observer) }
}
}
@@ -1239,7 +1239,7 @@ public class InstructionSet
{
int[] operands = statement.getOperands();
processJump(
((RegisterFile.getProgramCounter() & 0xF0000000)
((RegisterFile.getPc() & 0xF0000000)
| (operands[0] << 2)));
}
}));
@@ -1268,7 +1268,7 @@ public class InstructionSet
int[] operands = statement.getOperands();
processReturnAddress(31);// RegisterFile.updateRegister(31, RegisterFile.getProgramCounter());
processJump(
(RegisterFile.getProgramCounter() & 0xF0000000)
(RegisterFile.getPc() & 0xF0000000)
| (operands[0] << 2));
}
}));
@@ -3442,13 +3442,13 @@ public class InstructionSet
if (Globals.getSettings().getDelayedBranchingEnabled())
{
// Register the branch target address (absolute byte address).
DelayedBranch.register(RegisterFile.getProgramCounter() + (displacement << 2));
DelayedBranch.register(RegisterFile.getPc() + (displacement << 2));
}
else
{
// Decrement needed because PC has already been incremented
RegisterFile.setProgramCounter(
RegisterFile.getProgramCounter()
RegisterFile.getPc()
+ (displacement << 2)); // - Instruction.INSTRUCTION_LENGTH);
}
}
@@ -3489,7 +3489,7 @@ public class InstructionSet
private void processReturnAddress(int register)
{
RegisterFile.updateRegister(register, RegisterFile.getProgramCounter() +
RegisterFile.updateRegister(register, RegisterFile.getPc() +
((Globals.getSettings().getDelayedBranchingEnabled()) ?
Instruction.INSTRUCTION_LENGTH : 0));
}
@@ -222,7 +222,7 @@ public class BackStepper
private int pc()
{
// PC incremented prior to instruction simulation, so need to adjust for that.
return RegisterFile.getProgramCounter() - Instruction.INSTRUCTION_LENGTH;
return RegisterFile.getPc() - Instruction.INSTRUCTION_LENGTH;
}
/**
@@ -406,7 +406,7 @@ public class BackStepper
// Client does not have direct access to program statement, and rather than making all
// of them go through the methods below to obtain it, we will do it here.
// Want the program statement but do not want observers notified.
ps = Globals.memory.getStatementNoNotify(programCounter);
ps = Globals.memory.getStatement(programCounter);
}
catch (Exception e)
{
+1 -1
View File
@@ -88,7 +88,7 @@ public class Exceptions
// identify devices for External Interrupt (8=keyboard,9=display).
Coprocessor0.updateRegister(Coprocessor0.CAUSE, (Coprocessor0.getValue(Coprocessor0.CAUSE) & 0xFFFFFC83 | (cause << 2)));
// When exception occurred, PC had already been incremented so need to subtract 4 here.
Coprocessor0.updateRegister(Coprocessor0.EPC, RegisterFile.getProgramCounter() - Instruction.INSTRUCTION_LENGTH);
Coprocessor0.updateRegister(Coprocessor0.EPC, RegisterFile.getPc() - Instruction.INSTRUCTION_LENGTH);
// Set EXL (Exception Level) bit, bit position 1, in STATUS register to 1.
Coprocessor0.updateRegister(Coprocessor0.STATUS, Binary.setBit(Coprocessor0.getValue(Coprocessor0.STATUS), Coprocessor0.EXCEPTION_LEVEL));
}
+8 -8
View File
@@ -319,18 +319,18 @@ public class Simulator extends Observable
ProgramStatement statement = null;
try
{
statement = Globals.memory.getStatement(RegisterFile.getProgramCounter());
statement = Globals.memory.getStatement(RegisterFile.getPc());
}
catch (AddressErrorException e)
{
ErrorList el = new ErrorList();
el.add(new ErrorMessage((MIPSprogram) null, 0, 0, "invalid program counter value: " + Binary.intToHexString(RegisterFile.getProgramCounter())));
el.add(new ErrorMessage((MIPSprogram) null, 0, 0, "invalid program counter value: " + Binary.intToHexString(RegisterFile.getPc())));
this.pe = new ProcessingException(el, e);
// Next statement is a hack. Previous statement sets EPC register to ProgramCounter-4
// because it assumes the bad address comes from an operand so the ProgramCounter has already been
// incremented. In this case, bad address is the instruction fetch itself so Program Counter has
// not yet been incremented. We'll set the EPC directly here. DPS 8-July-2013
Coprocessor0.updateRegister(Coprocessor0.EPC, RegisterFile.getProgramCounter());
Coprocessor0.updateRegister(Coprocessor0.EPC, RegisterFile.getPc());
this.constructReturnReason = EXCEPTION;
this.done = true;
SystemIO.resetFiles(); // close any files opened in MIPS program
@@ -373,7 +373,7 @@ public class Simulator extends Observable
while (statement != null)
{
pc = RegisterFile.getProgramCounter(); // added: 7/26/06 (explanation above)
pc = RegisterFile.getPc(); // added: 7/26/06 (explanation above)
RegisterFile.incrementPC();
// Perform the MIPS instruction in synchronized block. If external threads agree
// to access MIPS memory and registers only through synchronized blocks on same
@@ -469,7 +469,7 @@ public class Simulator extends Observable
}
// Return if we've reached a breakpoint.
if ((breakPoints != null) &&
(Arrays.binarySearch(breakPoints, RegisterFile.getProgramCounter()) >= 0))
(Arrays.binarySearch(breakPoints, RegisterFile.getPc()) >= 0))
{
this.constructReturnReason = BREAKPOINT;
this.done = false;
@@ -518,18 +518,18 @@ public class Simulator extends Observable
try
{
statement = Globals.memory.getStatement(RegisterFile.getProgramCounter());
statement = Globals.memory.getStatement(RegisterFile.getPc());
}
catch (AddressErrorException e)
{
ErrorList el = new ErrorList();
el.add(new ErrorMessage((MIPSprogram) null, 0, 0, "invalid program counter value: " + Binary.intToHexString(RegisterFile.getProgramCounter())));
el.add(new ErrorMessage((MIPSprogram) null, 0, 0, "invalid program counter value: " + Binary.intToHexString(RegisterFile.getPc())));
this.pe = new ProcessingException(el, e);
// Next statement is a hack. Previous statement sets EPC register to ProgramCounter-4
// because it assumes the bad address comes from an operand so the ProgramCounter has already been
// incremented. In this case, bad address is the instruction fetch itself so Program Counter has
// not yet been incremented. We'll set the EPC directly here. DPS 8-July-2013
Coprocessor0.updateRegister(Coprocessor0.EPC, RegisterFile.getProgramCounter());
Coprocessor0.updateRegister(Coprocessor0.EPC, RegisterFile.getPc());
this.constructReturnReason = EXCEPTION;
this.done = true;
SystemIO.resetFiles(); // close any files opened in MIPS program
+1 -1
View File
@@ -365,7 +365,7 @@ public class BHTSimulator extends AbstractMarsToolAndApplication implements Acti
try
{
// access the statement in the text segment without notifying other tools etc.
ProgramStatement stmt = Memory.getInstance().getStatementNoNotify(memAccNotice.getAddress());
ProgramStatement stmt = Memory.getInstance().getStatement(memAccNotice.getAddress());
// necessary to handle possible null pointers at the end of the program
// (e.g., if the simulator tries to execute the next instruction after the last instruction in the text segment)
+31 -47
View File
@@ -13,7 +13,6 @@ import java.util.*
import javax.swing.*
import javax.swing.border.EmptyBorder
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.collections.HashSet
/*
@@ -51,10 +50,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class BitmapDisplay : AbstractMarsToolAndApplication
{
// Major GUI components
private lateinit var uiUnitWidthSelector: JComboBox<Int>
private lateinit var uiUnitHeightSelector: JComboBox<Int>
private lateinit var uiWidthSelector: JComboBox<Int>
private lateinit var uiHeightSelector: JComboBox<Int>
private lateinit var uiBaseAddressSelector: JComboBox<String>
private lateinit var uiKeyboardCheckbox: JCheckBox
private lateinit var canvas: JPanel
@@ -65,10 +60,10 @@ class BitmapDisplay : AbstractMarsToolAndApplication
private val backgroundColor = Color.WHITE
// Values for display canvas. Note their initialization uses the identifiers just above.
private val unitWidth get() = uiUnitWidthSelector.getInt()
private val unitHeight get() = uiUnitHeightSelector.getInt()
private val displayWidth get() = uiWidthSelector.getInt()
private val displayHeight get() = uiHeightSelector.getInt()
private var unitWidth: Int = 2
private var unitHeight: Int = 2
private var displayWidth: Int = 512
private var displayHeight: Int = 256
private val displayDimension get() = Dimension(displayWidth, displayHeight)
private val baseAddresses = intArrayOf(Memory.dataSegmentBaseAddress, Memory.globalPointer, Memory.dataBaseAddress,
@@ -78,6 +73,7 @@ class BitmapDisplay : AbstractMarsToolAndApplication
// Keyboard++
private var keyboardAddr: UInt = 0xFFFF0010u
private var displayUpdateAddr: UInt = 0xFFFF0008u
private var keyboardAttached = false
private lateinit var uiKeyboard: JTextField
@@ -180,7 +176,17 @@ class BitmapDisplay : AbstractMarsToolAndApplication
}
// For the display
updateColorForAddress(ac)
val value = ac.value
val offset = ((addr - baseAddress.toUInt()) / 4u).toInt()
try
{
grid.setElement(offset / grid.cols, offset % grid.cols, value)
}
catch (e: IndexOutOfBoundsException)
{
// If address is out of range for display, do nothing.
}
if (offset == 0) canvas.repaint()
}
/**
@@ -239,17 +245,10 @@ class BitmapDisplay : AbstractMarsToolAndApplication
*/
override fun reset()
{
resetCounts()
updateDisplay()
grid.reset()
canvas.repaint()
}
/**
* Updates display immediately after each update (AccessNotice) is processed, after display configuration changes as
* needed, and after each execution step when Mars is running in timed mode. Overrides inherited method that does
* nothing.
*/
override fun updateDisplay() = canvas.repaint()
/**
* Overrides default method, to provide a Help button for this tool/app.
*/
@@ -291,51 +290,55 @@ class BitmapDisplay : AbstractMarsToolAndApplication
// UI components and layout for left half of GUI, where settings are specified.
private fun buildOrganizationArea(): JComponent
{
uiUnitWidthSelector = JComboBox(arrayOf(1, 2, 4, 8, 16, 32)).apply {
val uiUnitWidthSelector = JComboBox(arrayOf(1, 2, 4, 8, 16, 32)).apply {
isEditable = false
background = backgroundColor
selectedIndex = 1
toolTipText = "Width in pixels of rectangle representing memory word"
addActionListener {
unitWidth = getInt()
grid = createNewGrid()
updateDisplay()
reset()
}
}
uiUnitHeightSelector = JComboBox(arrayOf(1, 2, 4, 8, 16, 32)).apply {
val uiUnitHeightSelector = JComboBox(arrayOf(1, 2, 4, 8, 16, 32)).apply {
isEditable = false
background = backgroundColor
selectedIndex = 1
toolTipText = "Height in pixels of rectangle representing memory word"
addActionListener {
unitHeight = getInt()
grid = createNewGrid()
updateDisplay()
reset()
}
}
uiWidthSelector = JComboBox(arrayOf(64, 128, 256, 512, 1024)).apply {
val uiWidthSelector = JComboBox(arrayOf(64, 128, 256, 512, 1024)).apply {
isEditable = false
background = backgroundColor
selectedIndex = 3
toolTipText = "Total width in pixels of display area"
addActionListener {
displayWidth = getInt()
canvas.preferredSize = displayDimension
canvas.size = displayDimension
grid = createNewGrid()
updateDisplay()
reset()
}
}
uiHeightSelector = JComboBox(arrayOf(64, 128, 256, 512, 1024)).apply {
val uiHeightSelector = JComboBox(arrayOf(64, 128, 256, 512, 1024)).apply {
isEditable = false
background = backgroundColor
selectedIndex = 2
toolTipText = "Total height in pixels of display area"
addActionListener {
displayHeight = getInt()
canvas.preferredSize = displayDimension
canvas.size = displayDimension
grid = createNewGrid()
updateDisplay()
reset()
}
}
@@ -358,7 +361,7 @@ class BitmapDisplay : AbstractMarsToolAndApplication
addAsObserver()
}
grid = createNewGrid()
updateDisplay()
reset()
}
}
@@ -467,9 +470,6 @@ class BitmapDisplay : AbstractMarsToolAndApplication
return canvas
}
// reset all counters in the Grid.
private fun resetCounts() = grid.reset()
private fun <T> JComboBox<T>.getInt() = selectedItem!!.toString().toInt()
// Use this for consistent results.
@@ -484,22 +484,6 @@ class BitmapDisplay : AbstractMarsToolAndApplication
return Grid(rows, columns)
}
// Given memory address, update color for the corresponding grid element.
private fun updateColorForAddress(notice: MemoryAccessNotice)
{
val address = notice.address
val value = notice.value
val offset = (address - baseAddress) / Memory.WORD_LENGTH_BYTES
try
{
grid.setElement(offset / grid.cols, offset % grid.cols, value)
}
catch (e: IndexOutOfBoundsException)
{
// If address is out of range for display, do nothing.
}
}
//////////////////////////////////////////////////////////////////////////////////////
// Specialized inner classes for modeling and animation.
//////////////////////////////////////////////////////////////////////////////////////
@@ -318,7 +318,7 @@ public class InstructionStatistics extends AbstractMarsToolAndApplication
{
// access the statement in the text segment without notifying other tools etc.
ProgramStatement stmt = Memory.getInstance().getStatementNoNotify(memAccNotice.getAddress());
ProgramStatement stmt = Memory.getInstance().getStatement(memAccNotice.getAddress());
// necessary to handle possible null pointers at the end of the program
// (e.g., if the simulator tries to execute the next instruction after the last instruction in the text segment)
-6
View File
@@ -9,7 +9,6 @@ import mars.mips.hardware.MemoryAccessNotice;
import mars.mips.instructions.BasicInstruction;
import mars.mips.instructions.BasicInstructionFormat;
import mars.venus.RunAssembleAction;
import mars.venus.RunBackstepAction;
import mars.venus.RunStepAction;
import mars.venus.VenusUI;
import org.w3c.dom.Document;
@@ -313,11 +312,6 @@ public class MipsXray extends AbstractMarsToolAndApplication
"Run one step at a time", Integer.valueOf(KeyEvent.VK_T),
KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0),
mainUI);
runBackstepAction = new RunBackstepAction("Backstep",
new ImageIcon(tk.getImage(cs.getResource(Globals.imagesPath + "StepBack22.png"))),
"Undo the last step", Integer.valueOf(KeyEvent.VK_B),
KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0),
mainUI);
}
catch (Exception e)
{
@@ -117,7 +117,7 @@ public class RegistersWindow extends JPanel implements Observer
}
tableData[32][0] = "pc";
tableData[32][1] = "";//new Integer(32);
tableData[32][2] = NumberDisplayBaseChooser.formatUnsignedInteger(RegisterFile.getProgramCounter(), valueBase);
tableData[32][2] = NumberDisplayBaseChooser.formatUnsignedInteger(RegisterFile.getPc(), valueBase);
tableData[33][0] = "hi";
tableData[33][1] = "";//new Integer(33);
@@ -184,7 +184,7 @@ public class RegistersWindow extends JPanel implements Observer
{
updateRegisterValue(registers[i].getNumber(), registers[i].getValue(), base);
}
updateRegisterUnsignedValue(32, RegisterFile.getProgramCounter(), base);
updateRegisterUnsignedValue(32, RegisterFile.getPc(), base);
updateRegisterValue(33, RegisterFile.getValue(33), base);
updateRegisterValue(34, RegisterFile.getValue(34), base);
}
@@ -227,6 +227,7 @@ public class RegistersWindow extends JPanel implements Observer
// or stepped mode.
if (notice.getRunSpeed() != RunSpeedPanel.UNLIMITED_SPEED || notice.getMaxSteps() == 1)
{
System.out.println("Running in timed mode");
RegisterFile.addRegistersObserver(this);
this.highlighting = true;
}
@@ -75,12 +75,12 @@ public class RunBackstepAction extends GuiAction
{
boolean inDelaySlot = Globals.program.getBackStepper().inDelaySlot(); // Added 25 June 2007
Memory.getInstance().addObserver(executePane.getDataSegmentWindow());
RegisterFile.addRegistersObserver(executePane.getRegistersWindow());
//RegisterFile.addRegistersObserver(executePane.getRegistersWindow());
Coprocessor0.addRegistersObserver(executePane.getCoprocessor0Window());
Coprocessor1.addRegistersObserver(executePane.getCoprocessor1Window());
Globals.program.getBackStepper().backStep();
Memory.getInstance().deleteObserver(executePane.getDataSegmentWindow());
RegisterFile.deleteRegistersObserver(executePane.getRegistersWindow());
//RegisterFile.deleteRegistersObserver(executePane.getRegistersWindow());
executePane.getRegistersWindow().updateRegisters();
executePane.getCoprocessor1Window().updateRegisters();
executePane.getCoprocessor0Window().updateRegisters();
+1 -1
View File
@@ -170,7 +170,7 @@ public class RunGoAction extends GuiAction
mainUI.getRegistersPane().setSelectedComponent(executePane.getCoprocessor0Window());
executePane.getTextSegmentWindow().setCodeHighlighting(true);
executePane.getTextSegmentWindow().unhighlightAllSteps();
executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4);
executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getPc() - 4);
}
switch (reason)
{
+1 -1
View File
@@ -126,7 +126,7 @@ public class RunStepAction extends GuiAction
FileStatus.set(FileStatus.TERMINATED); // should be redundant.
executePane.getTextSegmentWindow().setCodeHighlighting(true);
executePane.getTextSegmentWindow().unhighlightAllSteps();
executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getProgramCounter() - 4);
executePane.getTextSegmentWindow().highlightStepAtAddress(RegisterFile.getPc() - 4);
}
VenusUI.setReset(false);
}
@@ -577,7 +577,7 @@ public class TextSegmentWindow extends JInternalFrame implements Observer
*/
public void highlightStepAtPC()
{
highlightStepAtAddress(RegisterFile.getProgramCounter(), false);
highlightStepAtAddress(RegisterFile.getPc(), false);
}
/**
@@ -589,7 +589,7 @@ public class TextSegmentWindow extends JInternalFrame implements Observer
*/
public void highlightStepAtPC(boolean inDelaySlot)
{
highlightStepAtAddress(RegisterFile.getProgramCounter(), inDelaySlot);
highlightStepAtAddress(RegisterFile.getPc(), inDelaySlot);
}
/**
+14
View File
@@ -0,0 +1,14 @@
import mars.Globals
import mars.mips.hardware.MemoryConfigurations
import kotlin.system.measureTimeMillis
fun main(args: Array<String>)
{
Globals.initialize(true)
MemoryConfigurations.setCurrentConfiguration(MemoryConfigurations.getDefaultConfiguration())
println(measureTimeMillis {
for (n in 0..100)
for (i in 0..128*256)
Globals.memory.getWord(0x10008000 + i * 4)
})
}