Skip to content

Commit 1737cf9

Browse files
0cyngalenbwill
authored andcommitted
MIPS r5900 (PS2 EE) support
1 parent bf02a34 commit 1737cf9

File tree

4 files changed

+962
-69
lines changed

4 files changed

+962
-69
lines changed

arch/mips/arch_mips.cpp

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -179,27 +179,24 @@ static const char* GetRelocationString(ElfMipsRelocationType rel)
179179
class MipsArchitecture: public Architecture
180180
{
181181
protected:
182+
bool m_userWarnedAboutDelaySlots = false;
183+
MipsVersion m_version;
182184
size_t m_bits;
183185
BNEndianness m_endian;
184-
MipsVersion version_overwrite;
185186
uint32_t m_decomposeFlags;
186187

187188
virtual bool Disassemble(const uint8_t* data, uint64_t addr, size_t maxLen, Instruction& result)
188189
{
189-
MipsVersion version = version_overwrite;
190-
191190
memset(&result, 0, sizeof(result));
192-
if (m_bits == 64)
193-
{
194-
version = MIPS_64;
195-
}
196-
197-
if (mips_decompose((uint32_t*)data, maxLen, &result, version, addr, m_endian, m_decomposeFlags) != 0)
191+
if (mips_decompose((uint32_t*)data, maxLen, &result, m_bits == 64 ? MIPS_64 : MIPS_32, addr, m_endian, m_decomposeFlags) != 0)
198192
return false;
199193
return true;
200194
}
201195

202-
virtual size_t GetAddressSize() const override { return m_bits / 8; }
196+
virtual size_t GetAddressSize() const override
197+
{
198+
return m_bits / 8;
199+
}
203200

204201
size_t InstructionHasBranchDelay(const Instruction& instr)
205202
{
@@ -407,8 +404,8 @@ class MipsArchitecture: public Architecture
407404
}
408405

409406
public:
410-
MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits, MipsVersion version_in, uint32_t decomposeFlags = 0)
411-
: Architecture(name), m_bits(bits), m_endian(endian), version_overwrite(version_in), m_decomposeFlags(decomposeFlags)
407+
MipsArchitecture(const std::string& name, MipsVersion version, BNEndianness endian, size_t bits, uint32_t decomposeFlags = 0)
408+
: Architecture(name), m_version(version), m_bits(bits), m_endian(endian), m_decomposeFlags(decomposeFlags)
412409
{
413410
Ref<Settings> settings = Settings::Instance();
414411
uint32_t flag_pseudo_ops = settings->Get<bool>("arch.mips.disassembly.pseudoOps") ? DECOMPOSE_FLAGS_PSEUDO_OP : 0;
@@ -508,7 +505,16 @@ class MipsArchitecture: public Architecture
508505
{
509506
if (len < 8)
510507
{
511-
LogWarn("Can not lift instruction with delay slot @ 0x%08" PRIx64, addr);
508+
if (!m_userWarnedAboutDelaySlots)
509+
{
510+
511+
LogWarn("Can not lift instruction with delay slot @ 0x%08" PRIx64 "\n"
512+
"Any future delay slot errors will be printed as debug logs\n"
513+
"and can be viewed by setting the log capture level to debug.", addr);
514+
m_userWarnedAboutDelaySlots = true;
515+
}
516+
else
517+
LogDebug("Can not lift instruction with delay slot @ 0x%08" PRIx64, addr);
512518
return false;
513519
}
514520

@@ -847,15 +853,18 @@ class MipsArchitecture: public Architecture
847853
break;
848854
case MEM_IMM:
849855
result.emplace_back(BeginMemoryOperandToken, "");
850-
if (imm < -9)
851-
snprintf(operand, sizeof(operand), "-%#x", -imm);
852-
else if (imm < 0)
853-
snprintf(operand, sizeof(operand), "-%d", -imm);
854-
else if (imm < 10)
855-
snprintf(operand, sizeof(operand), "%d", imm);
856-
else
857-
snprintf(operand, sizeof(operand), "%#x", imm);
858-
result.emplace_back(IntegerToken, operand, imm);
856+
if (imm != 0)
857+
{
858+
if (imm < -9)
859+
snprintf(operand, sizeof(operand), "-%#x", -imm);
860+
else if (imm < 0)
861+
snprintf(operand, sizeof(operand), "-%d", -imm);
862+
else if (imm < 10)
863+
snprintf(operand, sizeof(operand), "%d", imm);
864+
else
865+
snprintf(operand, sizeof(operand), "%#x", imm);
866+
result.emplace_back(IntegerToken, operand, imm);
867+
}
859868
if (instr.operands[i].reg == REG_ZERO)
860869
break;
861870
result.emplace_back(BraceToken, "(");
@@ -3018,7 +3027,14 @@ class MipsElfRelocationHandler: public RelocationHandler
30183027
uint32_t inst2 = *(uint32_t*)(cur->relocationDataCache);
30193028
Instruction instruction;
30203029
memset(&instruction, 0, sizeof(instruction));
3021-
if (mips_decompose(&inst2, sizeof(uint32_t), &instruction, arch->GetAddressSize() == 8 ? MIPS_64 : MIPS_32, cur->address, arch->GetEndianness(), DECOMPOSE_FLAGS_PSEUDO_OP))
3030+
3031+
MipsVersion version;
3032+
if (arch->GetName().substr(0, 5) == "r5900")
3033+
version = MIPS_R5900;
3034+
else
3035+
version = arch->GetAddressSize() == 8 ? MIPS_64 : MIPS_32;
3036+
3037+
if (mips_decompose(&inst2, sizeof(uint32_t), &instruction, version, cur->address, arch->GetEndianness(), DECOMPOSE_FLAGS_PSEUDO_OP))
30223038
break;
30233039

30243040
int32_t immediate = swap(inst2) & 0xffff;
@@ -3195,8 +3211,6 @@ class MipsElfRelocationHandler: public RelocationHandler
31953211
case R_MIPS_LO16:
31963212
case R_MIPS_CALL16:
31973213
case R_MIPS_GOT16:
3198-
case R_MIPS_HIGHER:
3199-
case R_MIPS_HIGHEST:
32003214
result = BN_NOCOERCE_EXTERN_PTR;
32013215
break;
32023216
default:
@@ -3267,16 +3281,20 @@ extern "C"
32673281
{
32683282
InitMipsSettings();
32693283

3270-
Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32, MIPS_32);
3271-
Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32, MIPS_32);
3272-
Architecture* mips3 = new MipsArchitecture("mips3", BigEndian, 32, MIPS_3);
3273-
Architecture* mips3el = new MipsArchitecture("mipsel3", LittleEndian, 32, MIPS_3);
3274-
Architecture* mips64el = new MipsArchitecture("mipsel64", LittleEndian, 64, MIPS_64);
3275-
Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64, MIPS_64);
3276-
Architecture* cnmips64eb = new MipsArchitecture("cavium-mips64", BigEndian, 64, MIPS_64, DECOMPOSE_FLAGS_CAVIUM);
3284+
Architecture* mipsel = new MipsArchitecture("mipsel32", MIPS_32, LittleEndian, 32);
3285+
Architecture* mipseb = new MipsArchitecture("mips32", MIPS_32, BigEndian, 32);
3286+
Architecture* mips3 = new MipsArchitecture("mips3", MIPS_3, BigEndian, 32);
3287+
Architecture* mips3el = new MipsArchitecture("mipsel3", MIPS_3, LittleEndian, 32);
3288+
Architecture* mips64el = new MipsArchitecture("mipsel64", MIPS_64, LittleEndian, 64);
3289+
Architecture* mips64eb = new MipsArchitecture("mips64", MIPS_64, BigEndian, 64);
3290+
Architecture* cnmips64eb = new MipsArchitecture("cavium-mips64", MIPS_64, BigEndian, 64, DECOMPOSE_FLAGS_CAVIUM);
3291+
Architecture* r5900l = new MipsArchitecture("r5900l", MIPS_R5900, LittleEndian, 32);
3292+
Architecture* r5900b = new MipsArchitecture("r5900b", MIPS_R5900, BigEndian, 32);
32773293

