diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa index d15412825..e553b180d 100644 --- a/src/arch/arm/isa/formats/fp.isa +++ b/src/arch/arm/isa/formats/fp.isa @@ -640,8 +640,17 @@ let {{ // Between half and single precision. return new WarnUnimplemented("vcvtb, vcvtt", machInst); case 0x4: + if (single) { + return new VcmpS(machInst, vd, vm); + } else { + return new VcmpD(machInst, vd, vm); + } case 0x5: - return new WarnUnimplemented("vcmp, vcmpe", machInst); + if (single) { + return new VcmpZeroS(machInst, vd, 0); + } else { + return new VcmpZeroD(machInst, vd, 0); + } case 0x7: if (opc3 == 0x3) { if (single) { diff --git a/src/arch/arm/isa/insts/fp.isa b/src/arch/arm/isa/insts/fp.isa index e2c7dd79b..0c1ce626b 100644 --- a/src/arch/arm/isa/insts/fp.isa +++ b/src/arch/arm/isa/insts/fp.isa @@ -851,4 +851,89 @@ let {{ header_output += VfpRegRegOpDeclare.subst(vcvtFpDFpSIop); decoder_output += VfpRegRegOpConstructor.subst(vcvtFpDFpSIop); exec_output += PredOpExecute.subst(vcvtFpDFpSIop); + + vcmpSCode = ''' + FPSCR fpscr = Fpscr; + if (FpDest == FpOp1) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (FpDest < FpOp1) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (FpDest > FpOp1) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpSIop = InstObjParams("vcmps", "VcmpS", "VfpRegRegOp", + { "code": vcmpSCode, + "predicate_test": predicateTest }, []) + header_output += VfpRegRegOpDeclare.subst(vcmpSIop); + decoder_output += VfpRegRegOpConstructor.subst(vcmpSIop); + exec_output += PredOpExecute.subst(vcmpSIop); + + vcmpDCode = ''' + IntDoubleUnion cOp1, cDest; + cDest.bits = ((uint64_t)FpDestP0.uw | ((uint64_t)FpDestP1.uw << 32)); + cOp1.bits = ((uint64_t)FpOp1P0.uw | ((uint64_t)FpOp1P1.uw << 32)); + FPSCR fpscr = Fpscr; + if (cDest.fp == cOp1.fp) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (cDest.fp < cOp1.fp) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (cDest.fp > cOp1.fp) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpDIop = InstObjParams("vcmpd", "VcmpD", "VfpRegRegOp", + { "code": vcmpDCode, + "predicate_test": predicateTest }, []) + header_output += VfpRegRegOpDeclare.subst(vcmpDIop); + decoder_output += VfpRegRegOpConstructor.subst(vcmpDIop); + exec_output += PredOpExecute.subst(vcmpDIop); + + vcmpZeroSCode = ''' + FPSCR fpscr = Fpscr; + if (FpDest == imm) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (FpDest < imm) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (FpDest > imm) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpZeroSIop = InstObjParams("vcmpZeros", "VcmpZeroS", "VfpRegImmOp", + { "code": vcmpZeroSCode, + "predicate_test": predicateTest }, []) + header_output += VfpRegImmOpDeclare.subst(vcmpZeroSIop); + decoder_output += VfpRegImmOpConstructor.subst(vcmpZeroSIop); + exec_output += PredOpExecute.subst(vcmpZeroSIop); + + vcmpZeroDCode = ''' + IntDoubleUnion cDest; + cDest.bits = ((uint64_t)FpDestP0.uw | ((uint64_t)FpDestP1.uw << 32)); + FPSCR fpscr = Fpscr; + if (cDest.fp == imm) { + fpscr.n = 0; fpscr.z = 1; fpscr.c = 1; fpscr.v = 0; + } else if (cDest.fp < imm) { + fpscr.n = 1; fpscr.z = 0; fpscr.c = 0; fpscr.v = 0; + } else if (cDest.fp > imm) { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 0; + } else { + fpscr.n = 0; fpscr.z = 0; fpscr.c = 1; fpscr.v = 1; + } + Fpscr = fpscr; + ''' + vcmpZeroDIop = InstObjParams("vcmpZerod", "VcmpZeroD", "VfpRegImmOp", + { "code": vcmpZeroDCode, + "predicate_test": predicateTest }, []) + header_output += VfpRegImmOpDeclare.subst(vcmpZeroDIop); + decoder_output += VfpRegImmOpConstructor.subst(vcmpZeroDIop); + exec_output += PredOpExecute.subst(vcmpZeroDIop); }};