Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/rars/Globals.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
import rars.riscv.hardware.Memory;
import rars.riscv.InstructionSet;
import rars.riscv.SyscallNumberOverride;
import rars.riscv.hardware.MemoryConfiguration;
import rars.riscv.hardware.MemoryConfigurations;
import rars.util.PropertiesFile;
import rars.venus.VenusUI;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
Expand Down Expand Up @@ -173,6 +176,12 @@ public static void initialize(boolean gui) {
settings = new Settings(gui);
initialized = true;
debug = false;
String tmp = settings.getMemoryCustomConfiguration();
if(!tmp.equals("")){
MemoryConfiguration mc = MemoryConfigurations.loadNewConfig(new ByteArrayInputStream(tmp.getBytes()));
if (mc != null) MemoryConfigurations.addNewConfig(mc);
}
MemoryConfigurations.setCurrentConfiguration(MemoryConfigurations.getConfigurationByName(settings.getMemoryConfiguration()));
memory.clear(); // will establish memory configuration from setting
}
}
Expand Down
41 changes: 21 additions & 20 deletions src/rars/Launch.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,16 @@
import rars.riscv.dump.DumpFormat;
import rars.riscv.dump.DumpFormatLoader;
import rars.riscv.hardware.*;
import rars.simulator.ProgramArgumentList;
import rars.simulator.Simulator;
import rars.util.Binary;
import rars.util.FilenameFinder;
import rars.util.MemoryDump;
import rars.venus.VenusUI;
import rars.api.Options;

import javax.swing.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

/*
Copyright (c) 2003-2012, Pete Sanderson and Kenneth Vollmar
Expand Down Expand Up @@ -175,14 +168,12 @@ private void dumpSegments(Program program) {

for (String[] triple : dumpTriples) {
File file = new File(triple[2]);
Integer[] segInfo = MemoryDump.getSegmentBounds(triple[0]);
Range segInfo = Memory.configuration.sections.get(triple[0]);
// If not segment name, see if it is address range instead. DPS 14-July-2008
if (segInfo == null) {
try {
String[] memoryRange = checkMemoryAddressRange(triple[0]);
segInfo = new Integer[2];
segInfo[0] = Binary.stringToInt(memoryRange[0]); // low end of range
segInfo[1] = Binary.stringToInt(memoryRange[1]); // high end of range
segInfo = new Range(Binary.stringToInt(memoryRange[0]),Binary.stringToInt(memoryRange[1]));
} catch (NumberFormatException nfe) {
segInfo = null;
} catch (NullPointerException npe) {
Expand All @@ -199,12 +190,12 @@ private void dumpSegments(Program program) {
continue;
}
try {
int highAddress = program.getMemory().getAddressOfFirstNull(segInfo[0], segInfo[1]) - Memory.WORD_LENGTH_BYTES;
if (highAddress < segInfo[0]) {
int highAddress = program.getMemory().getAddressOfFirstNull(segInfo.low, segInfo.high) - Memory.WORD_LENGTH_BYTES;
if (highAddress < segInfo.low) {
out.println("This segment has not been written to, there is nothing to dump.");
continue;
}
format.dumpMemoryRange(file, segInfo[0], highAddress, program.getMemory());
format.dumpMemoryRange(file, segInfo.low, highAddress, program.getMemory());
} catch (FileNotFoundException e) {
out.println("Error while attempting to save dump, file " + file + " was not found!");
} catch (AddressErrorException e) {
Expand Down Expand Up @@ -297,8 +288,17 @@ private boolean parseCommandArgs(String[] args) {
String configName = args[++i];
MemoryConfiguration config = MemoryConfigurations.getConfigurationByName(configName);
if (config == null) {
out.println("Invalid memory configuration: " + configName);
argsOK = false;
String error = "";
try {
config = MemoryConfigurations.loadNewConfig(new FileInputStream(new File(configName)));
if (config == null) error = " does not define a well specified config";
}catch(FileNotFoundException fe) {
error = " is not the name of a known config or a valid file path";
}
if(config == null) {
out.println("Invalid memory configuration: " + configName + error) ;
argsOK = false;
}
} else {
MemoryConfigurations.setCurrentConfiguration(config);
}
Expand Down Expand Up @@ -672,7 +672,7 @@ private void displayCopyright(String[] args, String noCopyrightSwitch) {
// Display command line help text

private void displayHelp() {
String[] segmentNames = MemoryDump.getSegmentNames();
String[] segmentNames = new String[]{".text",".data"};
String segments = "";
for (int i = 0; i < segmentNames.length; i++) {
segments += segmentNames[i];
Expand Down Expand Up @@ -708,8 +708,9 @@ private void displayHelp() {
out.println(" mc <config> -- set memory configuration. Argument <config> is");
out.println(" case-sensitive and possible values are: Default for the default");
out.println(" 32-bit address space, CompactDataAtZero for a 32KB memory with");
out.println(" data segment at address 0, or CompactTextAtZero for a 32KB");
out.println(" memory with text segment at address 0.");
out.println(" data segment at address 0, CompactTextAtZero for a 32KB");
out.println(" memory with text segment at address 0, the name of a custom");
out.println(" configuration, or a path to a config file.");
out.println(" me -- display RARS messages to standard err instead of standard out. ");
out.println(" Can separate messages from program output using redirection");
out.println(" nc -- do not display copyright notice (for cleaner redirected/piped output).");
Expand Down
26 changes: 24 additions & 2 deletions src/rars/Settings.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package rars;

import rars.riscv.hardware.MemoryConfiguration;
import rars.riscv.hardware.MemoryConfigurations;
import rars.util.Binary;
import rars.util.EditorFont;
import rars.venus.editors.jeditsyntax.SyntaxStyle;
Expand Down Expand Up @@ -199,16 +201,22 @@ String getName() {
* Number of letters to be matched by editor's instruction guide before popup generated (if popup enabled)
*/
public static final int EDITOR_POPUP_PREFIX_LENGTH = 6;