3278-
Architecture::Register(mipseb);
32793294
Architecture::Register(mipsel);
3295+
Architecture::Register(mipseb);
3296+
Architecture::Register(r5900l);
3297+
Architecture::Register(r5900b);
32803298
Architecture::Register(mips3);
32813299
Architecture::Register(mips3el);
32823300
Architecture::Register(mips64el);
@@ -3294,44 +3312,58 @@ extern "C"
32943312
mipseb->SetDefaultCallingConvention(o32BE);
32953313
mipsel->RegisterCallingConvention(o32LE);
32963314
mipsel->SetDefaultCallingConvention(o32LE);
3315+
r5900l->RegisterCallingConvention(o32LE);
3316+
r5900l->SetDefaultCallingConvention(o32LE);
3317+
r5900b->RegisterCallingConvention(o32BE);
3318+
r5900b->SetDefaultCallingConvention(o32BE);
32973319
mips3->RegisterCallingConvention(o32BE);
32983320
mips3->SetDefaultCallingConvention(o32BE);
3299-
mips3->RegisterCallingConvention(o32LE);
3300-
mips3->SetDefaultCallingConvention(o32LE);
3321+
mips3el->RegisterCallingConvention(o32LE);
3322+
mips3el->SetDefaultCallingConvention(o32LE);
33013323
mips64el->RegisterCallingConvention(n64LE);
33023324
mips64el->SetDefaultCallingConvention(n64LE);
33033325
mips64eb->RegisterCallingConvention(n64BE);
33043326
mips64eb->SetDefaultCallingConvention(n64BE);
33053327
cnmips64eb->RegisterCallingConvention(n64BEc);
33063328
cnmips64eb->SetDefaultCallingConvention(n64BEc);
33073329

