Skip to content

Commit d18788c

Browse files
committed
WIP [mips] Fixing PR for r5900: lots more lifting of v* instructions
1 parent 82e1420 commit d18788c

File tree

4 files changed

+316
-64
lines changed

4 files changed

+316
-64
lines changed

arch/mips/arch_mips.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ enum ElfMipsRelocationType : uint32_t
102102

103103
// This range is reserved for vendor specific relocations.
104104
R_MIPS_LOVENDOR = 100,
105+
R_MIPS_VCALLMS = 119, // MIPS R5900 (Emotion Engine) specific relocation for the Vector Unit (VU) micromode call instruction
105106
R_MIPS64_COPY = 125,
106107
R_MIPS_COPY = 126,
107108
R_MIPS_JUMP_SLOT = 127,
@@ -165,6 +166,7 @@ static const char* GetRelocationString(ElfMipsRelocationType rel)
165166
{ R_MIPS_TLS_TPREL_LO16, "R_MIPS_TLS_TPREL_LO16"},
166167
{ R_MIPS_GLOB_DAT, "R_MIPS_GLOB_DAT"},
167168
{ R_MIPS_LOVENDOR, "R_MIPS_LOVENDOR"},
169+
{ R_MIPS_VCALLMS, "R_MIPS_VCALLMS"},
168170
{ R_MIPS64_COPY, "R_MIPS64_COPY"},
169171
{ R_MIPS_COPY, "R_MIPS_COPY"},
170172
{ R_MIPS_JUMP_SLOT, "R_MIPS_JUMP_SLOT"},
@@ -932,11 +934,19 @@ class MipsArchitecture: public Architecture
932934
reg = get_register((Reg)instr.operands[i].reg);
933935
if (reg != NULL)
934936
{
937+
char reg_tmp[sizeof(operand)] = {0};
935938
if (instr.operands[i].reg >= REG_VI0 && instr.operands[i].reg <= REG_VI15)
936939
{
937-
char reg_tmp[sizeof(operand)] = {0};
938940
switch (instr.operation)
939941
{
942+
case MIPS_VISWR:
943+
case MIPS_VILWR:
944+
if (i == 2)
945+
{
946+
snprintf(reg_tmp, sizeof(reg_tmp), "(%s).%s", reg, dest);
947+
reg = reg_tmp;
948+
}
949+
break;
940950
case MIPS_VLQI:
941951
case MIPS_VSQI:
942952
snprintf(reg_tmp, sizeof(reg_tmp), "(%s++)", reg);
@@ -951,6 +961,10 @@ class MipsArchitecture: public Architecture
951961
break;
952962
}
953963
}
964+
if (reg == reg_tmp)
965+
{
966+
// Done
967+
}
954968
else if (instr.operands[i].reg >= REG_VF0 && instr.operands[i].reg <= REG_VF31)
955969
{
956970
if (instr.operands[i].immediate > 0 && instr.operands[i].immediate <= 4)
@@ -3386,6 +3400,7 @@ class MipsElfRelocationHandler: public RelocationHandler
33863400
dest64[0] = swap64(originalValue + displacement);
33873401
break;
33883402
}
3403+
case R_MIPS_LITERAL:
33893404
case R_MIPS_GPREL32:
33903405
{
33913406
if (!GetGpAddr(view, gpAddr))
@@ -3394,6 +3409,8 @@ class MipsElfRelocationHandler: public RelocationHandler
33943409
dest32[0] = swap(vRel32);
33953410
break;
33963411
}
3412+
case R_MIPS_VCALLMS:
3413+
break;
33973414
default:
33983415
break;
33993416
}
@@ -3473,6 +3490,10 @@ class MipsElfRelocationHandler: public RelocationHandler
34733490
case R_MIPS_HIGHER:
34743491
case R_MIPS_HIGHEST:
34753492
break;
3493+
case R_MIPS_VCALLMS:
3494+
break;
3495+
case R_MIPS_LITERAL:
3496+
break;
34763497
default:
34773498
result[i].type = UnhandledRelocation;
34783499
LogWarn("Unsupported relocation type: %llu (%s) @0x%llX", result[i].nativeType,

arch/mips/il.cpp

Lines changed: 117 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3687,7 +3687,47 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
36873687
))));
36883688
break;
36893689
}
3690-
3690+
case MIPS_PHMADH:
3691+
{
3692+
for (int i = 0; i < 4; i++)
3693+
{
3694+
if (i == 0)
3695+
il.AddInstruction(il.SetRegister(4, LLIL_TEMP(i),
3696+
il.Add(4,
3697+
il.Mult(4,
3698+
il.And(4, il.Register(16, op2.reg), il.Const(2, 0xFFFF)),
3699+
il.And(4, il.Register(16, op3.reg), il.Const(2, 0xFFFF))),
3700+
il.Mult(4,
3701+
il.And(4, il.LogicalShiftRight(16, il.Register(16, op2.reg), il.Const(1, i * 32 + 16)), il.Const(2, 0xFFFF)),
3702+
il.And(4, il.LogicalShiftRight(16, il.Register(16, op3.reg), il.Const(1, i * 32 + 16)), il.Const(2, 0xFFFF)))
3703+
)));
3704+
else
3705+
il.AddInstruction(il.SetRegister(4, LLIL_TEMP(i),
3706+
il.Add(4,
3707+
il.Mult(4,
3708+
il.And(4, il.LogicalShiftRight(16, il.Register(16, op2.reg), il.Const(1, i * 32)), il.Const(2, 0xFFFF)),
3709+
il.And(4, il.LogicalShiftRight(16, il.Register(16, op3.reg), il.Const(1, i * 32)), il.Const(2, 0xFFFF))),
3710+
il.Mult(4,
3711+
il.And(4, il.LogicalShiftRight(16, il.Register(16, op2.reg), il.Const(1, i * 32 + 16)), il.Const(2, 0xFFFF)),
3712+
il.And(4, il.LogicalShiftRight(16, il.Register(16, op3.reg), il.Const(1, i * 32 + 16)), il.Const(2, 0xFFFF)))
3713+
)));
3714+
}
3715+
il.AddInstruction(il.SetRegister(16, REG_LO, il.Or(16,
3716+
il.LowPart(4, il.Register(4, LLIL_TEMP(0))),
3717+
il.ShiftLeft(16, il.LowPart(4, il.Register(4, LLIL_TEMP(2))), il.Const(1, 64)))));
3718+
il.AddInstruction(il.SetRegister(16, REG_HI, il.Or(16,
3719+
il.LowPart(4, il.Register(4, LLIL_TEMP(1))),
3720+
il.ShiftLeft(16, il.LowPart(4, il.Register(4, LLIL_TEMP(3))), il.Const(1, 64)))));
3721+
il.AddInstruction(il.SetRegister(16, op1.reg,
3722+
il.Or(16,
3723+
il.Or(16,
3724+
il.LowPart(4, il.Register(4, LLIL_TEMP(0))),
3725+
il.ShiftLeft(4, il.LowPart(4, il.Register(4, LLIL_TEMP(1))), il.Const(1, 32))),
3726+
il.Or(16,
3727+
il.ShiftLeft(4, il.LowPart(4, il.Register(4, LLIL_TEMP(2))), il.Const(1, 64)),
3728+
il.ShiftLeft(4, il.LowPart(4, il.Register(4, LLIL_TEMP(3))), il.Const(1, 96))))));
3729+
break;
3730+
}
36913731

