/*
* Instruction.java
*
* This file is part of the EduMIPS64 project, and is released under the GNU
* General Public License.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.edumips64.core.is;
import org.edumips64.core.BitSet32;
import org.edumips64.core.CPU;
import org.edumips64.core.Dinero;
import org.edumips64.core.DivisionByZeroException;
import org.edumips64.core.IrregularWriteOperationException;
import org.edumips64.core.MemoryElementNotFoundException;
import org.edumips64.core.NotAlignException;
import org.edumips64.core.Register;
import org.edumips64.core.RegisterFP;
import org.edumips64.core.fpu.FPDivideByZeroException;
import org.edumips64.core.fpu.FPInvalidOperationException;
import org.edumips64.core.fpu.FPOverflowException;
import org.edumips64.core.fpu.FPUnderflowException;
import org.edumips64.utils.*;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
/**Abstract class: it provides all methods and attributes for each instruction type
*
* @author Trubia Massimo, Russo Daniele
*/
public abstract class Instruction {
protected BitSet32 repr;
protected List<Integer> params;
protected int paramCount;
protected String syntax;
protected String name;
protected String comment;
//protected static CPU cpu;
protected Register[] TR; //is not static because each instruction has got its own registers
protected RegisterFP[] TRfp;
protected String fullname;
protected String label;
protected static final Logger logger = Logger.getLogger(Instruction.class.getName());
protected int serialNumber;
/** CPU instance. It is set through setCPU, and it should always be set before the instruction is considered
* fully built. InstructionBuilder + package-local instruction constructors enforce this.
*/
protected CPU cpu;
void setCPU(CPU cpu) {
this.cpu = cpu;
}
/** Dinero instance. It is set through setDinero, and it should always be set before the instruction is considered
* fully built. InstructionBuilder + package-local instruction constructors enforce this.
*/
protected Dinero dinero;
void setDinero(Dinero dinero) {
this.dinero = dinero;
}
void setSerialNumber(int serialNumber) {
this.serialNumber = serialNumber;
}
/** Creates a new instance of Instruction */
Instruction() {
params = new LinkedList<>();
TR = new Register[5];
TRfp = new RegisterFP[5];
repr = new BitSet32();
syntax = "";
repr.reset(false);
//initialization of temporary registers
for (int i = 0; i < TR.length; i++) {
TR[i] = new Register("TR " + i + "(Instruction " + serialNumber + ")");
TRfp[i] = new RegisterFP();
}
}
/** <pre>
* Returns a BitSet32 holding the binary representation of the Instruction
* @return the Bitset32 representing the instruction
* </pre>
* */
public BitSet32 getRepr() {
return repr;
}
/**
* <pre>
* Instruction fetch.
* Now it is used in order to generate the Dinero trace-file
*</pre>
*/
public void IF() throws BreakException {}
/**
* <pre>
* Decode stage of the Pipeline
* In this method all instructions that modify GPRs lock the involved register
*</pre>
**/
public abstract void ID() throws RAWException, IrregularWriteOperationException, IrregularStringOfBitsException, TwosComplementSumException, HaltException, JumpException, BreakException, WAWException, FPInvalidOperationException;
/**
* <pre>
* Execute stage of the Pipeline
* In this stage all Alu Instructions perform their computations and save results in temporary registers
* </pre>
**/
public abstract void EX() throws HaltException, IrregularStringOfBitsException, IntegerOverflowException, TwosComplementSumException, IrregularWriteOperationException, DivisionByZeroException, NotAlignException, FPInvalidOperationException, FPUnderflowException, FPOverflowException, FPDivideByZeroException, AddressErrorException;
/**
* <pre>
* Memory stage of the Pipeline
* In this stage all Load and Store instructions access memory for getting or putting data
* </pre>
**/
public abstract void MEM() throws HaltException, IrregularStringOfBitsException, NotAlignException, MemoryElementNotFoundException, AddressErrorException, IrregularWriteOperationException;
/**
* <pre>
* Write Back stage of the Pipeline
* In this stage all instructions that modify registers write and unlock them
* </pre>
**/
public abstract void WB() throws HaltException, IrregularStringOfBitsException;
/**
* <pre>
* Builds the binary encoding of instructions.
* Every instruction is represented by a 32 bit field
* </pre>
**/
public abstract void pack() throws IrregularStringOfBitsException;
/**
* <pre>
* Gets the syntax of any instruction as string composed by the following simbols
* %R Register
* %I Immediate
* %U Unsigned Immediate
* %L Memory Label
* %E Program Label used for Jump Instructions
* %B Program Label used for Brench Instructions
*
* examples:
* Instruction -----> Syntax
* DADD R1,R2,R3 | %R,%R,%R
* DADDI R1,R2,-3 | %R,%R,%I
* DSLL R1,R2,15 | %R,%R,%U
* LD R1,vet(R0) | %R,%L(%R)
* J loop | %E
* BNE R1,R2,loop | %R,%R,%B
* </pre>
**/
public String getSyntax() {
return syntax;
}
/**
* Returns the name of the instruction as string.
* @return the instruction name(e.g. "DADD")
**/
public String getName() {
return name;
}
/**
*<pre>
* Returns a list with the instruction parameters
* e.g. DADD R1,R2,R3 --> params= { 1, 2, 3}
* LD R1, var(R0)--> params= { 1, address memory corresponding with var, 0}
* </pre>
*@return the list of parameters
**/
public List<Integer> getParams() {
return params;
}
/**
*<pre>
* Sets the instruction with a list of parameters
* Passed list | Instruction to set
* e.g. list= { 1, 2, 3} | DADD R1,R2,R3
* list= { 1, address memory corresponding with var, 0} | LD R1, var(R0)
*@param params The list of parameters
**/
public void setParams(List<Integer> params) {
this.params = params;
}
/**
* Sets the full name of the instruction as string
*@param value full name of the instruction (e.g. "DADD R1,R2,R3")
*/
public void setFullName(String value) {
fullname = value;
}
/** Sets the comment of the instruction as string. The comment is the text
* after every semicolon in the file .s
* @param comment the comment associated with the instruction
*/
public void setComment(String comment) {
this.comment = comment;
}
/** Gets the comment of the instruction as string.The comment is the text
* after every semicolon in the file .s
* @return the comment
*/
public String getComment() {
return comment;
}
/** Gets the full name of the instruction as string.
* @return the full name of the instruction (e.g. "DADD R1,R2,R3")
*/
public String getFullName() {
return fullname;
}
/** Gets the serial number of this instruction */
public int getSerialNumber() {
return serialNumber;
}
public String toString() {
String repr = name + " (" + fullname + ") [# " + serialNumber + "]";
if (label != null && label.length() > 0) {
repr += " {label: " + label + "}";
}
return repr;
}
/**<pre>
* Gets the label of the instruction. Labels may be assigned to instructions
* when they are inserted in the symbol table
*</pre>
* @return label of the instruction
*/
public String getLabel() {
return label;
}
/**<pre>
* Sets the label of the instruction. Labels may be assigned to instructions
* when they are inserted in the symbol table
*</pre>
* @param value label of the instruction
*/
public void setLabel(String value) {
label = value;
}
/**<pre>
* The repr field of the passed instruction is compared with the repr field
* of this instruction. If they are identical then true is returned else false is returned
* </pre>
* @param instr instruction to compare with this
* @return the result of the comparison
*/
@Override
public boolean equals(Object instr) {
if (instr == null) {
return false;
}
if (instr == this) {
return true;
}
if (!(instr instanceof Instruction)) {
return false;
}
Instruction i = (Instruction) instr;
return i.getSerialNumber() == serialNumber;
}
/** Use the serial number as the hash code for the instruction.
* This is consistent with the overridden equals().
* @return the serial number of the instruction
*/
@Override
public int hashCode() {
return serialNumber;
}
/**<pre>
* Returns true if the instruction is a BUBBLE, false otherwise. BUBBLE is used to fill
* the pipeline and is not a real instruction, so some parts of the UI code need to know
* if the instruction is a BUBBLE or not. This method abstracts the details of how to check
* if an instruction is a BUBBLE.
* </pre>
*/
public boolean isBubble() {
return name.equals(" ");
}
}