3308-
MipsLinuxSyscallCallingConvention* linuxSyscallLE = new MipsLinuxSyscallCallingConvention(mipsel);
33093330
MipsLinuxSyscallCallingConvention* linuxSyscallBE = new MipsLinuxSyscallCallingConvention(mipseb);
3331+
MipsLinuxSyscallCallingConvention* linuxSyscallLE = new MipsLinuxSyscallCallingConvention(mipsel);
33103332
mipseb->RegisterCallingConvention(linuxSyscallBE);
33113333
mipsel->RegisterCallingConvention(linuxSyscallLE);
3334+
MipsLinuxSyscallCallingConvention* linuxSyscallBE3 = new MipsLinuxSyscallCallingConvention(mips3);
3335+
MipsLinuxSyscallCallingConvention* linuxSyscallLE3 = new MipsLinuxSyscallCallingConvention(mips3el);
33123336
mips3->RegisterCallingConvention(linuxSyscallBE);
33133337
mips3el->RegisterCallingConvention(linuxSyscallLE);
3338+
MipsLinuxSyscallCallingConvention* linuxSyscallr5900LE = new MipsLinuxSyscallCallingConvention(r5900l);
3339+
MipsLinuxSyscallCallingConvention* linuxSyscallr5900BE = new MipsLinuxSyscallCallingConvention(r5900b);
3340+
r5900l->RegisterCallingConvention(linuxSyscallr5900LE);
3341+
r5900b->RegisterCallingConvention(linuxSyscallr5900BE);
33143342

3315-
mipseb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipseb));
33163343
mipsel->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipsel));
3344+
mipseb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipseb));
3345+
r5900l->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(r5900l));
3346+
r5900b->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(r5900b));
33173347
mips3->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips3));
33183348
mips3el->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips3el));
33193349
mips64el->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64el));
33203350
mips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64eb));
33213351
cnmips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(cnmips64eb));
33223352

33233353
/* function recognizers */
3324-
mipseb->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer());
33253354
mipsel->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer());
3355+
mipseb->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer());
33263356
mips3->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer());
33273357
mips3el->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer());
33283358

33293359
mipseb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
33303360
mipsel->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
33313361
mips3->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
33323362
mips3el->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
3333-
mips64el->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
33343363
mips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
3364+
mips64el->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
3365+
r5900l->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
3366+
r5900b->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
33353367
cnmips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
33363368

33373369
// Register the architectures with the binary format parsers so that they know when to use

arch/mips/il.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,6 +2159,42 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
21592159

21602160
break;
21612161

2162+
case MIPS_MTSAB:
2163+
{
2164+
auto gprValue = il.Register(4, op1.reg);
2165+
auto gprLS4 = il.And(4, gprValue, il.Const(4, 0xF));
2166+
2167+
// Extract least-significant 4 bits of immediate value
2168+
auto immLS4 = il.And(4, il.Const(4, op2.immediate), il.Const(4, 0xF));
2169+
2170+
// Perform XOR operation between GPR[rs][3:0] and immediate[3:0]
2171+
auto xorResult = il.Xor(4, gprLS4, immLS4);
2172+
2173+
// Multiply result by 8 (equivalent to left shift by 3)
2174+
auto shiftAmount = il.ShiftLeft(4, xorResult, il.Const(4, 3));
2175+
2176+
// Write the result to the SA register
2177+
il.AddInstruction(il.SetRegister(4, R5900_SA, shiftAmount));
2178+
2179+
break;
2180+
}
2181+
case MIPS_MTSAH:
2182+
{
2183+
auto rsVal = il.And(4, il.Register(4, op1.reg), il.Const(4, 0b111));
2184+
auto immVal = il.Const(4, op2.immediate & 0b111);
2185+
2186+
// Perform XOR
2187+
auto xorVal = il.Xor(4, rsVal, immVal);
2188+
2189+
// Multiply by 16
2190+
auto shiftAmount = il.Mult(4, xorVal, il.Const(4, 16));
2191+
2192+
// Set the SA register
2193+
il.AddInstruction(il.SetRegister(4, R5900_SA, shiftAmount));
2194+
2195+
break;
2196+
}
2197+
21622198
case MIPS_ADDR:
21632199
case MIPS_LDXC1:
21642200
case MIPS_LLO:

0 commit comments

Comments
 (0)