X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Fmupen64plus-rsp-z64%2Fsrc%2Frsp_opinfo.cpp;fp=source%2Fmupen64plus-rsp-z64%2Fsrc%2Frsp_opinfo.cpp;h=d02b5617ed444073d99d8bec18a3170e789f3311;hb=fc5d46b49a19d41f9f2da5a9336daec452900475;hp=0000000000000000000000000000000000000000;hpb=292f9317f53c38c181439013be7276f86517fd6b;p=mupen64plus-pandora.git diff --git a/source/mupen64plus-rsp-z64/src/rsp_opinfo.cpp b/source/mupen64plus-rsp-z64/src/rsp_opinfo.cpp new file mode 100644 index 0000000..d02b561 --- /dev/null +++ b/source/mupen64plus-rsp-z64/src/rsp_opinfo.cpp @@ -0,0 +1,560 @@ +/* + * z64 + * + * Copyright (C) 2007 ziggy + * + * 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. + * +**/ + +#include "rsp_opinfo.h" + +static const int vector_elements_2[16][8] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7 }, // none + { 0, 1, 2, 3, 4, 5, 6, 7 }, // ??? + { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q + { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q + { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h + { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h + { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h + { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h + { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 + { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1 + { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2 + { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3 + { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4 + { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5 + { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6 + { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7 +}; + +void rsp_get_opinfo(UINT32 op, rsp_opinfo_t * info) +{ + int op2; + int i; + info->op = op; + switch (op>>26) { + case 0: /* SPECIAL */ + op2 = RSP_SPECIAL_OFFS + (op&0x3f); + break; + case 0x12: /* COP2 */ + if (((op>>21)&0x1f) >= 0x10) + op2 = RSP_COP2_2_OFFS + (op & 0x3f); + else + op2 = RSP_COP2_1_OFFS + ((op >> 21) & 0x1f); + break; + case 0x32: /* LWC2 */ + op2 = RSP_LWC2_OFFS + ((op>>11)&0x1f); + break; + case 0x3a: /* SWC2 */ + op2 = RSP_SWC2_OFFS + ((op>>11)&0x1f); + break; + default: + op2 = RSP_BASIC_OFFS + (op>>26); + if (op2 == RSP_REGIMM) { + switch (RTREG) + { + case 0x00: /* BLTZ */ + op2 = RSP_BLTZ; + break; + case 0x01: /* BGEZ */ + op2 = RSP_BGEZ; + break; + case 0x11: /* BGEZAL */ + op2 = RSP_BGEZAL; + break; + } + } + } + info->op2 = op2; + + memset(&info->used, 0, sizeof(info->used)); + memset(&info->set, 0, sizeof(info->set)); + info->used.accu = info->used.flag = 0; + info->set.accu = info->set.flag = 0; + info->flags = 0; + + int dest = (op >> 16) & 0x1f; + int index = (op >> 7) & 0xf; + int offset = (op & 0x7f); + if (offset & 0x40) + offset |= 0xffffffc0; + + switch(op2) { + case RSP_SPECIAL: + case RSP_BLTZ: + info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_USEPC; + break; + case RSP_BGEZ: + info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_USEPC; + break; + case RSP_BGEZAL: + info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_LINK | RSP_OPINFO_USEPC; + break; + case RSP_J: + info->flags = RSP_OPINFO_JUMP; + break; + case RSP_JAL: + info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_LINK | RSP_OPINFO_USEPC; + break; + case RSP_BEQ: + case RSP_BNE: + case RSP_BLEZ: + case RSP_BGTZ: + info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_COND | RSP_OPINFO_USEPC; + break; + case RSP_ADDI: + case RSP_ADDIU: + case RSP_SLTI: + case RSP_SLTIU: + case RSP_ANDI: + case RSP_ORI: + case RSP_XORI: + case RSP_LUI: + case RSP_COP0: + case RSP_LB: + case RSP_LH: + case RSP_LW: + case RSP_LBU: + case RSP_LHU: + case RSP_SB: + case RSP_SH: + case RSP_SW: + break; + + case RSP_SLL: + case RSP_SRL: + case RSP_SRA: + case RSP_SLLV: + case RSP_SRLV: + case RSP_SRAV: + break; + + case RSP_JR: + info->flags = RSP_OPINFO_JUMP; + break; + case RSP_JALR: + info->flags = RSP_OPINFO_JUMP | RSP_OPINFO_LINK | RSP_OPINFO_USEPC; + break; + case RSP_BREAK: + info->flags = RSP_OPINFO_BREAK; + break; + + case RSP_ADD: + case RSP_ADDU: + case RSP_SUB: + case RSP_SUBU: + case RSP_AND: + case RSP_OR: + case RSP_XOR: + case RSP_NOR: + case RSP_SLT: + case RSP_SLTU: + break; + + case RSP_MFC2: + { + int el = op >> 7; + RSP_SET_VEC_I(info->used, VS1REG, ((el+0)&0xf)>>1); + RSP_SET_VEC_I(info->used, VS1REG, ((el+1)&0xf)>>1); + break; + } + case RSP_CFC2: + RSP_SET_FLAG_I(info->used, RDREG & 3); + break; + case RSP_MTC2: + { + int el = op >> 7; + RSP_SET_VEC_I(info->set, VS1REG, ((el+0)&0xf)>>1); + RSP_SET_VEC_I(info->set, VS1REG, ((el+1)&0xf)>>1); + break; + } + case RSP_CTC2: + RSP_SET_FLAG_I(info->set, RDREG & 3); + break; + + + case RSP_LBV: + RSP_SET_VEC_I(info->set, dest, index>>1); + break; + case RSP_LSV: + for (i=index; iset, dest, (i>>1)&7); + break; + case RSP_LLV: + for (i=index; iset, dest, (i>>1)&7); + break; + case RSP_LDV: + for (i=index; iset, dest, (i>>1)&7); + break; + case RSP_LQV: + case RSP_LRV: + // WARNING WARNING WARNING + // we assume this instruction always used to load the full vector + // i.e. the address is always 16 bytes aligned + // for (i=0; i<8; i++) + // RSP_SET_VEC_I(info->set, dest, i); + break; + case RSP_LPV: + case RSP_LUV: + case RSP_LHV: + case RSP_LWV: + for (i=0; i<8; i++) + RSP_SET_VEC_I(info->set, dest, i); + break; + case RSP_LFV: + for (i=(index>>1); i<(index>>1)+4; i++) + RSP_SET_VEC_I(info->set, dest, i); + break; + case RSP_LTV: + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset | + // -------------------------------------------------- + // + // Loads one element to maximum of 8 vectors, while incrementing element index + + // FIXME: has a small problem with odd indices + + int element; + int vs = dest; + int ve = dest + 8; + if (ve > 32) + ve = 32; + + element = 7 - (index >> 1); + + if (index & 1) + log(M64MSG_ERROR, "RSP: LTV: index = %d\n", index); + + for (i=vs; i < ve; i++) + { + element = ((8 - (index >> 1) + (i-vs)) << 1); + RSP_SET_VEC_I(info->set, i, (element & 0xf)>>1); + RSP_SET_VEC_I(info->set, i, ((element+1) & 0xf)>>1); + } + break; + } + + case RSP_SBV: + RSP_SET_VEC_I(info->used, dest, index>>1); + break; + case RSP_SSV: + for (i=index; iused, dest, (i>>1)&7); + break; + case RSP_SLV: + for (i=index; iused, dest, (i>>1)&7); + break; + case RSP_SDV: + for (i=index; iused, dest, (i>>1)&7); + break; + case RSP_SQV: + case RSP_SRV: + // WARNING WARNING WARNING + // we assume this instruction always used to store the full vector + // i.e. the address is always 16 bytes aligned + for (i=0; i<8; i++) + RSP_SET_VEC_I(info->used, dest, i); + break; + case RSP_SPV: + case RSP_SUV: + case RSP_SHV: + case RSP_SWV: + for (i=0; i<8; i++) + RSP_SET_VEC_I(info->used, dest, i); + break; + case RSP_SFV: + for (i=(index>>1); i<(index>>1)+4; i++) + RSP_SET_VEC_I(info->used, dest, i); + break; + case RSP_STV: + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset | + // -------------------------------------------------- + // + // Stores one element from maximum of 8 vectors, while incrementing element index + + int element; + int vs = dest; + int ve = dest + 8; + if (ve > 32) + ve = 32; + + element = 8 - (index >> 1); + if (index & 0x1) + log(M64MSG_ERROR, "RSP: STV: index = %d at %08X\n", index, rsp.ppc); + + for (i=vs; i < ve; i++) + { + RSP_SET_VEC_I(info->used, i, element & 0x7); + element++; + } + break; + } + + case RSP_VMULF: + case RSP_VMULU: + case RSP_VMUDL: + case RSP_VMUDM: + case RSP_VMUDN: + case RSP_VMUDH: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 14); + } + break; + } + case RSP_VMACF: + case RSP_VMACU: + case RSP_VMADL: + case RSP_VMADM: + case RSP_VMADN: + case RSP_VMADH: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->used, i, 14); + RSP_SET_ACCU_I(info->set, i, 14); + } + break; + } + case RSP_VADD: + case RSP_VSUB: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + RSP_SET_FLAG_I(info->used, 0); + RSP_SET_FLAG_I(info->set, 0); + break; + } + case RSP_VABS: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + break; + } + case RSP_VADDC: + case RSP_VSUBC: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + RSP_SET_FLAG_I(info->set, 0); + break; + } + case RSP_VSAW: + switch (EL) + { + case 0x08: // VSAWH + { + for (i=0; i < 8; i++) + { + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->used, i, 8); + } + break; + } + case 0x09: // VSAWM + { + for (i=0; i < 8; i++) + { + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->used, i, 4); + } + break; + } + case 0x0a: // VSAWL + { + for (i=0; i < 8; i++) + { + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->used, i, 2); + } + break; + } + default: + log(M64MSG_ERROR, "RSP: VSAW: el = %d\n", EL); + } + break; + case RSP_VLT: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + RSP_SET_FLAG_I(info->set, 0); + RSP_SET_FLAG_I(info->set, 1); + break; + } + case RSP_VEQ: + case RSP_VNE: + case RSP_VGE: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + RSP_SET_FLAG_I(info->used, 0); + RSP_SET_FLAG_I(info->set, 0); + RSP_SET_FLAG_I(info->set, 1); + break; + } + case RSP_VCL: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + RSP_SET_FLAG_I(info->used, 0); + RSP_SET_FLAG_I(info->used, 1); + RSP_SET_FLAG_I(info->set, 0); + RSP_SET_FLAG_I(info->set, 1); + RSP_SET_FLAG_I(info->set, 2); + break; + } + case RSP_VCH: + case RSP_VCR: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + RSP_SET_FLAG_I(info->set, 0); + RSP_SET_FLAG_I(info->set, 1); + RSP_SET_FLAG_I(info->set, 2); + break; + } + case RSP_VMRG: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + RSP_SET_FLAG_I(info->used, 1); + break; + } + case RSP_VAND: + case RSP_VNAND: + case RSP_VOR: + case RSP_VNOR: + case RSP_VXOR: + case RSP_VNXOR: + { + for (i=0; i < 8; i++) + { + int sel = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS1REG, i); + RSP_SET_VEC_I(info->used, VS2REG, sel); + RSP_SET_VEC_I(info->set, VDREG, i); + RSP_SET_ACCU_I(info->set, i, 2); + } + break; + } + case RSP_VRCP: + case RSP_VRCPL: + case RSP_VRCPH: + case RSP_VRSQL: + case RSP_VRSQH: + { + int del = (VS1REG & 7); + int sel = VEC_EL_2(EL, del); + + RSP_SET_VEC_I(info->used, VS2REG, sel); + + for (i=0; i < 8; i++) + { + int element = VEC_EL_2(EL, i); + RSP_SET_VEC_I(info->used, VS2REG, element); + RSP_SET_ACCU_I(info->set, i, 2); + } + + RSP_SET_VEC_I(info->set, VDREG, del); + break; + } + case RSP_VMOV: + { + int element = VS1REG & 7; + RSP_SET_VEC_I(info->used, VS2REG, VEC_EL_2(EL, 7-element)); + RSP_SET_VEC_I(info->set, VDREG, element); + break; + } + + default: + { + // char string[200]; + // rsp_dasm_one(string, 0x800, op); + // if (strcmp(string, "???")) { + // printf("%s\n", string); + // printf("unimplemented opcode\n"); + // } + break; + } + } +}