diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/insts/static_inst.hh | 5 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/fp.isa | 20 | ||||
-rw-r--r-- | src/arch/arm/isa/insts/fp.isa | 32 |
3 files changed, 56 insertions, 1 deletions
diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index 33453bec6..3af9ef3b0 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -50,6 +50,11 @@ namespace ArmISA class ArmStaticInst : public StaticInst { protected: + union IntDoubleUnion { + uint64_t bits; + double fp; + }; + int32_t shift_rm_imm(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const; int32_t shift_rm_rs(uint32_t base, uint32_t shamt, diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa index 848ce907c..2222b1e62 100644 --- a/src/arch/arm/isa/formats/fp.isa +++ b/src/arch/arm/isa/formats/fp.isa @@ -486,7 +486,25 @@ let {{ return new WarnUnimplemented("vmla, vmls", machInst); case 0x2: if ((opc3 & 0x1) == 0) { - return new WarnUnimplemented("vmul", machInst); + uint32_t vd; + uint32_t vm; + uint32_t vn; + if (bits(machInst, 8) == 0) { + vd = bits(machInst, 22) | (bits(machInst, 15, 12) << 1); + vm = bits(machInst, 5) | (bits(machInst, 3, 0) << 1); + vn = bits(machInst, 7) | (bits(machInst, 19, 16) << 1); + return new VmulS(machInst, (IntRegIndex)vd, + (IntRegIndex)vn, (IntRegIndex)vm); + } else { + vd = (bits(machInst, 22) << 5) | + (bits(machInst, 15, 12) << 1); + vm = (bits(machInst, 5) << 5) | + (bits(machInst, 3, 0) << 1); + vn = (bits(machInst, 7) << 5) | + (bits(machInst, 19, 16) << 1); + return new VmulD(machInst, (IntRegIndex)vd, + (IntRegIndex)vn, (IntRegIndex)vm); + } } case 0x1: return new WarnUnimplemented("vnmla, vnmls, vnmul", machInst); diff --git a/src/arch/arm/isa/insts/fp.isa b/src/arch/arm/isa/insts/fp.isa index ab37c3e3b..ef79ea420 100644 --- a/src/arch/arm/isa/insts/fp.isa +++ b/src/arch/arm/isa/insts/fp.isa @@ -226,4 +226,36 @@ let {{ header_output += RegRegRegOpDeclare.subst(vmov2Core2RegIop); decoder_output += RegRegRegOpConstructor.subst(vmov2Core2RegIop); exec_output += PredOpExecute.subst(vmov2Core2RegIop); + + vmulSCode = ''' + FpDest = FpOp1 * FpOp2; + if ((isinf(FpOp1) && FpOp2 == 0) || (isinf(FpOp2) && FpOp1 == 0)) { + FpDest = NAN; + } + ''' + vmulSIop = InstObjParams("vmuls", "VmulS", "RegRegRegOp", + { "code": vmulSCode, + "predicate_test": predicateTest }, []) + header_output += RegRegRegOpDeclare.subst(vmulSIop); + decoder_output += RegRegRegOpConstructor.subst(vmulSIop); + exec_output += PredOpExecute.subst(vmulSIop); + + vmulDCode = ''' + IntDoubleUnion cOp1, cOp2, cDest; + cOp1.bits = ((uint64_t)FpOp1P0.uw | ((uint64_t)FpOp1P1.uw << 32)); + cOp2.bits = ((uint64_t)FpOp2P0.uw | ((uint64_t)FpOp2P1.uw << 32)); + cDest.fp = cOp1.fp * cOp2.fp; + if ((isinf(cOp1.fp) && cOp2.fp == 0) || + (isinf(cOp2.fp) && cOp1.fp == 0)) { + cDest.fp = NAN; + } + FpDestP0.uw = cDest.bits; + FpDestP1.uw = cDest.bits >> 32; + ''' + vmulDIop = InstObjParams("vmuld", "VmulD", "RegRegRegOp", + { "code": vmulDCode, + "predicate_test": predicateTest }, []) + header_output += RegRegRegOpDeclare.subst(vmulDIop); + decoder_output += RegRegRegOpConstructor.subst(vmulDIop); + exec_output += PredOpExecute.subst(vmulDIop); }}; |