arch-arm: Add support of AArch32 VCVTA/P/N/M instructions. (#1533)

Add decoder and function of AArch32 VCVTA, VCVTP, VCVTN and VCVTM
instructions. Support both 16-bit and 32-bit variants.

Only support A32 encoding.

Change-Id: I6ece0e1b779f9a7cc9d709894a49a7fdcda28373
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
Giacomo Travaglini
2024-10-10 11:58:37 +02:00
committed by GitHub
2 changed files with 268 additions and 2 deletions

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2010-2011, 2016-2019 ARM Limited
// Copyright (c) 2010-2011, 2016-2019, 2024 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -1891,6 +1891,150 @@ let {{
return new NVrsqrteD<uint32_t>(machInst, vd, vm);
}
}
} else if ((b & 0x1c) == 0x00) {
if (bits(b, 1)) {
switch(size) {
case 1:
if (q) {
return new NVcvt2uhAQ<uint16_t>(machInst, vd, vm);
} else {
return new NVcvt2uhAD<uint16_t>(machInst, vd, vm);
}
case 2:
if (q) {
return new NVcvt2usAQ<uint32_t>(machInst, vd, vm);
} else {
return new NVcvt2usAD<uint32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0b01:
if (q) {
return new NVcvt2shAQ<int16_t>(machInst, vd, vm);
} else {
return new NVcvt2shAD<int16_t>(machInst, vd, vm);
}
case 0b10:
if (q) {
return new NVcvt2ssAQ<int32_t>(machInst, vd, vm);
} else {
return new NVcvt2ssAD<int32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
}
} else if ((b & 0x1c) == 0x04) {
if (bits(b, 1)) {
switch (size) {
case 0b01:
if (q) {
return new NVcvt2uhNQ<uint16_t>(machInst, vd, vm);
} else {
return new NVcvt2uhND<uint16_t>(machInst, vd, vm);
}
case 0b10:
if (q) {
return new NVcvt2usNQ<uint32_t>(machInst, vd, vm);
} else {
return new NVcvt2usND<uint32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0b01:
if (q) {
return new NVcvt2shNQ<int16_t>(machInst, vd, vm);
} else {
return new NVcvt2shND<int16_t>(machInst, vd, vm);
}
case 0b10:
if (q) {
return new NVcvt2ssNQ<int32_t>(machInst, vd, vm);
} else {
return new NVcvt2ssND<int32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
}
} else if ((b & 0x1c) == 0x08) {
if (bits(b, 1)) {
switch (size) {
case 0b01:
if (q) {
return new NVcvt2uhPQ<uint16_t>(machInst, vd, vm);
} else {
return new NVcvt2uhPD<uint16_t>(machInst, vd, vm);
}
case 0b10:
if (q) {
return new NVcvt2usPQ<uint32_t>(machInst, vd, vm);
} else {
return new NVcvt2usPD<uint32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0b01:
if (q) {
return new NVcvt2shPQ<int16_t>(machInst, vd, vm);
} else {
return new NVcvt2shPD<int16_t>(machInst, vd, vm);
}
case 0b10:
if (q) {
return new NVcvt2ssPQ<int32_t>(machInst, vd, vm);
} else {
return new NVcvt2ssPD<int32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
}
} else if ((b & 0x1c) == 0x0c) {
if (bits(b, 1)) {
switch (size) {
case 0b01:
if (q) {
return new NVcvt2uhMQ<uint16_t>(machInst, vd, vm);
} else {
return new NVcvt2uhMD<uint16_t>(machInst, vd, vm);
}
case 0b10:
if (q) {
return new NVcvt2usMQ<uint32_t>(machInst, vd, vm);
} else {
return new NVcvt2usMD<uint32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0b01:
if (q) {
return new NVcvt2shMQ<int16_t>(machInst, vd, vm);
} else {
return new NVcvt2shMD<int16_t>(machInst, vd, vm);
}
case 0b10:
if (q) {
return new NVcvt2ssMQ<int32_t>(machInst, vd, vm);
} else {
return new NVcvt2ssMD<int32_t>(machInst, vd, vm);
}
default:
return new Unknown(machInst);
}
}
} else {
return new Unknown(machInst);
}

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2010-2011, 2015, 2019 ARM Limited
// Copyright (c) 2010-2011, 2015, 2019, 2024 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -3579,6 +3579,128 @@ let {{
'''
twoRegLongMiscInst("vcvt", "NVcvth2s", "SimdCvtOp", ("uint16_t",), vcvth2sCode)
vcvthp2hCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
VfpSavedState state = prepFpState(fpscr.rMode);
__asm__ __volatile__("" : "=m" (srcElem1) : "m" (srcElem1));
float mid = vcvtFpHFpS(fpscr, fpscr.dn, fpscr.ahp, srcElem1);
if (flushToZero(mid))
fpscr.idc = 1;
destElem = vfpFpToFixed<float>(mid, %s, 16, 0, true, %s);
__asm__ __volatile__("" :: "m" (destElem));
finishVfp(fpscr, state, true);
FpscrExc = fpscr;
'''
vcvtahp2uhCode = vcvthp2hCode % ("false", "VfpRoundAway")
twoRegMiscInst("vcvta.u16.f16", "NVcvt2uhAD", "SimdCvtOp",
("uint16_t",), 2, vcvtahp2uhCode)
twoRegMiscInst("vcvta.u16.f16", "NVcvt2uhAQ", "SimdCvtOp",
("uint16_t",), 4, vcvtahp2uhCode)
vcvtnhp2uhCode = vcvthp2hCode % ("false", "VfpRoundNearest")
twoRegMiscInst("vcvtn.u16.f16", "NVcvt2uhND", "SimdCvtOp",
("uint16_t",), 2, vcvtnhp2uhCode)
twoRegMiscInst("vcvtn.u16.f16", "NVcvt2uhNQ", "SimdCvtOp",
("uint16_t",), 4, vcvtnhp2uhCode)
vcvtphp2uhCode = vcvthp2hCode % ("false", "VfpRoundUpward")
twoRegMiscInst("vcvtp.u16.f16", "NVcvt2uhPD", "SimdCvtOp",
("uint16_t",), 2, vcvtphp2uhCode)
twoRegMiscInst("vcvtp.u16.f16", "NVcvt2uhPQ", "SimdCvtOp",
("uint16_t",), 4, vcvtphp2uhCode)
vcvtmhp2uhCode = vcvthp2hCode % ("false", "VfpRoundDown")
twoRegMiscInst("vcvtm.u16.f16", "NVcvt2uhMD", "SimdCvtOp",
("uint16_t",), 2, vcvtmhp2uhCode)
twoRegMiscInst("vcvtm.u16.f16", "NVcvt2uhMQ", "SimdCvtOp",
("uint16_t",), 4, vcvtmhp2uhCode)
vcvtahp2shCode = vcvthp2hCode % ("true", "VfpRoundAway")
twoRegMiscInst("vcvta.s16.f16", "NVcvt2shAD", "SimdCvtOp",
("int16_t",), 2, vcvtahp2shCode)
twoRegMiscInst("vcvta.s16.f16", "NVcvt2shAQ", "SimdCvtOp",
("int16_t",), 4, vcvtahp2shCode)
vcvtnhp2shCode = vcvthp2hCode % ("true", "VfpRoundNearest")
twoRegMiscInst("vcvtn.s16.f16", "NVcvt2shND", "SimdCvtOp",
("int16_t",), 2, vcvtnhp2shCode)
twoRegMiscInst("vcvtn.s16.f16", "NVcvt2shNQ", "SimdCvtOp",
("int16_t",), 4, vcvtnhp2shCode)
vcvtphp2shCode = vcvthp2hCode % ("true", "VfpRoundUpward")
twoRegMiscInst("vcvtp.s16.f16", "NVcvt2shPD", "SimdCvtOp",
("int16_t",), 2, vcvtphp2shCode)
twoRegMiscInst("vcvtp.s16.f16", "NVcvt2shPQ", "SimdCvtOp",
("int16_t",), 4, vcvtphp2shCode)
vcvtmhp2shCode = vcvthp2hCode % ("true", "VfpRoundDown")
twoRegMiscInst("vcvtm.s16.f16", "NVcvt2shMD", "SimdCvtOp",
("int16_t",), 2, vcvtmhp2shCode)
twoRegMiscInst("vcvtm.s16.f16", "NVcvt2shMQ", "SimdCvtOp",
("int16_t",), 4, vcvtmhp2shCode)
vcvtsp2sCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
VfpSavedState state = prepFpState(fpscr.rMode);
__asm__ __volatile__("" : "=m" (srcElem1) : "m" (srcElem1));
float mid = bitsToFp(srcElem1, (float)0.0);
if (flushToZero(mid))
fpscr.idc = 1;
destElem = vfpFpToFixed<float>(mid, %s, 32, 0, true, %s);
__asm__ __volatile__("" :: "m" (destElem));
finishVfp(fpscr, state, true);
FpscrExc = fpscr;
'''
vcvtasp2usCode = vcvtsp2sCode % ("false", "VfpRoundAway")
twoRegMiscInst("vcvta.u32.f32", "NVcvt2usAD", "SimdCvtOp",
("uint32_t",), 2, vcvtasp2usCode)
twoRegMiscInst("vcvta.u32.f32", "NVcvt2usAQ", "SimdCvtOp",
("uint32_t",), 4, vcvtasp2usCode)
vcvtnsp2usCode = vcvtsp2sCode % ("false", "VfpRoundNearest")
twoRegMiscInst("vcvtn.u32.f32", "NVcvt2usND", "SimdCvtOp",
("uint32_t",), 2, vcvtnsp2usCode)
twoRegMiscInst("vcvtn.u32.f32", "NVcvt2usNQ", "SimdCvtOp",
("uint32_t",), 4, vcvtnsp2usCode)
vcvtpsp2usCode = vcvtsp2sCode % ("false", "VfpRoundUpward")
twoRegMiscInst("vcvtp.u32.f32", "NVcvt2usPD", "SimdCvtOp",
("uint32_t",), 2, vcvtpsp2usCode)
twoRegMiscInst("vcvtp.u32.f32", "NVcvt2usPQ", "SimdCvtOp",
("uint32_t",), 4, vcvtpsp2usCode)
vcvtmsp2usCode = vcvtsp2sCode % ("false", "VfpRoundDown")
twoRegMiscInst("vcvtm.u32.f32", "NVcvt2usMD", "SimdCvtOp",
("uint32_t",), 2, vcvtmsp2usCode)
twoRegMiscInst("vcvtm.u32.f32", "NVcvt2usMQ", "SimdCvtOp",
("uint32_t",), 4, vcvtmsp2usCode)
vcvtasp2ssCode = vcvtsp2sCode % ("true", "VfpRoundAway")
twoRegMiscInst("vcvta.s32.f32", "NVcvt2ssAD", "SimdCvtOp",
("int32_t",), 2, vcvtasp2ssCode)
twoRegMiscInst("vcvta.s32.f32", "NVcvt2ssAQ", "SimdCvtOp",
("int32_t",), 4, vcvtasp2ssCode)
vcvtnsp2ssCode = vcvtsp2sCode % ("true", "VfpRoundNearest")
twoRegMiscInst("vcvtn.s32.f32", "NVcvt2ssND", "SimdCvtOp",
("int32_t",), 2, vcvtnsp2ssCode)
twoRegMiscInst("vcvtn.s32.f32", "NVcvt2ssNQ", "SimdCvtOp",
("int32_t",), 4, vcvtnsp2ssCode)
vcvtpsp2ssCode = vcvtsp2sCode % ("true", "VfpRoundUpward")
twoRegMiscInst("vcvtp.s32.f32", "NVcvt2ssPD", "SimdCvtOp",
("int32_t",), 2, vcvtpsp2ssCode)
twoRegMiscInst("vcvtp.s32.f32", "NVcvt2ssPQ", "SimdCvtOp",
("int32_t",), 4, vcvtpsp2ssCode)
vcvtmsp2ssCode = vcvtsp2sCode % ("true", "VfpRoundDown")
twoRegMiscInst("vcvtm.s32.f32", "NVcvt2ssMD", "SimdCvtOp",
("int32_t",), 2, vcvtmsp2ssCode)
twoRegMiscInst("vcvtm.s32.f32", "NVcvt2ssMQ", "SimdCvtOp",
("int32_t",), 4, vcvtmsp2ssCode)
vrsqrteCode = '''
destElem = unsignedRSqrtEstimate(srcElem1);
'''