ARM: Add support for VFP vector mode.
This commit is contained in:
@@ -68,8 +68,73 @@ setVfpMicroFlags(VfpMicroMode mode, T &flags)
|
||||
case VfpNotAMicroop:
|
||||
break;
|
||||
}
|
||||
if (mode == VfpMicroop || mode == VfpFirstMicroop) {
|
||||
flags[StaticInst::IsDelayedCommit] = true;
|
||||
}
|
||||
}
|
||||
|
||||
class VfpMacroOp : public PredMacroOp
|
||||
{
|
||||
public:
|
||||
static bool
|
||||
inScalarBank(IntRegIndex idx)
|
||||
{
|
||||
return (idx % 32) < 8;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool wide;
|
||||
|
||||
VfpMacroOp(const char *mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass, bool _wide) :
|
||||
PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
|
||||
{}
|
||||
|
||||
IntRegIndex
|
||||
addStride(IntRegIndex idx, unsigned stride)
|
||||
{
|
||||
if (wide) {
|
||||
stride *= 2;
|
||||
}
|
||||
unsigned offset = idx % 8;
|
||||
idx = (IntRegIndex)(idx - offset);
|
||||
offset += stride;
|
||||
idx = (IntRegIndex)(idx + (offset % 8));
|
||||
return idx;
|
||||
}
|
||||
|
||||
void
|
||||
nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2)
|
||||
{
|
||||
unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
|
||||
assert(!inScalarBank(dest));
|
||||
dest = addStride(dest, stride);
|
||||
op1 = addStride(op1, stride);
|
||||
if (!inScalarBank(op2)) {
|
||||
op2 = addStride(op2, stride);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nextIdxs(IntRegIndex &dest, IntRegIndex &op1)
|
||||
{
|
||||
unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
|
||||
assert(!inScalarBank(dest));
|
||||
dest = addStride(dest, stride);
|
||||
if (!inScalarBank(op1)) {
|
||||
op1 = addStride(op1, stride);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nextIdxs(IntRegIndex &dest)
|
||||
{
|
||||
unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
|
||||
assert(!inScalarBank(dest));
|
||||
dest = addStride(dest, stride);
|
||||
}
|
||||
};
|
||||
|
||||
class VfpRegRegOp : public RegRegOp
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -504,65 +504,83 @@ let {{
|
||||
case 0x0:
|
||||
if (bits(machInst, 6) == 0) {
|
||||
if (single) {
|
||||
return new VmlaS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VmlaS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VmlaD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VmlaD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
} else {
|
||||
if (single) {
|
||||
return new VmlsS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VmlsS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VmlsD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VmlsD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
}
|
||||
case 0x1:
|
||||
if (bits(machInst, 6) == 1) {
|
||||
if (single) {
|
||||
return new VnmlaS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VnmlaS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VnmlaD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VnmlaD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
} else {
|
||||
if (single) {
|
||||
return new VnmlsS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VnmlsS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VnmlsD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VnmlsD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
}
|
||||
case 0x2:
|
||||
if ((opc3 & 0x1) == 0) {
|
||||
if (single) {
|
||||
return new VmulS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VmulS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VmulD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VmulD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
} else {
|
||||
if (single) {
|
||||
return new VnmulS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VnmulS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VnmulD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VnmulD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
}
|
||||
case 0x3:
|
||||
if ((opc3 & 0x1) == 0) {
|
||||
if (single) {
|
||||
return new VaddS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VaddS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VaddD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VaddD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
} else {
|
||||
if (single) {
|
||||
return new VsubS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VsubS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VsubD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VsubD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
}
|
||||
case 0x8:
|
||||
if ((opc3 & 0x1) == 0) {
|
||||
if (single) {
|
||||
return new VdivS(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VdivS>(
|
||||
machInst, vd, vn, vm, false);
|
||||
} else {
|
||||
return new VdivD(machInst, vd, vn, vm);
|
||||
return decodeVfpRegRegRegOp<VdivD>(
|
||||
machInst, vd, vn, vm, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -572,39 +590,49 @@ let {{
|
||||
bits(machInst, 3, 0) | (bits(machInst, 19, 16) << 4);
|
||||
if (single) {
|
||||
uint32_t imm = vfp_modified_imm(baseImm, false);
|
||||
return new VmovImmS(machInst, vd, imm);
|
||||
return decodeVfpRegImmOp<VmovImmS>(
|
||||
machInst, vd, imm, false);
|
||||
} else {
|
||||
uint64_t imm = vfp_modified_imm(baseImm, true);
|
||||
return new VmovImmD(machInst, vd, imm);
|
||||
return decodeVfpRegImmOp<VmovImmD>(
|
||||
machInst, vd, imm, true);
|
||||
}
|
||||
}
|
||||
switch (opc2) {
|
||||
case 0x0:
|
||||
if (opc3 == 1) {
|
||||
if (single) {
|
||||
return new VmovRegS(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VmovRegS>(
|
||||
machInst, vd, vm, false);
|
||||
} else {
|
||||
return new VmovRegD(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VmovRegD>(
|
||||
machInst, vd, vm, true);
|
||||
}
|
||||
} else {
|
||||
if (single) {
|
||||
return new VabsS(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VabsS>(
|
||||
machInst, vd, vm, false);
|
||||
} else {
|
||||
return new VabsD(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VabsD>(
|
||||
machInst, vd, vm, true);
|
||||
}
|
||||
}
|
||||
case 0x1:
|
||||
if (opc3 == 1) {
|
||||
if (single) {
|
||||
return new VnegS(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VnegS>(
|
||||
machInst, vd, vm, false);
|
||||
} else {
|
||||
return new VnegD(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VnegD>(
|
||||
machInst, vd, vm, true);
|
||||
}
|
||||
} else {
|
||||
if (single) {
|
||||
return new VsqrtS(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VsqrtS>(
|
||||
machInst, vd, vm, false);
|
||||
} else {
|
||||
return new VsqrtD(machInst, vd, vm);
|
||||
return decodeVfpRegRegOp<VsqrtD>(
|
||||
machInst, vd, vm, true);
|
||||
}
|
||||
}
|
||||
case 0x2:
|
||||
|
||||
@@ -37,6 +37,154 @@
|
||||
//
|
||||
// Authors: Gabe Black
|
||||
|
||||
output header {{
|
||||
|
||||
template <class Micro>
|
||||
class VfpMacroRegRegOp : public VfpMacroOp
|
||||
{
|
||||
public:
|
||||
VfpMacroRegRegOp(ExtMachInst _machInst, IntRegIndex _dest,
|
||||
IntRegIndex _op1, bool _wide) :
|
||||
VfpMacroOp("VfpMacroRegRegOp", _machInst, No_OpClass, _wide)
|
||||
{
|
||||
numMicroops = machInst.fpscrLen + 1;
|
||||
assert(numMicroops > 1);
|
||||
microOps = new StaticInstPtr[numMicroops];
|
||||
for (unsigned i = 0; i < numMicroops; i++) {
|
||||
VfpMicroMode mode = VfpMicroop;
|
||||
if (i == 0)
|
||||
mode = VfpFirstMicroop;
|
||||
else if (i == numMicroops - 1)
|
||||
mode = VfpLastMicroop;
|
||||
microOps[i] = new Micro(_machInst, _dest, _op1, mode);
|
||||
nextIdxs(_dest, _op1);
|
||||
}
|
||||
}
|
||||
|
||||
%(BasicExecPanic)s
|
||||
};
|
||||
|
||||
template <class VfpOp>
|
||||
static StaticInstPtr
|
||||
decodeVfpRegRegOp(ExtMachInst machInst,
|
||||
IntRegIndex dest, IntRegIndex op1, bool wide)
|
||||
{
|
||||
if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
|
||||
return new VfpOp(machInst, dest, op1);
|
||||
} else {
|
||||
return new VfpMacroRegRegOp<VfpOp>(machInst, dest, op1, wide);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Micro>
|
||||
class VfpMacroRegImmOp : public VfpMacroOp
|
||||
{
|
||||
public:
|
||||
VfpMacroRegImmOp(ExtMachInst _machInst, IntRegIndex _dest, uint64_t _imm,
|
||||
bool _wide) :
|
||||
VfpMacroOp("VfpMacroRegImmOp", _machInst, No_OpClass, _wide)
|
||||
{
|
||||
numMicroops = machInst.fpscrLen + 1;
|
||||
microOps = new StaticInstPtr[numMicroops];
|
||||
for (unsigned i = 0; i < numMicroops; i++) {
|
||||
VfpMicroMode mode = VfpMicroop;
|
||||
if (i == 0)
|
||||
mode = VfpFirstMicroop;
|
||||
else if (i == numMicroops - 1)
|
||||
mode = VfpLastMicroop;
|
||||
microOps[i] = new Micro(_machInst, _dest, _imm, mode);
|
||||
nextIdxs(_dest);
|
||||
}
|
||||
}
|
||||
|
||||
%(BasicExecPanic)s
|
||||
};
|
||||
|
||||
template <class VfpOp>
|
||||
static StaticInstPtr
|
||||
decodeVfpRegImmOp(ExtMachInst machInst,
|
||||
IntRegIndex dest, uint64_t imm, bool wide)
|
||||
{
|
||||
if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
|
||||
return new VfpOp(machInst, dest, imm);
|
||||
} else {
|
||||
return new VfpMacroRegImmOp<VfpOp>(machInst, dest, imm, wide);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Micro>
|
||||
class VfpMacroRegRegImmOp : public VfpMacroOp
|
||||
{
|
||||
public:
|
||||
VfpMacroRegRegImmOp(ExtMachInst _machInst, IntRegIndex _dest,
|
||||
IntRegIndex _op1, uint64_t _imm, bool _wide) :
|
||||
VfpMacroOp("VfpMacroRegRegImmOp", _machInst, No_OpClass, _wide)
|
||||
{
|
||||
numMicroops = machInst.fpscrLen + 1;
|
||||
microOps = new StaticInstPtr[numMicroops];
|
||||
for (unsigned i = 0; i < numMicroops; i++) {
|
||||
VfpMicroMode mode = VfpMicroop;
|
||||
if (i == 0)
|
||||
mode = VfpFirstMicroop;
|
||||
else if (i == numMicroops - 1)
|
||||
mode = VfpLastMicroop;
|
||||
microOps[i] = new Micro(_machInst, _dest, _op1, _imm, mode);
|
||||
nextIdxs(_dest, _op1);
|
||||
}
|
||||
}
|
||||
|
||||
%(BasicExecPanic)s
|
||||
};
|
||||
|
||||
template <class VfpOp>
|
||||
static StaticInstPtr
|
||||
decodeVfpRegRegImmOp(ExtMachInst machInst, IntRegIndex dest,
|
||||
IntRegIndex op1, uint64_t imm, bool wide)
|
||||
{
|
||||
if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
|
||||
return new VfpOp(machInst, dest, op1, imm);
|
||||
} else {
|
||||
return new VfpMacroRegRegImmOp<VfpOp>(machInst, dest, op1, imm, wide);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Micro>
|
||||
class VfpMacroRegRegRegOp : public VfpMacroOp
|
||||
{
|
||||
public:
|
||||
VfpMacroRegRegRegOp(ExtMachInst _machInst, IntRegIndex _dest,
|
||||
IntRegIndex _op1, IntRegIndex _op2, bool _wide) :
|
||||
VfpMacroOp("VfpMacroRegRegRegOp", _machInst, No_OpClass, _wide)
|
||||
{
|
||||
numMicroops = machInst.fpscrLen + 1;
|
||||
microOps = new StaticInstPtr[numMicroops];
|
||||
for (unsigned i = 0; i < numMicroops; i++) {
|
||||
VfpMicroMode mode = VfpMicroop;
|
||||
if (i == 0)
|
||||
mode = VfpFirstMicroop;
|
||||
else if (i == numMicroops - 1)
|
||||
mode = VfpLastMicroop;
|
||||
microOps[i] = new Micro(_machInst, _dest, _op1, _op2, mode);
|
||||
nextIdxs(_dest, _op1, _op2);
|
||||
}
|
||||
}
|
||||
|
||||
%(BasicExecPanic)s
|
||||
};
|
||||
|
||||
template <class VfpOp>
|
||||
static StaticInstPtr
|
||||
decodeVfpRegRegRegOp(ExtMachInst machInst, IntRegIndex dest,
|
||||
IntRegIndex op1, IntRegIndex op2, bool wide)
|
||||
{
|
||||
if (machInst.fpscrLen == 0 || VfpMacroOp::inScalarBank(dest)) {
|
||||
return new VfpOp(machInst, dest, op1, op2);
|
||||
} else {
|
||||
return new VfpMacroRegRegRegOp<VfpOp>(machInst, dest, op1, op2, wide);
|
||||
}
|
||||
}
|
||||
}};
|
||||
|
||||
let {{
|
||||
|
||||
header_output = ""
|
||||
|
||||
@@ -294,6 +294,32 @@ namespace ArmISA
|
||||
Bitfield<11> wnr;
|
||||
Bitfield<12> ext;
|
||||
EndBitUnion(FSR)
|
||||
|
||||
BitUnion32(FPSCR)
|
||||
Bitfield<0> ioc;
|
||||
Bitfield<1> dzc;
|
||||
Bitfield<2> ofc;
|
||||
Bitfield<3> ufc;
|
||||
Bitfield<4> ixc;
|
||||
Bitfield<7> idc;
|
||||
Bitfield<8> ioe;
|
||||
Bitfield<9> dze;
|
||||
Bitfield<10> ofe;
|
||||
Bitfield<11> ufe;
|
||||
Bitfield<12> ixe;
|
||||
Bitfield<15> ide;
|
||||
Bitfield<18, 16> len;
|
||||
Bitfield<21, 20> stride;
|
||||
Bitfield<23, 22> rMode;
|
||||
Bitfield<24> fz;
|
||||
Bitfield<25> dn;
|
||||
Bitfield<26> ahp;
|
||||
Bitfield<27> qc;
|
||||
Bitfield<28> v;
|
||||
Bitfield<29> c;
|
||||
Bitfield<30> z;
|
||||
Bitfield<31> n;
|
||||
EndBitUnion(FPSCR)
|
||||
};
|
||||
|
||||
#endif // __ARCH_ARM_MISCREGS_HH__
|
||||
|
||||
@@ -142,6 +142,9 @@ namespace ArmISA
|
||||
data = inst;
|
||||
offset = (fetchPC >= pc) ? 0 : pc - fetchPC;
|
||||
emi.thumb = (pc & (ULL(1) << PcTBitShift)) ? 1 : 0;
|
||||
FPSCR fpscr = tc->readMiscReg(MISCREG_FPSCR);
|
||||
emi.fpscrLen = fpscr.len;
|
||||
emi.fpscrStride = fpscr.stride;
|
||||
process();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,10 @@ namespace ArmISA
|
||||
typedef uint32_t MachInst;
|
||||
|
||||
BitUnion64(ExtMachInst)
|
||||
// FPSCR fields
|
||||
Bitfield<41, 40> fpscrStride;
|
||||
Bitfield<39, 37> fpscrLen;
|
||||
|
||||
// Bitfields to select mode.
|
||||
Bitfield<36> thumb;
|
||||
Bitfield<35> bigThumb;
|
||||
|
||||
Reference in New Issue
Block a user