ARM64: More asimd scalar disasm, encoding fix

This commit is contained in:
Henrik Rydgard 2015-03-21 12:23:31 +01:00
parent 9f689b871a
commit 0f430e6cd1
3 changed files with 88 additions and 3 deletions

View File

@ -2157,7 +2157,7 @@ void ARM64FloatEmitter::EmitConvertScalarToInt(ARM64Reg Rd, ARM64Reg Rn, Roundin
else else
{ {
// Use the encoding (vector, single) that keeps the result in the fp register. // Use the encoding (vector, single) that keeps the result in the fp register.
int sz = Is64Bit(Rn); int sz = IsDouble(Rn);
Rd = DecodeReg(Rd); Rd = DecodeReg(Rd);
Rn = DecodeReg(Rn); Rn = DecodeReg(Rn);
int opcode = 0; int opcode = 0;

View File

@ -497,8 +497,91 @@ static void FPandASIMD2(uint32_t w, uint64_t addr, Instruction *instr) {
} }
} else if (((w >> 21) & 0x2F9) == 0xF8) { } else if (((w >> 21) & 0x2F9) == 0xF8) {
snprintf(instr->text, sizeof(instr->text), "(float data 3-source %08x)", w); snprintf(instr->text, sizeof(instr->text), "(float data 3-source %08x)", w);
} else if (((w >> 21) & 0x2F0) == 0x2F0) { } else if (((w >> 21) & 0x2F9) == 0x2F1) {
if (((w >> 10) & 3) == 0) {
snprintf(instr->text, sizeof(instr->text), "(asimd scalar three different %08x)", w);
} else if (((w >> 10) & 1) == 1) {
snprintf(instr->text, sizeof(instr->text), "(asimd scalar three same %08x)", w);
} else if (((w >> 10) & 3) == 2) {
// asimd scalar two-reg misc: This is a particularly sad and messy encoding :/
if (((w >> 17) & 0xf) == 0) {
int sz = (w >> 22) & 3;
char r = (sz & 1) ? 'd' : 's';
int opcode = (w >> 12) & 0x1f;
bool U = ((w >> 29) & 1);
const char *opname = NULL;
bool zero = false;
bool sign_suffix = false;
bool sign_prefix = false;
if ((sz & 2) == 0) {
switch (opcode) {
case 0x1a: opname = "fcvtn"; sign_suffix = true; break;
case 0x1b: opname = "fcvtm"; sign_suffix = true; break;
case 0x1c: opname = "fcvta"; sign_suffix = true; break;
case 0x1d: opname = "cvtf"; sign_prefix = true; break;
}
} else {
if (U == 0) {
switch (opcode) {
case 0xC: opname = "fcmgt"; zero = true; break;
case 0xD: opname = "fcmeq"; zero = true; break;
case 0xE: opname = "fcmlt"; zero = true; break;
case 0x1A: opname = "fcvtp"; sign_suffix = true; break;
case 0x1B: opname = "fcvtz"; sign_suffix = true; break;
}
} else {
switch (opcode) {
case 0x1A: opname = "fcvtp"; sign_suffix = true; break;
case 0x1B: opname = "fcvtz"; sign_suffix = true; break;
}
}
}
if (!opname) { // These ignore size.
if (U == 0) {
switch (opcode) {
case 3: opname = "suqadd"; break;
case 7: opname = "sqabs"; break;
case 8: opname = "cmgt"; zero = true; break;
case 9: opname = "cmeq"; zero = true; break;
case 0xa: opname = "cmlt"; zero = true; break;
case 0xb: opname = "abs"; break;
case 0xc: opname = "sqxtn?"; break;
}
} else {
switch (opcode) {
case 3: opname = "usqadd"; break;
case 7: opname = "sqneg"; break;
case 8: opname = "cmge"; zero = true; break;
case 9: opname = "cmle"; zero = true; break;
case 0xB: opname = "neg"; break;
case 0x12: opname = "sqxtun?"; break;
case 0x14: opname = "uqxtn?"; break;
}
}
}
if (opname) {
if (sign_suffix) {
char sign = U ? 'u' : 's';
snprintf(instr->text, sizeof(instr->text), "%s%c %c%d, %c%d", opname, sign, r, Rd, r, Rn);
} else if (sign_prefix) {
char sign = U ? 'u' : 's';
snprintf(instr->text, sizeof(instr->text), "%c%s %c%d, %c%d", sign, opname, r, Rd, r, Rn);
} else {
snprintf(instr->text, sizeof(instr->text), "%s (asimd scalar two-reg misc %08x)", opname, w);
}
} else {
snprintf(instr->text, sizeof(instr->text), "(asimd scalar two-reg misc %08x)", w);
}
} else if (((w >> 17) & 0xf) == 8) {
snprintf(instr->text, sizeof(instr->text), "(asimd scalar pair-wise %08x)", w);
} else {
snprintf(instr->text, sizeof(instr->text), "(asimd scalar stuff %08x)", w);
}
} else {
snprintf(instr->text, sizeof(instr->text), "(asimd stuff %08x)", w);
}
} else if (((w >> 21) & 0x2F1) == 0x2F0) {
// many lines // many lines
snprintf(instr->text, sizeof(instr->text), "(asimd stuff %08x)", w); snprintf(instr->text, sizeof(instr->text), "(asimd stuff %08x)", w);
} else { } else {

View File

@ -40,7 +40,9 @@ bool TestArm64Emitter() {
//fp.FMOV(32, false, X1, S3); //fp.FMOV(32, false, X1, S3);
//RET(CheckLast(emitter, "aa023be1 fmov x1, s3")); //RET(CheckLast(emitter, "aa023be1 fmov x1, s3"));
fp.FCVTS(S13, S12, ROUND_N); fp.FCVTS(S13, S12, ROUND_N);
RET(CheckLast(emitter, "7e21c98d fcvtns s13, s12")); RET(CheckLast(emitter, "5e21a98d fcvtns s13, s12"));
fp.FCVTS(D13, D12, ROUND_P);
RET(CheckLast(emitter, "5ee1a98d fcvtps d13, d12"));
fp.FCVTS(W13, S12, ROUND_N); fp.FCVTS(W13, S12, ROUND_N);
RET(CheckLast(emitter, "1e20018d fcvtns w13, s12")); RET(CheckLast(emitter, "1e20018d fcvtns w13, s12"));
fp.FCVTS(S22, S12, ROUND_Z); fp.FCVTS(S22, S12, ROUND_Z);