@@ -743,7 +743,8 @@ class MipsArchitecture: public Architecture
743743 else
744744 {
745745 proceed = proceed && (left->operands [1 ].immediate == (right->operands [1 ].immediate + 7 ));
746- addrToUse = (uint32_t )addr + ((&instr == right) ? 0 : 8 );
746+ // addrToUse = (uint32_t)addr + ((&instr == right) ? 0 : 8);
747+ addrToUse = (uint32_t )addr + ((&instr == right) ? 0 : 4 );
747748 }
748749 base = right;
749750 }
@@ -781,17 +782,38 @@ class MipsArchitecture: public Architecture
781782 virtual bool GetInstructionText (const uint8_t * data, uint64_t addr, size_t & len, vector<InstructionTextToken>& result) override
782783 {
783784 Instruction instr;
784- char operand[64 ];
785+ char operand[64 ] = {0 };
786+ char operation[64 ] = {0 };
785787 char padding[9 ];
786788 const char * reg = NULL ;
789+ char dest[5 ] = {0 };
790+ int first_operand = 0 ;
787791 if (!Disassemble (data, addr, len, instr))
788792 return false ;
789793
790794 len = instr.size ;
791795 memset (padding, 0x20 , sizeof (padding));
792- const char * operation = get_operation (instr.operation );
793- if (operation == NULL )
796+ const char * operation_name = get_operation (instr.operation );
797+ if (operation_name == NULL )
794798 return false ;
799+ strlcpy (operation, operation_name, sizeof (operation));
800+
801+ if (instr.operands [0 ].operandClass == V_DEST)
802+ {
803+ char * p = dest;
804+ if (instr.operands [0 ].reg & 8 )
805+ *p++ = ' x' ;
806+ if (instr.operands [0 ].reg & 4 )
807+ *p++ = ' y' ;
808+ if (instr.operands [0 ].reg & 2 )
809+ *p++ = ' z' ;
810+ if (instr.operands [0 ].reg & 1 )
811+ *p++ = ' w' ;
812+ *p = ' \0 ' ;
813+ strcat (operation, " ." );
814+ strcat (operation, dest);
815+ first_operand++;
816+ }
795817
796818 size_t operationLen = strlen (operation);
797819 if (operationLen < 8 )
@@ -803,15 +825,17 @@ class MipsArchitecture: public Architecture
803825
804826 result.emplace_back (InstructionToken, operation);
805827 result.emplace_back (TextToken, padding);
806- for (size_t i = 0 ; i < MAX_OPERANDS; i++)
828+ for (size_t i = first_operand ; i < MAX_OPERANDS; i++)
807829 {
808830 if (instr.operands [i].operandClass == NONE)
809831 return true ;
810832
833+ operand[0 ] = ' \0 ' ;
834+
811835 int32_t imm = instr.operands [i].immediate ;
812836 uint64_t label_imm = instr.operands [i].immediate ;
813837
814- if (i != 0 )
838+ if (i != first_operand )
815839 result.emplace_back (OperandSeparatorToken, " , " );
816840
817841 switch (instr.operands [i].operandClass )
@@ -858,18 +882,15 @@ class MipsArchitecture: public Architecture
858882 break ;
859883 case MEM_IMM:
860884 result.emplace_back (BeginMemoryOperandToken, " " );
861- if (imm != 0 )
862- {
863- if (imm < -9 )
864- snprintf (operand, sizeof (operand), " -%#x" , -imm);
865- else if (imm < 0 )
866- snprintf (operand, sizeof (operand), " -%d" , -imm);
867- else if (imm < 10 )
868- snprintf (operand, sizeof (operand), " %d" , imm);
869- else
870- snprintf (operand, sizeof (operand), " %#x" , imm);
871- result.emplace_back (IntegerToken, operand, imm);
872- }
885+ if (imm < -9 )
886+ snprintf (operand, sizeof (operand), " -%#x" , -imm);
887+ else if (imm < 0 )
888+ snprintf (operand, sizeof (operand), " -%d" , -imm);
889+ else if (imm < 10 )
890+ snprintf (operand, sizeof (operand), " %d" , imm);
891+ else
892+ snprintf (operand, sizeof (operand), " %#x" , imm);
893+ result.emplace_back (IntegerToken, operand, imm);
873894 if (instr.operands [i].reg == REG_ZERO)
874895 break ;
875896 result.emplace_back (BraceToken, " (" );
@@ -895,6 +916,102 @@ class MipsArchitecture: public Architecture
895916 result.emplace_back (BraceToken, " )" );
896917 result.emplace_back (EndMemoryOperandToken, " " );
897918 break ;
919+ case V_REG:
920+ // #define V_FMT "$vf%02d" // Use this if leading zeroes are preferred
921+ #define V_FMT " $vf%d"
922+ reg = NULL ;
923+ if (instr.operands [i].reg >= REG_VP)
924+ reg = get_register ((Reg)instr.operands [i].reg );
925+ if (reg != NULL )
926+ {
927+ if (instr.operands [i].reg >= REG_VI0 && instr.operands [i].reg <= REG_VI15)
928+ {
929+ char reg_tmp[sizeof (operand)] = {0 };
930+ switch (instr.operation )
931+ {
932+ case MIPS_VLQI:
933+ case MIPS_VSQI:
934+ snprintf (reg_tmp, sizeof (reg_tmp), " (%s++)" , reg);
935+ reg = reg_tmp;
936+ break ;
937+ case MIPS_VLQD:
938+ case MIPS_VSQD:
939+ snprintf (reg_tmp, sizeof (reg_tmp), " (--%s)" , reg);
940+ reg = reg_tmp;
941+ break ;
942+ default :
943+ break ;
944+ }
945+ }
946+ else if (instr.operands [i].reg >= REG_VF0 && instr.operands [i].reg <= REG_VF31)
947+ {
948+ if (instr.operands [i].immediate > 0 && instr.operands [i].immediate <= 4 )
949+ snprintf (operand, sizeof (operand), " %s.%c" ,
950+ reg,
951+ " xyzw" [instr.operands [i].immediate -1 ]);
952+ else if (dest[0 ])
953+ snprintf (operand, sizeof (operand), " %s.%s" , reg, dest);
954+ }
955+ if (!operand[0 ])
956+ snprintf (operand, sizeof (operand), " %s" , reg);
957+ }
958+ // else if ((instr.operands[i].reg >= REG_VACC && instr.operands[i].reg <= REG_VI15) &&
959+ // (reg = get_register((Reg)instr.operands[i].reg)) != NULL)
960+ // {
961+ // // if (instr.operands[i].reg == REG_VACC && dest[0])
962+ // // snprintf(operand, sizeof(operand), "%s.%s", reg, dest);
963+ // // else
964+ // snprintf(operand, sizeof(operand), "%s", reg);
965+ // }
966+ else if (instr.operands [i].immediate > 0 && instr.operands [i].immediate <= 4 )
967+ snprintf (operand, sizeof (operand), V_FMT " .%c" ,
968+ instr.operands [i].reg ,
969+ " xyzw" [instr.operands [i].immediate -1 ]);
970+ else if (instr.operands [i].immediate == ' A' )
971+ {
972+ if (dest[0 ])
973+ snprintf (operand, sizeof (operand), " ACC.%s" , dest);
974+ else
975+ snprintf (operand, sizeof (operand), " ACC" );
976+ }
977+ else if (instr.operands [i].immediate > ' A' && instr.operands [i].immediate <= ' Z' )
978+ snprintf (operand, sizeof (operand), " %c" ,
979+ (char ) instr.operands [i].immediate );
980+ else if (dest[0 ])
981+ snprintf (operand, sizeof (operand), V_FMT " .%s" ,
982+ instr.operands [i].reg , dest);
983+ else
984+ snprintf (operand, sizeof (operand), V_FMT, instr.operands [i].reg );
985+ result.emplace_back (RegisterToken, operand);
986+ break ;
987+ case V_DEST:
988+ {
989+ char * p = dest;
990+ if (*p == ' \0 ' && (instr.operands [i].reg & 0xF ) != 0 )
991+ {
992+ if (instr.operands [i].reg & 8 )
993+ *p++ = ' x' ;
994+ if (instr.operands [i].reg & 4 )
995+ *p++ = ' y' ;
996+ if (instr.operands [i].reg & 2 )
997+ *p++ = ' z' ;
998+ if (instr.operands [i].reg & 1 )
999+ *p++ = ' w' ;
1000+ *p = ' \0 ' ;
1001+ }
1002+ break ;
1003+ }
1004+ case V_REG_FIELD:
1005+ {
1006+ snprintf (operand, sizeof (operand), V_FMT " .%c" ,
1007+ instr.operands [i].reg ,
1008+ " xyzw" [instr.operands [i].immediate ]);
1009+ // char *p = operand;
1010+ // *p++ = "xyzw"[instr.operands[i].reg];
1011+ // *p = '\0';
1012+ result.emplace_back (RegisterToken, operand);
1013+ break ;
1014+ }
8981015 default :
8991016 LogError (" operandClass %x\n " , instr.operands [i].operandClass );
9001017 return false ;
@@ -1016,14 +1133,17 @@ class MipsArchitecture: public Architecture
10161133 return " _countOnes32" ;
10171134 case CNMIPS_INTRIN_DPOP:
10181135 return " _countOnes64" ;
1136+
1137+ case MIPS_INTRIN_R5900_VWAITQ:
1138+ return " __vwaitq" ;
10191139 default :
10201140 return " " ;
10211141 }
10221142 }
10231143
10241144 virtual vector<uint32_t > GetAllIntrinsics () override
10251145 {
1026- return vector<uint32_t >{
1146+ auto intrinsics = vector<uint32_t >{
10271147 MIPS_INTRIN_WSBH,
10281148 MIPS_INTRIN_DSBH,
10291149 MIPS_INTRIN_DSHD,
@@ -1075,6 +1195,14 @@ class MipsArchitecture: public Architecture
10751195 CNMIPS_INTRIN_POP,
10761196 CNMIPS_INTRIN_DPOP,
10771197 };
1198+ if (m_version == MIPS_R5900)
1199+ {
1200+ auto r5900_intrinsics = {
1201+ MIPS_INTRIN_R5900_VWAITQ,
1202+ };
1203+ intrinsics.insert (intrinsics.end (), std::begin (r5900_intrinsics), std::end (r5900_intrinsics));
1204+ }
1205+ return intrinsics;
10781206 }
10791207
10801208 virtual vector<NameAndType> GetIntrinsicInputs (uint32_t intrinsic) override
@@ -1231,6 +1359,8 @@ class MipsArchitecture: public Architecture
12311359 return {
12321360 NameAndType (" index" , Type::IntegerType (8 , false )),
12331361 };
1362+
1363+ case MIPS_INTRIN_R5900_VWAITQ:
12341364 default :
12351365 return vector<NameAndType>();
12361366 }
@@ -1287,6 +1417,7 @@ class MipsArchitecture: public Architecture
12871417 };
12881418 case MIPS_INTRIN_TLBSEARCH:
12891419 return { Type::IntegerType (8 , false ) };
1420+ case MIPS_INTRIN_R5900_VWAITQ:
12901421 default :
12911422 return vector<Confidence<Ref<Type>>>();
12921423 }
@@ -1577,7 +1708,27 @@ class MipsArchitecture: public Architecture
15771708
15781709 if (m_version == MIPS_R5900) {
15791710 // TODO: R5900 has 128-bit wide GPRs, $lo and $hi are 128-bit, and $lo1 and $hi1 are the upper 64 bits of $lo and $hi
1580- uint32_t r5900_registers[] = { REG_LO1, REG_HI1 };
1711+ uint32_t r5900_registers[] = {
1712+ R5900_SA,
1713+ REG_LO1, REG_HI1,
1714+
1715+ REG_VP,
1716+
1717+ REG_VI0, REG_VI1, REG_VI2, REG_VI3, REG_VI4, REG_VI5, REG_VI6, REG_VI7, REG_VI8, REG_VI9,
1718+ REG_VI10, REG_VI11, REG_VI12, REG_VI13, REG_VI14, REG_VI15,
1719+ REG_VCCR_STATUS, REG_VCCR_MAC, REG_VCCR_CLIPPING, REG_VCCR_19,
1720+ REG_VR, // CCR[2,20]
1721+ REG_VI, // CCR[2,21]
1722+ REG_VQ, // CCR[2,22]
1723+ REG_VCCR_23, REG_VCCR_24, REG_VCCR_25, REG_VCCR_TPC, REG_VCCR_CMSAR0,
1724+ REG_VCCR_FBRST, REG_VCCR_VPU_STAT, REG_VCCR_30, REG_VCCR_CMSAR1,
1725+
1726+ REG_VACC,
1727+ REG_VF0, REG_VF1, REG_VF2, REG_VF3, REG_VF4, REG_VF5, REG_VF6, REG_VF7, REG_VF8, REG_VF9,
1728+ REG_VF10, REG_VF11, REG_VF12, REG_VF13, REG_VF14, REG_VF15, REG_VF16, REG_VF17, REG_VF18, REG_VF19,
1729+ REG_VF20, REG_VF21, REG_VF22, REG_VF23, REG_VF24, REG_VF25, REG_VF26, REG_VF27, REG_VF28, REG_VF29,
1730+ REG_VF30, REG_VF31,
1731+ };
15811732 registers.insert (registers.end (), std::begin (r5900_registers), std::end (r5900_registers));
15821733 }
15831734 else if ((m_decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0 )
@@ -1899,8 +2050,36 @@ class MipsArchitecture: public Architecture
18992050 };
19002051
19012052 if (m_version == MIPS_R5900) {
1902- uint32_t r5900_registers[] = { REG_LO1, REG_HI1 };
2053+ // TODO: R5900 has 128-bit wide GPRs, $lo and $hi are 128-bit, and $lo1 and $hi1 are the upper 64 bits of $lo and $hi
2054+ uint32_t r5900_registers[] = {
2055+ R5900_SA,
2056+ REG_LO1, REG_HI1,
2057+ REG_VP,
2058+
2059+ REG_VI0, REG_VI1, REG_VI2, REG_VI3, REG_VI4, REG_VI5, REG_VI6, REG_VI7, REG_VI8, REG_VI9,
2060+ REG_VI10, REG_VI11, REG_VI12, REG_VI13, REG_VI14, REG_VI15,
2061+ REG_VCCR_STATUS, REG_VCCR_MAC, REG_VCCR_CLIPPING, REG_VCCR_19,
2062+ REG_VR, // CCR[2,20]
2063+ REG_VI, // CCR[2,21]
2064+ REG_VQ, // CCR[2,22]
2065+ REG_VCCR_23, REG_VCCR_24, REG_VCCR_25, REG_VCCR_TPC, REG_VCCR_CMSAR0,
2066+ REG_VCCR_FBRST, REG_VCCR_VPU_STAT, REG_VCCR_30, REG_VCCR_CMSAR1,
2067+
2068+ REG_VACC,
2069+ REG_VF0, REG_VF1, REG_VF2, REG_VF3, REG_VF4, REG_VF5, REG_VF6, REG_VF7, REG_VF8, REG_VF9,
2070+ REG_VF10, REG_VF11, REG_VF12, REG_VF13, REG_VF14, REG_VF15, REG_VF16, REG_VF17, REG_VF18, REG_VF19,
2071+ REG_VF20, REG_VF21, REG_VF22, REG_VF23, REG_VF24, REG_VF25, REG_VF26, REG_VF27, REG_VF28, REG_VF29,
2072+ REG_VF30, REG_VF31,
2073+ };
19032074 registers.insert (registers.end (), std::begin (r5900_registers), std::end (r5900_registers));
2075+ constexpr auto _r5900_registers_vpu = []() {
2076+ vector<Reg> registers;
2077+ for (uint32_t i = REG_VACC_X; i < REG_VF31_XYZW; i++)
2078+ registers.push_back ((Reg) i);
2079+ return registers;
2080+ };
2081+ auto r5900_registers_vpu = _r5900_registers_vpu ();
2082+ registers.insert (registers.end (), r5900_registers_vpu.begin (), r5900_registers_vpu.end ());
19042083 }
19052084 else if ((m_decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0 )
19062085 {
@@ -2122,15 +2301,33 @@ class MipsArchitecture: public Architecture
21222301 case REG_LO1:
21232302 case REG_HI1:
21242303 // result.size = (128 / 2);
2304+ result.offset = 8 ;
21252305 if (reg == REG_LO1)
21262306 result.fullWidthRegister = REG_LO;
21272307 else if (reg == REG_HI1)
21282308 result.fullWidthRegister = REG_HI;
21292309 break ;
21302310 default :
2131- break ;
2132- // if (REG_ZERO <= reg && reg < REG_GP)
2133- // result.size = 128 / 8;
2311+ if (reg >= REG_VACC_X && reg <= REG_VF31_XYZW)
2312+ {
2313+ result.fullWidthRegister = REG_VACC + ((reg - REG_VACC_X) % 33 );
2314+ if (reg >= REG_VACC_Y && reg <= REG_VF31_Y)
2315+ result.offset = 4 ;
2316+ else if (reg >= REG_VACC_Z && reg <= REG_VF31_Z)
2317+ result.offset = 8 ;
2318+ else if (reg >= REG_VACC_W && reg <= REG_VF31_W)
2319+ result.offset = 12 ;
2320+
2321+ else if (reg >= REG_VACC_YZ && reg <= REG_VF31_YZ)
2322+ result.offset = 4 ;
2323+ else if (reg >= REG_VACC_ZW && reg <= REG_VF31_ZW)
2324+ result.offset = 12 ;
2325+
2326+ else if (reg >= REG_VACC_YZW && reg <= REG_VF31_YZW)
2327+ result.offset = 4 ;
2328+
2329+ // XXX: offsets are just wrong for discontinuous registers: XZ, XW, YW, XYW, XZW
2330+ }
21342331 }
21352332 }
21362333 return result;
0 commit comments