ARM: Add support for VFP vector mode.

This commit is contained in:
Gabe Black
2010-06-02 12:58:14 -05:00
parent f245f4937b
commit c1f7bf7f0e
6 changed files with 302 additions and 28 deletions

View File

@@ -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:

View File

@@ -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:

View File

@@ -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 = ""

View File

@@ -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__

View File

@@ -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();
}

View File

@@ -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;