36923732
case MIPS_CTC1:
36933733
case MIPS_CTC2:
@@ -3859,7 +3899,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
38593899
case MIPS_PDIVW:
38603900
// case MIPS_PCPYLD:
38613901
case MIPS_PMADDH:
3862-
case MIPS_PHMADH:
3902+
// case MIPS_PHMADH:
38633903
// case MIPS_PAND:
38643904
// case MIPS_PXOR:
38653905
case MIPS_PMSUBH:
@@ -4219,13 +4259,13 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
42194259
{
42204260
unsigned char dest = op1.reg;
42214261
if (dest & (1 << 3))
4222-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_X, il.FloatAdd(4, il.Register(4, op2.reg + REG_VACC_X - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_X), il.Register(4, op4.reg + REG_VF0_X)))));
4262+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_X, il.FloatAdd(4, il.Register(4, REG_VACC_X), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_X), il.Register(4, op4.reg + REG_VF0_X)))));
42234263
if (dest & (1 << 2))
4224-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Y, il.FloatAdd(4, il.Register(4, op2.reg + REG_VACC_Y - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Y), il.Register(4, op4.reg + REG_VF0_Y)))));
4264+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Y, il.FloatAdd(4, il.Register(4, REG_VACC_Y), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Y), il.Register(4, op4.reg + REG_VF0_Y)))));
42254265
if (dest & (1 << 1))
4226-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Z, il.FloatAdd(4, il.Register(4, op2.reg + REG_VACC_Z - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Z), il.Register(4, op4.reg + REG_VF0_Z)))));
4266+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Z, il.FloatAdd(4, il.Register(4, REG_VACC_Z), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Z), il.Register(4, op4.reg + REG_VF0_Z)))));
42274267
if (dest & (1 << 0))
4228-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_W, il.FloatAdd(4, il.Register(4, op2.reg + REG_VACC_W - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_W), il.Register(4, op4.reg + REG_VF0_W)))));
4268+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_W, il.FloatAdd(4, il.Register(4, REG_VACC_W), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_W), il.Register(4, op4.reg + REG_VF0_W)))));
42294269
break;
42304270
}
42314271
case MIPS_VMADDA:
@@ -4245,13 +4285,13 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
42454285
{
42464286
unsigned char dest = op1.reg;
42474287
if (dest & (1 << 3))
4248-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_X, il.FloatSub(4, il.Register(4, op2.reg + REG_VACC_X - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_X), il.Register(4, op4.reg + REG_VF0_X)))));
4288+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_X, il.FloatSub(4, il.Register(4, REG_VACC_X), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_X), il.Register(4, op4.reg + REG_VF0_X)))));
42494289
if (dest & (1 << 2))
4250-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Y, il.FloatSub(4, il.Register(4, op2.reg + REG_VACC_Y - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Y), il.Register(4, op4.reg + REG_VF0_Y)))));
4290+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Y, il.FloatSub(4, il.Register(4, REG_VACC_Y), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Y), il.Register(4, op4.reg + REG_VF0_Y)))));
42514291
if (dest & (1 << 1))
4252-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Z, il.FloatSub(4, il.Register(4, op2.reg + REG_VACC_Z - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Z), il.Register(4, op4.reg + REG_VF0_Z)))));
4292+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Z, il.FloatSub(4, il.Register(4, REG_VACC_Z), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_Z), il.Register(4, op4.reg + REG_VF0_Z)))));
42534293
if (dest & (1 << 0))
4254-
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_W, il.FloatSub(4, il.Register(4, op2.reg + REG_VACC_W - REG_VACC), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_W), il.Register(4, op4.reg + REG_VF0_W)))));
4294+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_W, il.FloatSub(4, il.Register(4, REG_VACC_W), il.FloatMult(4, il.Register(4, op3.reg + REG_VF0_W), il.Register(4, op4.reg + REG_VF0_W)))));
42554295
break;
42564296
}
42574297
case MIPS_VMSUBA:
@@ -4392,6 +4432,34 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
43924432
break;
43934433
}
43944434

4435+
case MIPS_VILWR:
4436+
{
4437+
unsigned char dest = op1.reg;
4438+
if (dest & (1 << 3))
4439+
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op2.reg)}, MIPS_INTRIN_R5900_VU_MEM_LOAD, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 0)}));
4440+
if (dest & (1 << 2))
4441+
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op2.reg)}, MIPS_INTRIN_R5900_VU_MEM_LOAD, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 1)}));
4442+
if (dest & (1 << 1))
4443+
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op2.reg)}, MIPS_INTRIN_R5900_VU_MEM_LOAD, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 2)}));
4444+
if (dest & (1 << 0))
4445+
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op2.reg)}, MIPS_INTRIN_R5900_VU_MEM_LOAD, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 3)}));
4446+
break;
4447+
}
4448+
4449+
case MIPS_VISWR:
4450+
{
4451+
unsigned char dest = op1.reg;
4452+
if (dest & (1 << 3))
4453+
il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_R5900_VU_MEM_STORE, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 0), il.Register(4, op2.reg)}));
4454+
if (dest & (1 << 2))
4455+
il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_R5900_VU_MEM_STORE, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 1), il.Register(4, op2.reg)}));
4456+
if (dest & (1 << 1))
4457+
il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_R5900_VU_MEM_STORE, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 2), il.Register(4, op2.reg)}));
4458+
if (dest & (1 << 0))
4459+
il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_R5900_VU_MEM_STORE, {il.Mult(4, il.Register(4, op3.reg), il.Const(4, 16)), il.Const(2, 3), il.Register(4, op2.reg)}));
4460+
break;
4461+
}
4462+
43954463
case MIPS_VLQI:
43964464
case MIPS_VLQD:
43974465
{
@@ -4428,7 +4496,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
44284496

44294497
case MIPS_VCALLMS:
44304498
{
4431-
il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_R5900_VU0_CALLMS, {il.Const(4, op1.immediate)}));
4499+
il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_R5900_VU0_CALLMS, {il.Const(4, op1.immediate << 3)}));
44324500
break;
44334501
}
44344502
case MIPS_VCALLMSR:
@@ -4443,11 +4511,40 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
44434511
il.AddInstruction(il.SetRegister(2, op1.reg, il.Add(2, il.Register(2, op2.reg), ReadILOperand(il, instr, 3, 2, 1))));
44444512
break;
44454513
}
4446-
4514+
case MIPS_VFTOI0:
4515+
{
4516+
unsigned char dest = op1.reg;
4517+
if (dest & (1 << 3))
4518+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_X, il.FloatToInt(4, il.Register(4, op3.reg + REG_VF0_X))));
4519+
if (dest & (1 << 2))
4520+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Y, il.FloatToInt(4, il.Register(4, op3.reg + REG_VF0_Y))));
4521+
if (dest & (1 << 1))
4522+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Z, il.FloatToInt(4, il.Register(4, op3.reg + REG_VF0_Z))));
4523+
if (dest & (1 << 0))
4524+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_W, il.FloatToInt(4, il.Register(4, op3.reg + REG_VF0_W))));
4525+
break;
4526+
}
4527+
case MIPS_VITOF0:
4528+
{
4529+
unsigned char dest = op1.reg;
4530+
if (dest & (1 << 3))
4531+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_X, il.IntToFloat(4, il.Register(4, op3.reg + REG_VF0_X))));
4532+
if (dest & (1 << 2))
4533+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Y, il.IntToFloat(4, il.Register(4, op3.reg + REG_VF0_Y))));
4534+
if (dest & (1 << 1))
4535+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_Z, il.IntToFloat(4, il.Register(4, op3.reg + REG_VF0_Z))));
4536+
if (dest & (1 << 0))
4537+
il.AddInstruction(il.SetRegister(4, op2.reg + REG_VF0_W, il.IntToFloat(4, il.Register(4, op3.reg + REG_VF0_W))));
4538+
break;
4539+
}
4540+
case MIPS_VIOR:
4541+
{
4542+
il.AddInstruction(il.SetRegister(2, op1.reg, il.Or(2, il.Register(2, op2.reg), il.Register(2, op3.reg))));
4543+
break;
4544+
}
44474545
// case MIPS_VDIV:
44484546
// case MIPS_VIADD:
44494547
// case MIPS_VIADDI:
4450-
case MIPS_VIOR:
44514548
// case MIPS_VMADD:
44524549
// case MIPS_VMADDAx:
44534550
// case MIPS_VMADDAy:
@@ -4498,14 +4595,15 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
44984595
// case MIPS_VRSQRT:
44994596
// case MIPS_VSQRT:
45004597

4501-
case MIPS_VFTOI0:
4502-
case MIPS_VFTOI15:
4598+
45034599
case MIPS_VFTOI4:
4504-
case MIPS_VITOF0:
4505-
case MIPS_VITOF15:
4600+
case MIPS_VFTOI12:
4601+
case MIPS_VFTOI15:
45064602
case MIPS_VITOF4:
4507-
4508-
4603+
case MIPS_VITOF12:
4604+
case MIPS_VITOF15:
4605+
il.AddInstruction(il.Unimplemented());
4606+
break;
45094607

45104608
// instructions that are just internal placeholders for other
45114609
// decode tables; these will never be implemented because they're

0 commit comments

Comments
 (0)