ARM64 emitter: Fix UXTL/SXTL and friends. Add disasm.

This commit is contained in:
Henrik Rydgård 2015-04-04 21:18:30 +02:00 committed by Henrik Rydgard
parent 853d6ea34b
commit a3db3ed5c1
4 changed files with 60 additions and 20 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);