/** * **************************************************************************** * Copyright (c) 2010-2016 by Min Cai (min.cai.china@gmail.com). * <p> * This file is part of the Archimulator multicore architectural simulator. * <p> * Archimulator 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 3 of the License, or * (at your option) any later version. * <p> * Archimulator 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. * <p> * You should have received a copy of the GNU General Public License * along with Archimulator. If not, see <http://www.gnu.org/licenses/>. * **************************************************************************** */ package archimulator.isa; import archimulator.core.functionalUnit.FunctionalUnitOperationType; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * Mnemonic. * * @author Min Cai */ public enum Mnemonic { /** * No operation (NOP). */ NOP, /** * Break. */ BREAK, /** * System call. */ SYSTEM_CALL, /** * Add. */ ADD, /** * Addi. */ ADDI, /** * Addiu. */ ADDIU, /** * Addu. */ ADDU, /** * Sub. */ SUB, /** * Subu. */ SUBU, /** * And. */ AND, /** * Andi. */ ANDI, /** * Nor. */ NOR, /** * Or. */ OR, /** * Ori. */ ORI, /** * Xor. */ XOR, /** * Xori. */ XORI, /** * Mult. */ MULT, /** * Multu. */ MULTU, /** * Div. */ DIV, /** * Divu. */ DIVU, /** * Sll. */ SLL, /** * Sllv. */ SLLV, /** * Slt. */ SLT, /** * Slti. */ SLTI, /** * Sltiu. */ SLTIU, /** * Sltu. */ SLTU, /** * Sra. */ SRA, /** * Srav. */ SRAV, /** * Srl. */ SRL, /** * Srlv. */ SRLV, /** * Madd. */ MADD, /** * Msub. */ MSUB, /** * B. */ B, /** * Bal. */ BAL, /** * Beq. */ BEQ, /** * Beql. */ BEQL, /** * Bgez. */ BGEZ, /** * Bgezl. */ BGEZL, /** * Bgezal. */ BGEZAL, /** * Bgezall. */ BGEZALL, /** * Bgtz. */ BGTZ, /** * Bgtzl. */ BGTZL, /** * Blez. */ BLEZ, /** * Blezl. */ BLEZL, /** * Bltz. */ BLTZ, /** * Bltzl. */ BLTZL, /** * Bltzal. */ BLTZAL, /** * Bltzall. */ BLTZALL, /** * Bne. */ BNE, /** * Bnel. */ BNEL, /** * J. */ J, /** * Jal. */ JAL, /** * Jalr. */ JALR, /** * Jr. */ JR, /** * Lb. */ LB, /** * Lbu. */ LBU, /** * Lh. */ LH, /** * Lhu. */ LHU, /** * Lui. */ LUI, /** * Lw. */ LW, /** * Lwl. */ LWL, /** * Lwr. */ LWR, /** * Sb. */ SB, /** * Sh. */ SH, /** * Sw. */ SW, /** * Swl. */ SWL, /** * Swr. */ SWR, /** * Ldc1. */ LDC1, /** * Lwc1. */ LWC1, /** * Sdc1. */ SDC1, /** * Swc1. */ SWC1, /** * Mfhi. */ MFHI, /** * Mflo. */ MFLO, /** * Mthi. */ MTHI, /** * Mtlo. */ MTLO, /** * Cfc1. */ CFC1, /** * Ctc1. */ CTC1, /** * Mfc1. */ MFC1, /** * Mtc1. */ MTC1, /** * Ll. */ LL, /** * Sc. */ SC, /** * Neg_d. */ NEG_D, /** * Mov_d. */ MOV_D, /** * Sqrt_d. */ SQRT_D, /** * Abs_d. */ ABS_D, /** * Mul_d. */ MUL_D, /** * Div_d. */ DIV_D, /** * Add_d. */ ADD_D, /** * Sub_d. */ SUB_D, /** * Mul_s. */ MUL_S, /** * Div_s. */ DIV_S, /** * Add_s. */ ADD_S, /** * Sub_s. */ SUB_S, /** * Mov_s. */ MOV_S, /** * Neg_s. */ NEG_S, /** * Abs_s. */ ABS_S, /** * Sqrt_s. */ SQRT_S, /** * C_cond_d. */ C_COND_D, /** * C_cond_s. */ C_COND_S, /** * Cvt_d_l. */ CVT_D_L, /** * Cvt_s_l. */ CVT_S_L, /** * Cvt_d_w. */ CVT_D_W, /** * Cvt_s_w. */ CVT_S_W, /** * Cvt_l_d. */ CVT_L_D, /** * Cvt_w_d. */ CVT_W_D, /** * Cvt_s_d. */ CVT_S_D, /** * Cvt_l_s. */ CVT_L_S, /** * Cvt_w_s. */ CVT_W_S, /** * Cvt_d_s. */ CVT_D_S, /** * Bc1fl. */ BC1FL, /** * Bc1tl. */ BC1TL, /** * Bc1f. */ BC1F, /** * Bc1t. */ BC1T, /** * Movf. */ MOVF, /** * _movf. */ _MOVF, /** * Movn. */ MOVN, /** * _movn. */ _MOVN, /** * _movt. */ _MOVT, /** * Movz. */ MOVZ, /** * _movz. */ _MOVZ, /** * Mul. */ MUL, /** * Trunc_w. */ TRUNC_W, /** * Unknown. */ UNKNOWN; private Method method; private int mask; private int bits; private BitField extraBitField; private int extraBitFieldValue; private StaticInstructionType type; private FunctionalUnitOperationType functionalUnitOperationType; /** * Get the list of input dependencies for the specified machine instruction. * * @param machineInstruction the machine instruction * @return the list of input dependencies for the specified machine instruction */ public List<Integer> getInputDependencies(final int machineInstruction) { return new ArrayList<Integer>() {{ for (StaticInstruction.Dependency dependency : Mnemonic.this.getMethod().getAnnotation(InputDependencies.class).value()) { add(toRegisterDependency(dependency, machineInstruction)); } }}; } /** * Get the list of output dependencies for the specified machine instruction. * * @param machineInstruction the machine instruction * @return the list of output dependencies for the specified machine instruction */ public List<Integer> getOutputDependencies(final int machineInstruction) { return new ArrayList<Integer>() {{ for (StaticInstruction.Dependency dependency : Mnemonic.this.getMethod().getAnnotation(OutputDependencies.class).value()) { add(toRegisterDependency(dependency, machineInstruction)); } }}; } /** * Get the non effective address base dependency for the specified machine instruction. * * @param machineInstruction the machine instruction * @return the non effective address base dependency for the specified machine instruction */ public int getNonEffectiveAddressBaseDep(int machineInstruction) { return toRegisterDependency(this.getMethod().getAnnotation(NonEffectiveAddressBaseDependency.class).value(), machineInstruction); } /** * Get the method. * * @return the method */ public Method getMethod() { return this.method; } /** * Set the method. * * @param method the method */ public void setMethod(Method method) { this.method = method; DecodeMethod decodeMethod = method.getAnnotation(DecodeMethod.class); DecodeCondition decodeCondition = method.getAnnotation(DecodeCondition.class); this.mask = decodeMethod.mask(); this.bits = decodeMethod.bits(); if (decodeCondition != null) { this.extraBitField = BitField.get(decodeCondition.bitField()); this.extraBitFieldValue = decodeCondition.value(); } StaticInstructionIntrinsic staticInstructionIntrinsic = method.getAnnotation(StaticInstructionIntrinsic.class); Collection<StaticInstructionFlag> flags = Arrays.asList(method.getAnnotation(StaticInstructionFlags.class).value()); this.determineInstructionType(flags); this.functionalUnitOperationType = staticInstructionIntrinsic.functionalUnitOperationType(); } /** * Determine the instruction type for the specified collection of tags. * * @param flags the collection of tags */ private void determineInstructionType(Collection<StaticInstructionFlag> flags) { if (flags.contains(StaticInstructionFlag.INTEGER_COMPUTATION)) { this.type = StaticInstructionType.INTEGER_COMPUTATION; } else if (flags.contains(StaticInstructionFlag.FLOAT_COMPUTATION)) { this.type = StaticInstructionType.FLOAT_COMPUTATION; } else if (flags.contains(StaticInstructionFlag.LOAD)) { this.type = StaticInstructionType.LOAD; } else if (flags.contains(StaticInstructionFlag.STORE)) { this.type = StaticInstructionType.STORE; } else if (flags.contains(StaticInstructionFlag.CONDITIONAL)) { this.type = StaticInstructionType.CONDITIONAL; } else if (flags.contains(StaticInstructionFlag.FUNCTION_CALL)) { this.type = StaticInstructionType.FUNCTION_CALL; } else if (flags.contains(StaticInstructionFlag.UNCONDITIONAL) && flags.contains(StaticInstructionFlag.DIRECT_JUMP)) { this.type = StaticInstructionType.UNCONDITIONAL; } else if (flags.contains(StaticInstructionFlag.UNCONDITIONAL) && flags.contains(StaticInstructionFlag.INDIRECT_JUMP)) { this.type = StaticInstructionType.FUNCTION_RETURN; } else if (flags.contains(StaticInstructionFlag.TRAP)) { this.type = StaticInstructionType.TRAP; } else if (flags.contains(StaticInstructionFlag.NOP)) { this.type = StaticInstructionType.NOP; } else if (flags.contains(StaticInstructionFlag.UNIMPLEMENTED)) { this.type = StaticInstructionType.UNIMPLEMENTED; } else if (flags.contains(StaticInstructionFlag.UNKNOWN)) { this.type = StaticInstructionType.UNKNOWN; } else { throw new IllegalArgumentException(); } } /** * Get the mask. * * @return the mask */ public int getMask() { return this.mask; } /** * Get the bits. * * @return the bits */ public int getBits() { return this.bits; } /** * Get the extra bit field. * * @return the extra bit field */ public BitField getExtraBitField() { return this.extraBitField; } /** * Get the value of the extra bit field. * * @return the value of the extra bit field */ public int getExtraBitFieldValue() { return this.extraBitFieldValue; } /** * Get the static instruction type. * * @return the static instruction type */ public StaticInstructionType getType() { return this.type; } /** * Get the functional unit operation type. * * @return the functional unit operation type */ public FunctionalUnitOperationType getFunctionalUnitOperationType() { return this.functionalUnitOperationType; } /** * Get a value indicating whether the mnemonic is control or not. * * @return a value indicating whether the mnemonic is control or not */ public boolean isControl() { return this.getType() == StaticInstructionType.CONDITIONAL || this.getType() == StaticInstructionType.FUNCTION_CALL || this.getType() == StaticInstructionType.UNCONDITIONAL || this.getType() == StaticInstructionType.FUNCTION_RETURN; } /** * Get the register dependency from the annotated machine instruction. * * @param dependencyA the dependency annotation * @param machineInstruction the machine instruction * @return the register dependency from the annotated machine instruction */ private static int toRegisterDependency(StaticInstruction.Dependency dependencyA, int machineInstruction) { switch (dependencyA) { case RS: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.INTEGER, BitField.RS.valueOf(machineInstruction)); case RT: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.INTEGER, BitField.RT.valueOf(machineInstruction)); case RD: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.INTEGER, BitField.RD.valueOf(machineInstruction)); case FS: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.FLOAT, BitField.FS.valueOf(machineInstruction)); case FT: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.FLOAT, BitField.FT.valueOf(machineInstruction)); case FD: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.FLOAT, BitField.FD.valueOf(machineInstruction)); case REGISTER_RA: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.INTEGER, ArchitecturalRegisterFile.REGISTER_RA); case REGISTER_V0: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.INTEGER, ArchitecturalRegisterFile.REGISTER_V0); case REGISTER_HI: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.MISC, ArchitecturalRegisterFile.REGISTER_MISC_HI); case REGISTER_LO: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.MISC, ArchitecturalRegisterFile.REGISTER_MISC_LO); case REGISTER_FCSR: return RegisterDependencyType.toRegisterDependency(RegisterDependencyType.FLOAT, ArchitecturalRegisterFile.REGISTER_MISC_FCSR); default: throw new IllegalArgumentException(); } } }