mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-10 00:05:07 +00:00
ARM64 emitter: Fix UXTL/SXTL and friends. Add disasm.
This commit is contained in:
parent
853d6ea34b
commit
a3db3ed5c1
@ -2282,16 +2282,15 @@ void ARM64FloatEmitter::EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64R
|
||||
(imm8 << 13) | (1 << 12) | (imm5 << 5) | Rd);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::EmitShiftImm(bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
|
||||
void ARM64FloatEmitter::EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
|
||||
{
|
||||
bool quad = IsQuad(Rd);
|
||||
|
||||
_assert_msg_(DYNA_REC, immh, "%s bad encoding! Can't have zero immh", __FUNCTION__);
|
||||
|
||||
Rd = DecodeReg(Rd);
|
||||
Rn = DecodeReg(Rn);
|
||||
|
||||
Write32((quad << 30) | (U << 29) | (0xF << 24) | (immh << 19) | (immb << 16) | \
|
||||
Write32((Q << 30) | (U << 29) | (0xF << 24) | (immh << 19) | (immb << 16) | \
|
||||
(opcode << 11) | (1 << 10) | (Rn << 5) | Rd);
|
||||
}
|
||||
void ARM64FloatEmitter::EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn)
|
||||
@ -3193,7 +3192,7 @@ void ARM64FloatEmitter::ZIP2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||
}
|
||||
|
||||
// Shift by immediate
|
||||
void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
|
||||
void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, shift < src_size, "%s shift amount must less than the element size!", __FUNCTION__);
|
||||
u32 immh = 0;
|
||||
@ -3211,10 +3210,10 @@ void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
|
||||
{
|
||||
immh = 4 | ((shift >> 3) & 3);;
|
||||
}
|
||||
EmitShiftImm(0, immh, immb, 0x14, Rd, Rn);
|
||||
EmitShiftImm(upper, 0, immh, immb, 0x14, Rd, Rn);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
|
||||
void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
||||
{
|
||||
_assert_msg_(DYNA_REC, shift < src_size, "%s shift amount must less than the element size!", __FUNCTION__);
|
||||
u32 immh = 0;
|
||||
@ -3232,7 +3231,7 @@ void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
|
||||
{
|
||||
immh = 4 | ((shift >> 3) & 3);;
|
||||
}
|
||||
EmitShiftImm(1, immh, immb, 0x14, Rd, Rn);
|
||||
EmitShiftImm(upper, 1, immh, immb, 0x14, Rd, Rn);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
|
||||
@ -3253,17 +3252,17 @@ void ARM64FloatEmitter::SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift)
|
||||
{
|
||||
immh = 4 | ((shift >> 3) & 3);;
|
||||
}
|
||||
EmitShiftImm(1, immh, immb, 0x10, Rd, Rn);
|
||||
EmitShiftImm(IsQuad(Rd), 1, immh, immb, 0x10, Rd, Rn);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
|
||||
void ARM64FloatEmitter::SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper)
|
||||
{
|
||||
SSHLL(src_size, Rd, Rn, 0);
|
||||
SSHLL(src_size, Rd, Rn, 0, upper);
|
||||
}
|
||||
|
||||
void ARM64FloatEmitter::UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
|
||||
void ARM64FloatEmitter::UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper)
|
||||
{
|
||||
USHLL(src_size, Rd, Rn, 0);
|
||||
USHLL(src_size, Rd, Rn, 0, upper);
|
||||
}
|
||||
|
||||
// vector x indexed element
|
||||
|
@ -872,11 +872,11 @@ public:
|
||||
void ZIP2(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
|
||||
// Shift by immediate
|
||||
void SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift);
|
||||
void USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift);
|
||||
void SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper = false);
|
||||
void USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper = false);
|
||||
void SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift);
|
||||
void SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void SXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper = false);
|
||||
void UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper = false);
|
||||
|
||||
// vector x indexed element
|
||||
void FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index);
|
||||
@ -907,7 +907,7 @@ private:
|
||||
void EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
void EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64Reg Rd, u32 imm8);
|
||||
void EmitShiftImm(bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitLoadStoreMultipleStructure(u32 size, bool L, u32 opcode, ARM64Reg Rt, ARM64Reg Rn);
|
||||
void EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn);
|
||||
void EmitVectorxElement(bool U, u32 size, bool L, u32 opcode, bool H, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
|
||||
|
@ -197,7 +197,7 @@ static void BranchExceptionAndSystem(uint32_t w, uint64_t addr, Instruction *ins
|
||||
// Unconditional branch / branch+link
|
||||
int offset = SignExtend26(w) << 2;
|
||||
uint64_t target = addr + offset;
|
||||
snprintf(instr->text, sizeof(instr->text), "b%s %04x%08x", (w >> 31) ? "l" : "", (target >> 32), (target & 0xFFFFFFFF));
|
||||
snprintf(instr->text, sizeof(instr->text), "b%s %04x%08x", (w >> 31) ? "l" : "", (uint32_t)(target >> 32), (target & 0xFFFFFFFF));
|
||||
} else if (((w >> 25) & 0x3F) == 0x1A) {
|
||||
// Compare and branch
|
||||
int op = (w >> 24) & 1;
|
||||
@ -213,7 +213,7 @@ static void BranchExceptionAndSystem(uint32_t w, uint64_t addr, Instruction *ins
|
||||
int offset = SignExtend19(w >> 5) << 2;
|
||||
uint64_t target = addr + offset;
|
||||
int cond = w & 0xF;
|
||||
snprintf(instr->text, sizeof(instr->text), "b.%s %04x%08x", condnames[cond], (target >> 32), (target & 0xFFFFFFFF));
|
||||
snprintf(instr->text, sizeof(instr->text), "b.%s %04x%08x", condnames[cond], (uint32_t)(target >> 32), (target & 0xFFFFFFFF));
|
||||
} else if ((w >> 24) == 0xD4) {
|
||||
if (((w >> 21) & 0x7) == 1 && Rt == 0) {
|
||||
int imm = (w >> 5) & 0xFFFF;
|
||||
@ -544,7 +544,44 @@ static void FPandASIMD1(uint32_t w, uint64_t addr, Instruction *instr) {
|
||||
if (((w >> 19) & 0xf) == 0) {
|
||||
snprintf(instr->text, sizeof(instr->text), "(asimd modified immediate %08x)", w);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "(asimd shift-by-immediate %08x)", w);
|
||||
bool Q = GetQ(w);
|
||||
bool U = GetU(w);
|
||||
int immh = (w >> 19) & 0xf;
|
||||
int immb = (w >> 16) & 7;
|
||||
int opcode = (w >> 11) & 0x1f;
|
||||
const char *opnamesU0[32] = {
|
||||
"sshr", 0, "ssra", 0,
|
||||
"srshr", 0, "srsra", 0,
|
||||
0, 0, "shl", 0,
|
||||
0, 0, "sqshl", 0,
|
||||
"shrn", "rshrn", "sqshrn", "sqrshrn",
|
||||
"sshll", 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
"scvtf", 0, 0, "fcvtzs",
|
||||
};
|
||||
const char *opnamesU1[32] = {
|
||||
"ushr", 0, "usra", 0,
|
||||
"urshr", 0, "ursra", 0,
|
||||
"sri", 0, "sli", 0,
|
||||
"sqslu", 0, "uqshl", 0,
|
||||
"sqshrun", "sqrshrun", "uqshrn", "uqrshrn",
|
||||
"ushll", 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
"ucvtf", 0, 0, "fcvtzu",
|
||||
};
|
||||
const char *opname = U ? opnamesU1[opcode] : opnamesU0[opcode];
|
||||
const char *two = Q ? "2" : ""; // TODO: This doesn't apply to all the ops
|
||||
if (opname) {
|
||||
int esize = (8 << HighestSetBit(immh));
|
||||
int shift = ((immh << 3) | immb) - esize;
|
||||
if (shift == 0 && opcode == 0x14) {
|
||||
snprintf(instr->text, sizeof(instr->text), "%cxtl%s.%d.%d q%d, d%d", U ? 'u' : 's', two, esize * 2, esize, Rd, Rn);
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "%s%s.%d.%d q%d, d%d, #%d", opname, two, esize * 2, esize, Rd, Rn, shift);
|
||||
}
|
||||
} else {
|
||||
snprintf(instr->text, sizeof(instr->text), "(asimd shift-by-immediate %08x)", w);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bool Q = GetQ(w);
|
||||
|
@ -39,6 +39,10 @@ bool TestArm64Emitter() {
|
||||
ARM64XEmitter emitter((u8 *)code);
|
||||
ARM64FloatEmitter fp(&emitter);
|
||||
|
||||
fp.UXTL(8, Q1, D8);
|
||||
RET(CheckLast(emitter, "2f08a501 uxtl.16.8 q1, d8"));
|
||||
fp.LDR(16, INDEX_UNSIGNED, Q1, X1, 64);
|
||||
RET(CheckLast(emitter, "7d408021 ldr h1, [x1, #64]"));
|
||||
fp.FMLA(32, D1, D2, D3);
|
||||
RET(CheckLast(emitter, "0e23cc41 fmla.32 d1, d2, d3"));
|
||||
fp.FMLS(64, Q1, Q2, Q3);
|
||||
|
Loading…
x
Reference in New Issue
Block a user