ARM64: Fix DUP disasm, INS disasm

This commit is contained in:
Henrik Rydgård 2015-04-04 22:15:58 +02:00 committed by Henrik Rydgard
parent a3db3ed5c1
commit 013bbc71af
4 changed files with 24 additions and 5 deletions

View file

@ -3518,6 +3518,14 @@ void ARM64FloatEmitter::MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch, bool
}
}
// TODO: Quite a few values could be generated easily using the MOVI instruction and friends.
void ARM64FloatEmitter::MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch) {
// TODO: Make it work with more element sizes
// TODO: Optimize - there are shorter solution for many values
MOVI2F(Rd, value, scratch);
DUP(32, Rd, Rd, 0);
}
void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) {
u32 val;
bool shift;

View file

@ -883,6 +883,7 @@ public:
void FMLA(u8 esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index);
void MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG, bool negate = false);
void MOVI2FDUP(ARM64Reg Rd, float value, ARM64Reg scratch = INVALID_REG);
// ABI related
void ABI_PushRegisters(BitSet32 registers);

View file

@ -533,12 +533,20 @@ static void FPandASIMD1(uint32_t w, uint64_t addr, Instruction *instr) {
int imm4 = (w >> 11) & 0xF;
int dst_index = imm5 >> (size + 1);
int src_index = imm4 >> size;
int op = (w >> 29) & 1;
char s = "bhsd"[size];
if (op == 0 && imm4 == 0) {
// DUP (element)
int idxdsize = (imm5 & 8) ? 128 : 64;
char r = "dq"[idxdsize == 128];
snprintf(instr->text, sizeof(instr->text), "dup %c%d, %c%d.%c[%d]", r, Rd, r, Rn, s, dst_index);
} else {
int idxdsize = (imm4 & 8) ? 128 : 64;
char s = "bhdx"[size];
char r = "dq"[idxdsize == 128];
snprintf(instr->text, sizeof(instr->text), "ins %c%d.%c[%d], %c%d.%c[%d]", r, Rd, s, dst_index, r, Rn, s, src_index);
}
}
}
} else if (((w >> 21) & 0x4F8) == 0x78) {
if ((w >> 10) & 1) {
if (((w >> 19) & 0xf) == 0) {

View file

@ -39,6 +39,8 @@ bool TestArm64Emitter() {
ARM64XEmitter emitter((u8 *)code);
ARM64FloatEmitter fp(&emitter);
fp.DUP(32, Q1, Q30, 3);
RET(CheckLast(emitter, "4e1c07c1 dup q1, q30.s[3]"));
fp.UXTL(8, Q1, D8);
RET(CheckLast(emitter, "2f08a501 uxtl.16.8 q1, d8"));
fp.LDR(16, INDEX_UNSIGNED, Q1, X1, 64);
@ -52,7 +54,7 @@ bool TestArm64Emitter() {
fp.FMUL(32, D1, D13, D21);
RET(CheckLast(emitter, "2e35dda1 fmul.32 d1, d13, d21"));
fp.INS(32, Q3, 1, Q12, 3);
RET(CheckLast(emitter, "6e0c6583 ins q3.d[1], q12.d[3]"));
RET(CheckLast(emitter, "6e0c6583 ins q3.s[1], q12.s[3]"));
fp.INS(8, D4, 5, D11, 2);
RET(CheckLast(emitter, "6e0b1564 ins d4.b[5], d11.b[2]"));
emitter.NEG(X1, X2);