/**
* String representing a custom memory config property file
*/
public static final int CUSTOM_MEMORY_CONFIG = 7;

// Match the above by position.
private static final String[] stringSettingsKeys = {"ExceptionHandler", "TextColumnOrder", "LabelSortState", "MemoryConfiguration", "CaretBlinkRate", "EditorTabSize", "EditorPopupPrefixLength"};
private static final String[] stringSettingsKeys = {"ExceptionHandler", "TextColumnOrder", "LabelSortState", "MemoryConfiguration", "CaretBlinkRate", "EditorTabSize", "EditorPopupPrefixLength", "CustomMemoryConfig"};

/**
* Last resort default values for String settings;
* will use only if neither the Preferences nor the properties file work.
* If you wish to change, do so before instantiating the Settings object.
* Must match key by list position.
*/
private static String[] defaultStringSettingsValues = {"", "0 1 2 3 4", "0", "", "500", "8", "2"};
private static String[] defaultStringSettingsValues = {"", "0 1 2 3 4", "0", "", "500", "8", "2",""};


// FONT SETTINGS. Each array position has associated name.
Expand Down Expand Up @@ -551,6 +559,16 @@ public String getMemoryConfiguration() {
return stringSettingsValues[MEMORY_CONFIGURATION];
}

/**
* Returns a properties file contents representing a custom memory configuration
*
* @return a memory configuration, empty if none.
*/
public String getMemoryCustomConfiguration() {
return stringSettingsValues[CUSTOM_MEMORY_CONFIG];
}


