blob: 1e0c1164fe888a4722d251d5a13d94165af16077 [file] [log] [blame]
// -*- mode:c++ -*-
// Copyright (c) 2010-2011, 2015 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder. You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
output header {{
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUThreeUReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
switch (size) {
case 0:
return new Base<uint8_t>(machInst, dest, op1, op2);
case 1:
return new Base<uint16_t>(machInst, dest, op1, op2);
case 2:
return new Base<uint32_t>(machInst, dest, op1, op2);
case 3:
return new Base<uint64_t>(machInst, dest, op1, op2);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSThreeUReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
switch (size) {
case 0:
return new Base<int8_t>(machInst, dest, op1, op2);
case 1:
return new Base<int16_t>(machInst, dest, op1, op2);
case 2:
return new Base<int32_t>(machInst, dest, op1, op2);
case 3:
return new Base<int64_t>(machInst, dest, op1, op2);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUSThreeUReg(bool notSigned, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (notSigned) {
return decodeNeonUThreeUReg<Base>(size, machInst, dest, op1, op2);
} else {
return decodeNeonSThreeUReg<Base>(size, machInst, dest, op1, op2);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUThreeUSReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
switch (size) {
case 0:
return new Base<uint8_t>(machInst, dest, op1, op2);
case 1:
return new Base<uint16_t>(machInst, dest, op1, op2);
case 2:
return new Base<uint32_t>(machInst, dest, op1, op2);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSThreeUSReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
switch (size) {
case 0:
return new Base<int8_t>(machInst, dest, op1, op2);
case 1:
return new Base<int16_t>(machInst, dest, op1, op2);
case 2:
return new Base<int32_t>(machInst, dest, op1, op2);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSThreeHAndWReg(unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1,
IntRegIndex op2)
{
switch (size) {
case 1:
return new Base<int16_t>(machInst, dest, op1, op2);
case 2:
return new Base<int32_t>(machInst, dest, op1, op2);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSThreeImmHAndWReg(unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1,
IntRegIndex op2, uint64_t imm)
{
switch (size) {
case 1:
return new Base<int16_t>(machInst, dest, op1, op2, imm);
case 2:
return new Base<int32_t>(machInst, dest, op1, op2, imm);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUSThreeUSReg(bool notSigned, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (notSigned) {
return decodeNeonUThreeUSReg<Base>(
size, machInst, dest, op1, op2);
} else {
return decodeNeonSThreeUSReg<Base>(
size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUThreeSReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (q) {
return decodeNeonUThreeUSReg<BaseQ>(
size, machInst, dest, op1, op2);
} else {
return decodeNeonUThreeUSReg<BaseD>(
size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSThreeSReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (q) {
return decodeNeonSThreeUSReg<BaseQ>(
size, machInst, dest, op1, op2);
} else {
return decodeNeonSThreeUSReg<BaseD>(
size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSThreeXReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (q) {
return decodeNeonSThreeUReg<BaseQ>(
size, machInst, dest, op1, op2);
} else {
return decodeNeonSThreeUSReg<BaseD>(
size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUThreeXReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (q) {
return decodeNeonUThreeUReg<BaseQ>(
size, machInst, dest, op1, op2);
} else {
return decodeNeonUThreeUSReg<BaseD>(
size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUSThreeSReg(bool q, bool notSigned, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (notSigned) {
return decodeNeonUThreeSReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, op2);
} else {
return decodeNeonSThreeSReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUThreeReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (q) {
return decodeNeonUThreeUReg<BaseQ>(
size, machInst, dest, op1, op2);
} else {
return decodeNeonUThreeUReg<BaseD>(
size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSThreeReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (q) {
return decodeNeonSThreeUReg<BaseQ>(
size, machInst, dest, op1, op2);
} else {
return decodeNeonSThreeUReg<BaseD>(
size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUSThreeReg(bool q, bool notSigned, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, IntRegIndex op2)
{
if (notSigned) {
return decodeNeonUThreeReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, op2);
} else {
return decodeNeonSThreeReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, op2);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUThreeFpReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1, IntRegIndex op2)
{
if (q) {
if (size)
return new BaseQ<uint64_t>(machInst, dest, op1, op2);
else
return new BaseQ<uint32_t>(machInst, dest, op1, op2);
} else {
if (size)
return new Unknown(machInst);
else
return new BaseD<uint32_t>(machInst, dest, op1, op2);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUThreeScFpReg(bool size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1, IntRegIndex op2)
{
if (size)
return new Base<uint64_t>(machInst, dest, op1, op2);
else
return new Base<uint32_t>(machInst, dest, op1, op2);
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUThreeImmScFpReg(bool size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1,
IntRegIndex op2, uint64_t imm)
{
if (size)
return new Base<uint64_t>(machInst, dest, op1, op2, imm);
else
return new Base<uint32_t>(machInst, dest, op1, op2, imm);
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUThreeImmHAndWReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1,
IntRegIndex op2, uint64_t imm)
{
if (q) {
switch (size) {
case 1:
return new BaseQ<uint16_t>(machInst, dest, op1, op2, imm);
case 2:
return new BaseQ<uint32_t>(machInst, dest, op1, op2, imm);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 1:
return new BaseD<uint16_t>(machInst, dest, op1, op2, imm);
case 2:
return new BaseD<uint32_t>(machInst, dest, op1, op2, imm);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSThreeImmHAndWReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1,
IntRegIndex op2, uint64_t imm)
{
if (q) {
switch (size) {
case 1:
return new BaseQ<int16_t>(machInst, dest, op1, op2, imm);
case 2:
return new BaseQ<int32_t>(machInst, dest, op1, op2, imm);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 1:
return new BaseD<int16_t>(machInst, dest, op1, op2, imm);
case 2:
return new BaseD<int32_t>(machInst, dest, op1, op2, imm);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUThreeImmFpReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1,
IntRegIndex op2, uint64_t imm)
{
if (q) {
if (size)
return new BaseQ<uint64_t>(machInst, dest, op1, op2, imm);
else
return new BaseQ<uint32_t>(machInst, dest, op1, op2, imm);
} else {
if (size)
return new Unknown(machInst);
else
return new BaseD<uint32_t>(machInst, dest, op1, op2, imm);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoShiftReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
if (q) {
switch (size) {
case 0:
return new BaseQ<uint8_t>(machInst, dest, op1, imm);
case 1:
return new BaseQ<uint16_t>(machInst, dest, op1, imm);
case 2:
return new BaseQ<uint32_t>(machInst, dest, op1, imm);
case 3:
return new BaseQ<uint64_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0:
return new BaseD<uint8_t>(machInst, dest, op1, imm);
case 1:
return new BaseD<uint16_t>(machInst, dest, op1, imm);
case 2:
return new BaseD<uint32_t>(machInst, dest, op1, imm);
case 3:
return new BaseD<uint64_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSTwoShiftReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
if (q) {
switch (size) {
case 0:
return new BaseQ<int8_t>(machInst, dest, op1, imm);
case 1:
return new BaseQ<int16_t>(machInst, dest, op1, imm);
case 2:
return new BaseQ<int32_t>(machInst, dest, op1, imm);
case 3:
return new BaseQ<int64_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0:
return new BaseD<int8_t>(machInst, dest, op1, imm);
case 1:
return new BaseD<int16_t>(machInst, dest, op1, imm);
case 2:
return new BaseD<int32_t>(machInst, dest, op1, imm);
case 3:
return new BaseD<int64_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUSTwoShiftReg(bool q, bool notSigned, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
if (notSigned) {
return decodeNeonUTwoShiftReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, imm);
} else {
return decodeNeonSTwoShiftReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, imm);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUTwoShiftUSReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
switch (size) {
case 0:
return new Base<uint8_t>(machInst, dest, op1, imm);
case 1:
return new Base<uint16_t>(machInst, dest, op1, imm);
case 2:
return new Base<uint32_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUTwoShiftUReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
switch (size) {
case 0:
return new Base<uint8_t>(machInst, dest, op1, imm);
case 1:
return new Base<uint16_t>(machInst, dest, op1, imm);
case 2:
return new Base<uint32_t>(machInst, dest, op1, imm);
case 3:
return new Base<uint64_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSTwoShiftUReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
switch (size) {
case 0:
return new Base<int8_t>(machInst, dest, op1, imm);
case 1:
return new Base<int16_t>(machInst, dest, op1, imm);
case 2:
return new Base<int32_t>(machInst, dest, op1, imm);
case 3:
return new Base<int64_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoShiftSReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
if (q) {
return decodeNeonUTwoShiftUSReg<BaseQ>(
size, machInst, dest, op1, imm);
} else {
return decodeNeonUTwoShiftUSReg<BaseD>(
size, machInst, dest, op1, imm);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSTwoShiftUSReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
switch (size) {
case 0:
return new Base<int8_t>(machInst, dest, op1, imm);
case 1:
return new Base<int16_t>(machInst, dest, op1, imm);
case 2:
return new Base<int32_t>(machInst, dest, op1, imm);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSTwoShiftSReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
if (q) {
return decodeNeonSTwoShiftUSReg<BaseQ>(
size, machInst, dest, op1, imm);
} else {
return decodeNeonSTwoShiftUSReg<BaseD>(
size, machInst, dest, op1, imm);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUSTwoShiftSReg(bool q, bool notSigned, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1, uint64_t imm)
{
if (notSigned) {
return decodeNeonUTwoShiftSReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, imm);
} else {
return decodeNeonSTwoShiftSReg<BaseD, BaseQ>(
q, size, machInst, dest, op1, imm);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoShiftXReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1, uint64_t imm)
{
if (q) {
return decodeNeonUTwoShiftUReg<BaseQ>(
size, machInst, dest, op1, imm);
} else {
return decodeNeonUTwoShiftUSReg<BaseD>(
size, machInst, dest, op1, imm);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSTwoShiftXReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1, uint64_t imm)
{
if (q) {
return decodeNeonSTwoShiftUReg<BaseQ>(
size, machInst, dest, op1, imm);
} else {
return decodeNeonSTwoShiftUSReg<BaseD>(
size, machInst, dest, op1, imm);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUTwoShiftUFpReg(unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1, uint64_t imm)
{
if (size)
return new Base<uint64_t>(machInst, dest, op1, imm);
else
return new Base<uint32_t>(machInst, dest, op1, imm);
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoShiftFpReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1, uint64_t imm)
{
if (q) {
if (size)
return new BaseQ<uint64_t>(machInst, dest, op1, imm);
else
return new BaseQ<uint32_t>(machInst, dest, op1, imm);
} else {
if (size)
return new Unknown(machInst);
else
return new BaseD<uint32_t>(machInst, dest, op1, imm);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUTwoMiscUSReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
switch (size) {
case 0:
return new Base<uint8_t>(machInst, dest, op1);
case 1:
return new Base<uint16_t>(machInst, dest, op1);
case 2:
return new Base<uint32_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSTwoMiscUSReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
switch (size) {
case 0:
return new Base<int8_t>(machInst, dest, op1);
case 1:
return new Base<int16_t>(machInst, dest, op1);
case 2:
return new Base<int32_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoMiscSReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
if (q) {
return decodeNeonUTwoMiscUSReg<BaseQ>(size, machInst, dest, op1);
} else {
return decodeNeonUTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSTwoMiscSReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
if (q) {
return decodeNeonSTwoMiscUSReg<BaseQ>(size, machInst, dest, op1);
} else {
return decodeNeonSTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUTwoMiscUReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
switch (size) {
case 0:
return new Base<uint8_t>(machInst, dest, op1);
case 1:
return new Base<uint16_t>(machInst, dest, op1);
case 2:
return new Base<uint32_t>(machInst, dest, op1);
case 3:
return new Base<uint64_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonSTwoMiscUReg(unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
switch (size) {
case 0:
return new Base<int8_t>(machInst, dest, op1);
case 1:
return new Base<int16_t>(machInst, dest, op1);
case 2:
return new Base<int32_t>(machInst, dest, op1);
case 3:
return new Base<int64_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSTwoMiscReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
if (q) {
return decodeNeonSTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
} else {
return decodeNeonSTwoMiscUReg<BaseD>(size, machInst, dest, op1);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoMiscReg(bool q, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
if (q) {
return decodeNeonUTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
} else {
return decodeNeonUTwoMiscUReg<BaseD>(size, machInst, dest, op1);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUSTwoMiscSReg(bool q, bool notSigned, unsigned size,
ExtMachInst machInst, IntRegIndex dest,
IntRegIndex op1)
{
if (notSigned) {
return decodeNeonUTwoShiftSReg<BaseD, BaseQ>(
q, size, machInst, dest, op1);
} else {
return decodeNeonSTwoShiftSReg<BaseD, BaseQ>(
q, size, machInst, dest, op1);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoMiscXReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
return decodeNeonUTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
} else {
return decodeNeonUTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSTwoMiscXReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
return decodeNeonSTwoMiscUReg<BaseQ>(size, machInst, dest, op1);
} else {
return decodeNeonSTwoMiscUSReg<BaseD>(size, machInst, dest, op1);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoMiscFpReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
if (size)
return new BaseQ<uint64_t>(machInst, dest, op1);
else
return new BaseQ<uint32_t>(machInst, dest, op1);
} else {
if (size)
return new Unknown(machInst);
else
return new BaseD<uint32_t>(machInst, dest, op1);
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUTwoMiscPwiseScFpReg(unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (size)
return new BaseQ<uint64_t>(machInst, dest, op1);
else
return new BaseD<uint32_t>(machInst, dest, op1);
}
template <template <typename T> class Base>
StaticInstPtr
decodeNeonUTwoMiscScFpReg(unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (size)
return new Base<uint64_t>(machInst, dest, op1);
else
return new Base<uint32_t>(machInst, dest, op1);
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonUAcrossLanesReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
switch (size) {
case 0x0:
return new BaseQ<uint8_t>(machInst, dest, op1);
case 0x1:
return new BaseQ<uint16_t>(machInst, dest, op1);
case 0x2:
return new BaseQ<uint32_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0x0:
return new BaseD<uint8_t>(machInst, dest, op1);
case 0x1:
return new BaseD<uint16_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ,
template <typename T> class BaseBQ>
StaticInstPtr
decodeNeonUAcrossLanesReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
switch (size) {
case 0x0:
return new BaseQ<uint8_t>(machInst, dest, op1);
case 0x1:
return new BaseQ<uint16_t>(machInst, dest, op1);
case 0x2:
return new BaseBQ<uint32_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0x0:
return new BaseD<uint8_t>(machInst, dest, op1);
case 0x1:
return new BaseD<uint16_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ>
StaticInstPtr
decodeNeonSAcrossLanesReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
switch (size) {
case 0x0:
return new BaseQ<int8_t>(machInst, dest, op1);
case 0x1:
return new BaseQ<int16_t>(machInst, dest, op1);
case 0x2:
return new BaseQ<int32_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0x0:
return new BaseD<int8_t>(machInst, dest, op1);
case 0x1:
return new BaseD<int16_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ,
template <typename T> class BaseBQ>
StaticInstPtr
decodeNeonUAcrossLanesLongReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
switch (size) {
case 0x0:
return new BaseQ<uint8_t>(machInst, dest, op1);
case 0x1:
return new BaseQ<uint16_t>(machInst, dest, op1);
case 0x2:
return new BaseBQ<uint32_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0x0:
return new BaseD<uint8_t>(machInst, dest, op1);
case 0x1:
return new BaseD<uint16_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
}
template <template <typename T> class BaseD,
template <typename T> class BaseQ,
template <typename T> class BaseBQ>
StaticInstPtr
decodeNeonSAcrossLanesLongReg(bool q, unsigned size, ExtMachInst machInst,
IntRegIndex dest, IntRegIndex op1)
{
if (q) {
switch (size) {
case 0x0:
return new BaseQ<int8_t>(machInst, dest, op1);
case 0x1:
return new BaseQ<int16_t>(machInst, dest, op1);
case 0x2:
return new BaseBQ<int32_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
} else {
switch (size) {
case 0x0:
return new BaseD<int8_t>(machInst, dest, op1);
case 0x1:
return new BaseD<int16_t>(machInst, dest, op1);
default:
return new Unknown(machInst);
}
}
}
}};
let {{
header_output = ""
exec_output = ""
vcompares = '''
static float
vcgtFunc(float op1, float op2)
{
if (std::isnan(op1) || std::isnan(op2))
return 2.0;
return (op1 > op2) ? 0.0 : 1.0;
}
static float
vcgeFunc(float op1, float op2)
{
if (std::isnan(op1) || std::isnan(op2))
return 2.0;
return (op1 >= op2) ? 0.0 : 1.0;
}
static float
vceqFunc(float op1, float op2)
{
if (isSnan(op1) || isSnan(op2))
return 2.0;
return (op1 == op2) ? 0.0 : 1.0;
}
'''
vcomparesL = '''
static float
vcleFunc(float op1, float op2)
{
if (std::isnan(op1) || std::isnan(op2))
return 2.0;
return (op1 <= op2) ? 0.0 : 1.0;
}
static float
vcltFunc(float op1, float op2)
{
if (std::isnan(op1) || std::isnan(op2))
return 2.0;
return (op1 < op2) ? 0.0 : 1.0;
}
'''
vacomparesG = '''
static float
vacgtFunc(float op1, float op2)
{
if (std::isnan(op1) || std::isnan(op2))
return 2.0;
return (fabsf(op1) > fabsf(op2)) ? 0.0 : 1.0;
}
static float
vacgeFunc(float op1, float op2)
{
if (std::isnan(op1) || std::isnan(op2))
return 2.0;
return (fabsf(op1) >= fabsf(op2)) ? 0.0 : 1.0;
}
'''
exec_output += vcompares + vacomparesG
smallUnsignedTypes = ("uint8_t", "uint16_t", "uint32_t")
unsignedTypes = smallUnsignedTypes + ("uint64_t",)
smallSignedTypes = ("int8_t", "int16_t", "int32_t")
signedTypes = smallSignedTypes + ("int64_t",)
smallTypes = smallUnsignedTypes + smallSignedTypes
allTypes = unsignedTypes + signedTypes
def threeEqualRegInst(name, Name, opClass, types, rCount, op,
readDest=False, pairwise=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1, srcReg2, destReg;
'''
for reg in range(rCount):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
if pairwise:
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
Element srcElem1 = gtoh(2 * i < eCount ?
srcReg1.elements[2 * i] :
srcReg2.elements[2 * i - eCount]);
Element srcElem2 = gtoh(2 * i < eCount ?
srcReg1.elements[2 * i + 1] :
srcReg2.elements[2 * i + 1 - eCount]);
Element destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
else:
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
Element srcElem1 = gtoh(srcReg1.elements[i]);
Element srcElem2 = gtoh(srcReg2.elements[i]);
Element destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegRegOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegRegOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def threeEqualRegInstFp(name, Name, opClass, types, rCount, op,
readDest=False, pairwise=False, toInt=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
typedef float FloatVect[rCount];
FloatVect srcRegs1, srcRegs2;
'''
if toInt:
eWalkCode += 'RegVect destRegs;\n'
else:
eWalkCode += 'FloatVect destRegs;\n'
for reg in range(rCount):
eWalkCode += '''
srcRegs1[%(reg)d] = FpOp1P%(reg)d;
srcRegs2[%(reg)d] = FpOp2P%(reg)d;
''' % { "reg" : reg }
if readDest:
if toInt:
eWalkCode += '''
destRegs.regs[%(reg)d] = FpDestP%(reg)d.bits;
''' % { "reg" : reg }
else:
eWalkCode += '''
destRegs[%(reg)d] = FpDestP%(reg)d;
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destReg = destRegs[r];'
destType = 'float'
writeDest = 'destRegs[r] = destReg;'
if toInt:
destType = 'uint32_t'
writeDest = 'destRegs.regs[r] = destReg;'
if pairwise:
eWalkCode += '''
for (unsigned r = 0; r < rCount; r++) {
float srcReg1 = (2 * r < rCount) ?
srcRegs1[2 * r] : srcRegs2[2 * r - rCount];
float srcReg2 = (2 * r < rCount) ?
srcRegs1[2 * r + 1] : srcRegs2[2 * r + 1 - rCount];
%(destType)s destReg;
%(readDest)s
%(op)s
%(writeDest)s
}
''' % { "op" : op,
"readDest" : readDestCode,
"destType" : destType,
"writeDest" : writeDest }
else:
eWalkCode += '''
for (unsigned r = 0; r < rCount; r++) {
float srcReg1 = srcRegs1[r];
float srcReg2 = srcRegs2[r];
%(destType)s destReg;
%(readDest)s
%(op)s
%(writeDest)s
}
''' % { "op" : op,
"readDest" : readDestCode,
"destType" : destType,
"writeDest" : writeDest }
for reg in range(rCount):
if toInt:
eWalkCode += '''
FpDestP%(reg)d_uw = destRegs.regs[%(reg)d];
''' % { "reg" : reg }
else:
eWalkCode += '''
FpDestP%(reg)d = destRegs[%(reg)d];
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"FpRegRegRegOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegRegOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def threeUnequalRegInst(name, Name, opClass, types, op,
bigSrc1, bigSrc2, bigDest, readDest):
global header_output, exec_output
src1Cnt = src2Cnt = destCnt = 2
src1Prefix = src2Prefix = destPrefix = ''
if bigSrc1:
src1Cnt = 4
src1Prefix = 'Big'
if bigSrc2:
src2Cnt = 4
src2Prefix = 'Big'
if bigDest:
destCnt = 4
destPrefix = 'Big'
eWalkCode = simdEnabledCheckCode + '''
%sRegVect srcReg1;
%sRegVect srcReg2;
%sRegVect destReg;
''' % (src1Prefix, src2Prefix, destPrefix)
for reg in range(src1Cnt):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
for reg in range(src2Cnt):
eWalkCode += '''
srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
for reg in range(destCnt):
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
%(src1Prefix)sElement srcElem1 = gtoh(srcReg1.elements[i]);
%(src1Prefix)sElement srcElem2 = gtoh(srcReg2.elements[i]);
%(destPrefix)sElement destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode,
"src1Prefix" : src1Prefix, "src2Prefix" : src2Prefix,
"destPrefix" : destPrefix }
for reg in range(destCnt):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegRegOp",
{ "code": eWalkCode,
"r_count": 2,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegRegOpDeclare.subst(iop)
exec_output += NeonUnequalRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def threeRegNarrowInst(name, Name, opClass, types, op, readDest=False):
threeUnequalRegInst(name, Name, opClass, types, op,
True, True, False, readDest)
def threeRegLongInst(name, Name, opClass, types, op, readDest=False):
threeUnequalRegInst(name, Name, opClass, types, op,
False, False, True, readDest)
def threeRegWideInst(name, Name, opClass, types, op, readDest=False):
threeUnequalRegInst(name, Name, opClass, types, op,
True, False, True, readDest)
def twoEqualRegInst(name, Name, opClass, types, rCount, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1, srcReg2, destReg;
'''
for reg in range(rCount):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
if (imm < 0 && imm >= eCount) {
fault = std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
} else {
for (unsigned i = 0; i < eCount; i++) {
Element srcElem1 = gtoh(srcReg1.elements[i]);
Element srcElem2 = gtoh(srcReg2.elements[imm]);
Element destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegRegImmOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegRegImmOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegLongInst(name, Name, opClass, types, op, readDest=False):
global header_output, exec_output
rCount = 2
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1, srcReg2;
BigRegVect destReg;
'''
for reg in range(rCount):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
srcReg2.regs[%(reg)d] = htog(FpOp2P%(reg)d_uw);;
''' % { "reg" : reg }
if readDest:
for reg in range(2 * rCount):
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
if (imm < 0 && imm >= eCount) {
fault = std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
} else {
for (unsigned i = 0; i < eCount; i++) {
Element srcElem1 = gtoh(srcReg1.elements[i]);
Element srcElem2 = gtoh(srcReg2.elements[imm]);
BigElement destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(2 * rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegRegImmOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegRegImmOpDeclare.subst(iop)
exec_output += NeonUnequalRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoEqualRegInstFp(name, Name, opClass, types, rCount, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
typedef float FloatVect[rCount];
FloatVect srcRegs1, srcRegs2, destRegs;
'''
for reg in range(rCount):
eWalkCode += '''
srcRegs1[%(reg)d] = FpOp1P%(reg)d;
srcRegs2[%(reg)d] = FpOp2P%(reg)d;
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
destRegs[%(reg)d] = FpDestP%(reg)d;
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destReg = destRegs[i];'
eWalkCode += '''
if (imm < 0 && imm >= eCount) {
fault = std::make_shared<UndefinedInstruction>(machInst, false,
mnemonic);
} else {
for (unsigned i = 0; i < rCount; i++) {
float srcReg1 = srcRegs1[i];
float srcReg2 = srcRegs2[imm];
float destReg;
%(readDest)s
%(op)s
destRegs[i] = destReg;
}
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d = destRegs[%(reg)d];
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"FpRegRegRegImmOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegRegImmOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegShiftInst(name, Name, opClass, types, rCount, op,
readDest=False, toInt=False, fromInt=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcRegs1, destRegs;
'''
for reg in range(rCount):
eWalkCode += '''
srcRegs1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
destRegs.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destRegs.elements[i]);'
if toInt:
readDestCode = 'destReg = gtoh(destRegs.regs[i]);'
readOpCode = 'Element srcElem1 = gtoh(srcRegs1.elements[i]);'
if fromInt:
readOpCode = 'uint32_t srcReg1 = gtoh(srcRegs1.regs[i]);'
declDest = 'Element destElem;'
writeDestCode = 'destRegs.elements[i] = htog(destElem);'
if toInt:
declDest = 'uint32_t destReg;'
writeDestCode = 'destRegs.regs[i] = htog(destReg);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
%(readOp)s
%(declDest)s
%(readDest)s
%(op)s
%(writeDest)s
}
''' % { "readOp" : readOpCode,
"declDest" : declDest,
"readDest" : readDestCode,
"op" : op,
"writeDest" : writeDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destRegs.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegImmOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegImmOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegNarrowShiftInst(name, Name, opClass, types, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
BigRegVect srcReg1;
RegVect destReg;
'''
for reg in range(4):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
for reg in range(2):
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
BigElement srcElem1 = gtoh(srcReg1.elements[i]);
Element destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(2):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegImmOp",
{ "code": eWalkCode,
"r_count": 2,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegImmOpDeclare.subst(iop)
exec_output += NeonUnequalRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegLongShiftInst(name, Name, opClass, types, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1;
BigRegVect destReg;
'''
for reg in range(2):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
for reg in range(4):
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destReg = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
Element srcElem1 = gtoh(srcReg1.elements[i]);
BigElement destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(4):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegImmOp",
{ "code": eWalkCode,
"r_count": 2,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegImmOpDeclare.subst(iop)
exec_output += NeonUnequalRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegMiscInst(name, Name, opClass, types, rCount, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1, destReg;
'''
for reg in range(rCount):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
unsigned j = i;
Element srcElem1 = gtoh(srcReg1.elements[i]);
Element destElem;
%(readDest)s
%(op)s
destReg.elements[j] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegMiscScInst(name, Name, opClass, types, rCount, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1, destReg;
'''
for reg in range(rCount):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
Element srcElem1 = gtoh(srcReg1.elements[imm]);
Element destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegImmOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegImmOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegMiscScramble(name, Name, opClass, types, rCount, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1, destReg;
'''
for reg in range(rCount):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += op
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
FpOp1P%(reg)d_uw = gtoh(srcReg1.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegMiscInstFp(name, Name, opClass, types, rCount, op,
readDest=False, toInt=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
typedef float FloatVect[rCount];
FloatVect srcRegs1;
'''
if toInt:
eWalkCode += 'RegVect destRegs;\n'
else:
eWalkCode += 'FloatVect destRegs;\n'
for reg in range(rCount):
eWalkCode += '''
srcRegs1[%(reg)d] = FpOp1P%(reg)d;
''' % { "reg" : reg }
if readDest:
if toInt:
eWalkCode += '''
destRegs.regs[%(reg)d] = FpDestP%(reg)d.bits;
''' % { "reg" : reg }
else:
eWalkCode += '''
destRegs[%(reg)d] = FpDestP%(reg)d;
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destReg = destRegs[i];'
destType = 'float'
writeDest = 'destRegs[r] = destReg;'
if toInt:
destType = 'uint32_t'
writeDest = 'destRegs.regs[r] = destReg;'
eWalkCode += '''
for (unsigned r = 0; r < rCount; r++) {
float srcReg1 = srcRegs1[r];
%(destType)s destReg;
%(readDest)s
%(op)s
%(writeDest)s
}
''' % { "op" : op,
"readDest" : readDestCode,
"destType" : destType,
"writeDest" : writeDest }
for reg in range(rCount):
if toInt:
eWalkCode += '''
FpDestP%(reg)d_uw = destRegs.regs[%(reg)d];
''' % { "reg" : reg }
else:
eWalkCode += '''
FpDestP%(reg)d = destRegs[%(reg)d];
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"FpRegRegOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegCondenseInst(name, Name, opClass, types, rCount, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcRegs;
BigRegVect destReg;
'''
for reg in range(rCount):
eWalkCode += '''
srcRegs.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount / 2; i++) {
Element srcElem1 = gtoh(srcRegs.elements[2 * i]);
Element srcElem2 = gtoh(srcRegs.elements[2 * i + 1]);
BigElement destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegOpDeclare.subst(iop)
exec_output += NeonUnequalRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegNarrowMiscInst(name, Name, opClass, types, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
BigRegVect srcReg1;
RegVect destReg;
'''
for reg in range(4):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
for reg in range(2):
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
BigElement srcElem1 = gtoh(srcReg1.elements[i]);
Element destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(2):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegOp",
{ "code": eWalkCode,
"r_count": 2,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegOpDeclare.subst(iop)
exec_output += NeonUnequalRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def oneRegImmInst(name, Name, opClass, types, rCount, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect destReg;
'''
if readDest:
for reg in range(rCount):
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destElem = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
Element destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(rCount):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegImmOp",
{ "code": eWalkCode,
"r_count": rCount,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegImmOpDeclare.subst(iop)
exec_output += NeonEqualRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
def twoRegLongMiscInst(name, Name, opClass, types, op, readDest=False):
global header_output, exec_output
eWalkCode = simdEnabledCheckCode + '''
RegVect srcReg1;
BigRegVect destReg;
'''
for reg in range(2):
eWalkCode += '''
srcReg1.regs[%(reg)d] = htog(FpOp1P%(reg)d_uw);
''' % { "reg" : reg }
if readDest:
for reg in range(4):
eWalkCode += '''
destReg.regs[%(reg)d] = htog(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
readDestCode = ''
if readDest:
readDestCode = 'destReg = gtoh(destReg.elements[i]);'
eWalkCode += '''
for (unsigned i = 0; i < eCount; i++) {
Element srcElem1 = gtoh(srcReg1.elements[i]);
BigElement destElem;
%(readDest)s
%(op)s
destReg.elements[i] = htog(destElem);
}
''' % { "op" : op, "readDest" : readDestCode }
for reg in range(4):
eWalkCode += '''
FpDestP%(reg)d_uw = gtoh(destReg.regs[%(reg)d]);
''' % { "reg" : reg }
iop = InstObjParams(name, Name,
"RegRegOp",
{ "code": eWalkCode,
"r_count": 2,
"predicate_test": predicateTest,
"op_class": opClass }, [])
header_output += NeonRegRegOpDeclare.subst(iop)
exec_output += NeonUnequalRegExecute.subst(iop)
for type in types:
substDict = { "targs" : type,
"class_name" : Name }
exec_output += NeonExecDeclare.subst(substDict)
vhaddCode = '''
Element carryBit =
(((unsigned)srcElem1 & 0x1) +
((unsigned)srcElem2 & 0x1)) >> 1;
// Use division instead of a shift to ensure the sign extension works
// right. The compiler will figure out if it can be a shift. Mask the
// inputs so they get truncated correctly.
destElem = (((srcElem1 & ~(Element)1) / 2) +
((srcElem2 & ~(Element)1) / 2)) + carryBit;
'''
threeEqualRegInst("vhadd", "VhaddD", "SimdAddOp", allTypes, 2, vhaddCode)
threeEqualRegInst("vhadd", "VhaddQ", "SimdAddOp", allTypes, 4, vhaddCode)
vrhaddCode = '''
Element carryBit =
(((unsigned)srcElem1 & 0x1) +
((unsigned)srcElem2 & 0x1) + 1) >> 1;
// Use division instead of a shift to ensure the sign extension works
// right. The compiler will figure out if it can be a shift. Mask the
// inputs so they get truncated correctly.
destElem = (((srcElem1 & ~(Element)1) / 2) +
((srcElem2 & ~(Element)1) / 2)) + carryBit;
'''
threeEqualRegInst("vrhadd", "VrhaddD", "SimdAddOp", allTypes, 2, vrhaddCode)
threeEqualRegInst("vrhadd", "VrhaddQ", "SimdAddOp", allTypes, 4, vrhaddCode)
vhsubCode = '''
Element barrowBit =
(((srcElem1 & 0x1) - (srcElem2 & 0x1)) >> 1) & 0x1;
// Use division instead of a shift to ensure the sign extension works
// right. The compiler will figure out if it can be a shift. Mask the
// inputs so they get truncated correctly.
destElem = (((srcElem1 & ~(Element)1) / 2) -
((srcElem2 & ~(Element)1) / 2)) - barrowBit;
'''
threeEqualRegInst("vhsub", "VhsubD", "SimdAddOp", allTypes, 2, vhsubCode)
threeEqualRegInst("vhsub", "VhsubQ", "SimdAddOp", allTypes, 4, vhsubCode)
vandCode = '''
destElem = srcElem1 & srcElem2;
'''
threeEqualRegInst("vand", "VandD", "SimdAluOp", unsignedTypes, 2, vandCode)
threeEqualRegInst("vand", "VandQ", "SimdAluOp", unsignedTypes, 4, vandCode)
vbicCode = '''
destElem = srcElem1 & ~srcElem2;
'''
threeEqualRegInst("vbic", "VbicD", "SimdAluOp", unsignedTypes, 2, vbicCode)
threeEqualRegInst("vbic", "VbicQ", "SimdAluOp", unsignedTypes, 4, vbicCode)
vorrCode = '''
destElem = srcElem1 | srcElem2;
'''
threeEqualRegInst("vorr", "VorrD", "SimdAluOp", unsignedTypes, 2, vorrCode)
threeEqualRegInst("vorr", "VorrQ", "SimdAluOp", unsignedTypes, 4, vorrCode)
threeEqualRegInst("vmov", "VmovD", "SimdMiscOp", unsignedTypes, 2, vorrCode)
threeEqualRegInst("vmov", "VmovQ", "SimdMiscOp", unsignedTypes, 4, vorrCode)
vornCode = '''
destElem = srcElem1 | ~srcElem2;
'''
threeEqualRegInst("vorn", "VornD", "SimdAluOp", unsignedTypes, 2, vornCode)
threeEqualRegInst("vorn", "VornQ", "SimdAluOp", unsignedTypes, 4, vornCode)
veorCode = '''
destElem = srcElem1 ^ srcElem2;
'''
threeEqualRegInst("veor", "VeorD", "SimdAluOp", unsignedTypes, 2, veorCode)
threeEqualRegInst("veor", "VeorQ", "SimdAluOp", unsignedTypes, 4, veorCode)
vbifCode = '''
destElem = (destElem & srcElem2) | (srcElem1 & ~srcElem2);
'''
threeEqualRegInst("vbif", "VbifD", "SimdAluOp", unsignedTypes, 2, vbifCode, True)
threeEqualRegInst("vbif", "VbifQ", "SimdAluOp", unsignedTypes, 4, vbifCode, True)
vbitCode = '''
destElem = (srcElem1 & srcElem2) | (destElem & ~srcElem2);
'''
threeEqualRegInst("vbit", "VbitD", "SimdAluOp", unsignedTypes, 2, vbitCode, True)
threeEqualRegInst("vbit", "VbitQ", "SimdAluOp", unsignedTypes, 4, vbitCode, True)
vbslCode = '''
destElem = (srcElem1 & destElem) | (srcElem2 & ~destElem);
'''
threeEqualRegInst("vbsl", "VbslD", "SimdAluOp", unsignedTypes, 2, vbslCode, True)
threeEqualRegInst("vbsl", "VbslQ", "SimdAluOp", unsignedTypes, 4, vbslCode, True)
vmaxCode = '''
destElem = (srcElem1 > srcElem2) ? srcElem1 : srcElem2;
'''
threeEqualRegInst("vmax", "VmaxD", "SimdCmpOp", allTypes, 2, vmaxCode)
threeEqualRegInst("vmax", "VmaxQ", "SimdCmpOp", allTypes, 4, vmaxCode)
vminCode = '''
destElem = (srcElem1 < srcElem2) ? srcElem1 : srcElem2;
'''
threeEqualRegInst("vmin", "VminD", "SimdCmpOp", allTypes, 2, vminCode)
threeEqualRegInst("vmin", "VminQ", "SimdCmpOp", allTypes, 4, vminCode)
vaddCode = '''
destElem = srcElem1 + srcElem2;
'''
threeEqualRegInst("vadd", "NVaddD", "SimdAddOp", unsignedTypes, 2, vaddCode)
threeEqualRegInst("vadd", "NVaddQ", "SimdAddOp", unsignedTypes, 4, vaddCode)
threeEqualRegInst("vpadd", "NVpaddD", "SimdAddOp", smallUnsignedTypes,
2, vaddCode, pairwise=True)
vaddlwCode = '''
destElem = (BigElement)srcElem1 + (BigElement)srcElem2;
'''
threeRegLongInst("vaddl", "Vaddl", "SimdAddOp", smallTypes, vaddlwCode)
threeRegWideInst("vaddw", "Vaddw", "SimdAddOp", smallTypes, vaddlwCode)
vaddhnCode = '''
destElem = ((BigElement)srcElem1 + (BigElement)srcElem2) >>
(sizeof(Element) * 8);
'''
threeRegNarrowInst("vaddhn", "Vaddhn", "SimdAddOp", smallTypes, vaddhnCode)
vraddhnCode = '''
destElem = ((BigElement)srcElem1 + (BigElement)srcElem2 +
((BigElement)1 << (sizeof(Element) * 8 - 1))) >>
(sizeof(Element) * 8);
'''
threeRegNarrowInst("vraddhn", "Vraddhn", "SimdAddOp", smallTypes, vraddhnCode)
vsubCode = '''
destElem = srcElem1 - srcElem2;
'''
threeEqualRegInst("vsub", "NVsubD", "SimdAddOp", unsignedTypes, 2, vsubCode)
threeEqualRegInst("vsub", "NVsubQ", "SimdAddOp", unsignedTypes, 4, vsubCode)
vsublwCode = '''
destElem = (BigElement)srcElem1 - (BigElement)srcElem2;
'''
threeRegLongInst("vsubl", "Vsubl", "SimdAddOp", smallTypes, vsublwCode)
threeRegWideInst("vsubw", "Vsubw", "SimdAddOp", smallTypes, vsublwCode)
vqaddUCode = '''
destElem = srcElem1 + srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
if (destElem < srcElem1 || destElem < srcElem2) {
destElem = (Element)(-1);
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqadd", "VqaddUD", "SimdAddOp", unsignedTypes, 2, vqaddUCode)
threeEqualRegInst("vqadd", "VqaddUQ", "SimdAddOp", unsignedTypes, 4, vqaddUCode)
vsubhnCode = '''
destElem = ((BigElement)srcElem1 - (BigElement)srcElem2) >>
(sizeof(Element) * 8);
'''
threeRegNarrowInst("vsubhn", "Vsubhn", "SimdAddOp", smallTypes, vsubhnCode)
vrsubhnCode = '''
destElem = ((BigElement)srcElem1 - (BigElement)srcElem2 +
((BigElement)1 << (sizeof(Element) * 8 - 1))) >>
(sizeof(Element) * 8);
'''
threeRegNarrowInst("vrsubhn", "Vrsubhn", "SimdAddOp", smallTypes, vrsubhnCode)
vqaddSCode = '''
destElem = srcElem1 + srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
bool negDest = (destElem < 0);
bool negSrc1 = (srcElem1 < 0);
bool negSrc2 = (srcElem2 < 0);
if ((negDest != negSrc1) && (negSrc1 == negSrc2)) {
if (negDest)
/* If (>=0) plus (>=0) yields (<0), saturate to +. */
destElem = std::numeric_limits<Element>::max();
else
/* If (<0) plus (<0) yields (>=0), saturate to -. */
destElem = std::numeric_limits<Element>::min();
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqadd", "VqaddSD", "SimdAddOp", signedTypes, 2, vqaddSCode)
threeEqualRegInst("vqadd", "VqaddSQ", "SimdAddOp", signedTypes, 4, vqaddSCode)
vqsubUCode = '''
destElem = srcElem1 - srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
if (destElem > srcElem1) {
destElem = 0;
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqsub", "VqsubUD", "SimdAddOp", unsignedTypes, 2, vqsubUCode)
threeEqualRegInst("vqsub", "VqsubUQ", "SimdAddOp", unsignedTypes, 4, vqsubUCode)
vqsubSCode = '''
destElem = srcElem1 - srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
bool negDest = (destElem < 0);
bool negSrc1 = (srcElem1 < 0);
bool posSrc2 = (srcElem2 >= 0);
if ((negDest != negSrc1) && (negSrc1 == posSrc2)) {
if (negDest)
/* If (>=0) minus (<0) yields (<0), saturate to +. */
destElem = std::numeric_limits<Element>::max();
else
/* If (<0) minus (>=0) yields (>=0), saturate to -. */
destElem = std::numeric_limits<Element>::min();
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqsub", "VqsubSD", "SimdAddOp", signedTypes, 2, vqsubSCode)
threeEqualRegInst("vqsub", "VqsubSQ", "SimdAddOp", signedTypes, 4, vqsubSCode)
vcgtCode = '''
destElem = (srcElem1 > srcElem2) ? (Element)(-1) : 0;
'''
threeEqualRegInst("vcgt", "VcgtD", "SimdCmpOp", allTypes, 2, vcgtCode)
threeEqualRegInst("vcgt", "VcgtQ", "SimdCmpOp", allTypes, 4, vcgtCode)
vcgeCode = '''
destElem = (srcElem1 >= srcElem2) ? (Element)(-1) : 0;
'''
threeEqualRegInst("vcge", "VcgeD", "SimdCmpOp", allTypes, 2, vcgeCode)
threeEqualRegInst("vcge", "VcgeQ", "SimdCmpOp", allTypes, 4, vcgeCode)
vceqCode = '''
destElem = (srcElem1 == srcElem2) ? (Element)(-1) : 0;
'''
threeEqualRegInst("vceq", "VceqD", "SimdCmpOp", unsignedTypes, 2, vceqCode)
threeEqualRegInst("vceq", "VceqQ", "SimdCmpOp", unsignedTypes, 4, vceqCode)
vshlCode = '''
int16_t shiftAmt = (int8_t)srcElem2;
if (shiftAmt < 0) {
shiftAmt = -shiftAmt;
if (shiftAmt >= sizeof(Element) * 8) {
shiftAmt = sizeof(Element) * 8 - 1;
destElem = 0;
} else {
destElem = (srcElem1 >> shiftAmt);
}
// Make sure the right shift sign extended when it should.
if (ltz(srcElem1) && !ltz(destElem)) {
destElem |= -((Element)1 << (sizeof(Element) * 8 -
1 - shiftAmt));
}
} else {
if (shiftAmt >= sizeof(Element) * 8) {
destElem = 0;
} else {
destElem = srcElem1 << shiftAmt;
}
}
'''
threeEqualRegInst("vshl", "VshlD", "SimdShiftOp", allTypes, 2, vshlCode)
threeEqualRegInst("vshl", "VshlQ", "SimdShiftOp", allTypes, 4, vshlCode)
vrshlCode = '''
int16_t shiftAmt = (int8_t)srcElem2;
if (shiftAmt < 0) {
shiftAmt = -shiftAmt;
Element rBit = 0;
if (shiftAmt <= sizeof(Element) * 8)
rBit = bits(srcElem1, shiftAmt - 1);
if (shiftAmt > sizeof(Element) * 8 && ltz(srcElem1))
rBit = 1;
if (shiftAmt >= sizeof(Element) * 8) {
shiftAmt = sizeof(Element) * 8 - 1;
destElem = 0;
} else {
destElem = (srcElem1 >> shiftAmt);
}
// Make sure the right shift sign extended when it should.
if (ltz(srcElem1) && !ltz(destElem)) {
destElem |= -((Element)1 << (sizeof(Element) * 8 -
1 - shiftAmt));
}
destElem += rBit;
} else if (shiftAmt > 0) {
if (shiftAmt >= sizeof(Element) * 8) {
destElem = 0;
} else {
destElem = srcElem1 << shiftAmt;
}
} else {
destElem = srcElem1;
}
'''
threeEqualRegInst("vrshl", "VrshlD", "SimdAluOp", allTypes, 2, vrshlCode)
threeEqualRegInst("vrshl", "VrshlQ", "SimdAluOp", allTypes, 4, vrshlCode)
vqshlUCode = '''
int16_t shiftAmt = (int8_t)srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
if (shiftAmt < 0) {
shiftAmt = -shiftAmt;
if (shiftAmt >= sizeof(Element) * 8) {
shiftAmt = sizeof(Element) * 8 - 1;
destElem = 0;
} else {
destElem = (srcElem1 >> shiftAmt);
}
} else if (shiftAmt > 0) {
if (shiftAmt >= sizeof(Element) * 8) {
if (srcElem1 != 0) {
destElem = mask(sizeof(Element) * 8);
fpscr.qc = 1;
} else {
destElem = 0;
}
} else {
if (bits(srcElem1, sizeof(Element) * 8 - 1,
sizeof(Element) * 8 - shiftAmt)) {
destElem = mask(sizeof(Element) * 8);
fpscr.qc = 1;
} else {
destElem = srcElem1 << shiftAmt;
}
}
} else {
destElem = srcElem1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqshl", "VqshlUD", "SimdAluOp", unsignedTypes, 2, vqshlUCode)
threeEqualRegInst("vqshl", "VqshlUQ", "SimdAluOp", unsignedTypes, 4, vqshlUCode)
vqshlSCode = '''
int16_t shiftAmt = (int8_t)srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
if (shiftAmt < 0) {
shiftAmt = -shiftAmt;
if (shiftAmt >= sizeof(Element) * 8) {
shiftAmt = sizeof(Element) * 8 - 1;
destElem = 0;
} else {
destElem = (srcElem1 >> shiftAmt);
}
// Make sure the right shift sign extended when it should.
if (srcElem1 < 0 && destElem >= 0) {
destElem |= -((Element)1 << (sizeof(Element) * 8 -
1 - shiftAmt));
}
} else if (shiftAmt > 0) {
bool sat = false;
if (shiftAmt >= sizeof(Element) * 8) {
if (srcElem1 != 0)
sat = true;
else
destElem = 0;
} else {
if (bits(srcElem1, sizeof(Element) * 8 - 1,
sizeof(Element) * 8 - 1 - shiftAmt) !=
((srcElem1 < 0) ? mask(shiftAmt + 1) : 0)) {
sat = true;
} else {
destElem = srcElem1 << shiftAmt;
}
}
if (sat) {
fpscr.qc = 1;
destElem = mask(sizeof(Element) * 8 - 1);
if (srcElem1 < 0)
destElem = ~destElem;
}
} else {
destElem = srcElem1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqshl", "VqshlSD", "SimdCmpOp", signedTypes, 2, vqshlSCode)
threeEqualRegInst("vqshl", "VqshlSQ", "SimdCmpOp", signedTypes, 4, vqshlSCode)
vqrshlUCode = '''
int16_t shiftAmt = (int8_t)srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
if (shiftAmt < 0) {
shiftAmt = -shiftAmt;
Element rBit = 0;
if (shiftAmt <= sizeof(Element) * 8)
rBit = bits(srcElem1, shiftAmt - 1);
if (shiftAmt >= sizeof(Element) * 8) {
shiftAmt = sizeof(Element) * 8 - 1;
destElem = 0;
} else {
destElem = (srcElem1 >> shiftAmt);
}
destElem += rBit;
} else {
if (shiftAmt >= sizeof(Element) * 8) {
if (srcElem1 != 0) {
destElem = mask(sizeof(Element) * 8);
fpscr.qc = 1;
} else {
destElem = 0;
}
} else {
if (bits(srcElem1, sizeof(Element) * 8 - 1,
sizeof(Element) * 8 - shiftAmt)) {
destElem = mask(sizeof(Element) * 8);
fpscr.qc = 1;
} else {
destElem = srcElem1 << shiftAmt;
}
}
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqrshl", "VqrshlUD", "SimdCmpOp", unsignedTypes, 2, vqrshlUCode)
threeEqualRegInst("vqrshl", "VqrshlUQ", "SimdCmpOp", unsignedTypes, 4, vqrshlUCode)
vqrshlSCode = '''
int16_t shiftAmt = (int8_t)srcElem2;
FPSCR fpscr = (FPSCR) FpscrQc;
if (shiftAmt < 0) {
shiftAmt = -shiftAmt;
Element rBit = 0;
if (shiftAmt <= sizeof(Element) * 8)
rBit = bits(srcElem1, shiftAmt - 1);
if (shiftAmt > sizeof(Element) * 8 && srcElem1 < 0)
rBit = 1;
if (shiftAmt >= sizeof(Element) * 8) {
shiftAmt = sizeof(Element) * 8 - 1;
destElem = 0;
} else {
destElem = (srcElem1 >> shiftAmt);
}
// Make sure the right shift sign extended when it should.
if (srcElem1 < 0 && destElem >= 0) {
destElem |= -((Element)1 << (sizeof(Element) * 8 -
1 - shiftAmt));
}
destElem += rBit;
} else if (shiftAmt > 0) {
bool sat = false;
if (shiftAmt >= sizeof(Element) * 8) {
if (srcElem1 != 0)
sat = true;
else
destElem = 0;
} else {
if (bits(srcElem1, sizeof(Element) * 8 - 1,
sizeof(Element) * 8 - 1 - shiftAmt) !=
((srcElem1 < 0) ? mask(shiftAmt + 1) : 0)) {
sat = true;
} else {
destElem = srcElem1 << shiftAmt;
}
}
if (sat) {
fpscr.qc = 1;
destElem = mask(sizeof(Element) * 8 - 1);
if (srcElem1 < 0)
destElem = ~destElem;
}
} else {
destElem = srcElem1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqrshl", "VqrshlSD", "SimdCmpOp", signedTypes, 2, vqrshlSCode)
threeEqualRegInst("vqrshl", "VqrshlSQ", "SimdCmpOp", signedTypes, 4, vqrshlSCode)
vabaCode = '''
destElem += (srcElem1 > srcElem2) ? (srcElem1 - srcElem2) :
(srcElem2 - srcElem1);
'''
threeEqualRegInst("vaba", "VabaD", "SimdAddAccOp", allTypes, 2, vabaCode, True)
threeEqualRegInst("vaba", "VabaQ", "SimdAddAccOp", allTypes, 4, vabaCode, True)
vabalCode = '''
destElem += (srcElem1 > srcElem2) ?
((BigElement)srcElem1 - (BigElement)srcElem2) :
((BigElement)srcElem2 - (BigElement)srcElem1);
'''
threeRegLongInst("vabal", "Vabal", "SimdAddAccOp", smallTypes, vabalCode, True)
vabdCode = '''
destElem = (srcElem1 > srcElem2) ? (srcElem1 - srcElem2) :
(srcElem2 - srcElem1);
'''
threeEqualRegInst("vabd", "VabdD", "SimdAddOp", allTypes, 2, vabdCode)
threeEqualRegInst("vabd", "VabdQ", "SimdAddOp", allTypes, 4, vabdCode)
vabdlCode = '''
destElem = (srcElem1 > srcElem2) ?
((BigElement)srcElem1 - (BigElement)srcElem2) :
((BigElement)srcElem2 - (BigElement)srcElem1);
'''
threeRegLongInst("vabdl", "Vabdl", "SimdAddOp", smallTypes, vabdlCode)
vtstCode = '''
destElem = (srcElem1 & srcElem2) ? (Element)(-1) : 0;
'''
threeEqualRegInst("vtst", "VtstD", "SimdAluOp", unsignedTypes, 2, vtstCode)
threeEqualRegInst("vtst", "VtstQ", "SimdAluOp", unsignedTypes, 4, vtstCode)
vmulCode = '''
destElem = srcElem1 * srcElem2;
'''
threeEqualRegInst("vmul", "NVmulD", "SimdMultOp", allTypes, 2, vmulCode)
threeEqualRegInst("vmul", "NVmulQ", "SimdMultOp", allTypes, 4, vmulCode)
vmullCode = '''
destElem = (BigElement)srcElem1 * (BigElement)srcElem2;
'''
threeRegLongInst("vmull", "Vmull", "SimdMultOp", smallTypes, vmullCode)
vmlaCode = '''
destElem = destElem + srcElem1 * srcElem2;
'''
threeEqualRegInst("vmla", "NVmlaD", "SimdMultAccOp", allTypes, 2, vmlaCode, True)
threeEqualRegInst("vmla", "NVmlaQ", "SimdMultAccOp", allTypes, 4, vmlaCode, True)
vmlalCode = '''
destElem = destElem + (BigElement)srcElem1 * (BigElement)srcElem2;
'''
threeRegLongInst("vmlal", "Vmlal", "SimdMultAccOp", smallTypes, vmlalCode, True)
vqdmlalCode = '''
FPSCR fpscr = (FPSCR) FpscrQc;
BigElement midElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2);
Element maxNeg = std::numeric_limits<Element>::min();
Element halfNeg = maxNeg / 2;
if ((srcElem1 == maxNeg && srcElem2 == maxNeg) ||
(srcElem1 == halfNeg && srcElem2 == maxNeg) ||
(srcElem1 == maxNeg && srcElem2 == halfNeg)) {
midElem = ~((BigElement)maxNeg << (sizeof(Element) * 8));
fpscr.qc = 1;
}
bool negPreDest = ltz(destElem);
destElem += midElem;
bool negDest = ltz(destElem);
bool negMid = ltz(midElem);
if (negPreDest == negMid && negMid != negDest) {
destElem = mask(sizeof(BigElement) * 8 - 1);
if (negPreDest)
destElem = ~destElem;
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeRegLongInst("vqdmlal", "Vqdmlal", "SimdMultAccOp", smallTypes, vqdmlalCode, True)
vqdmlslCode = '''
FPSCR fpscr = (FPSCR) FpscrQc;
BigElement midElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2);
Element maxNeg = std::numeric_limits<Element>::min();
Element halfNeg = maxNeg / 2;
if ((srcElem1 == maxNeg && srcElem2 == maxNeg) ||
(srcElem1 == halfNeg && srcElem2 == maxNeg) ||
(srcElem1 == maxNeg && srcElem2 == halfNeg)) {
midElem = ~((BigElement)maxNeg << (sizeof(Element) * 8));
fpscr.qc = 1;
}
bool negPreDest = ltz(destElem);
destElem -= midElem;
bool negDest = ltz(destElem);
bool posMid = ltz((BigElement)-midElem);
if (negPreDest == posMid && posMid != negDest) {
destElem = mask(sizeof(BigElement) * 8 - 1);
if (negPreDest)
destElem = ~destElem;
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeRegLongInst("vqdmlsl", "Vqdmlsl", "SimdMultAccOp", smallTypes, vqdmlslCode, True)
vqdmullCode = '''
FPSCR fpscr = (FPSCR) FpscrQc;
destElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2);
if (srcElem1 == srcElem2 &&
srcElem1 == (Element)(std::numeric_limits<Element>::min())) {
destElem = ~((BigElement)srcElem1 << (sizeof(Element) * 8));
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeRegLongInst("vqdmull", "Vqdmull", "SimdMultAccOp", smallTypes, vqdmullCode)
vmlsCode = '''
destElem = destElem - srcElem1 * srcElem2;
'''
threeEqualRegInst("vmls", "NVmlsD", "SimdMultAccOp", allTypes, 2, vmlsCode, True)
threeEqualRegInst("vmls", "NVmlsQ", "SimdMultAccOp", allTypes, 4, vmlsCode, True)
vmlslCode = '''
destElem = destElem - (BigElement)srcElem1 * (BigElement)srcElem2;
'''
threeRegLongInst("vmlsl", "Vmlsl", "SimdMultAccOp", smallTypes, vmlslCode, True)
vmulpCode = '''
destElem = 0;
for (unsigned j = 0; j < sizeof(Element) * 8; j++) {
if (bits(srcElem2, j))
destElem ^= srcElem1 << j;
}
'''
threeEqualRegInst("vmul", "NVmulpD", "SimdMultOp", unsignedTypes, 2, vmulpCode)
threeEqualRegInst("vmul", "NVmulpQ", "SimdMultOp", unsignedTypes, 4, vmulpCode)
vmullpCode = '''
destElem = 0;
for (unsigned j = 0; j < sizeof(Element) * 8; j++) {
if (bits(srcElem2, j))
destElem ^= (BigElement)srcElem1 << j;
}
'''
threeRegLongInst("vmull", "Vmullp", "SimdMultOp", smallUnsignedTypes, vmullpCode)
threeEqualRegInst("vpmax", "VpmaxD", "SimdCmpOp", smallTypes, 2, vmaxCode, pairwise=True)
threeEqualRegInst("vpmin", "VpminD", "SimdCmpOp", smallTypes, 2, vminCode, pairwise=True)
vqdmulhCode = '''
FPSCR fpscr = (FPSCR) FpscrQc;
destElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2) >>
(sizeof(Element) * 8);
if (srcElem1 == srcElem2 &&
srcElem1 == (Element)(std::numeric_limits<Element>::min())) {
destElem = ~srcElem1;
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqdmulh", "VqdmulhD", "SimdMultOp", smallSignedTypes, 2, vqdmulhCode)
threeEqualRegInst("vqdmulh", "VqdmulhQ", "SimdMultOp", smallSignedTypes, 4, vqdmulhCode)
vqrdmulhCode = '''
FPSCR fpscr = (FPSCR) FpscrQc;
destElem = (2 * (int64_t)srcElem1 * (int64_t)srcElem2 +
((int64_t)1 << (sizeof(Element) * 8 - 1))) >>
(sizeof(Element) * 8);
Element maxNeg = std::numeric_limits<Element>::min();
Element halfNeg = maxNeg / 2;
if ((srcElem1 == maxNeg && srcElem2 == maxNeg) ||
(srcElem1 == halfNeg && srcElem2 == maxNeg) ||
(srcElem1 == maxNeg && srcElem2 == halfNeg)) {
if (destElem < 0) {
destElem = mask(sizeof(Element) * 8 - 1);
} else {
destElem = std::numeric_limits<Element>::min();
}
fpscr.qc = 1;
}
FpscrQc = fpscr;
'''
threeEqualRegInst("vqrdmulh", "VqrdmulhD",
"SimdMultOp", smallSignedTypes, 2, vqrdmulhCode)
threeEqualRegInst("vqrdmulh", "VqrdmulhQ",
"SimdMultOp", smallSignedTypes, 4, vqrdmulhCode)
vmaxfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
bool done;
destReg = processNans(fpscr, done, true, srcReg1, srcReg2);
if (!done) {
destReg = binaryOp(fpscr, srcReg1, srcReg2, fpMax<float>,
true, true, VfpRoundNearest);
} else if (flushToZero(srcReg1, srcReg2)) {
fpscr.idc = 1;
}
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vmax", "VmaxDFp", "SimdFloatCmpOp", ("float",), 2, vmaxfpCode)
threeEqualRegInstFp("vmax", "VmaxQFp", "SimdFloatCmpOp", ("float",), 4, vmaxfpCode)
vminfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
bool done;
destReg = processNans(fpscr, done, true, srcReg1, srcReg2);
if (!done) {
destReg = binaryOp(fpscr, srcReg1, srcReg2, fpMin<float>,
true, true, VfpRoundNearest);
} else if (flushToZero(srcReg1, srcReg2)) {
fpscr.idc = 1;
}
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vmin", "VminDFp", "SimdFloatCmpOp", ("float",), 2, vminfpCode)
threeEqualRegInstFp("vmin", "VminQFp", "SimdFloatCmpOp", ("float",), 4, vminfpCode)
threeEqualRegInstFp("vpmax", "VpmaxDFp", "SimdFloatCmpOp", ("float",),
2, vmaxfpCode, pairwise=True)
threeEqualRegInstFp("vpmax", "VpmaxQFp", "SimdFloatCmpOp", ("float",),
4, vmaxfpCode, pairwise=True)
threeEqualRegInstFp("vpmin", "VpminDFp", "SimdFloatCmpOp", ("float",),
2, vminfpCode, pairwise=True)
threeEqualRegInstFp("vpmin", "VpminQFp", "SimdFloatCmpOp", ("float",),
4, vminfpCode, pairwise=True)
vaddfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
destReg = binaryOp(fpscr, srcReg1, srcReg2, fpAddS,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vadd", "VaddDFp", "SimdFloatAddOp", ("float",), 2, vaddfpCode)
threeEqualRegInstFp("vadd", "VaddQFp", "SimdFloatAddOp", ("float",), 4, vaddfpCode)
threeEqualRegInstFp("vpadd", "VpaddDFp", "SimdFloatAddOp", ("float",),
2, vaddfpCode, pairwise=True)
threeEqualRegInstFp("vpadd", "VpaddQFp", "SimdFloatAddOp", ("float",),
4, vaddfpCode, pairwise=True)
vsubfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
destReg = binaryOp(fpscr, srcReg1, srcReg2, fpSubS,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vsub", "VsubDFp", "SimdFloatAddOp", ("float",), 2, vsubfpCode)
threeEqualRegInstFp("vsub", "VsubQFp", "SimdFloatAddOp", ("float",), 4, vsubfpCode)
vmulfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
destReg = binaryOp(fpscr, srcReg1, srcReg2, fpMulS,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vmul", "NVmulDFp", "SimdFloatMultOp", ("float",), 2, vmulfpCode)
threeEqualRegInstFp("vmul", "NVmulQFp", "SimdFloatMultOp", ("float",), 4, vmulfpCode)
vmlafpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float mid = binaryOp(fpscr, srcReg1, srcReg2, fpMulS,
true, true, VfpRoundNearest);
destReg = binaryOp(fpscr, mid, destReg, fpAddS,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vmla", "NVmlaDFp", "SimdFloatMultAccOp", ("float",), 2, vmlafpCode, True)
threeEqualRegInstFp("vmla", "NVmlaQFp", "SimdFloatMultAccOp", ("float",), 4, vmlafpCode, True)
vfmafpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
destReg = ternaryOp(fpscr, srcReg1, srcReg2, destReg, fpMulAdd<float>,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vfma", "NVfmaDFp", "SimdFloatMultAccOp", ("float",), 2, vfmafpCode, True)
threeEqualRegInstFp("vfma", "NVfmaQFp", "SimdFloatMultAccOp", ("float",), 4, vfmafpCode, True)
vfmsfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
destReg = ternaryOp(fpscr, -srcReg1, srcReg2, destReg, fpMulAdd<float>,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vfms", "NVfmsDFp", "SimdFloatMultAccOp", ("float",), 2, vfmsfpCode, True)
threeEqualRegInstFp("vfms", "NVfmsQFp", "SimdFloatMultAccOp", ("float",), 4, vfmsfpCode, True)
vmlsfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float mid = binaryOp(fpscr, srcReg1, srcReg2, fpMulS,
true, true, VfpRoundNearest);
destReg = binaryOp(fpscr, destReg, mid, fpSubS,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vmls", "NVmlsDFp", "SimdFloatMultAccOp", ("float",), 2, vmlsfpCode, True)
threeEqualRegInstFp("vmls", "NVmlsQFp", "SimdFloatMultAccOp", ("float",), 4, vmlsfpCode, True)
vcgtfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float res = binaryOp(fpscr, srcReg1, srcReg2, vcgtFunc,
true, true, VfpRoundNearest);
destReg = (res == 0) ? -1 : 0;
if (res == 2.0)
fpscr.ioc = 1;
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vcgt", "VcgtDFp", "SimdFloatCmpOp", ("float",),
2, vcgtfpCode, toInt = True)
threeEqualRegInstFp("vcgt", "VcgtQFp", "SimdFloatCmpOp", ("float",),
4, vcgtfpCode, toInt = True)
vcgefpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float res = binaryOp(fpscr, srcReg1, srcReg2, vcgeFunc,
true, true, VfpRoundNearest);
destReg = (res == 0) ? -1 : 0;
if (res == 2.0)
fpscr.ioc = 1;
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vcge", "VcgeDFp", "SimdFloatCmpOp", ("float",),
2, vcgefpCode, toInt = True)
threeEqualRegInstFp("vcge", "VcgeQFp", "SimdFloatCmpOp", ("float",),
4, vcgefpCode, toInt = True)
vacgtfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float res = binaryOp(fpscr, srcReg1, srcReg2, vacgtFunc,
true, true, VfpRoundNearest);
destReg = (res == 0) ? -1 : 0;
if (res == 2.0)
fpscr.ioc = 1;
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vacgt", "VacgtDFp", "SimdFloatCmpOp", ("float",),
2, vacgtfpCode, toInt = True)
threeEqualRegInstFp("vacgt", "VacgtQFp", "SimdFloatCmpOp", ("float",),
4, vacgtfpCode, toInt = True)
vacgefpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float res = binaryOp(fpscr, srcReg1, srcReg2, vacgeFunc,
true, true, VfpRoundNearest);
destReg = (res == 0) ? -1 : 0;
if (res == 2.0)
fpscr.ioc = 1;
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vacge", "VacgeDFp", "SimdFloatCmpOp", ("float",),
2, vacgefpCode, toInt = True)
threeEqualRegInstFp("vacge", "VacgeQFp", "SimdFloatCmpOp", ("float",),
4, vacgefpCode, toInt = True)
vceqfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float res = binaryOp(fpscr, srcReg1, srcReg2, vceqFunc,
true, true, VfpRoundNearest);
destReg = (res == 0) ? -1 : 0;
if (res == 2.0)
fpscr.ioc = 1;
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vceq", "VceqDFp", "SimdFloatCmpOp", ("float",),
2, vceqfpCode, toInt = True)
threeEqualRegInstFp("vceq", "VceqQFp", "SimdFloatCmpOp", ("float",),
4, vceqfpCode, toInt = True)
vrecpsCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
destReg = binaryOp(fpscr, srcReg1, srcReg2, fpRecpsS,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vrecps", "VrecpsDFp", "SimdFloatMultAccOp", ("float",), 2, vrecpsCode)
threeEqualRegInstFp("vrecps", "VrecpsQFp", "SimdFloatMultAccOp", ("float",), 4, vrecpsCode)
vrsqrtsCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
destReg = binaryOp(fpscr, srcReg1, srcReg2, fpRSqrtsS,
true, true, VfpRoundNearest);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vrsqrts", "VrsqrtsDFp", "SimdFloatMiscOp", ("float",), 2, vrsqrtsCode)
threeEqualRegInstFp("vrsqrts", "VrsqrtsQFp", "SimdFloatMiscOp", ("float",), 4, vrsqrtsCode)
vabdfpCode = '''
FPSCR fpscr = (FPSCR) FpscrExc;
float mid = binaryOp(fpscr, srcReg1, srcReg2, fpSubS,
true, true, VfpRoundNearest);
destReg = fabs(mid);
FpscrExc = fpscr;
'''
threeEqualRegInstFp("vabd", "VabdDFp", "SimdFloatAddOp", ("float",), 2, vabdfpCode)
threeEqualRegInstFp("vabd", "VabdQFp", "SimdFloatAddOp", ("float",), 4, vabdfpCode)
twoEqualRegInst("vmla", "VmlasD", "SimdMultAccOp", unsignedTypes, 2, vmlaCode, True)
twoEqualRegInst("vmla", "VmlasQ", "SimdMultAccOp", unsignedTypes, 4, vmlaCode