package org.edumips64.core.is;
import org.edumips64.core.CPU;
import org.edumips64.core.Dinero;
import org.edumips64.core.IOManager;
import org.edumips64.core.Memory;
import org.edumips64.utils.ConfigKey;
import org.edumips64.utils.ConfigStore;
/** InstructionBuilder should be used to build all the instructions to be run by the CPU. The only exception is
* BUBBLE, which has a public constructor to allow the CPU to build it without depending on InstructionBuilder.
*
* BUBBLE is a special instruction that should not be used by programs (it's not rendered), therefore InstructionBuilder
* will refuse to build it.
*/
public class InstructionBuilder {
private Memory memory;
private IOManager iom;
private CPU cpu;
private Dinero dinero;
private ConfigStore config;
public InstructionBuilder(Memory memory, IOManager iom, CPU cpu, Dinero dinero, ConfigStore config) {
this.memory = memory;
this.iom = iom;
this.cpu = cpu;
this.dinero = dinero;
this.config = config;
}
/**
* Creates a new instance of an Instruction's subclass
* @param instructionName string value to pass in order to instantiate an instruction object
* @return the instruction object, or null if the instruction is not implemented.
*
*/
public Instruction buildInstruction(String instructionName) {
// If the name of the requested instruction has got a dot, the instruction is FP and an
// underscore takes the place of the dot because classes names cannot contain dots
String name = instructionName.replaceAll("\\.", "_");
Instruction instruction;
switch(name) {
//ALU R-Type 32-bits
case "ADD":
instruction = new ADD();
break;
case "ADDU":
instruction = new ADDU();
break;
case "SUB":
instruction = new SUB();
break;
case "SUBU":
instruction = new SUBU();
break;
case "DIV":
instruction = new DIV();
break;
case "DIVU":
instruction = new DIVU();
break;
case "MULT":
instruction = new MULT();
break;
case "MULTU":
instruction = new MULTU();
break;
//ALU I-Type 32-bits
case "ADDI":
instruction = new ADDI();
break;
case "ADDIU":
instruction = new ADDIU();
break;
//ALU Shifting 32-bits
case "SLL":
instruction = new SLL();
break;
case "SLLV":
instruction = new SLLV();
break;
case "SRA":
instruction = new SRA();
break;
case "SRAV":
instruction = new SRAV();
break;
case "SRL":
instruction = new SRL();
break;
case "SRLV":
instruction = new SRLV();
break;
//ALU R-Type
case "AND":
instruction = new AND();
break;
case "DADD":
instruction = new DADD();
break;
case "DADDU":
instruction = new DADDU();
break;
case "DSUB":
instruction = new DSUB();
break;
case "DSUBU":
instruction = new DSUBU();
break;
case "OR":
instruction = new OR();
break;
case "SLT":
instruction = new SLT();
break;
case "SLTU":
instruction = new SLTU();
break;
case "XOR":
instruction = new XOR();
break;
case "MOVN":
instruction = new MOVN();
break;
case "MOVZ":
instruction = new MOVZ();
break;
case "DDIV":
instruction = new DDIV();
break;
case "DDIVU":
instruction = new DDIVU();
break;
case "DMULT":
instruction = new DMULT();
break;
case "DMULTU":
instruction = new DMULTU();
break;
case "MFLO":
instruction = new MFLO();
break;
case "MFHI":
instruction = new MFHI();
break;
//ALU I-Type
case "ANDI":
instruction = new ANDI();
break;
case "DADDI":
instruction = new DADDI();
break;
case "DADDUI":
instruction = new DADDUI();
break;
case "DADDIU":
instruction = new DADDIU();
break;
case "LUI":
instruction = new LUI();
break;
case "ORI":
instruction = new ORI();
break;
case "SLTI":
instruction = new SLTI();
break;
case "SLTIU":
instruction = new SLTIU();
break;
case "XORI":
instruction = new XORI();
break;
//ALU Shifting
case "DSLL":
instruction = new DSLL();
break;
case "DSLLV":
instruction = new DSLLV();
break;
case "DSRA":
instruction = new DSRA();
break;
case "DSRAV":
instruction = new DSRAV();
break;
case "DSRL":
instruction = new DSRL();
break;
case "DSRLV":
instruction = new DSRLV();
break;
//Load-Signed
case "LB":
instruction = new LB(memory);
break;
case "LH":
instruction = new LH(memory);
break;
case "LW":
instruction = new LW(memory);
break;
case "LD":
instruction = new LD(memory);
break;
//Load-Unsigned
case "LBU":
instruction = new LBU(memory);
break;
case "LHU":
instruction = new LHU(memory);
break;
case "LWU":
instruction = new LWU(memory);
break;
//Store
case "SB":
instruction = new SB(memory);
break;
case "SH":
instruction = new SH(memory);
break;
case "SW":
instruction = new SW(memory);
break;
case "SD":
instruction = new SD(memory);
break;
//Unconditional branches
case "J":
instruction = new J();
break;
case "JAL":
instruction = new JAL();
break;
case "JALR":
instruction = new JALR();
break;
case "JR":
instruction = new JR();
break;
case "B":
instruction = new B();
break;
//Conditional branches
case "BEQ":
instruction = new BEQ();
break;
case "BNE":
instruction = new BNE();
break;
case "BNEZ":
instruction = new BNEZ();
break;
case "BEQZ":
instruction = new BEQZ();
break;
case "BGEZ":
instruction = new BGEZ();
break;
//Special instructions
case "NOP":
instruction = new NOP();
break;
case "HALT":
instruction = new HALT();
break;
case "TRAP":
instruction = new TRAP(memory, iom);
break;
case "SYSCALL":
instruction = new SYSCALL(memory, iom);
break;
case "BREAK":
instruction = new BREAK();
break;
//Floating point instructions
//Arithmetic
case "ADD_D":
instruction = new ADD_D(cpu.getFCSR());
break;
case "SUB_D":
instruction = new SUB_D(cpu.getFCSR());
break;
case "MUL_D":
instruction = new MUL_D(cpu.getFCSR());
break;
case "DIV_D":
instruction = new DIV_D(cpu.getFCSR());
break;
//Load store
case "LDC1":
instruction = new LDC1(memory);
break;
case "L_D":
instruction = new L_D(memory);
break;
case "SDC1":
instruction = new SDC1(memory);
break;
case "S_D":
instruction = new S_D(memory);
break;
case "LWC1":
instruction = new LWC1(memory);
break;
case "SWC1":
instruction = new SWC1(memory);
break;
//Move to and from
case "DMTC1":
instruction = new DMTC1();
break;
case "DMFC1":
instruction = new DMFC1();
break;
case "MTC1":
instruction = new MTC1();
break;
case "MFC1":
instruction = new MFC1();
break;
//Formatted operand move
case "MOV_D":
instruction = new MOV_D();
break;
case "MOVZ_D":
instruction = new MOVZ_D();
break;
case "MOVN_D":
instruction = new MOVN_D();
break;
//Special arithmetic instructions
case "C_LT_D":
instruction = new C_LT_D();
break;
case "C_EQ_D":
instruction = new C_EQ_D();
break;
//Conditional branches instructions
case "BC1T":
instruction = new BC1T();
break;
case "BC1F":
instruction = new BC1F();
break;
//Conditional move on CC instructions
case "MOVT_D":
instruction = new MOVT_D();
break;
case "MOVF_D":
instruction = new MOVF_D();
break;
//Conversion instructions
case "CVT_L_D":
instruction = new CVT_L_D();
break;
case "CVT_D_L":
instruction = new CVT_D_L();
break;
case "CVT_W_D":
instruction = new CVT_W_D();
break;
case "CVT_D_W":
instruction = new CVT_D_W();
break;
default:
return null;
}
// Serial number for the instruction being built.
int serialNumber = config.getInt(ConfigKey.SERIAL_NUMBER);
config.putInt(ConfigKey.SERIAL_NUMBER, serialNumber + 1);
instruction.setSerialNumber(serialNumber);
// Inject other dependencies.
instruction.setCPU(cpu);
instruction.setDinero(dinero);
return instruction;
}
}