--- /dev/null
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Mupen64plus - interpreter_special.def *
+ * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
+ * Copyright (C) 2002 Hacktarux *
+ * *
+ * 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., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+DECLARE_INSTRUCTION(NOP)
+{
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SLL)
+{
+ rrd32 = (unsigned int)(rrt32) << rsa;
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SRL)
+{
+ rrd32 = (unsigned int)rrt32 >> rsa;
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SRA)
+{
+ rrd32 = (signed int)rrt32 >> rsa;
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SLLV)
+{
+ rrd32 = (unsigned int)(rrt32) << (rrs32&0x1F);
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SRLV)
+{
+ rrd32 = (unsigned int)rrt32 >> (rrs32 & 0x1F);
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SRAV)
+{
+ rrd32 = (signed int)rrt32 >> (rrs32 & 0x1F);
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_JUMP(JR, irs32, 1, ®[0], 0, 0)
+DECLARE_JUMP(JALR, irs32, 1, PC->f.r.rd, 0, 0)
+
+DECLARE_INSTRUCTION(SYSCALL)
+{
+ Cause = 8 << 2;
+ exception_general();
+}
+
+DECLARE_INSTRUCTION(SYNC)
+{
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(MFHI)
+{
+ rrd = hi;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(MTHI)
+{
+ hi = rrs;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(MFLO)
+{
+ rrd = lo;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(MTLO)
+{
+ lo = rrs;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSLLV)
+{
+ rrd = rrt << (rrs32&0x3F);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSRLV)
+{
+ rrd = (unsigned long long)rrt >> (rrs32 & 0x3F);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSRAV)
+{
+ rrd = (long long)rrt >> (rrs32 & 0x3F);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(MULT)
+{
+ long long int temp;
+ temp = rrs * rrt;
+ hi = temp >> 32;
+ lo = temp;
+ sign_extended(lo);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(MULTU)
+{
+ unsigned long long int temp;
+ temp = (unsigned int)rrs * (unsigned long long)((unsigned int)rrt);
+ hi = (long long)temp >> 32;
+ lo = temp;
+ sign_extended(lo);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DIV)
+{
+ if (rrt32)
+ {
+ lo = rrs32 / rrt32;
+ hi = rrs32 % rrt32;
+ sign_extended(lo);
+ sign_extended(hi);
+ }
+ else DebugMessage(M64MSG_ERROR, "DIV: divide by 0");
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DIVU)
+{
+ if (rrt32)
+ {
+ lo = (unsigned int)rrs32 / (unsigned int)rrt32;
+ hi = (unsigned int)rrs32 % (unsigned int)rrt32;
+ sign_extended(lo);
+ sign_extended(hi);
+ }
+ else DebugMessage(M64MSG_ERROR, "DIVU: divide by 0");
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DMULT)
+{
+ unsigned long long int op1, op2, op3, op4;
+ unsigned long long int result1, result2, result3, result4;
+ unsigned long long int temp1, temp2, temp3, temp4;
+ int sign = 0;
+
+ if (rrs < 0)
+ {
+ op2 = -rrs;
+ sign = 1 - sign;
+ }
+ else op2 = rrs;
+ if (rrt < 0)
+ {
+ op4 = -rrt;
+ sign = 1 - sign;
+ }
+ else op4 = rrt;
+
+ op1 = op2 & 0xFFFFFFFF;
+ op2 = (op2 >> 32) & 0xFFFFFFFF;
+ op3 = op4 & 0xFFFFFFFF;
+ op4 = (op4 >> 32) & 0xFFFFFFFF;
+
+ temp1 = op1 * op3;
+ temp2 = (temp1 >> 32) + op1 * op4;
+ temp3 = op2 * op3;
+ temp4 = (temp3 >> 32) + op2 * op4;
+
+ result1 = temp1 & 0xFFFFFFFF;
+ result2 = temp2 + (temp3 & 0xFFFFFFFF);
+ result3 = (result2 >> 32) + temp4;
+ result4 = (result3 >> 32);
+
+ lo = result1 | (result2 << 32);
+ hi = (result3 & 0xFFFFFFFF) | (result4 << 32);
+ if (sign)
+ {
+ hi = ~hi;
+ if (!lo) hi++;
+ else lo = ~lo + 1;
+ }
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DMULTU)
+{
+ unsigned long long int op1, op2, op3, op4;
+ unsigned long long int result1, result2, result3, result4;
+ unsigned long long int temp1, temp2, temp3, temp4;
+
+ op1 = rrs & 0xFFFFFFFF;
+ op2 = (rrs >> 32) & 0xFFFFFFFF;
+ op3 = rrt & 0xFFFFFFFF;
+ op4 = (rrt >> 32) & 0xFFFFFFFF;
+
+ temp1 = op1 * op3;
+ temp2 = (temp1 >> 32) + op1 * op4;
+ temp3 = op2 * op3;
+ temp4 = (temp3 >> 32) + op2 * op4;
+
+ result1 = temp1 & 0xFFFFFFFF;
+ result2 = temp2 + (temp3 & 0xFFFFFFFF);
+ result3 = (result2 >> 32) + temp4;
+ result4 = (result3 >> 32);
+
+ lo = result1 | (result2 << 32);
+ hi = (result3 & 0xFFFFFFFF) | (result4 << 32);
+
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DDIV)
+{
+ if (rrt)
+ {
+ lo = (long long int)rrs / (long long int)rrt;
+ hi = (long long int)rrs % (long long int)rrt;
+ }
+ else DebugMessage(M64MSG_ERROR, "DDIV: divide by 0");
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DDIVU)
+{
+ if (rrt)
+ {
+ lo = (unsigned long long int)rrs / (unsigned long long int)rrt;
+ hi = (unsigned long long int)rrs % (unsigned long long int)rrt;
+ }
+ else DebugMessage(M64MSG_ERROR, "DDIVU: divide by 0");
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(ADD)
+{
+ rrd32 = rrs32 + rrt32;
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(ADDU)
+{
+ rrd32 = rrs32 + rrt32;
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SUB)
+{
+ rrd32 = rrs32 - rrt32;
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SUBU)
+{
+ rrd32 = rrs32 - rrt32;
+ sign_extended(rrd);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(AND)
+{
+ rrd = rrs & rrt;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(OR)
+{
+ rrd = rrs | rrt;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(XOR)
+{
+ rrd = rrs ^ rrt;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(NOR)
+{
+ rrd = ~(rrs | rrt);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SLT)
+{
+ if (rrs < rrt) rrd = 1;
+ else rrd = 0;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(SLTU)
+{
+ if ((unsigned long long)rrs < (unsigned long long)rrt)
+ rrd = 1;
+ else rrd = 0;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DADD)
+{
+ rrd = rrs + rrt;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DADDU)
+{
+ rrd = rrs + rrt;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSUB)
+{
+ rrd = rrs - rrt;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSUBU)
+{
+ rrd = rrs - rrt;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(TEQ)
+{
+ if (rrs == rrt)
+ {
+ DebugMessage(M64MSG_ERROR, "trap exception in TEQ");
+ stop=1;
+ }
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSLL)
+{
+ rrd = rrt << rsa;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSRL)
+{
+ rrd = (unsigned long long)rrt >> rsa;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSRA)
+{
+ rrd = rrt >> rsa;
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSLL32)
+{
+ rrd = rrt << (32+rsa);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSRL32)
+{
+ rrd = (unsigned long long int)rrt >> (32+rsa);
+ ADD_TO_PC(1);
+}
+
+DECLARE_INSTRUCTION(DSRA32)
+{
+ rrd = (signed long long int)rrt >> (32+rsa);
+ ADD_TO_PC(1);
+}