0da1c5dcca
First commit of the 4.5 version (latest version available)
262 lines
9.2 KiB
Java
262 lines
9.2 KiB
Java
package mars.assembler;
|
|
import mars.*;
|
|
import java.util.*;
|
|
|
|
/*
|
|
Copyright (c) 2003-2006, 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)
|
|
*/
|
|
|
|
/**
|
|
* Creats a table of Symbol objects.
|
|
* @author Jason Bumgarner, Jason Shrewsbury
|
|
* @version June 2003
|
|
**/
|
|
|
|
public class SymbolTable {
|
|
private static String startLabel = "main";
|
|
private String filename;
|
|
private ArrayList table;
|
|
// Note -1 is legal 32 bit address (0xFFFFFFFF) but it is the high address in
|
|
// kernel address space so highly unlikely that any symbol will have this as
|
|
// its associated address!
|
|
public static final int NOT_FOUND = -1;
|
|
|
|
/**
|
|
* Create a new empty symbol table for given file
|
|
* @param filename name of file this symbol table is associated with. Will be
|
|
* used only for output/display so it can be any descriptive string.
|
|
*/
|
|
public SymbolTable(String filename) {
|
|
this.filename = filename;
|
|
this.table = new ArrayList();
|
|
}
|
|
/**
|
|
* Adds a Symbol object into the array of Symbols.
|
|
* @param token The token representing the Symbol.
|
|
* @param address The address of the Symbol.
|
|
* @param b The type of Symbol, true for data, false for text.
|
|
* @param errors List to which to add any processing errors that occur.
|
|
**/
|
|
|
|
public void addSymbol(Token token, int address, boolean b, ErrorList errors) {
|
|
String label = token.getValue();
|
|
if (getSymbol(label) != null) {
|
|
errors.add(new ErrorMessage(token.getSourceMIPSprogram(), token.getSourceLine(),token.getStartPos(),"label \""+label+"\" already defined"));
|
|
}
|
|
else {
|
|
Symbol s= new Symbol(label, address, b);
|
|
table.add(s);
|
|
if (Globals.debug) System.out.println("The symbol " + label + " with address " + address + " has been added to the "+this.filename+" symbol table.");
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Removes a symbol from the Symbol table. If not found, it does nothing.
|
|
* This will rarely happen (only when variable is declared .globl after already
|
|
* being defined in the local symbol table).
|
|
* @param token The token representing the Symbol.
|
|
**/
|
|
|
|
public void removeSymbol(Token token) {
|
|
String label = token.getValue();
|
|
for (int i=0; i < table.size(); i++) {
|
|
if (((Symbol)(table.get(i))).getName().equals(label)){
|
|
table.remove(i);
|
|
if (Globals.debug) System.out.println("The symbol " + label + " has been removed from the "+this.filename+" symbol table.");
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/**
|
|
* Method to return the address associated with the given label.
|
|
* @param s The label.
|
|
* @return The memory address of the label given, or NOT_FOUND if not found in symbol table.
|
|
**/
|
|
public int getAddress(String s){
|
|
for(int i=0; i < table.size(); i++){
|
|
if (((Symbol)(table.get(i))).getName().equals(s)){
|
|
return((Symbol) table.get(i)).getAddress();
|
|
}
|
|
}
|
|
return NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
* Method to return the address associated with the given label. Look first
|
|
* in this (local) symbol table then in symbol table of labels declared
|
|
* global (.globl directive).
|
|
* @param s The label.
|
|
* @return The memory address of the label given, or NOT_FOUND if not found in symbol table.
|
|
**/
|
|
public int getAddressLocalOrGlobal(String s) {
|
|
int address = this.getAddress(s);
|
|
return (address==NOT_FOUND) ? Globals.symbolTable.getAddress(s) : address ;
|
|
}
|
|
|
|
|
|
/**
|
|
* Produce Symbol object from symbol table that corresponds to given String.
|
|
* @param s target String
|
|
* @return Symbol object for requested target, null if not found in symbol table.
|
|
**/
|
|
|
|
public Symbol getSymbol(String s){
|
|
for(int i=0; i < table.size(); i++){
|
|
if (((Symbol)(table.get(i))).getName().equals(s)){
|
|
return (Symbol) table.get(i);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Produce Symbol object from symbol table that has the given address.
|
|
* @param s String representing address
|
|
* @return Symbol object having requested address, null if address not found in symbol table.
|
|
**/
|
|
|
|
public Symbol getSymbolGivenAddress(String s){
|
|
int address = 0;
|
|
try {
|
|
address = mars.util.Binary.stringToInt(s);// DPS 2-Aug-2010: was Integer.parseInt(s) but croaked on hex
|
|
}
|
|
catch (NumberFormatException e) {
|
|
return null;
|
|
}
|
|
for(int i=0; i < table.size(); i++){
|
|
if (((Symbol)(table.get(i))).getAddress() == address){
|
|
return (Symbol) table.get(i);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Produce Symbol object from either local or global symbol table that has the
|
|
* given address.
|
|
* @param s String representing address
|
|
* @return Symbol object having requested address, null if address not found in symbol table.
|
|
**/
|
|
public Symbol getSymbolGivenAddressLocalOrGlobal(String s){
|
|
Symbol sym = this.getSymbolGivenAddress(s);
|
|
return (sym==null) ? Globals.symbolTable.getSymbolGivenAddress(s) : sym ;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* For obtaining the Data Symbols.
|
|
* @return An ArrayList of Symbol objects.
|
|
**/
|
|
|
|
public ArrayList getDataSymbols(){
|
|
ArrayList list= new ArrayList();
|
|
for(int i=0; i<table.size(); i++){
|
|
if(((Symbol)table.get(i)).getType()){
|
|
list.add(table.get(i));
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
|
|
/**
|
|
* For obtaining the Text Symbols.
|
|
* @return An ArrayList of Symbol objects.
|
|
**/
|
|
|
|
public ArrayList getTextSymbols(){
|
|
ArrayList list= new ArrayList();
|
|
for(int i=0; i<table.size(); i++){
|
|
if(!((Symbol)table.get(i)).getType()){
|
|
list.add(table.get(i));
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* For obtaining all the Symbols.
|
|
* @return An ArrayList of Symbol objects.
|
|
**/
|
|
|
|
public ArrayList getAllSymbols(){
|
|
ArrayList list= new ArrayList();
|
|
for(int i=0; i<table.size(); i++){
|
|
list.add(table.get(i));
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* Get the count of entries currently in the table.
|
|
* @return Number of symbol table entries.
|
|
**/
|
|
|
|
public int getSize(){
|
|
return table.size();
|
|
}
|
|
|
|
/**
|
|
* Creates a fresh arrayList for a new table.
|
|
**/
|
|
|
|
public void clear(){
|
|
table= new ArrayList();
|
|
}
|
|
|
|
/**
|
|
* Fix address in symbol table entry. Any and all entries that match the original
|
|
* address will be modified to contain the replacement address. There is no effect,
|
|
* if none of the addresses matches.
|
|
* @param originalAddress Address associated with 0 or more symtab entries.
|
|
* @param replacementAddress Any entry that has originalAddress will have its
|
|
* address updated to this value. Does nothing if none do.
|
|
*/
|
|
|
|
public void fixSymbolTableAddress(int originalAddress, int replacementAddress) {
|
|
Symbol label = getSymbolGivenAddress(Integer.toString(originalAddress));
|
|
while (label != null) {
|
|
label.setAddress(replacementAddress);
|
|
label = getSymbolGivenAddress(Integer.toString(originalAddress));
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Fetches the text segment label (symbol) which, if declared global, indicates
|
|
* the starting address for execution.
|
|
* @return String containing global label whose text segment address is starting address for program execution.
|
|
**/
|
|
public static String getStartLabel() {
|
|
return startLabel;
|
|
}
|
|
} |