Skip to content

Commit 1fe1a52

Browse files
committed
WIP [mips] Fixing PR for r5900: lots more lifting
1 parent b1f58dd commit 1fe1a52

File tree

5 files changed

+2798
-335
lines changed

5 files changed

+2798
-335
lines changed

arch/mips/arch_mips.cpp

Lines changed: 221 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)