/******************************************************************************* * openDLX - A DLX/MIPS processor simulator. * Copyright (C) 2013 The openDLX project, University of Augsburg, Germany * Project URL: <https://sourceforge.net/projects/opendlx> * Development branch: <https://github.com/smetzlaff/openDLX> * * * 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 3 of the License, or * 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, see <LICENSE>. If not, see * <http://www.gnu.org/licenses/>. ******************************************************************************/ package openDLX.asm.instruction; import java.util.Hashtable; public class Instructions { private static Instructions instance_; private Hashtable<String, Instruction> str2instr_; private Hashtable<InstructionWrapper, String> instr2str_; private Hashtable<InstructionWrapper, InstructionType> instr2type_; private Hashtable<String, String> str2desc_; public static Instructions instance() { if (instance_ == null) instance_ = new Instructions(); return instance_; } /** * e.g. getMnemonic(new Instruction(0, 0, 0, 0, 0, 0x20)) == add * * @param instr * @return */ public String getMnemonic(Instruction instr) { if (instr == null) return null; else if (instr.instrWord() == 0x0) return "nop"; else return instr2str_.get(new InstructionWrapper(instr)); } /** * e.g. getType(new Instruction(0, 0, 0, 0, 0, 0x20)) == * InstructionType.ALU_REGISTER * * @param instr * @return */ public InstructionType getType(Instruction instr) { if (instr == null) return null; else if (instr.instrWord() == 0x0) return InstructionType.NOP; else return instr2type_.get(new InstructionWrapper(instr)); } /** * e.g. getInstruction("add") == new Instruction(0, 0, 0, 0, 0, 0x20) * * @param mnem * @return */ public Instruction getInstruction(String mnem) { if (mnem == null) return null; if (mnem.equalsIgnoreCase("nop")) return new Instruction(0x0); return str2instr_.get(mnem.toLowerCase()); } /** * e.g. getDescription("addi") = * "addi rt,rs,immediate: add immediate and rs and save result in rt" * * @param mnem * @return */ public String getDescription(String mnem) { if (mnem == null) return null; if (mnem.equalsIgnoreCase("nop")) return ""; return str2desc_.get(mnem); } private Instructions() { str2instr_ = new Hashtable<String, Instruction>(); instr2str_ = new Hashtable<InstructionWrapper, String>(); instr2type_ = new Hashtable<InstructionWrapper, InstructionType>(); str2desc_ = new Hashtable<String, String>(); try { //add("nop", new Instruction(), InstructionType.NOP); //normal add("j", new Instruction(0x02, 0), InstructionType.JUMP, "j[Jump] target: jump to target"); add("jal", new Instruction(0x03, 0), InstructionType.JUMP, "jal[Jump And Link] target: save next adress in r31 and jump to target"); add("beqz", new Instruction(0x04, 0, 0, 0), InstructionType.BRANCH, "beqz[Branch on Equal Zero] rs,offset: compare rs to zero then do a conditional branch");//beq $rt = 0 add("bnez", new Instruction(0x05, 0, 0, 0), InstructionType.BRANCH, "bnez[Branch on Not Equal Zero] rs, offset: compare rs to non-zero then do a conditional branch");//bne $rt = 0 add("addi", new Instruction(0x08, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "addi[ADD Immediate word] rt,rs,immediate: add immediate and rs and save result in rt"); add("addui", new Instruction(0x09, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "addui[ADD Unsigned Immediate word] rt,rs,immediate: add unsigned immediate to rs and save result in rt"); add("slti", new Instruction(0x0A, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "slti[Set on Less Than Immediate] rt,rs,immediate: record result of less-than comparison with rs and immediate in rt"); add("sltui", new Instruction(0x0B, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sltui[Set on Less Than Unsigned Immediate] rt,rs,immediate: record result of less-than comparison with rs and unsigned immediate in rt"); add("andi", new Instruction(0x0C, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "andi[AND Immediate] rt,rs,immediate: do a bitwise logical AND with rs and immediate and save result in rt"); add("ori", new Instruction(0x0D, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "ori[OR Immediate] rt,rs,immediate: do a bitwise logical OR with rs and immediate and save result in rt"); add("xori", new Instruction(0x0E, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "xori[eXclusive OR Immediate] rt,rs,immediate: do a bitwise logical exclusive OR with rs and immediate and save result in rt"); add("lhi", new Instruction(0x0F, 0, 0, 0), InstructionType.LOAD_IMMEDIATE, "lhi[Load High Immediate] rt, immediate: load immediate in upper 16 bit of rt");//lui add("subi", new Instruction(0x10, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "subi[SUBtract Immediate word] rt,rs,immediate: subtract immediate and rs and save result in rt"); //COP0 add("subui", new Instruction(0x11, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "subui[SUBtract Unsigned Immediate word] rt,rs,immediate: subtract unsigned immediate and rs and save result in rt");//COP1 add("sgti", new Instruction(0x12, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sgti[Set on Greater Than Immediate] rt,rs,immediate: record result of greater-than comparison with rs and immediate in rt");//COP2 add("sgtui", new Instruction(0x13, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sgtui[Set on Greater Than Unsigned Immediate] rt,rs,immediate: record result of greater-than comparison with rs and unsigned immediate in rt");//COP1X add("lb", new Instruction(0x20, 0, 0, 0), InstructionType.LOAD, "lb[Load Byte] rt,offset(base): load byte from adress at register base + offset to rt"); add("lh", new Instruction(0x21, 0, 0, 0), InstructionType.LOAD, "lh[Load Half] rt,offset(base): load half from adress at register base + offset to rt"); add("lw", new Instruction(0x23, 0, 0, 0), InstructionType.LOAD, "lw[Load Word] rt,offset(base): load word from adress at register base + offset to rt"); add("lbu", new Instruction(0x24, 0, 0, 0), InstructionType.LOAD, "lbu[Load Byte Unsigned] rt,offset(base): load unsigned byte from adress at register base + offset to rt"); add("lhu", new Instruction(0x25, 0, 0, 0), InstructionType.LOAD, "lhu[Load Half Unsigned] rt,offset(base): load unsigned half from adress at register base + offset to rt"); add("sb", new Instruction(0x28, 0, 0, 0), InstructionType.SAVE, "sb[Save Byte] rt,offset(base): save byte from rt to adress at register base + offset"); add("sh", new Instruction(0x29, 0, 0, 0), InstructionType.SAVE, "sh[Save Half] rt,offset(base): save half from rt to adress at register base + offset"); add("sw", new Instruction(0x2B, 0, 0, 0), InstructionType.SAVE, "sw[Save Word] rt,offset(base): save word from rt to adress at register base + offset"); add("seqi", new Instruction(0x31, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "seqi[Set on EQual Immediate] rt,rs,immediate: record result of equality comparison with rs and immediate in rt");//LWC1 add("snei", new Instruction(0x32, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "seqi[Set on Not Equal Immediate] rt,rs,immediate: record result of non-equality comparison with rs and immediate in rt");//LWC2 add("slei", new Instruction(0x35, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "seqi[Set on Less Equal Immediate] rt,rs,immediate: record result of less-equal comparison with rs and immediate in rt");//LDC1 add("sgei", new Instruction(0x36, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sgei[Set on Greater Equal Immediate] rt,rs,immediate: record result of greater-equal comparison with rs and immediate in rt");//LDC2 add("sequi", new Instruction(0x39, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sequi[Set on EQual Unsigned Immediate] rt,rs,immediate: record result of equality comparison with rs and unsigned immediate in rt");//SWC1 add("sneui", new Instruction(0x3A, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sneui[Set on Not Equal Unsigned Immediate] rt,rs,immediate: record result of non-equality comparison with rs and unsigned immediate in rt");//SWC2 add("sleui", new Instruction(0x3D, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sleui[Set on Less Equal Unsigned Immediate] rt,rs,immediate: record result of less-equal comparison with rs and unsigned immediate in rt");//SDC1 add("sgeui", new Instruction(0x3E, 0, 0, 0), InstructionType.ALU_IMMEDIATE, "sgeui[Set on Greater Equal Unsigned Immediate] rt,rs,immediate: record result of greater-equal comparison with rs and unsigned immediate in rt");//SDC2 //special add("slli", new Instruction(0, 0, 0, 0, 0, 0x00), InstructionType.SHIFT_IMMEDIATE, "slli[Shift word Left Logical Immediate] rd,rt,sa: do an left logical shift on rt by sa bits and save result in rd");//sll add("srli", new Instruction(0, 0, 0, 0, 0, 0x02), InstructionType.SHIFT_IMMEDIATE, "srli[Shift word Right Logical Immediate] rd,rt,sa: do an right logical shift on rt by sa bits and save result in rd");//srl add("srai", new Instruction(0, 0, 0, 0, 0, 0x03), InstructionType.SHIFT_IMMEDIATE, "srai[Shift word Right Arithmetic Immediate] rd,rt,sa: do an right arithmetic shift on rt by sa bits and save result in rd");//srai add("sll", new Instruction(0, 0, 0, 0, 0, 0x04), InstructionType.SHIFT_REGISTER, "sll[Shift word Left Logical] rd,rt,rs: do an left logical shift on rt by rs bits and save result in rd");//sllv add("srl", new Instruction(0, 0, 0, 0, 0, 0x06), InstructionType.SHIFT_REGISTER, "srl[Shift word Right Logical] rd,rt,rs: do an right logical shift on rt by rs bits and save result in rd");//srlv add("sra", new Instruction(0, 0, 0, 0, 0, 0x07), InstructionType.SHIFT_REGISTER, "sra[Shift word Right Arithmetic] rd,rt,sa: do an right artihmetic shift on rt by rs bits and save result in rd");//srav add("jr", new Instruction(0, 0, 0, 0, 0, 0x08), InstructionType.JUMP_REGISTER, "jr[Jump Register] rs: jump to rs"); add("jalr", new Instruction(0, 0, 0, 31, 0, 0x09), InstructionType.JUMP_REGISTER, "jalr[Jump And Link Register] rs: save next adress in r31 and jump to target");//$rd = 31 add("trap", new Instruction(0, 0, 0, 0, 0, 0x0C), InstructionType.TRAP, "trap id: execute trap with given id. Available trap ids are:\n0: terminate programm\n5: print formatted String\nAll parameters are fetched from r14");//syscall add("mult", new Instruction(0, 0, 0, 0, 0, 0x18), InstructionType.ALU_REGISTER, "mult[MULTiply word] rd,rs,rt: multiply rs and rt and save result in rd"); add("multu", new Instruction(0, 0, 0, 0, 0, 0x19), InstructionType.ALU_REGISTER, "multu[MULTiply Unsigned word] rd,rs,rt: multiply rs and rt as unsigned and save result in rd"); add("div", new Instruction(0, 0, 0, 0, 0, 0x1A), InstructionType.ALU_REGISTER, "div[Divide word] rd,rs,rt: divide rs and rt and save result in rd"); add("divu", new Instruction(0, 0, 0, 0, 0, 0x1B), InstructionType.ALU_REGISTER, "divu[Divide Unsigned word] rd,rs,rt: divide rs and rt as unsigned and save result in rd"); add("add", new Instruction(0, 0, 0, 0, 0, 0x20), InstructionType.ALU_REGISTER, "add[ADD word] rd,rs,rt: add rs and rt and save result in rd"); add("addu", new Instruction(0, 0, 0, 0, 0, 0x21), InstructionType.ALU_REGISTER, "addu[ADD Unsigned word] rd,rs,rt: add rs and rt as unsigned and save result in rd"); add("sub", new Instruction(0, 0, 0, 0, 0, 0x22), InstructionType.ALU_REGISTER, "sub[SUBtract word] rd,rs,rt: subtract rs and rt and save result in rd"); add("subu", new Instruction(0, 0, 0, 0, 0, 0x23), InstructionType.ALU_REGISTER, "subu[SUBtract Unsigned word] rd,rs,rt: subtract rs and rt as unsigned and save result in rd"); add("and", new Instruction(0, 0, 0, 0, 0, 0x24), InstructionType.ALU_REGISTER, "and[AND] rd,rs,rt: do a bitwise logical AND with rt and rs and save result in rt"); add("or", new Instruction(0, 0, 0, 0, 0, 0x25), InstructionType.ALU_REGISTER, "or[OR] rd,rs,rt: do a bitwise logical OR with rt and rs and save result in rt"); add("xor", new Instruction(0, 0, 0, 0, 0, 0x26), InstructionType.ALU_REGISTER, "xor[eXclusive OR] rd,rs,rt: do a bitwise logical XOR with rt and rs and save result in rt"); add("sgt", new Instruction(0, 0, 0, 0, 0, 0x28), InstructionType.ALU_REGISTER, "sgt[Set on Greater Than] rd,rs,rt: record result of greater-than comparison with rs and rt in rd"); add("sgtu", new Instruction(0, 0, 0, 0, 0, 0x29), InstructionType.ALU_REGISTER, "sgtu[Set on Greater Than Unsigned] rd,rs,rt: record result of unsigned greater-than comparison with rs and rt in rd"); add("slt", new Instruction(0, 0, 0, 0, 0, 0x2A), InstructionType.ALU_REGISTER, "slt[Set on Less Than] rd,rs,rt: record result of less-than comparison with rs and rt in rd"); add("sltu", new Instruction(0, 0, 0, 0, 0, 0x2B), InstructionType.ALU_REGISTER, "sltu[Set on Less Than Unsigned] rd,rs,rt: record result of unsigned less-than comparison with rs and rt in rd"); add("seq", new Instruction(0, 0, 0, 0, 0, 0x35), InstructionType.ALU_REGISTER, "seq[Set on EQual] rd,rs,rt: record result of equal comparison with rs and rt in rd"); add("sne", new Instruction(0, 0, 0, 0, 0, 0x37), InstructionType.ALU_REGISTER, "sne[Set on Not Equal] rd,rs,rt: record result of not-equal comparison with rs and rt in rd"); add("sle", new Instruction(0, 0, 0, 0, 0, 0x38), InstructionType.ALU_REGISTER, "sle[Set on Less Equal] rd,rs,rt: record result of less-equal comparison with rs and rt in rd");//DSLL add("sge", new Instruction(0, 0, 0, 0, 0, 0x39), InstructionType.ALU_REGISTER, "sge[Set on Greater Equal] rd,rs,rt: record result of greater-equal comparison with rs and rt in rd"); add("sequ", new Instruction(0, 0, 0, 0, 0, 0x3A), InstructionType.ALU_REGISTER, "sequ[Set on EQual Unsigned] rd,rs,rt: record result of unsigned equal comparison with rs and rt in rd");//DSRL add("sneu", new Instruction(0, 0, 0, 0, 0, 0x3B), InstructionType.ALU_REGISTER, "sneu[Set on Not Equal Unsigned] rd,rs,rt: record result of not-equal comparison with rs and rt in rd");//DSRA add("sleu", new Instruction(0, 0, 0, 0, 0, 0x3C), InstructionType.ALU_REGISTER, "sleu[Set on Less Equal Unsigned] rd,rs,rt: record result of unsigned less-equal comparison with rs and rt in rd");//DSLL32 add("sgeu", new Instruction(0, 0, 0, 0, 0, 0x3D), InstructionType.ALU_REGISTER, "sgeu[Set on Grater Equal Unsigned] rd,rs,rt: record result of unsigned greater-equal comparison with rs and rt in rd"); } catch (InstructionException e) { e.printStackTrace(); } } private void add(String mnemonic, Instruction instruction, InstructionType encoding, String desc) { str2instr_.put(mnemonic, instruction); InstructionWrapper wrapper = new InstructionWrapper(instruction); instr2str_.put(wrapper, mnemonic); instr2type_.put(wrapper, encoding); str2desc_.put(mnemonic, desc); } /** * This wrapper is used so that the test for equality is only applied on the * skeleton. * */ private class InstructionWrapper { public Instruction instr_; public InstructionWrapper(Instruction instr) { this.instr_ = instr; } public boolean equals(Object o) { if (o instanceof InstructionWrapper) { return ((InstructionWrapper) o).instr_.equalsFamily((instr_)); } return false; } public int hashCode() { return instr_.skeleton(); } } }