mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-28 10:51:06 +00:00
ARM64 emitter: Add MRS/MSR support (only for the flags register). Add some more to ARM64 Disasm
This commit is contained in:
parent
524583d53e
commit
f732fbb885
@ -909,6 +909,9 @@ void ARM64XEmitter::B(CCFlags cond, const void* ptr)
|
||||
|
||||
_assert_msg_(DYNA_REC, distance >= -0xFFFFF && distance < 0xFFFFF, "%s: Received too large distance: %lx", __FUNCTION__, (int)distance);
|
||||
|
||||
// Let's not overrun the opcode bits with the sign extension.
|
||||
distance &= 0x7FFFF;
|
||||
|
||||
Write32((0x54 << 24) | (distance << 5) | cond);
|
||||
}
|
||||
|
||||
@ -1007,18 +1010,41 @@ void ARM64XEmitter::_MSR(PStateField field, u8 imm)
|
||||
u32 op1 = 0, op2 = 0;
|
||||
switch (field)
|
||||
{
|
||||
case FIELD_SPSel:
|
||||
op1 = 0; op2 = 5;
|
||||
case FIELD_SPSel: op1 = 0; op2 = 5; break;
|
||||
case FIELD_DAIFSet: op1 = 3; op2 = 6; break;
|
||||
case FIELD_DAIFClr: op1 = 3; op2 = 7; break;
|
||||
default:
|
||||
_assert_msg_(JIT, false, "Invalid PStateField to do a imm move to");
|
||||
break;
|
||||
}
|
||||
EncodeSystemInst(0, op1, 4, imm, op2, WSP);
|
||||
}
|
||||
|
||||
static void GetSystemReg(PStateField field, int &o0, int &op1, int &CRn, int &CRm, int &op2) {
|
||||
switch (field) {
|
||||
case FIELD_NZCV:
|
||||
o0 = 3; op1 = 3; CRn = 4; CRm = 2; op2 = 0;
|
||||
break;
|
||||
case FIELD_DAIFSet:
|
||||
op1 = 3; op2 = 6;
|
||||
break;
|
||||
case FIELD_DAIFClr:
|
||||
op1 = 3; op2 = 7;
|
||||
default:
|
||||
_assert_msg_(JIT, false, "Invalid PStateField to do a register move from/to");
|
||||
break;
|
||||
}
|
||||
EncodeSystemInst(0, op1, 3, imm, op2, WSP);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::_MSR(PStateField field, ARM64Reg Rt) {
|
||||
int o0, op1, CRn, CRm, op2;
|
||||
_assert_msg_(JIT, Is64Bit(Rt), "MSR: Rt must be 64-bit");
|
||||
GetSystemReg(field, o0, op1, CRn, CRm, op2);
|
||||
EncodeSystemInst(o0, op1, CRn, CRm, op2, DecodeReg(Rt));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::MRS(ARM64Reg Rt, PStateField field) {
|
||||
int o0, op1, CRn, CRm, op2;
|
||||
_assert_msg_(JIT, Is64Bit(Rt), "MRS: Rt must be 64-bit");
|
||||
GetSystemReg(field, o0, op1, CRn, CRm, op2);
|
||||
EncodeSystemInst(o0 | 4, op1, CRn, CRm, op2, DecodeReg(Rt));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::HINT(SystemHint op)
|
||||
{
|
||||
EncodeSystemInst(0, 3, 2, 0, op, WSP);
|
||||
|
@ -129,6 +129,13 @@ enum ExtendType
|
||||
EXTEND_SXTX = 7,
|
||||
};
|
||||
|
||||
// The only system registers accessible from EL0 (user space)
|
||||
enum SystemRegister { // Three digits : Op1, CRm, Op2
|
||||
SYSREG_NZCV = 0x320,
|
||||
SYSREG_FPCR = 0x340,
|
||||
SYSREG_FPSR = 0x341,
|
||||
};
|
||||
|
||||
struct FixupBranch
|
||||
{
|
||||
u8* ptr;
|
||||
@ -157,6 +164,7 @@ enum PStateField
|
||||
FIELD_SPSel = 0,
|
||||
FIELD_DAIFSet,
|
||||
FIELD_DAIFClr,
|
||||
FIELD_NZCV,
|
||||
};
|
||||
|
||||
enum SystemHint
|
||||
@ -414,6 +422,10 @@ public:
|
||||
|
||||
// System
|
||||
void _MSR(PStateField field, u8 imm);
|
||||
|
||||
void _MSR(PStateField field, ARM64Reg Rt);
|
||||
void MRS(ARM64Reg Rt, PStateField field);
|
||||
|
||||
void HINT(SystemHint op);
|
||||
void CLREX();
|
||||
void DSB(BarrierType type);
|
||||
|
@ -16,7 +16,10 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
// Basic ARM64 disassembler.
|
||||
|
||||
// No promises of accuracy, mostly just made to debug JIT code.
|
||||
// Contains just enough to sort of understand what's going on without having to resort to an
|
||||
// external disassembler all the time...
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -43,8 +46,20 @@ static void BranchExceptionAndSystem(uint32_t w, uint64_t addr, Instruction *ins
|
||||
int offset = SignExtend26(w & 0x03FFFFFF) << 2;
|
||||
uint64_t target = addr + offset;
|
||||
snprintf(instr->text, sizeof(instr->text), "b%s %08x%08x", (w >> 31) ? "l" : "", (target >> 32), (target & 0xFFFFFFFF));
|
||||
} else if (((w >> 25) & 0x3F) == 0x1A) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(comp & branch %08x)", w);
|
||||
} else if (((w >> 25) & 0x3F) == 0x1B) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(test & branch %08x)", w);
|
||||
} else if (((w >> 25) & 0x7F) == 0x2A) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(cond-branch %08x)", w);
|
||||
} else if ((w >> 24) == 0xD4) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(exception-gen %08x)", w);
|
||||
} else if (((w >> 20) & 0xFFC) == 0xD50) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(system-reg %08x)", w);
|
||||
} else if (((w >> 25) & 0x7F) == 0x6B) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(branch-reg %08x)", w);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "(BRX %08x)", w);
|
||||
snprintf(instr->text, sizeof(instr->text), "(BRX ?? %08x)", w);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,12 +71,20 @@ static void DataProcessingRegister(uint32_t w, uint64_t addr, Instruction *instr
|
||||
int rd = w & 0x1F;
|
||||
int rn = (w >> 5) & 0x1F;
|
||||
int rm = (w >> 16) & 0x1F;
|
||||
char r = ((w >> 31) & 1) ? 'x' : 'w';
|
||||
|
||||
if (((w >> 21) & 0xF) == 9) {
|
||||
bool S = (w >> 29) & 1;
|
||||
char r = ((w >> 31) & 1) ? 'x' : 'w';
|
||||
bool sub = (w >> 30) & 1;
|
||||
snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, %c%d, %c%d", sub ? "sub" : "add", S ? "s" : "", r, rd, r, rn, r, rm);
|
||||
if (rd == 31 && S) {
|
||||
// It's a CMP
|
||||
snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, %c%d", "cmp", S ? "s" : "", r, rn, r, rm);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, %c%d, %c%d", sub ? "sub" : "add", S ? "s" : "", r, rd, r, rn, r, rm);
|
||||
}
|
||||
} else if (((w >> 23) & 0x3f) == 0x25) {
|
||||
int imm16 = (w >> 5) & 0xFFFF;
|
||||
snprintf(instr->text, sizeof(instr->text), "%s %c%d, 0x%04x", "movew", r, rd, imm16);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "(DPR %08x)", w);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user