Source: lib/instructions.js

/*
 *  MIPS-Simulator : instructions.js [Provide instruction information]
 *  Copyright (C)  2017  Progyan Bhattacharya, Bytes Club
 *
 *  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
 *  (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, see <http://www.gnu.org/licenses/>.
 */

"use strict";

/** function: isInstruction
 * @desc Parses Operation Code From an Instruction
 * @param  {string} opcode - Operation Code (MIPS-IV)
 * @return {Object} Operation Specification
 */
const isInstruction = opcode => {
    if (typeof opcode !== "string") {
        throw new TypeError("opcode is expected to be a string.");
    }
    switch (opcode.toLowerCase()) {
        case "li": {
            return {
                action: "Load",
                type: "Integer",
                arguments: 2,
                argument: ["dest", "integer"],
                argumentType: ["Register", "Integer"]
            };
        }
        case "la": {
            return {
                action: "Load",
                type: "Address",
                arguments: 2,
                argument: ["dest", "address"],
                argumentType: ["Register", "Label"]
            };
        }
        case "lw": {
            return {
                action: "Load",
                type: "Register",
                arguments: 3,
                argument: ["dest", "src", "offset"],
                argumentType: ["Register", "Register", "Integer"]
            };
        }
        case "move": case "mfc0": {
            return {
                action: "Move",
                type: "Register",
                arguments: 2,
                argument: ["dest", "src"],
                argumentType: ["Register", "Register"]
            };
        }
        case "sw": {
            return {
                action: "Store",
                type: "Register",
                arguments: 3,
                argument: ["dest", "src", "offset"],
                argumentType: ["Register", "Register", "Integer"]
            };
        }
        case "add": {
            return {
                action: "Add",
                type: "Register",
                arguments: 3,
                argument: ["dest", "src1", "src2"],
                argumentType: ["Register", "Register", "Register"]
            };
        }
        case "addi": {
            return {
                action: "Add",
                type: "Immidiate",
                arguments: 3,
                argument: ["dest", "src", "addend"],
                argumentType: ["Register", "Register", "Integer"]
            };
        }
        case "sub": {
            return {
                action: "Subtract",
                type: "Register",
                arguments: 3,
                argument: ["dest", "src1", "src2"],
                argumentType: ["Register", "Register", "Register"]
            };
        }
        case "mult": {
            return {
                action: "Multiplication",
                type: "Register",
                arguments: 2,
                argument: ["multiplicand", "multiplier"],
                argumentType: ["Register", "Register"]
            };
        }
        case "div": {
            return {
                action: "Division",
                type: "Register",
                arguments: 2,
                argument: ["divisor", "dividend"],
                argumentType: ["Register", "Register"]
            };
        }
        case "mfhi": {
            return {
                action: "Move",
                type: "Register",
                arguments: 1,
                argument: ["dest", "$hi"],
                argumentType: ["Register", "Register"]
            };
        }
        case "mflo": {
            return {
                action: "Move",
                type: "Register",
                arguments: 1,
                argument: ["dest", "$lo"],
                argumentType: ["Register", "Register"]
            };
        }
        case "and": {
            return {
                action: "And",
                type: "Register",
                arguments: 3,
                argument: ["dest", "src1", "src2"],
                argumentType: ["Register", "Register", "Register"]
            };
        }
        case "andi": {
            return {
                action: "And",
                type: "Immidiate",
                arguments: 3,
                argument: ["dest", "src", "imm"],
                argumentType: ["Register", "Register", "Integer"]
            };
        }
        case "or": {
            return {
                action: "Or",
                type: "Register",
                arguments: 3,
                argument: ["dest", "src1", "src2"],
                argumentType: ["Register", "Register", "Register"]
            };
        }
        case "ori": {
            return {
                action: "Or",
                type: "Immidiate",
                arguments: 3,
                argument: ["dest", "src", "imm"],
                argumentType: ["Register", "Register", "Integer"]
            };
        }
        case "sll": {
            return {
                action: "Shift",
                type: "Left",
                arguments: 3,
                argument: ["dest", "src", "imm"],
                argumentType: ["Register", "Register", "Integer"]
            };
        }
        case "srl": {
            return {
                action: "Shift",
                type: "Right",
                arguments: 3,
                argument: ["dest", "src", "imm"],
                argumentType: ["Register", "Register", "Integer"]
            };
        }
        case "beq": {
            return {
                action: "Branch",
                type: "Equality",
                arguments: 3,
                argument: ["value", "comprator", "label"],
                argumentType: ["Register", "Register", "Label"]
            };
        }
        case "bne": {
            return {
                action: "Branch",
                type: "Inequality",
                arguments: 3,
                argument: ["value", "comprator", "label"],
                argumentType: ["Register", "Register", "Label"]
            };
        }
        case "bgt": {
            return {
                action: "Branch",
                type: "Greater",
                arguments: 3,
                argument: ["value", "comprator", "label"],
                argumentType: ["Register", "Register", "Label"]
            };
        }
        case "blt": {
            return {
                action: "Branch",
                type: "Lesser",
                arguments: 3,
                argument: ["value", "comprator", "label"],
                argumentType: ["Register", "Register", "Label"]
            };
        }
        case "bez": {
            return {
                action: "Branch",
                type: "EqualtoZero",
                arguments: 2,
                argument: ["value", "label"],
                argumentType: ["Register", "Label"]
            };
        }
        case "bnez": {
            return {
                action: "Branch",
                type: "InequaltoZero",
                arguments: 2,
                argument: ["value", "label"],
                argumentType: ["Register", "Label"]
            };
        }
        case "j": {
            return {
                action: "Branch",
                type: "JumpReg",
                arguments: 1,
                argument: ["label"],
                argumentType: ["Register"]
            };
        }
        case "jr": {
            return {
                action: "Branch",
                type: "Jump",
                arguments: 1,
                argument: ["label"],
                argumentType: ["Label"]
            };
        }
        case "syscall": {
            return {
                action: "OS",
                type: "Interrupt",
                arguments: 0,
                argumentType: []
            };
        }
        default:
            return null;
    }
};

module.exports = isInstruction; // ES5
// export default isInstruction; // ES6