47a48,93
> output header {{
>
> template<template <typename T> class Base>
> StaticInstPtr
> newNeonMemInst(const unsigned size,
> const ExtMachInst &machInst,
> const RegIndex dest, const RegIndex ra,
> const uint32_t imm, const unsigned extraMemFlags)
> {
> switch (size) {
> case 0:
> return new Base<uint8_t>(machInst, dest, ra, imm, extraMemFlags);
> case 1:
> return new Base<uint16_t>(machInst, dest, ra, imm, extraMemFlags);
> case 2:
> return new Base<uint32_t>(machInst, dest, ra, imm, extraMemFlags);
> case 3:
> return new Base<uint64_t>(machInst, dest, ra, imm, extraMemFlags);
> default:
> panic("Unrecognized width %d for Neon mem inst.\n", (1 << size));
> }
> }
>
> template<template <typename T> class Base>
> StaticInstPtr
> newNeonMixInst(const unsigned size,
> const ExtMachInst &machInst,
> const RegIndex dest, const RegIndex op1,
> const uint32_t step)
> {
> switch (size) {
> case 0:
> return new Base<uint8_t>(machInst, dest, op1, step);
> case 1:
> return new Base<uint16_t>(machInst, dest, op1, step);
> case 2:
> return new Base<uint32_t>(machInst, dest, op1, step);
> case 3:
> return new Base<uint64_t>(machInst, dest, op1, step);
> default:
> panic("Unrecognized width %d for Neon mem inst.\n", (1 << size));
> }
> }
>
> }};
>
62,63c108,110
< const bool a = bits(machInst, 23);
< const bool l = bits(machInst, 21);
---
> const bool single = bits(machInst, 23);
> const bool singleAll = single && (bits(b, 3, 2) == 3);
> const bool load = bits(machInst, 21);
65,78c112,158
< if (l) {
< // Load instructions.
< if (a) {
< if (bits(b, 3, 2) != 3) {
< switch (bits(b, 1, 0)) {
< case 0x0:
< return new WarnUnimplemented("vld1 single", machInst);
< case 0x1:
< return new WarnUnimplemented("vld2 single", machInst);
< case 0x2:
< return new WarnUnimplemented("vld3 single", machInst);
< case 0x3:
< return new WarnUnimplemented("vld4 single", machInst);
< }
---
> unsigned width = 0;
>
> if (single) {
> width = bits(b, 1, 0) + 1;
> } else {
> switch (bits(b, 3, 1)) {
> case 0x0: width = 4;
> break;
> case 0x1: width = (b & 0x1) ? 2 : 1;
> break;
> case 0x2: width = 3;
> break;
> case 0x3: width = 1;
> break;
> case 0x4: width = 2;
> break;
> case 0x5:
> if ((b & 0x1) == 0) {
> width = 1;
> break;
> }
> // Fall through on purpose.
> default:
> return new Unknown(machInst);
> }
> }
> assert(width > 0 && width <= 4);
>
> const RegIndex rm = (RegIndex)(uint32_t)bits(machInst, 3, 0);
> const RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 19, 16);
> const RegIndex vd = (RegIndex)(uint32_t)(bits(machInst, 15, 12) |
> bits(machInst, 22) << 4);
> const uint32_t type = bits(machInst, 11, 8);
> uint32_t size = 0;
> uint32_t align = 0;
> unsigned inc = 1;
> unsigned regs = 1;
> unsigned lane = 0;
> if (single) {
> if (singleAll) {
> size = bits(machInst, 7, 6);
> bool t = bits(machInst, 5);
> unsigned eBytes = (1 << size);
> align = (eBytes - 1) | TLB::AllowUnaligned;
> if (width == 1) {
> regs = t ? 2 : 1;
> inc = 1;
80,92c160,182
< switch (bits(b, 1, 0)) {
< case 0x0:
< return new WarnUnimplemented("vld1 single all",
< machInst);
< case 0x1:
< return new WarnUnimplemented("vld2 single all",
< machInst);
< case 0x2:
< return new WarnUnimplemented("vld3 single all",
< machInst);
< case 0x3:
< return new WarnUnimplemented("vld4 single all",
< machInst);
---
> regs = width;
> inc = t ? 2 : 1;
> }
> switch (width) {
> case 1:
> case 2:
> if (bits(machInst, 4))
> align = width * eBytes - 1;
> break;
> case 3:
> break;
> case 4:
> if (size == 3) {
> if (bits(machInst, 4) == 0)
> return new Unknown(machInst);
> size = 2;
> align = 0xf;
> } else if (size == 2) {
> if (bits(machInst, 4))
> align = 7;
> } else {
> if (bits(machInst, 4))
> align = 4 * eBytes - 1;
93a184
> break;
96,109c187,223
< switch (bits(b, 3, 1)) {
< case 0x0:
< return new WarnUnimplemented("vld4 multiple", machInst);
< case 0x2:
< return new WarnUnimplemented("vld3 multiple", machInst);
< case 0x3:
< return new WarnUnimplemented("vld1 multiple", machInst);
< case 0x4:
< return new WarnUnimplemented("vld2 multiple", machInst);
< case 0x1:
< if (b & 0x1) {
< return new WarnUnimplemented("vld2 multiple", machInst);
< } else {
< return new WarnUnimplemented("vld1 multiple", machInst);
---
> size = bits(machInst, 11, 10);
> unsigned eBytes = (1 << size);
> align = (eBytes - 1) | TLB::AllowUnaligned;
> regs = width;
> unsigned indexAlign = bits(machInst, 7, 4);
> // If width is 1, inc is always 1. That's overridden later.
> switch (size) {
> case 0:
> inc = 1;
> lane = bits(indexAlign, 3, 1);
> break;
> case 1:
> inc = bits(indexAlign, 1) ? 2 : 1;
> lane = bits(indexAlign, 3, 2);
> break;
> case 2:
> inc = bits(indexAlign, 2) ? 2 : 1;
> lane = bits(indexAlign, 3);
> break;
> }
> // Override inc for width of 1.
> if (width == 1) {
> inc = 1;
> }
> switch (width) {
> case 1:
> switch (size) {
> case 0:
> break;
> case 1:
> if (bits(indexAlign, 0))
> align = 1;
> break;
> case 2:
> if (bits(indexAlign, 1, 0))
> align = 3;
> break;
111,114c225,237
< case 0x5:
< if ((b & 0x1) == 0) {
< return new WarnUnimplemented("vld1 multiple", machInst);
< } else {
---
> break;
> case 2:
> if (bits(indexAlign, 0))
> align = (2 * eBytes) - 1;
> break;
> case 3:
> break;
> case 4:
> switch (size) {
> case 0:
> case 1:
> if (bits(indexAlign, 0))
> align = (4 * eBytes) - 1;
115a239,242
> case 2:
> if (bits(indexAlign, 0))
> align = (4 << bits(indexAlign, 1, 0)) - 1;
> break;
116a244
> break;
118a247,249
> if (size == 0x3) {
> return new Unknown(machInst);
> }
119a251,323
> size = bits(machInst, 7, 6);
> align = bits(machInst, 5, 4);
> if (align == 0) {
> // @align wasn't specified, so alignment can be turned off.
> align = ((1 << size) - 1) | TLB::AllowUnaligned;
> } else {
> align = ((4 << align) - 1);
> }
> switch (width) {
> case 1:
> switch (type) {
> case 0x7: regs = 1;
> break;
> case 0xa: regs = 2;
> break;
> case 0x6: regs = 3;
> break;
> case 0x2: regs = 4;
> break;
> default:
> return new Unknown(machInst);
> }
> break;
> case 2:
> // Regs doesn't behave exactly as it does in the manual
> // because they loop over regs registers twice and we break
> // it down in the macroop.
> switch (type) {
> case 0x8: regs = 2; inc = 1;
> break;
> case 0x9: regs = 2; inc = 2;
> break;
> case 0x3: regs = 4; inc = 2;
> break;
> default:
> return new Unknown(machInst);
> }
> break;
> case 3:
> regs = 3;
> switch (type) {
> case 0x4: inc = 1;
> break;
> case 0x5: inc = 2;;
> break;
> default:
> return new Unknown(machInst);
> }
> break;
> case 4:
> regs = 4;
> switch (type) {
> case 0: inc = 1;
> break;
> case 1: inc = 2;
> break;
> default:
> return new Unknown(machInst);
> }
> break;
> }
> }
>
> if (load) {
> // Load instructions.
> if (single) {
> return new VldSingle(machInst, singleAll, width, rn, vd,
> regs, inc, size, align, rm, lane);
> } else {
> return new VldMult(machInst, width, rn, vd,
> regs, inc, size, align, rm);
> }
> } else {
121,132c325,327
< if (a) {
< if (bits(b, 3, 2) != 3) {
< switch (bits(b, 1, 0)) {
< case 0x0:
< return new WarnUnimplemented("vst1 single", machInst);
< case 0x1:
< return new WarnUnimplemented("vst2 single", machInst);
< case 0x2:
< return new WarnUnimplemented("vst3 single", machInst);
< case 0x3:
< return new WarnUnimplemented("vst4 single", machInst);
< }
---
> if (single) {
> if (singleAll) {
> return new Unknown(machInst);
134,147c329,330
< switch (bits(b, 1, 0)) {
< case 0x0:
< return new WarnUnimplemented("vst1 single all",
< machInst);
< case 0x1:
< return new WarnUnimplemented("vst2 single all",
< machInst);
< case 0x2:
< return new WarnUnimplemented("vst3 single all",
< machInst);
< case 0x3:
< return new WarnUnimplemented("vst4 single all",
< machInst);
< }
---
> return new VstSingle(machInst, false, width, rn, vd,
> regs, inc, size, align, rm, lane);
150,171c333,334
< switch (bits(b, 3, 1)) {
< case 0x0:
< return new WarnUnimplemented("vst4 multiple", machInst);
< case 0x2:
< return new WarnUnimplemented("vst3 multiple", machInst);
< case 0x3:
< return new WarnUnimplemented("vst1 multiple", machInst);
< case 0x4:
< return new WarnUnimplemented("vst2 multiple", machInst);
< case 0x1:
< if (b & 0x1) {
< return new WarnUnimplemented("vst2 multiple", machInst);
< } else {
< return new WarnUnimplemented("vst1 multiple", machInst);
< }
< case 0x5:
< if ((b & 0x1) == 0) {
< return new WarnUnimplemented("vst1 multiple", machInst);
< } else {
< break;
< }
< }
---
> return new VstMult(machInst, width, rn, vd,
> regs, inc, size, align, rm);
185a349,361
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const IntRegIndex vn =
> (IntRegIndex)(2 * (bits(machInst, 19, 16) |
> (bits(machInst, 7) << 4)));
> const IntRegIndex vm =
> (IntRegIndex)(2 * (bits(machInst, 3, 0) |
> (bits(machInst, 5) << 4)));
> const unsigned size = bits(machInst, 21, 20);
> const bool q = bits(machInst, 6);
> if (q && ((vd & 0x1) || (vn & 0x1) || (vm & 0x1)))
> return new Unknown(machInst);
189,190c365,367
< if (bits(machInst, 9) == 0) {
< return new WarnUnimplemented("vhadd", machInst);
---
> if (u) {
> return decodeNeonUThreeReg<VqaddUD, VqaddUQ>(
> q, size, machInst, vd, vn, vm);
192c369,370
< return new WarnUnimplemented("vhsub", machInst);
---
> return decodeNeonSThreeReg<VqaddSD, VqaddSQ>(
> q, size, machInst, vd, vn, vm);
195c373,376
< return new WarnUnimplemented("vqadd", machInst);
---
> if (size == 3)
> return new Unknown(machInst);
> return decodeNeonUSThreeReg<VhaddD, VhaddQ>(
> q, u, size, machInst, vd, vn, vm);
199c380,381
< return new WarnUnimplemented("vrhadd", machInst);
---
> return decodeNeonUSThreeReg<VrhaddD, VrhaddQ>(
> q, u, size, machInst, vd, vn, vm);
204c386,390
< return new WarnUnimplemented("veor", machInst);
---
> if (q) {
> return new VeorQ<uint64_t>(machInst, vd, vn, vm);
> } else {
> return new VeorD<uint64_t>(machInst, vd, vn, vm);
> }
206c392,396
< return new WarnUnimplemented("vbsl", machInst);
---
> if (q) {
> return new VbslQ<uint64_t>(machInst, vd, vn, vm);
> } else {
> return new VbslD<uint64_t>(machInst, vd, vn, vm);
> }
208c398,402
< return new WarnUnimplemented("vbit", machInst);
---
> if (q) {
> return new VbitQ<uint64_t>(machInst, vd, vn, vm);
> } else {
> return new VbitD<uint64_t>(machInst, vd, vn, vm);
> }
210c404,408
< return new WarnUnimplemented("vbif", machInst);
---
> if (q) {
> return new VbifQ<uint64_t>(machInst, vd, vn, vm);
> } else {
> return new VbifD<uint64_t>(machInst, vd, vn, vm);
> }
215c413,417
< return new WarnUnimplemented("vand (reg)", machInst);
---
> if (q) {
> return new VandQ<uint64_t>(machInst, vd, vn, vm);
> } else {
> return new VandD<uint64_t>(machInst, vd, vn, vm);
> }
217c419,423
< return new WarnUnimplemented("vbic (reg)", machInst);
---
> if (q) {
> return new VbicQ<uint64_t>(machInst, vd, vn, vm);
> } else {
> return new VbicD<uint64_t>(machInst, vd, vn, vm);
> }
219,228c425,428
< {
< const IntRegIndex n = (IntRegIndex)(
< (uint32_t)bits(machInst, 19, 16) |
< (uint32_t)(bits(machInst, 7) << 4));
< const IntRegIndex m = (IntRegIndex)(
< (uint32_t)bits(machInst, 3, 0) |
< (uint32_t)(bits(machInst, 5) << 4));
< if (n == m) {
< return new WarnUnimplemented("vmov (reg)",
< machInst);
---
> if (vn == vm) {
> if (q) {
> return new VmovQ<uint64_t>(
> machInst, vd, vn, vm);
230,231c430,431
< return new WarnUnimplemented("vorr (reg)",
< machInst);
---
> return new VmovD<uint64_t>(
> machInst, vd, vn, vm);
232a433,440
> } else {
> if (q) {
> return new VorrQ<uint64_t>(
> machInst, vd, vn, vm);
> } else {
> return new VorrD<uint64_t>(
> machInst, vd, vn, vm);
> }
235c443,449
< return new WarnUnimplemented("vorn (reg)", machInst);
---
> if (q) {
> return new VornQ<uint64_t>(
> machInst, vd, vn, vm);
> } else {
> return new VornD<uint64_t>(
> machInst, vd, vn, vm);
> }
241,244c455,457
< return new WarnUnimplemented("vqsub", machInst);
< } else {
< if (bits(machInst, 9) == 0) {
< return new WarnUnimplemented("vhadd", machInst);
---
> if (u) {
> return decodeNeonUThreeReg<VqsubUD, VqsubUQ>(
> q, size, machInst, vd, vn, vm);
246c459,460
< return new WarnUnimplemented("vhsub", machInst);
---
> return decodeNeonSThreeReg<VqsubSD, VqsubSQ>(
> q, size, machInst, vd, vn, vm);
247a462,466
> } else {
> if (size == 3)
> return new Unknown(machInst);
> return decodeNeonUSThreeReg<VhsubD, VhsubQ>(
> q, u, size, machInst, vd, vn, vm);
251c470,471
< return new WarnUnimplemented("vcge (reg)", machInst);
---
> return decodeNeonUSThreeReg<VcgeD, VcgeQ>(
> q, u, size, machInst, vd, vn, vm);
253c473,474
< return new WarnUnimplemented("vcgt (reg)", machInst);
---
> return decodeNeonUSThreeReg<VcgtD, VcgtQ>(
> q, u, size, machInst, vd, vn, vm);
257c478,484
< return new WarnUnimplemented("vqshl (reg)", machInst);
---
> if (u) {
> return decodeNeonUThreeReg<VqshlUD, VqshlUQ>(
> q, size, machInst, vd, vm, vn);
> } else {
> return decodeNeonSThreeReg<VqshlSD, VqshlSQ>(
> q, size, machInst, vd, vm, vn);
> }
259c486,487
< return new WarnUnimplemented("vshl (reg)", machInst);
---
> return decodeNeonUSThreeReg<VshlD, VshlQ>(
> q, u, size, machInst, vd, vm, vn);
263c491,497
< return new WarnUnimplemented("vqrshl", machInst);
---
> if (u) {
> return decodeNeonUThreeReg<VqrshlUD, VqrshlUQ>(
> q, size, machInst, vd, vm, vn);
> } else {
> return decodeNeonSThreeReg<VqrshlSD, VqrshlSQ>(
> q, size, machInst, vd, vm, vn);
> }
265c499,500
< return new WarnUnimplemented("vrshl", machInst);
---
> return decodeNeonUSThreeReg<VrshlD, VrshlQ>(
> q, u, size, machInst, vd, vm, vn);
269c504,505
< return new WarnUnimplemented("vmin (int)", machInst);
---
> return decodeNeonUSThreeReg<VminD, VminQ>(
> q, u, size, machInst, vd, vn, vm);
271c507,508
< return new WarnUnimplemented("vmax (int)", machInst);
---
> return decodeNeonUSThreeReg<VmaxD, VmaxQ>(
> q, u, size, machInst, vd, vn, vm);
275c512,513
< return new WarnUnimplemented("vaba", machInst);
---
> return decodeNeonUSThreeReg<VabaD, VabaQ>(
> q, u, size, machInst, vd, vn, vm);
278c516
< if (bits(machInst, 6) == 1) {
---
> if (q) {
281c519,520
< return new WarnUnimplemented("vabdl (int)", machInst);
---
> return decodeNeonUSThreeUSReg<Vabdl>(
> u, size, machInst, vd, vn, vm);
284c523,524
< return new WarnUnimplemented("vabd (int)", machInst);
---
> return decodeNeonUSThreeReg<VabdD, VabdQ>(
> q, u, size, machInst, vd, vn, vm);
290c530,531
< return new WarnUnimplemented("vceq (reg)", machInst);
---
> return decodeNeonUThreeReg<VceqD, VceqQ>(
> q, size, machInst, vd, vn, vm);
292c533,534
< return new WarnUnimplemented("vtst", machInst);
---
> return decodeNeonUThreeReg<VtstD, VtstQ>(
> q, size, machInst, vd, vn, vm);
296c538,539
< return new WarnUnimplemented("vsub (int)", machInst);
---
> return decodeNeonUThreeReg<NVsubD, NVsubQ>(
> q, size, machInst, vd, vn, vm);
298c541,542
< return new WarnUnimplemented("vadd (int)", machInst);
---
> return decodeNeonUThreeReg<NVaddD, NVaddQ>(
> q, size, machInst, vd, vn, vm);
304c548,549
< return new WarnUnimplemented("vmul (poly)", machInst);
---
> return decodeNeonUThreeReg<NVmulpD, NVmulpQ>(
> q, size, machInst, vd, vn, vm);
306c551,552
< return new WarnUnimplemented("vmul (int)", machInst);
---
> return decodeNeonSThreeReg<NVmulD, NVmulQ>(
> q, size, machInst, vd, vn, vm);
310c556,557
< return new WarnUnimplemented("vmls (int)", machInst);
---
> return decodeNeonUSThreeReg<NVmlsD, NVmlsQ>(
> q, u, size, machInst, vd, vn, vm);
312c559,560
< return new WarnUnimplemented("vmla (int)", machInst);
---
> return decodeNeonUSThreeReg<NVmlaD, NVmlaQ>(
> q, u, size, machInst, vd, vn, vm);
317c565,566
< return new WarnUnimplemented("vpmin (int)", machInst);
---
> return decodeNeonUSThreeReg<VpminD, VpminQ>(
> q, u, size, machInst, vd, vn, vm);
319c568,569
< return new WarnUnimplemented("vpmax (int)", machInst);
---
> return decodeNeonUSThreeReg<VpmaxD, VpmaxQ>(
> q, u, size, machInst, vd, vn, vm);
326c576,577
< return new WarnUnimplemented("vpadd (int)", machInst);
---
> return decodeNeonUThreeReg<NVpaddD, NVpaddQ>(
> q, size, machInst, vd, vn, vm);
330c581,582
< return new WarnUnimplemented("vqrdmulh", machInst);
---
> return decodeNeonSThreeSReg<VqrdmulhD, VqrdmulhQ>(
> q, size, machInst, vd, vn, vm);
332c584,585
< return new WarnUnimplemented("vqdmulh", machInst);
---
> return decodeNeonSThreeSReg<VqdmulhD, VqdmulhQ>(
> q, size, machInst, vd, vn, vm);
341c594,598
< return new WarnUnimplemented("vmul (fp)", machInst);
---
> if (q) {
> return new NVmulQFp<float>(machInst, vd, vn, vm);
> } else {
> return new NVmulDFp<float>(machInst, vd, vn, vm);
> }
347c604,608
< return new WarnUnimplemented("vmla (fp)", machInst);
---
> if (q) {
> return new NVmlaQFp<float>(machInst, vd, vn, vm);
> } else {
> return new NVmlaDFp<float>(machInst, vd, vn, vm);
> }
349c610,614
< return new WarnUnimplemented("vmls (fp)", machInst);
---
> if (q) {
> return new NVmlsQFp<float>(machInst, vd, vn, vm);
> } else {
> return new NVmlsDFp<float>(machInst, vd, vn, vm);
> }
355c620,624
< return new WarnUnimplemented("vpadd (fp)", machInst);
---
> if (q) {
> return new VpaddQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VpaddDFp<float>(machInst, vd, vn, vm);
> }
357c626,630
< return new WarnUnimplemented("vabd (fp)", machInst);
---
> if (q) {
> return new VabdQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VabdDFp<float>(machInst, vd, vn, vm);
> }
361c634,638
< return new WarnUnimplemented("vadd (fp)", machInst);
---
> if (q) {
> return new VaddQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VaddDFp<float>(machInst, vd, vn, vm);
> }
363c640,644
< return new WarnUnimplemented("vsub (fp)", machInst);
---
> if (q) {
> return new VsubQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VsubDFp<float>(machInst, vd, vn, vm);
> }
371c652,656
< return new WarnUnimplemented("vacge", machInst);
---
> if (q) {
> return new VacgeQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VacgeDFp<float>(machInst, vd, vn, vm);
> }
373c658,662
< return new WarnUnimplemented("vacgt", machInst);
---
> if (q) {
> return new VacgtQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VacgtDFp<float>(machInst, vd, vn, vm);
> }
381c670,674
< return new WarnUnimplemented("vcge (reg)", machInst);
---
> if (q) {
> return new VcgeQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VcgeDFp<float>(machInst, vd, vn, vm);
> }
383c676,680
< return new WarnUnimplemented("vcgt (reg)", machInst);
---
> if (q) {
> return new VcgtQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VcgtDFp<float>(machInst, vd, vn, vm);
> }
387c684,688
< return new WarnUnimplemented("vceq (reg)", machInst);
---
> if (q) {
> return new VceqQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VceqDFp<float>(machInst, vd, vn, vm);
> }
399c700,704
< return new WarnUnimplemented("vrecps", machInst);
---
> if (q) {
> return new VrecpsQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VrecpsDFp<float>(machInst, vd, vn, vm);
> }
401c706,710
< return new WarnUnimplemented("vrsqrts", machInst);
---
> if (q) {
> return new VrsqrtsQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VrsqrtsDFp<float>(machInst, vd, vn, vm);
> }
407c716,720
< return new WarnUnimplemented("vpmax (fp)", machInst);
---
> if (q) {
> return new VpmaxQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VpmaxDFp<float>(machInst, vd, vn, vm);
> }
409c722,726
< return new WarnUnimplemented("vpmin (fp)", machInst);
---
> if (q) {
> return new VpminQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VpminDFp<float>(machInst, vd, vn, vm);
> }
413c730,734
< return new WarnUnimplemented("vmax (fp)", machInst);
---
> if (q) {
> return new VmaxQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VmaxDFp<float>(machInst, vd, vn, vm);
> }
415c736,740
< return new WarnUnimplemented("vmin (fp)", machInst);
---
> if (q) {
> return new VminQFp<float>(machInst, vd, vn, vm);
> } else {
> return new VminDFp<float>(machInst, vd, vn, vm);
> }
425a751,754
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const bool q = bits(machInst, 6);
427c756,761
< const uint32_t cmode = bits(machInst, 11, 8);
---
> const uint8_t cmode = bits(machInst, 11, 8);
> const uint8_t imm = ((THUMB ? bits(machInst, 28) :
> bits(machInst, 24)) << 7) |
> (bits(machInst, 18, 16) << 4) |
> (bits(machInst, 3, 0) << 0);
> const uint64_t bigImm = simd_modified_imm(op, cmode, imm);
431c765,768
< return new WarnUnimplemented("vmov (imm)", machInst);
---
> if (q)
> return new NVmvniQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVmvniD<uint64_t>(machInst, vd, bigImm);
433c770,773
< return new WarnUnimplemented("vorr (imm)", machInst);
---
> if (q)
> return new NVbiciQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVbiciD<uint64_t>(machInst, vd, bigImm);
437c777,794
< return new WarnUnimplemented("vmov (imm)", machInst);
---
> switch (bits(cmode, 1, 0)) {
> case 0:
> case 1:
> if (q)
> return new NVmvniQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVmvniD<uint64_t>(machInst, vd, bigImm);
> case 2:
> if (q)
> return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVmoviD<uint64_t>(machInst, vd, bigImm);
> case 3:
> if (q)
> return new Unknown(machInst);
> else
> return new Unknown(machInst);
> }
440c797,800
< return new WarnUnimplemented("vmov (imm)", machInst);
---
> if (q)
> return new NVmvniQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVmvniD<uint64_t>(machInst, vd, bigImm);
442c802,805
< return new WarnUnimplemented("vorr (imm)", machInst);
---
> if (q)
> return new NVbiciQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVbiciD<uint64_t>(machInst, vd, bigImm);
449c812,815
< return new WarnUnimplemented("vmvn (imm)", machInst);
---
> if (q)
> return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVmoviD<uint64_t>(machInst, vd, bigImm);
451c817,820
< return new WarnUnimplemented("vbic (imm)", machInst);
---
> if (q)
> return new NVorriQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVorriD<uint64_t>(machInst, vd, bigImm);
455,464c824,827
< switch (bits(cmode, 1, 0)) {
< case 0:
< case 1:
< return new WarnUnimplemented("vmvn (imm)", machInst);
< case 2:
< return new WarnUnimplemented("vmov (imm)", machInst);
< case 3:
< return new Unknown(machInst);
< }
< return new WarnUnimplemented("vmov (imm)", machInst);
---
> if (q)
> return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVmoviD<uint64_t>(machInst, vd, bigImm);
467c830,833
< return new WarnUnimplemented("vmvn (imm)", machInst);
---
> if (q)
> return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVmoviD<uint64_t>(machInst, vd, bigImm);
469c835,838
< return new WarnUnimplemented("vbic (imm)", machInst);
---
> if (q)
> return new NVorriQ<uint64_t>(machInst, vd, bigImm);
> else
> return new NVorriD<uint64_t>(machInst, vd, bigImm);
483a853,878
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const IntRegIndex vm =
> (IntRegIndex)(2 * (bits(machInst, 3, 0) |
> (bits(machInst, 5) << 4)));
> unsigned imm6 = bits(machInst, 21, 16);
> unsigned imm = ((l ? 1 : 0) << 6) | imm6;
> unsigned size = 3;
> unsigned lShiftAmt = 0;
> unsigned bitSel;
> for (bitSel = 1 << 6; true; bitSel >>= 1) {
> if (bitSel & imm)
> break;
> else if (!size)
> return new Unknown(machInst);
> size--;
> }
> lShiftAmt = imm6 & ~bitSel;
> unsigned rShiftAmt = 0;
> if (a != 0xe && a != 0xf) {
> if (size > 2)
> rShiftAmt = 64 - imm6;
> else
> rShiftAmt = 2 * (8 << size) - imm6;
> }
487c882,883
< return new WarnUnimplemented("vshr", machInst);
---
> return decodeNeonUSTwoShiftReg<NVshrD, NVshrQ>(
> b, u, size, machInst, vd, vm, rShiftAmt);
489c885,886
< return new WarnUnimplemented("vsra", machInst);
---
> return decodeNeonUSTwoShiftReg<NVsraD, NVsraQ>(
> b, u, size, machInst, vd, vm, rShiftAmt);
491c888,889
< return new WarnUnimplemented("vrshr", machInst);
---
> return decodeNeonUSTwoShiftReg<NVrshrD, NVrshrQ>(
> b, u, size, machInst, vd, vm, rShiftAmt);
493c891,892
< return new WarnUnimplemented("vrsra", machInst);
---
> return decodeNeonUSTwoShiftReg<NVrsraD, NVrsraQ>(
> b, u, size, machInst, vd, vm, rShiftAmt);
496c895,896
< return new WarnUnimplemented("vsri", machInst);
---
> return decodeNeonUTwoShiftReg<NVsriD, NVsriQ>(
> b, size, machInst, vd, vm, rShiftAmt);
502c902,903
< return new WarnUnimplemented("vsli", machInst);
---
> return decodeNeonUTwoShiftReg<NVsliD, NVsliQ>(
> b, size, machInst, vd, vm, lShiftAmt);
504c905,906
< return new WarnUnimplemented("vshl (imm)", machInst);
---
> return decodeNeonUTwoShiftReg<NVshlD, NVshlQ>(
> b, size, machInst, vd, vm, lShiftAmt);
508c910,921
< return new WarnUnimplemented("vqshl, vqshlu (imm)", machInst);
---
> if (u) {
> if (a == 0x6) {
> return decodeNeonSTwoShiftReg<NVqshlusD, NVqshlusQ>(
> b, size, machInst, vd, vm, lShiftAmt);
> } else {
> return decodeNeonUTwoShiftReg<NVqshluD, NVqshluQ>(
> b, size, machInst, vd, vm, lShiftAmt);
> }
> } else {
> return decodeNeonSTwoShiftReg<NVqshlD, NVqshlQ>(
> b, size, machInst, vd, vm, lShiftAmt);
> }
513,517c926,927
< if (b) {
< return new WarnUnimplemented("vqrshrn, vqrshrun", machInst);
< } else {
< return new WarnUnimplemented("vqshrn, vqshrun", machInst);
< }
---
> return decodeNeonSTwoShiftSReg<NVqshruns, NVqrshruns>(
> b, size, machInst, vd, vm, rShiftAmt);
519,523c929,930
< if (b) {
< return new WarnUnimplemented("vrshrn", machInst);
< } else {
< return new WarnUnimplemented("vshrn", machInst);
< }
---
> return decodeNeonUTwoShiftSReg<NVshrn, NVrshrn>(
> b, size, machInst, vd, vm, rShiftAmt);
528,529c935,937
< } else if (b) {
< return new WarnUnimplemented("vqrshrn, vqrshrun", machInst);
---
> } else if (u) {
> return decodeNeonUTwoShiftSReg<NVqshrun, NVqrshrun>(
> b, size, machInst, vd, vm, rShiftAmt);
531c939,940
< return new WarnUnimplemented("vqshrn, vqshrun", machInst);
---
> return decodeNeonSTwoShiftSReg<NVqshrn, NVqrshrn>(
> b, size, machInst, vd, vm, rShiftAmt);
537,538c946,947
< // If the shift amount is zero, it's vmovl.
< return new WarnUnimplemented("vshll, vmovl", machInst);
---
> return decodeNeonUSTwoShiftSReg<NVmovl, NVshll>(
> lShiftAmt, u, size, machInst, vd, vm, lShiftAmt);
540a950,972
> if (l) {
> return new Unknown(machInst);
> } else {
> if (bits(imm6, 5) == 0)
> return new Unknown(machInst);
> if (u) {
> if (b) {
> return new NVcvtu2fpQ<float>(
> machInst, vd, vm, 64 - imm6);
> } else {
> return new NVcvtu2fpD<float>(
> machInst, vd, vm, 64 - imm6);
> }
> } else {
> if (b) {
> return new NVcvts2fpQ<float>(
> machInst, vd, vm, 64 - imm6);
> } else {
> return new NVcvts2fpD<float>(
> machInst, vd, vm, 64 - imm6);
> }
> }
> }
544,547c976,995
< } else if (a == 0xe) {
< return new WarnUnimplemented("vcvt (fixed to fp)", machInst);
< } else if (a == 0xf) {
< return new WarnUnimplemented("vcvt (fp to fixed)", machInst);
---
> } else {
> if (bits(imm6, 5) == 0)
> return new Unknown(machInst);
> if (u) {
> if (b) {
> return new NVcvt2ufxQ<float>(
> machInst, vd, vm, 64 - imm6);
> } else {
> return new NVcvt2ufxD<float>(
> machInst, vd, vm, 64 - imm6);
> }
> } else {
> if (b) {
> return new NVcvt2sfxQ<float>(
> machInst, vd, vm, 64 - imm6);
> } else {
> return new NVcvt2sfxD<float>(
> machInst, vd, vm, 64 - imm6);
> }
> }
558c1006,1015
<
---
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const IntRegIndex vn =
> (IntRegIndex)(2 * (bits(machInst, 19, 16) |
> (bits(machInst, 7) << 4)));
> const IntRegIndex vm =
> (IntRegIndex)(2 * (bits(machInst, 3, 0) |
> (bits(machInst, 5) << 4)));
> const unsigned size = bits(machInst, 21, 20);
561c1018,1019
< return new WarnUnimplemented("vaddl", machInst);
---
> return decodeNeonUSThreeUSReg<Vaddl>(
> u, size, machInst, vd, vn, vm);
563c1021,1022
< return new WarnUnimplemented("vaddw", machInst);
---
> return decodeNeonUSThreeUSReg<Vaddw>(
> u, size, machInst, vd, vn, vm);
565c1024,1025
< return new WarnUnimplemented("vsubl", machInst);
---
> return decodeNeonUSThreeUSReg<Vsubl>(
> u, size, machInst, vd, vn, vm);
567c1027,1028
< return new WarnUnimplemented("vsubw", machInst);
---
> return decodeNeonUSThreeUSReg<Vsubw>(
> u, size, machInst, vd, vn, vm);
570c1031,1032
< return new WarnUnimplemented("vraddhn", machInst);
---
> return decodeNeonUThreeUSReg<Vraddhn>(
> size, machInst, vd, vn, vm);
572c1034,1035
< return new WarnUnimplemented("vaddhn", machInst);
---
> return decodeNeonUThreeUSReg<Vaddhn>(
> size, machInst, vd, vn, vm);
575c1038,1039
< return new WarnUnimplemented("vabal", machInst);
---
> return decodeNeonUSThreeUSReg<Vabal>(
> u, size, machInst, vd, vn, vm);
578c1042,1043
< return new WarnUnimplemented("vrsubhn", machInst);
---
> return decodeNeonUThreeUSReg<Vrsubhn>(
> size, machInst, vd, vn, vm);
580c1045,1046
< return new WarnUnimplemented("vsubhn", machInst);
---
> return decodeNeonUThreeUSReg<Vsubhn>(
> size, machInst, vd, vn, vm);
584c1050,1051
< return new WarnUnimplemented("vabdl (int)", machInst);
---
> return decodeNeonUSThreeUSReg<Vabdl>(
> u, size, machInst, vd, vn, vm);
586c1053,1054
< return new WarnUnimplemented("vabd (int)", machInst);
---
> return decodeNeonUSThreeReg<VabdD, VabdQ>(
> bits(machInst, 6), u, size, machInst, vd, vn, vm);
589c1057,1058
< return new WarnUnimplemented("vmlal (int)", machInst);
---
> return decodeNeonUSThreeUSReg<Vmlal>(
> u, size, machInst, vd, vn, vm);
591c1060,1061
< return new WarnUnimplemented("vmlsl (int)", machInst);
---
> return decodeNeonUSThreeUSReg<Vmlsl>(
> u, size, machInst, vd, vn, vm);
593,606c1063,1064
< if (bits(machInst, 23) == 0) {
< if (bits(machInst, 4) == 0) {
< if (u) {
< return new WarnUnimplemented("vmls (int)", machInst);
< } else {
< return new WarnUnimplemented("vmla (int)", machInst);
< }
< } else {
< if (u) {
< return new WarnUnimplemented("vmul (poly)", machInst);
< } else {
< return new WarnUnimplemented("vmul (int)", machInst);
< }
< }
---
> if (u) {
> return new Unknown(machInst);
608c1066,1067
< return new WarnUnimplemented("vqdmlal", machInst);
---
> return decodeNeonSThreeUSReg<Vqdmlal>(
> size, machInst, vd, vn, vm);
611c1070
< if (!u) {
---
> if (u) {
614c1073,1074
< return new WarnUnimplemented("vqdmlsl", machInst);
---
> return decodeNeonSThreeUSReg<Vqdmlsl>(
> size, machInst, vd, vn, vm);
617c1077,1078
< return new WarnUnimplemented("vmull (int)", machInst);
---
> return decodeNeonUSThreeUSReg<Vmull>(
> u, size, machInst, vd, vn, vm);
619c1080
< if (!u) {
---
> if (u) {
622c1083,1084
< return new WarnUnimplemented("vqdmull", machInst);
---
> return decodeNeonSThreeUSReg<Vqdmull>(
> size, machInst, vd, vn, vm);
625c1087,1088
< return new WarnUnimplemented("vmull (poly)", machInst);
---
> return decodeNeonUThreeUSReg<Vmullp>(
> size, machInst, vd, vn, vm);
635c1098,1109
<
---
> const unsigned size = bits(machInst, 21, 20);
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const IntRegIndex vn =
> (IntRegIndex)(2 * (bits(machInst, 19, 16) |
> (bits(machInst, 7) << 4)));
> const IntRegIndex vm = (size == 2) ?
> (IntRegIndex)(2 * bits(machInst, 3, 0)) :
> (IntRegIndex)(2 * bits(machInst, 2, 0));
> const unsigned index = (size == 2) ? (unsigned)bits(machInst, 5) :
> (bits(machInst, 3) | (bits(machInst, 5) << 1));
638c1112,1130
< return new WarnUnimplemented("vmla (int scalar)", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new VmlasQ<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new VmlasQ<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new VmlasD<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new VmlasD<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
640c1132,1135
< return new WarnUnimplemented("vmla (fp scalar)", machInst);
---
> if (u)
> return new VmlasQFp<float>(machInst, vd, vn, vm, index);
> else
> return new VmlasDFp<float>(machInst, vd, vn, vm, index);
642c1137,1155
< return new WarnUnimplemented("vmls (int scalar)", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new VmlssQ<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new VmlssQ<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new VmlssD<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new VmlssD<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
644c1157,1160
< return new WarnUnimplemented("vmls (fp scalar)", machInst);
---
> if (u)
> return new VmlssQFp<float>(machInst, vd, vn, vm, index);
> else
> return new VmlssDFp<float>(machInst, vd, vn, vm, index);
646c1162,1180
< return new WarnUnimplemented("vmlal (scalar)", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new Vmlals<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vmlals<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new Vmlals<int16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vmlals<int32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
648c1182,1200
< return new WarnUnimplemented("vmlsl (scalar)", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new Vmlsls<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vmlsls<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new Vmlsls<int16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vmlsls<int32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
653c1205,1212
< return new WarnUnimplemented("vqdmlal", machInst);
---
> switch (size) {
> case 1:
> return new Vqdmlals<int16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vqdmlals<int32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
659c1218,1225
< return new WarnUnimplemented("vqdmlsl", machInst);
---
> switch (size) {
> case 1:
> return new Vqdmlsls<int16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vqdmlsls<int32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
662c1228,1246
< return new WarnUnimplemented("vmul (int scalar)", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new VmulsQ<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new VmulsQ<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new VmulsD<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new VmulsD<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
664c1248,1251
< return new WarnUnimplemented("vmul (fp scalar)", machInst);
---
> if (u)
> return new VmulsQFp<float>(machInst, vd, vn, vm, index);
> else
> return new VmulsDFp<float>(machInst, vd, vn, vm, index);
666c1253,1271
< return new WarnUnimplemented("vmull (scalar)", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new Vmulls<uint16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vmulls<uint32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new Vmulls<int16_t>(machInst, vd, vn, vm, index);
> case 2:
> return new Vmulls<int32_t>(machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
671c1276,1298
< return new WarnUnimplemented("vqdmull", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new Vqdmulls<uint16_t>(
> machInst, vd, vn, vm, index);
> case 2:
> return new Vqdmulls<uint32_t>(
> machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new Vqdmulls<int16_t>(
> machInst, vd, vn, vm, index);
> case 2:
> return new Vqdmulls<int32_t>(
> machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
674c1301,1323
< return new WarnUnimplemented("vqdmulh", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new VqdmulhsQ<int16_t>(
> machInst, vd, vn, vm, index);
> case 2:
> return new VqdmulhsQ<int32_t>(
> machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new VqdmulhsD<int16_t>(
> machInst, vd, vn, vm, index);
> case 2:
> return new VqdmulhsD<int32_t>(
> machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
676c1325,1347
< return new WarnUnimplemented("vqrdmulh", machInst);
---
> if (u) {
> switch (size) {
> case 1:
> return new VqrdmulhsQ<int16_t>(
> machInst, vd, vn, vm, index);
> case 2:
> return new VqrdmulhsQ<int32_t>(
> machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> } else {
> switch (size) {
> case 1:
> return new VqrdmulhsD<int16_t>(
> machInst, vd, vn, vm, index);
> case 2:
> return new VqrdmulhsD<int32_t>(
> machInst, vd, vn, vm, index);
> default:
> return new Unknown(machInst);
> }
> }
685a1357,1364
> const bool q = bits(machInst, 6);
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const IntRegIndex vm =
> (IntRegIndex)(2 * (bits(machInst, 3, 0) |
> (bits(machInst, 5) << 4)));
> const unsigned size = bits(machInst, 19, 18);
690c1369,1390
< return new WarnUnimplemented("vrev64", machInst);
---
> switch (size) {
> case 0:
> if (q) {
> return new NVrev64Q<uint8_t>(machInst, vd, vm);
> } else {
> return new NVrev64D<uint8_t>(machInst, vd, vm);
> }
> case 1:
> if (q) {
> return new NVrev64Q<uint16_t>(machInst, vd, vm);
> } else {
> return new NVrev64D<uint16_t>(machInst, vd, vm);
> }
> case 2:
> if (q) {
> return new NVrev64Q<uint32_t>(machInst, vd, vm);
> } else {
> return new NVrev64D<uint32_t>(machInst, vd, vm);
> }
> default:
> return new Unknown(machInst);
> }
692c1392,1407
< return new WarnUnimplemented("vrev32", machInst);
---
> switch (size) {
> case 0:
> if (q) {
> return new NVrev32Q<uint8_t>(machInst, vd, vm);
> } else {
> return new NVrev32D<uint8_t>(machInst, vd, vm);
> }
> case 1:
> if (q) {
> return new NVrev32Q<uint16_t>(machInst, vd, vm);
> } else {
> return new NVrev32D<uint16_t>(machInst, vd, vm);
> }
> default:
> return new Unknown(machInst);
> }
694c1409,1415
< return new WarnUnimplemented("vrev16", machInst);
---
> if (size != 0) {
> return new Unknown(machInst);
> } else if (q) {
> return new NVrev16Q<uint8_t>(machInst, vd, vm);
> } else {
> return new NVrev16D<uint8_t>(machInst, vd, vm);
> }
695a1417,1418
> return decodeNeonSTwoMiscSReg<NVpaddlD, NVpaddlQ>(
> q, size, machInst, vd, vm);
697c1420,1421
< return new WarnUnimplemented("vpaddl", machInst);
---
> return decodeNeonUTwoMiscSReg<NVpaddlD, NVpaddlQ>(
> q, size, machInst, vd, vm);
699c1423,1424
< return new WarnUnimplemented("vcls", machInst);
---
> return decodeNeonSTwoMiscReg<NVclsD, NVclsQ>(
> q, size, machInst, vd, vm);
701c1426,1427
< return new WarnUnimplemented("vclz", machInst);
---
> return decodeNeonSTwoMiscReg<NVclzD, NVclzQ>(
> q, size, machInst, vd, vm);
703c1429,1430
< return new WarnUnimplemented("vcnt", machInst);
---
> return decodeNeonUTwoMiscReg<NVcntD, NVcntQ>(
> q, size, machInst, vd, vm);
705c1432,1435
< return new WarnUnimplemented("vmvn (reg)", machInst);
---
> if (q)
> return new NVmvnQ<uint64_t>(machInst, vd, vm);
> else
> return new NVmvnD<uint64_t>(machInst, vd, vm);
706a1437,1438
> return decodeNeonSTwoMiscSReg<NVpadalD, NVpadalQ>(
> q, size, machInst, vd, vm);
708c1440,1441
< return new WarnUnimplemented("vpadal", machInst);
---
> return decodeNeonUTwoMiscSReg<NVpadalD, NVpadalQ>(
> q, size, machInst, vd, vm);
710c1443,1444
< return new WarnUnimplemented("vqabs", machInst);
---
> return decodeNeonSTwoMiscReg<NVqabsD, NVqabsQ>(
> q, size, machInst, vd, vm);
712c1446,1447
< return new WarnUnimplemented("vqneg", machInst);
---
> return decodeNeonSTwoMiscReg<NVqnegD, NVqnegQ>(
> q, size, machInst, vd, vm);
719c1454,1463
< return new WarnUnimplemented("vcgt (imm #0)", machInst);
---
> if (bits(b, 4)) {
> if (q) {
> return new NVcgtQFp<float>(machInst, vd, vm);
> } else {
> return new NVcgtDFp<float>(machInst, vd, vm);
> }
> } else {
> return decodeNeonSTwoMiscReg<NVcgtD, NVcgtQ>(
> q, size, machInst, vd, vm);
> }
721c1465,1474
< return new WarnUnimplemented("vcge (imm #0)", machInst);
---
> if (bits(b, 4)) {
> if (q) {
> return new NVcgeQFp<float>(machInst, vd, vm);
> } else {
> return new NVcgeDFp<float>(machInst, vd, vm);
> }
> } else {
> return decodeNeonSTwoMiscReg<NVcgeD, NVcgeQ>(
> q, size, machInst, vd, vm);
> }
723c1476,1485
< return new WarnUnimplemented("vceq (imm #0)", machInst);
---
> if (bits(b, 4)) {
> if (q) {
> return new NVceqQFp<float>(machInst, vd, vm);
> } else {
> return new NVceqDFp<float>(machInst, vd, vm);
> }
> } else {
> return decodeNeonSTwoMiscReg<NVceqD, NVceqQ>(
> q, size, machInst, vd, vm);
> }
725c1487,1496
< return new WarnUnimplemented("vcle (imm #0)", machInst);
---
> if (bits(b, 4)) {
> if (q) {
> return new NVcleQFp<float>(machInst, vd, vm);
> } else {
> return new NVcleDFp<float>(machInst, vd, vm);
> }
> } else {
> return decodeNeonSTwoMiscReg<NVcleD, NVcleQ>(
> q, size, machInst, vd, vm);
> }
727c1498,1507
< return new WarnUnimplemented("vclt (imm #0)", machInst);
---
> if (bits(b, 4)) {
> if (q) {
> return new NVcltQFp<float>(machInst, vd, vm);
> } else {
> return new NVcltDFp<float>(machInst, vd, vm);
> }
> } else {
> return decodeNeonSTwoMiscReg<NVcltD, NVcltQ>(
> q, size, machInst, vd, vm);
> }
729c1509,1517
< return new WarnUnimplemented("vabs (imm #0)", machInst);
---
> if (bits(machInst, 10)) {
> if (q)
> return new NVabsQFp<float>(machInst, vd, vm);
> else
> return new NVabsDFp<float>(machInst, vd, vm);
> } else {
> return decodeNeonSTwoMiscReg<NVabsD, NVabsQ>(
> q, size, machInst, vd, vm);
> }
731c1519,1527
< return new WarnUnimplemented("vneg (imm #0)", machInst);
---
> if (bits(machInst, 10)) {
> if (q)
> return new NVnegQFp<float>(machInst, vd, vm);
> else
> return new NVnegDFp<float>(machInst, vd, vm);
> } else {
> return decodeNeonSTwoMiscReg<NVnegD, NVnegQ>(
> q, size, machInst, vd, vm);
> }
736c1532,1535
< return new WarnUnimplemented("vswp", machInst);
---
> if (q)
> return new NVswpQ<uint64_t>(machInst, vd, vm);
> else
> return new NVswpD<uint64_t>(machInst, vd, vm);
738c1537,1538
< return new WarnUnimplemented("vtrn", machInst);
---
> return decodeNeonUTwoMiscReg<NVtrnD, NVtrnQ>(
> q, size, machInst, vd, vm);
740c1540,1541
< return new WarnUnimplemented("vuzp", machInst);
---
> return decodeNeonUTwoMiscReg<NVuzpD, NVuzpQ>(
> q, size, machInst, vd, vm);
742c1543,1544
< return new WarnUnimplemented("vzip", machInst);
---
> return decodeNeonUTwoMiscReg<NVzipD, NVzipQ>(
> q, size, machInst, vd, vm);
745c1547,1548
< return new WarnUnimplemented("vmovn", machInst);
---
> return decodeNeonUTwoMiscUSReg<NVmovn>(
> size, machInst, vd, vm);
747c1550,1551
< return new WarnUnimplemented("vqmovun", machInst);
---
> return decodeNeonSTwoMiscUSReg<NVqmovuns>(
> size, machInst, vd, vm);
750c1554,1560
< return new WarnUnimplemented("vqmovn", machInst);
---
> if (q) {
> return decodeNeonUTwoMiscUSReg<NVqmovun>(
> size, machInst, vd, vm);
> } else {
> return decodeNeonSTwoMiscUSReg<NVqmovn>(
> size, machInst, vd, vm);
> }
753c1563,1571
< return new WarnUnimplemented("vshll", machInst);
---
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const IntRegIndex vm =
> (IntRegIndex)(2 * (bits(machInst, 3, 0) |
> (bits(machInst, 5) << 4)));
> unsigned size = bits(machInst, 19, 18);
> return decodeNeonSTwoShiftUSReg<NVshll>(
> size, machInst, vd, vm, 8 << size);
760,761c1578,1580
< return new WarnUnimplemented("vcvt (single to half)",
< machInst);
---
> if (size != 1 || (vm % 2))
> return new Unknown(machInst);
> return new NVcvts2h<uint16_t>(machInst, vd, vm);
763,764c1582,1584
< return new WarnUnimplemented("vcvt (half to single)",
< machInst);
---
> if (size != 1 || (vd % 2))
> return new Unknown(machInst);
> return new NVcvth2s<uint16_t>(machInst, vd, vm);
773c1593,1633
< return new WarnUnimplemented("vcvt (fp and int)", machInst);
---
> if ((q && (vd % 2 || vm % 2)) || size != 2) {
> return new Unknown(machInst);
> } else {
> if (bits(b, 2)) {
> if (bits(b, 1)) {
> if (q) {
> return new NVcvt2ufxQ<float>(
> machInst, vd, vm, 0);
> } else {
> return new NVcvt2ufxD<float>(
> machInst, vd, vm, 0);
> }
> } else {
> if (q) {
> return new NVcvt2sfxQ<float>(
> machInst, vd, vm, 0);
> } else {
> return new NVcvt2sfxD<float>(
> machInst, vd, vm, 0);
> }
> }
> } else {
> if (bits(b, 1)) {
> if (q) {
> return new NVcvtu2fpQ<float>(
> machInst, vd, vm, 0);
> } else {
> return new NVcvtu2fpD<float>(
> machInst, vd, vm, 0);
> }
> } else {
> if (q) {
> return new NVcvts2fpQ<float>(
> machInst, vd, vm, 0);
> } else {
> return new NVcvts2fpD<float>(
> machInst, vd, vm, 0);
> }
> }
> }
> }
775c1635,1647
< return new WarnUnimplemented("vrecpe", machInst);
---
> if (bits(b, 2)) {
> if (q) {
> return new NVrecpeQFp<float>(machInst, vd, vm);
> } else {
> return new NVrecpeDFp<float>(machInst, vd, vm);
> }
> } else {
> if (q) {
> return new NVrecpeQ<uint32_t>(machInst, vd, vm);
> } else {
> return new NVrecpeD<uint32_t>(machInst, vd, vm);
> }
> }
777c1649,1661
< return new WarnUnimplemented("vrsqrte", machInst);
---
> if (bits(b, 2)) {
> if (q) {
> return new NVrsqrteQFp<float>(machInst, vd, vm);
> } else {
> return new NVrsqrteDFp<float>(machInst, vd, vm);
> }
> } else {
> if (q) {
> return new NVrsqrteQ<uint32_t>(machInst, vd, vm);
> } else {
> return new NVrsqrteD<uint32_t>(machInst, vd, vm);
> }
> }
802,803c1686,1687
< } else if ((c & 0x5) == 0) {
< if (bits(a, 3, 2) != 0x3) {
---
> } else if (bits(a, 2, 1) != 0x3) {
> if ((c & 0x5) == 0) {
805,807c1689
< }
< } else if ((c & 0x5) == 4) {
< if (bits(a, 3, 2) != 0x3) {
---
> } else if ((c & 0x5) == 4) {
810a1693,1701
> const IntRegIndex vd =
> (IntRegIndex)(2 * (bits(machInst, 15, 12) |
> (bits(machInst, 22) << 4)));
> const IntRegIndex vn =
> (IntRegIndex)(2 * (bits(machInst, 19, 16) |
> (bits(machInst, 7) << 4)));
> const IntRegIndex vm =
> (IntRegIndex)(2 * (bits(machInst, 3, 0) |
> (bits(machInst, 5) << 4)));
813c1704,1712
< return new WarnUnimplemented("vext", machInst);
---
> unsigned imm4 = bits(machInst, 11, 8);
> bool q = bits(machInst, 6);
> if (imm4 >= 16 && !q)
> return new Unknown(machInst);
> if (q) {
> return new NVextQ<uint8_t>(machInst, vd, vn, vm, imm4);
> } else {
> return new NVextD<uint8_t>(machInst, vd, vn, vm, imm4);
> }
817a1717,1719
> unsigned length = bits(machInst, 9, 8) + 1;
> if ((uint32_t)vn / 2 + length > 32)
> return new Unknown(machInst);
819c1721,1730
< return new WarnUnimplemented("vtbl", machInst);
---
> switch (length) {
> case 1:
> return new NVtbl1(machInst, vd, vn, vm);
> case 2:
> return new NVtbl2(machInst, vd, vn, vm);
> case 3:
> return new NVtbl3(machInst, vd, vn, vm);
> case 4:
> return new NVtbl4(machInst, vd, vn, vm);
> }
821c1732,1741
< return new WarnUnimplemented("vtbx", machInst);
---
> switch (length) {
> case 1:
> return new NVtbx1(machInst, vd, vn, vm);
> case 2:
> return new NVtbx2(machInst, vd, vn, vm);
> case 3:
> return new NVtbx3(machInst, vd, vn, vm);
> case 4:
> return new NVtbx4(machInst, vd, vn, vm);
> }
824c1744,1755
< return new WarnUnimplemented("vdup (scalar)", machInst);
---
> unsigned imm4 = bits(machInst, 19, 16);
> if (bits(imm4, 2, 0) == 0)
> return new Unknown(machInst);
> unsigned size = 0;
> while ((imm4 & 0x1) == 0) {
> size++;
> imm4 >>= 1;
> }
> unsigned index = imm4 >> 1;
> const bool q = bits(machInst, 6);
> return decodeNeonUTwoShiftSReg<NVdupD, NVdupQ>(
> q, size, machInst, vd, vm, index);
840c1771
< return decodeNeonMem(machInst);
---
> return decodeNeonData(machInst);
896c1827
< if (offset == 0 || vd + offset > NumFloatArchRegs) {
---
> if (offset == 0 || vd + offset/2 > NumFloatArchRegs) {
1047c1978,1979
< uint32_t index, size;
---
> // Handle accessing each single precision half of the vector.
> vd += bits(machInst, 21);
1051,1053c1983,1984
< size = 8;
< index = (bits(machInst, 21) << 2) |
< bits(machInst, 6, 5);
---
> return new VmovCoreRegB(machInst, (IntRegIndex)vd,
> rt, bits(machInst, 6, 5));
1055,1057c1986,1987
< size = 16;
< index = (bits(machInst, 21) << 1) |
< bits(machInst, 6);
---
> return new VmovCoreRegH(machInst, (IntRegIndex)vd,
> rt, bits(machInst, 6));
1059,1060c1989
< size = 32;
< index = bits(machInst, 21);
---
> return new VmovCoreRegW(machInst, (IntRegIndex)vd, rt);
1064,1077d1992
< if (index >= (32 / size)) {
< index -= (32 / size);
< vd++;
< }
< switch (size) {
< case 8:
< return new VmovCoreRegB(machInst, (IntRegIndex)vd,
< rt, index);
< case 16:
< return new VmovCoreRegH(machInst, (IntRegIndex)vd,
< rt, index);
< case 32:
< return new VmovCoreRegW(machInst, (IntRegIndex)vd, rt);
< }
1079,1080c1994,2022
< // A8-594
< return new WarnUnimplemented("vdup", machInst);
---
> bool q = bits(machInst, 21);
> unsigned be = (bits(machInst, 22) << 1) | (bits(machInst, 5));
> IntRegIndex vd = (IntRegIndex)(2 * (uint32_t)
> (bits(machInst, 19, 16) | (bits(machInst, 7) << 4)));
> IntRegIndex rt = (IntRegIndex)(uint32_t)
> bits(machInst, 15, 12);
> if (q) {
> switch (be) {
> case 0:
> return new NVdupQGpr<uint32_t>(machInst, vd, rt);
> case 1:
> return new NVdupQGpr<uint16_t>(machInst, vd, rt);
> case 2:
> return new NVdupQGpr<uint8_t>(machInst, vd, rt);
> case 3:
> return new Unknown(machInst);
> }
> } else {
> switch (be) {
> case 0:
> return new NVdupDGpr<uint32_t>(machInst, vd, rt);
> case 1:
> return new NVdupDGpr<uint16_t>(machInst, vd, rt);
> case 2:
> return new NVdupDGpr<uint8_t>(machInst, vd, rt);
> case 3:
> return new Unknown(machInst);
> }
> }
1131c2073,2075
< uint32_t index, size;
---
> // Handle indexing into each single precision half of the vector.
> vd += bits(machInst, 21);
> uint32_t index;
1136,1154c2080
< size = 8;
< index = (bits(machInst, 21) << 2) |
< bits(machInst, 6, 5);
< } else if (bits(machInst, 5) == 1) {
< size = 16;
< index = (bits(machInst, 21) << 1) |
< bits(machInst, 6);
< } else if (bits(machInst, 6) == 0 && !u) {
< size = 32;
< index = bits(machInst, 21);
< } else {
< return new Unknown(machInst);
< }
< if (index >= (32 / size)) {
< index -= (32 / size);
< vd++;
< }
< switch (size) {
< case 8:
---
> index = bits(machInst, 6, 5);
1162c2088,2089
< case 16:
---
> } else if (bits(machInst, 5) == 1) {
> index = bits(machInst, 6);
1170c2097
< case 32:
---
> } else if (bits(machInst, 6) == 0 && !u) {
1171a2099,2100
> } else {
> return new Unknown(machInst);