/**
* Current editor font. Retained for compatibility but replaced
* by: getFontByPosition(Settings.EDITOR_FONT)
Expand Down Expand Up @@ -773,6 +791,10 @@ public void setExceptionHandler(String newFilename) {

public void setMemoryConfiguration(String config) {
setStringSetting(MEMORY_CONFIGURATION, config);
MemoryConfiguration tmp = MemoryConfigurations.getConfigurationByName(config);
if (tmp != null && !tmp.builtin) {
setStringSetting(CUSTOM_MEMORY_CONFIG, tmp.toPropertiesString());
}
}

/**
Expand Down
105 changes: 53 additions & 52 deletions src/rars/assembler/Assembler.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,20 @@ public class Assembler {
private AddressSpace dataAddress;
private DataSegmentForwardReferences currentFileDataSegmentForwardReferences,
accumulatedDataSegmentForwardReferences;

private ArrayList<DataStruct> datalist;
class DataStruct {
int address, data, size;
ErrorMessage iffails;
DataStruct(int address, int data, int size, ErrorMessage iffails){
this.address = address;
this.data = data;
this.size = size;
this.iffails = iffails;
}
}
private void setData(int address, int data, int size, ErrorMessage iffails){
datalist.add(new DataStruct(address,data,size,iffails));
}
/**
* Get list of assembler errors and warnings
*
Expand Down Expand Up @@ -99,14 +112,15 @@ public ArrayList<ProgramStatement> assemble(ArrayList<RISCVprogram> tokenizedPro

if (tokenizedProgramFiles == null || tokenizedProgramFiles.size() == 0)
return null;
textAddress = new AddressSpace(Memory.textBaseAddress);
dataAddress = new AddressSpace(Memory.dataBaseAddress);
externAddress = Memory.externBaseAddress;
textAddress = new AddressSpace(Memory.configuration.getTextBaseAddress());
dataAddress = new AddressSpace(Memory.configuration.getDataBaseAddress());
externAddress = Memory.configuration.getExternBaseAddress();
currentFileDataSegmentForwardReferences = new DataSegmentForwardReferences();
accumulatedDataSegmentForwardReferences = new DataSegmentForwardReferences();
Globals.symbolTable.clear();
Globals.memory.clear();
ArrayList<ProgramStatement> machineList = new ArrayList<>();
datalist = new ArrayList<>();
this.errors = new ErrorList();
if (Globals.debug)
System.out.println("Assembler first pass begins:");
Expand Down Expand Up @@ -288,9 +302,18 @@ public ArrayList<ProgramStatement> assemble(ArrayList<RISCVprogram> tokenizedPro
} catch (AddressErrorException e) {
Token t = statement.getOriginalTokenList().get(0);
errors.add(new ErrorMessage(t.getSourceProgram(), t.getSourceLine(), t
.getStartPos(), "Invalid address for text segment: " + e.getAddress()));
.getStartPos(), "Invalid address for text segment: " + statement.getAddress()));
}
}

for (DataStruct ds : datalist) {
try {
Globals.memory.set(ds.address, ds.data, ds.size);
} catch (AddressErrorException e) {
if(ds.iffails != null) errors.add(ds.iffails);
}
}

// Aug. 24, 2005 Ken Vollmar
// Ensure that I/O "file descriptors" are initialized for a new program run
SystemIO.resetFiles();
Expand Down Expand Up @@ -952,15 +975,10 @@ private void storeInteger(Token token, Directives directive, ErrorList errors) {
* instruction)
*/
else {
try {
Globals.memory.set(this.textAddress.get(), value, lengthInBytes);
} catch (AddressErrorException e) {
errors.add(new ErrorMessage(token.getSourceProgram(),
token.getSourceLine(), token.getStartPos(), "\""
+ this.textAddress.get()
+ "\" is not a valid text segment address"));
return;
}
setData(this.textAddress.get(),value,lengthInBytes,new ErrorMessage(token.getSourceProgram(),
token.getSourceLine(), token.getStartPos(), "\""
+ this.textAddress.get()
+ "\" is not a valid text segment address"));
this.textAddress.increment(lengthInBytes);
}
} // end of "if integer token type"
Expand Down Expand Up @@ -1112,27 +1130,19 @@ private void storeStrings(TokenList tokens, Directives direct, ErrorList errors)
}
}
byte[] bytesOfChar = String.valueOf(theChar).getBytes(StandardCharsets.UTF_8);
try {
for (byte b : bytesOfChar) {
Globals.memory.set(this.dataAddress.get(), b,
DataTypes.CHAR_SIZE);
this.dataAddress.increment(DataTypes.CHAR_SIZE);
}
} catch (AddressErrorException e) {
errors.add(new ErrorMessage(token.getSourceProgram(), token
.getSourceLine(), token.getStartPos(), "\""
+ this.dataAddress.get() + "\" is not a valid data segment address"));
ErrorMessage e = new ErrorMessage(token.getSourceProgram(), token
.getSourceLine(), token.getStartPos(), "\""
+ this.dataAddress.get() + "\" is not a valid data segment address");
for (byte b : bytesOfChar) {
setData(this.dataAddress.get(),b,DataTypes.CHAR_SIZE, e);
this.dataAddress.increment(DataTypes.CHAR_SIZE);
}

}
if (direct == Directives.ASCIZ || direct == Directives.STRING) {
try {
Globals.memory.set(this.dataAddress.get(), 0, DataTypes.CHAR_SIZE);
} catch (AddressErrorException e) {
errors.add(new ErrorMessage(token.getSourceProgram(), token
.getSourceLine(), token.getStartPos(), "\""
+ this.dataAddress.get() + "\" is not a valid data segment address"));
}
ErrorMessage e = new ErrorMessage(token.getSourceProgram(), token
.getSourceLine(), token.getStartPos(), "\""
+ this.dataAddress.get() + "\" is not a valid data segment address");
setData(this.dataAddress.get(),0,DataTypes.CHAR_SIZE, e);
this.dataAddress.increment(DataTypes.CHAR_SIZE);
}
}
Expand Down Expand Up @@ -1160,14 +1170,10 @@ private int writeToDataSegment(int value, int lengthInBytes, Token token, ErrorL
if (this.autoAlign) {
this.dataAddress.set(this.alignToBoundary(this.dataAddress.get(), lengthInBytes));
}
try {
Globals.memory.set(this.dataAddress.get(), value, lengthInBytes);
} catch (AddressErrorException e) {
errors.add(new ErrorMessage(token.getSourceProgram(), token.getSourceLine(), token
.getStartPos(), "\"" + this.dataAddress.get()
+ "\" is not a valid data segment address"));
return this.dataAddress.get();
}
ErrorMessage e = new ErrorMessage(token.getSourceProgram(), token
.getSourceLine(), token.getStartPos(), "\""
+ this.dataAddress.get() + "\" is not a valid data segment address");
setData(this.dataAddress.get(),value,lengthInBytes, e);
int address = this.dataAddress.get();
this.dataAddress.increment(lengthInBytes);
return address;
Expand All @@ -1183,14 +1189,12 @@ private void writeDoubleToDataSegment(double value, Token token, ErrorList error
if (this.autoAlign) {
this.dataAddress.set(this.alignToBoundary(this.dataAddress.get(), lengthInBytes));
}
try {
Globals.memory.setDouble(this.dataAddress.get(), value);
} catch (AddressErrorException e) {
errors.add(new ErrorMessage(token.getSourceProgram(), token.getSourceLine(), token
.getStartPos(), "\"" + this.dataAddress.get()
+ "\" is not a valid data segment address"));
return;
}
ErrorMessage e = new ErrorMessage(token.getSourceProgram(), token.getSourceLine(), token
.getStartPos(), "\"" + this.dataAddress.get()
+ "\" is not a valid data segment address");
long longValue = Double.doubleToLongBits(value);
setData(this.dataAddress.get(),(int)longValue, DataTypes.WORD_SIZE,e);
setData(this.dataAddress.get()+DataTypes.WORD_SIZE,(int)(longValue>>32), DataTypes.WORD_SIZE,e);
this.dataAddress.increment(lengthInBytes);
}

Expand Down Expand Up @@ -1295,10 +1299,7 @@ private void resolve(SymbolTable localSymtab) {
labelAddress = localSymtab.getAddressLocalOrGlobal(entry.token.getValue());
if (labelAddress != SymbolTable.NOT_FOUND) {
// patch address has to be valid b/c we already stored there...
try {
Globals.memory.set(entry.patchAddress, labelAddress, entry.length);
} catch (AddressErrorException aee) {
}
setData(entry.patchAddress,labelAddress,entry.length, null);
forwardReferenceList.remove(i);
i--; // needed because removal shifted the remaining list indices down
}
Expand Down
4 changes: 2 additions & 2 deletions src/rars/extras/Documentation.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import rars.Globals;
import rars.assembler.Directives;
import rars.riscv.*;
import rars.riscv.hardware.Memory;

import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -17,8 +18,7 @@
public class Documentation {

public static void main(String[] args){
Globals.instructionSet = new InstructionSet();
Globals.instructionSet.populate();
Globals.initialize(false);
System.out.println(createDirectiveMarkdown());
System.out.println(createSyscallMarkdown());
System.out.println(createInstructionMarkdown(BasicInstruction.class));
Expand Down
Loading