mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
ARM64 emitter: Default to non-extend instruction forms (LSL 0), fix bugs. also fixes to disasm.
This commit is contained in:
parent
d3669daba4
commit
70f44c3894
3 changed files with 59 additions and 41 deletions
|
@ -496,7 +496,7 @@ void ARM64XEmitter::EncodeArithmeticInst(u32 instenc, bool flags, ARM64Reg Rd, A
|
|||
Rn = DecodeReg(Rn);
|
||||
Rm = DecodeReg(Rm);
|
||||
Write32((b64Bit << 31) | (flags << 29) | (ArithEnc[instenc] << 21) | \
|
||||
(Option.GetType() == ArithOption::TYPE_EXTENDEDREG ? 1 << 21 : 0) | (Rm << 16) | Option.GetData() | (Rn << 5) | Rd);
|
||||
(Option.GetType() == ArithOption::TYPE_EXTENDEDREG ? (1 << 21) : 0) | (Rm << 16) | Option.GetData() | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::EncodeArithmeticCarryInst(u32 op, bool flags, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
|
@ -589,7 +589,7 @@ void ARM64XEmitter::EncodeLogicalInst(u32 instenc, ARM64Reg Rd, ARM64Reg Rn, ARM
|
|||
Rd = DecodeReg(Rd);
|
||||
Rm = DecodeReg(Rm);
|
||||
Rn = DecodeReg(Rn);
|
||||
Write32((b64Bit << 31) | (LogicalEnc[instenc][0] << 29) | (0x50 << 21) | (LogicalEnc[instenc][1] << 21) | \
|
||||
Write32((b64Bit << 31) | (LogicalEnc[instenc][0] << 29) | (0x5 << 25) | (LogicalEnc[instenc][1] << 21) | \
|
||||
Shift.GetData() | (Rm << 16) | (Rn << 5) | Rd);
|
||||
}
|
||||
|
||||
|
@ -1103,7 +1103,7 @@ void ARM64XEmitter::ISB(BarrierType type)
|
|||
// Add/Subtract (extended register)
|
||||
void ARM64XEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
ADD(Rd, Rn, Rm, ArithOption(Rd));
|
||||
ADD(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
|
||||
|
@ -1113,7 +1113,7 @@ void ARM64XEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Optio
|
|||
|
||||
void ARM64XEmitter::ADDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
EncodeArithmeticInst(0, true, Rd, Rn, Rm, ArithOption(Rd));
|
||||
EncodeArithmeticInst(0, true, Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::ADDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
|
||||
|
@ -1123,7 +1123,7 @@ void ARM64XEmitter::ADDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Opti
|
|||
|
||||
void ARM64XEmitter::SUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
SUB(Rd, Rn, Rm, ArithOption(Rd));
|
||||
SUB(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::SUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
|
||||
|
@ -1133,7 +1133,7 @@ void ARM64XEmitter::SUB(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Optio
|
|||
|
||||
void ARM64XEmitter::SUBS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
EncodeArithmeticInst(1, false, Rd, Rn, Rm, ArithOption(Rd));
|
||||
EncodeArithmeticInst(1, true, Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::SUBS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
|
||||
|
@ -1143,22 +1143,22 @@ void ARM64XEmitter::SUBS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Opti
|
|||
|
||||
void ARM64XEmitter::CMN(ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
CMN(Rn, Rm, ArithOption(Rn));
|
||||
CMN(Rn, Rm, ArithOption(Rn, ST_LSL, 0));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::CMN(ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
|
||||
{
|
||||
EncodeArithmeticInst(0, true, SP, Rn, Rm, Option);
|
||||
EncodeArithmeticInst(0, true, Is64Bit(Rn) ? ZR : WZR, Rn, Rm, Option);
|
||||
}
|
||||
|
||||
void ARM64XEmitter::CMP(ARM64Reg Rn, ARM64Reg Rm)
|
||||
{
|
||||
CMP(Rn, Rm, ArithOption(Rn));
|
||||
CMP(Rn, Rm, ArithOption(Rn, ST_LSL, 0));
|
||||
}
|
||||
|
||||
void ARM64XEmitter::CMP(ARM64Reg Rn, ARM64Reg Rm, ArithOption Option)
|
||||
{
|
||||
EncodeArithmeticInst(1, true, SP, Rn, Rm, Option);
|
||||
EncodeArithmeticInst(1, true, Is64Bit(Rn) ? ZR : WZR, Rn, Rm, Option);
|
||||
}
|
||||
|
||||
// Add/Subtract (with carry)
|
||||
|
|
|
@ -133,14 +133,6 @@ enum ShiftAmount
|
|||
SHIFT_48 = 3,
|
||||
};
|
||||
|
||||
enum ExtendType
|
||||
{
|
||||
EXTEND_UXTW = 2,
|
||||
EXTEND_LSL = 3, // Default for zero shift amount
|
||||
EXTEND_SXTW = 6,
|
||||
EXTEND_SXTX = 7,
|
||||
};
|
||||
|
||||
// The only system registers accessible from EL0 (user space)
|
||||
enum SystemRegister { // Three digits : Op1, CRm, Op2
|
||||
SYSREG_NZCV = 0x320,
|
||||
|
@ -272,6 +264,7 @@ public:
|
|||
m_width = WIDTH_32BIT;
|
||||
m_extend = EXTEND_UXTW;
|
||||
}
|
||||
m_shifttype = ST_LSL;
|
||||
}
|
||||
ArithOption(ARM64Reg Rd, ShiftType shift_type, u32 shift)
|
||||
{
|
||||
|
@ -532,14 +525,14 @@ public:
|
|||
void BICS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shift);
|
||||
|
||||
// Wrap the above for saner syntax
|
||||
void AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { AND(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void BIC(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { BIC(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void ORR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { ORR(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void ORN(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { ORN(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void EOR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EOR(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void EON(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EON(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void ANDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { ANDS(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void BICS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { BICS(Rd, Rn, Rm, ArithOption(Rd, 0)); }
|
||||
void AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { AND(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
void BIC(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { BIC(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
void ORR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { ORR(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
void ORN(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { ORN(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
void EOR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EOR(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
void EON(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { EON(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
void ANDS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { ANDS(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
void BICS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) { BICS(Rd, Rn, Rm, ArithOption(Rd, ST_LSL, 0)); }
|
||||
|
||||
// Convenience wrappers around ORR. These match the official convenience syntax.
|
||||
void MOV(ARM64Reg Rd, ARM64Reg Rm);
|
||||
|
|
|
@ -33,6 +33,9 @@ struct Instruction {
|
|||
bool oddbits;
|
||||
};
|
||||
|
||||
static const char * const shiftnames[4] = { "lsl", "lsr", "asr", "ror" };
|
||||
static const char * const extendnames[8] = { "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx" };
|
||||
|
||||
int SignExtend26(int x) {
|
||||
return (x & 0x02000000) ? (0xFC000000 | x) : (x & 0x3FFFFFF);
|
||||
}
|
||||
|
@ -58,14 +61,14 @@ int HighestSetBit(int value) {
|
|||
return highest;
|
||||
}
|
||||
|
||||
uint64_t Ones(int len) {
|
||||
static uint64_t Ones(int len) {
|
||||
if (len == 0x40) {
|
||||
return 0xFFFFFFFFFFFFFFFF;
|
||||
}
|
||||
return (1ULL << len) - 1;
|
||||
}
|
||||
|
||||
uint64_t Replicate(uint64_t value, int esize) {
|
||||
static uint64_t Replicate(uint64_t value, int esize) {
|
||||
uint64_t out = 0;
|
||||
value &= Ones(esize);
|
||||
for (int i = 0; i < 64; i += esize) {
|
||||
|
@ -74,7 +77,7 @@ uint64_t Replicate(uint64_t value, int esize) {
|
|||
return out;
|
||||
}
|
||||
|
||||
uint64_t ROR(uint64_t value, int amount, int esize) {
|
||||
static uint64_t ROR(uint64_t value, int amount, int esize) {
|
||||
uint64_t rotated = (value >> amount) | (value << (esize - amount));
|
||||
return rotated & Ones(esize);
|
||||
}
|
||||
|
@ -144,8 +147,9 @@ static void DataProcessingImmediate(uint32_t w, uint64_t addr, Instruction *inst
|
|||
int op = (w >> 30) & 1;
|
||||
int imm = ((w >> 10) & 0xFFF);
|
||||
int shift = ((w >> 22) & 0x3) * 16;
|
||||
const char *s = ((w >> 29) & 1) ? "s" : "";
|
||||
imm <<= shift;
|
||||
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d, #%d", op == 0 ? "add" : "sub", r, Rd, r, Rn, imm);
|
||||
snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, %c%d, #%d", op == 0 ? "add" : "sub", s, r, Rd, r, Rn, imm);
|
||||
} else if (((w >> 23) & 0x3f) == 0x24) {
|
||||
int immr = (w >> 16) & 0x3f;
|
||||
int imms = (w >> 10) & 0x3f;
|
||||
|
@ -249,16 +253,7 @@ static void DataProcessingRegister(uint32_t w, uint64_t addr, Instruction *instr
|
|||
int Rm = (w >> 16) & 0x1F;
|
||||
char r = ((w >> 31) & 1) ? 'x' : 'w';
|
||||
|
||||
if (((w >> 21) & 0xF) == 9) {
|
||||
bool S = (w >> 29) & 1;
|
||||
bool sub = (w >> 30) & 1;
|
||||
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 >> 21) & 0x2FF) == 0x2D6) {
|
||||
if (((w >> 21) & 0x2FF) == 0x2D6) {
|
||||
// Data processing
|
||||
int opcode2 = (w >> 16) & 0x1F;
|
||||
if (opcode2 == 0) {
|
||||
|
@ -281,12 +276,42 @@ static void DataProcessingRegister(uint32_t w, uint64_t addr, Instruction *instr
|
|||
if (opc == 2 && Rn == 31) {
|
||||
// Special case for MOV (which is constructed from an ORR)
|
||||
snprintf(instr->text, sizeof(instr->text), "mov %c%d, %c%d", r, Rd, r, Rm);
|
||||
} else if (imm6 == 0) {
|
||||
} else if (imm6 == 0 && shift == 0) {
|
||||
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d, %c%d", opnames[opc], r, Rd, r, Rn, r, Rm);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "(logical-shifted-register %08x", w);
|
||||
}
|
||||
} else if (((w >> 24) & 0x1f) == 0xB) {
|
||||
// Arithmetic (shifted register)
|
||||
bool S = (w >> 29) & 1;
|
||||
int shift = (w >> 22) & 0x3;
|
||||
int imm6 = (w >> 10) & 0x3f;
|
||||
int opc = ((w >> 29) & 3);
|
||||
const char *opnames[8] = { "add", "adds", "sub", "subs"};
|
||||
if (imm6 == 0 && shift == 0) {
|
||||
if (Rd == 31 && opc == 3) {
|
||||
// It's a CMP
|
||||
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d", "cmp", r, Rn, r, Rm);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "%s %c%d, %c%d, %c%d", opnames[opc], r, Rd, r, Rn, r, Rm);
|
||||
}
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "(logical-shifted-register %08x", w);
|
||||
}
|
||||
} else if (((w >> 21) & 0xF) == 9) {
|
||||
// Add/sub (extended register)
|
||||
bool S = (w >> 29) & 1;
|
||||
bool sub = (w >> 30) & 1;
|
||||
int option = (w >> 13) & 0x7;
|
||||
int imm3 = (w >> 10) & 0x7;
|
||||
if (Rd == 31 && sub && S) {
|
||||
// It's a CMP
|
||||
snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, %c%d, %s", "cmp", S ? "s" : "", r, Rn, r, Rm, extendnames[option]);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "%s%s %c%d, %c%d, %c%d, %s", sub ? "sub" : "add", S ? "s" : "", r, Rd, r, Rn, r, Rm, extendnames[option]);
|
||||
}
|
||||
} else {
|
||||
// Logical (extended register)
|
||||
snprintf(instr->text, sizeof(instr->text), "(DPR %08x)", w);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue