CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/MIPS/MIPSDisVFPU.cpp
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include <cstring>18#include "Common/Data/Convert/SmallDataConvert.h"19#include "Common/StringUtils.h"20#include "Core/MIPS/MIPS.h"21#include "Core/MIPS/MIPSDis.h"22#include "Core/MIPS/MIPSTables.h"23#include "Core/MIPS/MIPSDebugInterface.h"24#include "Core/MIPS/MIPSVFPUUtils.h"2526#define _RS ((op>>21) & 0x1F)27#define _RT ((op>>16) & 0x1F)28#define _RD ((op>>11) & 0x1F)29#define _FS ((op>>11) & 0x1F)30#define _FT ((op>>16) & 0x1F)31#define _FD ((op>>6 ) & 0x1F)32#define _POS ((op>>6 ) & 0x1F)33#define _SIZE ((op>>11) & 0x1F)343536#define RN(i) (currentDebugMIPS->GetRegName(0, i).c_str())37#define FN(i) (currentDebugMIPS->GetRegName(1, i).c_str())38//#define VN(i) (currentDebugMIPS->GetRegName(2, i).c_str())394041#define S_not(a,b,c) (a<<2)|(b)|(c<<5)42#define SgetA(v) (((v)>>2)&0x7)43#define SgetB(v) ((v)&3)44#define SgetC(v) (((v)>>5)&0x3)4546#define HorizOff 3247#define VertOff 148#define MtxOff 44950inline std::string VNStr(int v, VectorSize size) {51static const char * const vfpuCtrlNames[VFPU_CTRL_MAX] = {52"SPFX",53"TPFX",54"DPFX",55"CC",56"INF4",57"RSV5",58"RSV6",59"REV",60"RCX0",61"RCX1",62"RCX2",63"RCX3",64"RCX4",65"RCX5",66"RCX6",67"RCX7",68};69if (size == V_Single && v >= 128 && v < 128 + VFPU_CTRL_MAX) {70return vfpuCtrlNames[v - 128];71} else if (size == V_Single && v == 255) {72return "(interlock)";73}7475return GetVectorNotation(v, size);76}7778inline std::string MNStr(int v, MatrixSize size) {79return GetMatrixNotation(v, size);80}8182#define VN(v, s) (VNStr(v, s).c_str())83#define MN(v, s) (MNStr(v, s).c_str())8485inline const char *VSuff(MIPSOpcode op)86{87int a = (op>>7)&1;88int b = (op>>15)&1;89a+=(b<<1);90switch (a)91{92case 0: return ".s";93case 1: return ".p";94case 2: return ".t";95case 3: return ".q";96default: return "%";97}98}99100namespace MIPSDis101{102std::string SignedHex(int i);103104void Dis_SV(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {105int offset = SignExtend16ToS32(op & 0xFFFC);106int vt = ((op>>16)&0x1f)|((op&3)<<5);107int rs = (op>>21) & 0x1f;108const char *name = MIPSGetName(op);109snprintf(out, outSize, "%s\t%s, %s(%s)", name, VN(vt, V_Single), SignedHex(offset).c_str(), RN(rs));110}111112void Dis_SVQ(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {113int offset = SignExtend16ToS32(op & 0xFFFC);114int vt = (((op>>16)&0x1f))|((op&1)<<5);115int rs = (op>>21) & 0x1f;116const char *name = MIPSGetName(op);117size_t outpos = 0;118outpos += snprintf(out, outSize, "%s\t%s, %s(%s)", name, VN(vt, V_Quad), SignedHex(offset).c_str(), RN(rs));119if ((op & 2) && outpos < outSize)120truncate_cpy(out + outpos, outSize - outpos, ", wb");121}122123void Dis_SVLRQ(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {124int offset = SignExtend16ToS32(op & 0xFFFC);125int vt = (((op>>16)&0x1f))|((op&1)<<5);126int rs = (op>>21) & 0x1f;127int lr = (op>>1)&1;128const char *name = MIPSGetName(op);129snprintf(out, outSize, "%s%s.q\t%s, %s(%s)", name, lr ? "r" : "l", VN(vt, V_Quad), SignedHex(offset).c_str(), RN(rs));130}131132void Dis_Mftv(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {133int vr = op & 0xFF;134int rt = _RT;135const char *name = MIPSGetName(op);136snprintf(out, outSize, "%s%s\t%s, %s", name, vr > 127 ? "c" : "", RN(rt), VN(vr, V_Single));137}138139void Dis_Vmfvc(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {140int vd = _VD;141int vr = (op >> 8) & 0x7F;142const char* name = MIPSGetName(op);143snprintf(out, outSize, "%s\t%s, %s", name, VN(vd, V_Single), VN(vr + 128, V_Single));144}145146void Dis_Vmtvc(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {147int vr = op & 0x7F;148int vs = _VS;149const char *name = MIPSGetName(op);150snprintf(out, outSize, "%s\t%s, %s", name, VN(vs, V_Single), VN(vr + 128, V_Single));151}152153void Dis_VPFXST(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {154int data = op & 0xFFFFF;155const char *name = MIPSGetName(op);156size_t outpos = snprintf(out, outSize, "%s\t[", name);157158static const char * const regnam[4] = {"X","Y","Z","W"};159static const char * const constan[8] = {"0","1","2","1/2","3","1/3","1/4","1/6"};160for (int i=0; i<4; i++)161{162int regnum = (data>>(i*2)) & 3;163int abs = (data>>(8+i)) & 1;164int negate = (data>>(16+i)) & 1;165int constants = (data>>(12+i)) & 1;166if (negate && outpos < outSize)167outpos += truncate_cpy(out + outpos, outSize - outpos, "-");168if (abs && !constants && outpos < outSize)169outpos += truncate_cpy(out + outpos, outSize - outpos, "|");170if (!constants) {171if (outpos < outSize)172outpos += truncate_cpy(out + outpos, outSize - outpos, regnam[regnum]);173} else {174if (abs)175regnum+=4;176if (outpos < outSize)177outpos += truncate_cpy(out + outpos, outSize - outpos, constan[regnum]);178}179if (abs && !constants && outpos < outSize)180outpos += truncate_cpy(out + outpos, outSize - outpos, "|");181if (i != 3 && outpos < outSize)182outpos += truncate_cpy(out + outpos, outSize - outpos, ",");183}184185if (outpos < outSize)186outpos += truncate_cpy(out + outpos, outSize - outpos, "]");187}188189void Dis_VPFXD(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {190int data = op & 0xFFFFF;191const char *name = MIPSGetName(op);192size_t outpos = snprintf(out, outSize, "%s\t[", name);193194static const char * const satNames[4] = {"", "0:1", "X", "-1:1"};195for (int i=0; i<4; i++)196{197int sat = (data>>i*2)&3;198int mask = (data>>(8+i))&1;199if (sat && outpos < outSize)200outpos += truncate_cpy(out + outpos, outSize - outpos, satNames[sat]);201if (mask && outpos < outSize)202outpos += truncate_cpy(out + outpos, outSize - outpos, "M");203if (i < 4 - 1 && outpos < outSize)204outpos += truncate_cpy(out + outpos, outSize - outpos, ",");205}206207if (outpos < outSize)208outpos += truncate_cpy(out + outpos, outSize - outpos, "]");209}210211212void Dis_Viim(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {213int vt = _VT;214int imm = SignExtend16ToS32(op & 0xFFFF);215const char *name = MIPSGetName(op);216217int type = (op >> 23) & 7;218if (type == 6)219snprintf(out, outSize, "%s\t%s, %i", name, VN(vt, V_Single), imm);220else if (type == 7)221snprintf(out, outSize, "%s\t%s, %f", name, VN(vt, V_Single), Float16ToFloat32((u16)imm));222else223snprintf(out, outSize, "%s\tARGH", name);224}225226void Dis_Vcst(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {227int conNum = (op>>16) & 0x1f;228int vd = _VD;229VectorSize sz = GetVecSize(op);230static const char * const constants[32] =231{232"(undef)",233"MaxFloat",234"Sqrt(2)",235"Sqrt(1/2)",236"2/Sqrt(PI)",237"2/PI",238"1/PI",239"PI/4",240"PI/2",241"PI",242"e",243"Log2(e)",244"Log10(e)",245"ln(2)",246"ln(10)",247"2*PI",248"PI/6",249"Log10(2)",250"Log2(10)",251"Sqrt(3)/2"252};253const char *name = MIPSGetName(op);254const char *c = constants[conNum];255if (c==0) c = constants[0];256snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd,sz), c);257}258259260void Dis_MatrixSet1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {261const char *name = MIPSGetName(op);262int vd = _VD;263MatrixSize sz = GetMtxSize(op);264snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), MN(vd, sz));265}266void Dis_MatrixSet2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {267const char *name = MIPSGetName(op);268int vd = _VD;269int vs = _VS;270MatrixSize sz = GetMtxSize(op);271snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), MN(vd, sz), MN(vs,sz));272}273void Dis_MatrixSet3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {274const char *name = MIPSGetName(op);275int vd = _VD;276int vs = _VS;277int vt = _VT;278MatrixSize sz = GetMtxSize(op);279snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(vs,sz), MN(vt,sz));280}281282void Dis_MatrixMult(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {283const char *name = MIPSGetName(op);284int vd = _VD;285int vs = _VS;286int vt = _VT;287MatrixSize sz = GetMtxSize(op);288// TODO: Xpose?289snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(Xpose(vs),sz), MN(vt,sz));290}291292void Dis_Vmscl(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {293const char *name = MIPSGetName(op);294int vd = _VD;295int vs = _VS;296int vt = _VT;297MatrixSize sz = GetMtxSize(op);298snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), MN(vd, sz), MN(vs, sz), VN(vt, V_Single));299}300301void Dis_VectorDot(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {302const char *name = MIPSGetName(op);303int vd = _VD;304int vs = _VS;305int vt = _VT;306VectorSize sz = GetVecSize(op);307snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz), VN(vt, sz));308}309310void Dis_Vtfm(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {311int vd = _VD;312int vs = _VS;313int vt = _VT;314int ins = (op>>23) & 7;315VectorSize sz = GetVecSize(op);316MatrixSize msz = GetMtxSize(op);317int n = GetNumVectorElements(sz);318319if (n == ins)320{321//homogenous322snprintf(out, outSize, "vhtfm%i%s\t%s, %s, %s", n, VSuff(op), VN(vd, sz), MN(vs, msz), VN(vt, sz));323}324else if (n == ins+1)325{326snprintf(out, outSize, "vtfm%i%s\t%s, %s, %s", n, VSuff(op), VN(vd, sz), MN(vs, msz), VN(vt, sz));327}328else329{330truncate_cpy(out, outSize, "BADVTFM");331}332}333334void Dis_Vflush(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {335truncate_cpy(out, outSize, "vflush");336}337338void Dis_Vcrs(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {339const char *name = MIPSGetName(op);340int vt = _VT;341int vs = _VS;342int vd = _VD;343VectorSize sz = GetVecSize(op);344if (sz != V_Triple)345{346truncate_cpy(out, outSize, "vcrs\tERROR");347}348else349snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz), VN(vt,sz));350}351352353void Dis_Vcmp(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {354const char *name = MIPSGetName(op);355int vt = _VT;356int vs = _VS;357int cond = op&15;358VectorSize sz = GetVecSize(op);359const char *condNames[16] = {"FL","EQ","LT","LE","TR","NE","GE","GT","EZ","EN","EI","ES","NZ","NN","NI","NS"};360snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), condNames[cond], VN(vs, sz), VN(vt,sz));361}362363void Dis_Vcmov(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {364const char *name = MIPSGetName(op);365VectorSize sz = GetVecSize(op);366int vd = _VD;367int vs = _VS;368int tf = (op >> 19)&3;369int imm3 = (op>>16)&7;370if (tf > 1)371{372snprintf(out, outSize, "%s\tARGH%i", name, tf);373return;374}375if (imm3<6)376snprintf(out, outSize, "%s%s%s\t%s, %s, CC[%i]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz), imm3);377else if (imm3 == 6)378snprintf(out, outSize, "%s%s%s\t%s, %s, CC[...]", name, tf==0?"t":"f", VSuff(op), VN(vd, sz), VN(vs,sz));379}380381void Dis_Vfad(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {382const char *name = MIPSGetName(op);383int vd = _VD;384int vs = _VS;385VectorSize sz = GetVecSize(op);386snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, V_Single), VN(vs,sz));387}388389void Dis_VScl(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {390const char *name = MIPSGetName(op);391int vd = _VD;392int vs = _VS;393int vt = _VT;394VectorSize sz = GetVecSize(op);395snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, V_Single));396}397398void Dis_VectorSet1(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {399const char *name = MIPSGetName(op);400int vd = _VD;401VectorSize sz = GetVecSize(op);402snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), VN(vd, sz));403}404void Dis_VectorSet2(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {405const char *name = MIPSGetName(op);406int vd = _VD;407int vs = _VS;408VectorSize sz = GetVecSize(op);409snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz));410}411void Dis_VectorSet3(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {412const char *name = MIPSGetName(op);413int vd = _VD;414int vs = _VS;415int vt = _VT;416VectorSize sz = GetVecSize(op);417snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz));418}419420void Dis_VRot(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {421int vd = _VD;422int vs = _VS;423int imm = (op>>16) & 0x1f;424bool negSin = (imm & 0x10) ? true : false;425char c[5] = "0000";426char temp[16]={""};427if (((imm>>2)&3)==(imm&3))428{429for (int i=0; i<4; i++)430c[i]='S';431}432c[(imm>>2) & 3] = 'S';433c[imm&3] = 'C';434VectorSize sz = GetVecSize(op);435int numElems = GetNumVectorElements(sz);436int pos = 0;437temp[pos++] = '[';438for (int i=0; i<numElems; i++)439{440if (c[i] == 'S' && negSin)441temp[pos++] = '-';442temp[pos++] = c[i];443if (i != numElems-1)444temp[pos++] = ',';445}446temp[pos++] = ']';447temp[pos]=0;448const char *name = MIPSGetName(op);449snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs, V_Single),temp);450}451452void Dis_CrossQuat(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {453VectorSize sz = GetVecSize(op);454const char *name;455switch (sz)456{457case V_Triple:458name = "vcrsp";459//Ah, a regular cross product.460break;461case V_Quad:462name = "vqmul";463//Ah, a quaternion multiplication.464break;465default:466// invalid467name = "???";468break;469}470int vd = _VD;471int vs = _VS;472int vt = _VT;473snprintf(out, outSize, "%s%s\t%s, %s, %s", name, VSuff(op), VN(vd, sz), VN(vs,sz), VN(vt, sz));474}475476void Dis_Vbfy(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {477VectorSize sz = GetVecSize(op);478int vd = _VD;479int vs = _VS;480const char *name = MIPSGetName(op);481snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz));482}483484void Dis_Vf2i(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {485VectorSize sz = GetVecSize(op);486int vd = _VD;487int vs = _VS;488int imm = (op>>16)&0x1f;489const char *name = MIPSGetName(op);490snprintf(out, outSize, "%s%s\t%s, %s, %i", name, VSuff(op), VN(vd, sz), VN(vs, sz), imm);491}492493void Dis_Vs2i(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {494VectorSize sz = GetVecSize(op);495int vd = _VD;496int vs = _VS;497const char *name = MIPSGetName(op);498snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, sz), VN(vs, sz));499}500501void Dis_Vi2x(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {502VectorSize sz = GetVecSize(op);503VectorSize dsz = GetHalfVectorSizeSafe(sz);504if (((op>>16)&3)==0)505dsz = V_Single;506507int vd = _VD;508int vs = _VS;509const char *name = MIPSGetName(op);510snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz));511}512513void Dis_Vwbn(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {514VectorSize sz = GetVecSize(op);515516int vd = _VD;517int vs = _VS;518int imm = (int)((op >> 16) & 0xFF);519const char *name = MIPSGetName(op);520snprintf(out, outSize, "%s%s\t%s, %s, %d", name, VSuff(op), VN(vd, sz), VN(vs, sz), imm);521}522523void Dis_Vf2h(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {524VectorSize sz = GetVecSize(op);525VectorSize dsz = GetHalfVectorSizeSafe(sz);526if (((op>>16)&3)==0)527dsz = V_Single;528529int vd = _VD;530int vs = _VS;531const char *name = MIPSGetName(op);532snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz));533}534535void Dis_Vh2f(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {536VectorSize sz = GetVecSize(op);537VectorSize dsz = GetDoubleVectorSizeSafe(sz);538539int vd = _VD;540int vs = _VS;541const char *name = MIPSGetName(op);542snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz));543}544545void Dis_ColorConv(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {546VectorSize sz = GetVecSize(op);547VectorSize dsz = GetHalfVectorSizeSafe(sz);548549int vd = _VD;550int vs = _VS;551const char *name = MIPSGetName(op);552snprintf(out, outSize, "%s%s\t%s, %s", name, VSuff(op), VN(vd, dsz), VN(vs, sz));553}554555void Dis_Vrnds(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {556int vd = _VD;557const char *name = MIPSGetName(op);558snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), VN(vd, V_Single));559}560561void Dis_VrndX(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {562VectorSize sz = GetVecSize(op);563564int vd = _VD;565const char *name = MIPSGetName(op);566snprintf(out, outSize, "%s%s\t%s", name, VSuff(op), VN(vd, sz));567}568569void Dis_VBranch(MIPSOpcode op, uint32_t pc, char *out, size_t outSize) {570u32 off = pc;571int imm = SignExtend16ToS32(op&0xFFFF) << 2;572int imm3 = (op>>18)&7;573off += imm + 4;574const char *name = MIPSGetName(op);575snprintf(out, outSize, "%s\t->$%08x (CC[%i])", name, off, imm3);576}577578}579580581