MULHD R7, R2, R1 // b90400b2b98600a7ebb7003f000ab98000b2b90900abebb2003f000ab98000b7b9e9b01a
MULHDU R3, R4 // b90400b4b98600a3b904004a
MULHDU R5, R6, R7 // b90400b6b98600a5b904007a
+ MLGR R1, R2 // b9860021
DIVD R1, R2 // b90400b2b90d00a1b904002b
DIVD R1, R2, R3 // b90400b2b90d00a1b904003b
DIVW R4, R5 // b90400b5b91d00a4b904005b
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1])
},
- sys.AMD64, sys.ARM64, sys.PPC64)
- alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64)
+ sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X)
+ alias("math/bits", "Mul", "math/bits", "Mul64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchS390X)
addF("math/bits", "Add64",
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
return s.newValue3(ssa.OpAdd64carry, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2])
v.Fatalf("input[0] and output not in same register %s", v.LongString())
}
opregreg(s, v.Op.Asm(), r, v.Args[1].Reg())
+ case ssa.OpS390XMLGR:
+ // MLGR Rx R3 -> R2:R3
+ r0 := v.Args[0].Reg()
+ r1 := v.Args[1].Reg()
+ if r1 != s390x.REG_R3 {
+ v.Fatalf("We require the multiplcand to be stored in R3 for MLGR %s", v.LongString())
+ }
+ p := s.Prog(s390x.AMLGR)
+ p.From.Type = obj.TYPE_REG
+ p.From.Reg = r0
+ p.To.Reg = s390x.REG_R2
+ p.To.Type = obj.TYPE_REG
+
case ssa.OpS390XFMADD, ssa.OpS390XFMADDS,
ssa.OpS390XFMSUB, ssa.OpS390XFMSUBS:
r := v.Reg()
(Mul(32|16|8) x y) -> (MULLW x y)
(Mul32F x y) -> (FMULS x y)
(Mul64F x y) -> (FMUL x y)
+(Mul64uhilo x y) -> (MLGR x y)
(Div32F x y) -> (FDIVS x y)
(Div64F x y) -> (FDIV x y)
clobberFlags: true,
},
+ // unsigned multiplication (64x64 → 128)
+ //
+ // Multiply the two 64-bit input operands together and place the 128-bit result into
+ // an even-odd register pair. The second register in the target pair also contains
+ // one of the input operands. Since we don't currently have a way to specify an
+ // even-odd register pair we hardcode this register pair as R2:R3.
+ {
+ name: "MLGR",
+ argLength: 2,
+ reg: regInfo{inputs: []regMask{gp, r3}, outputs: []regMask{r2, r3}},
+ asm: "MLGR",
+ },
+
// pseudo operations to sum the output of the POPCNT instruction
{name: "SumBytes2", argLength: 1, typ: "UInt8"}, // sum the rightmost 2 bytes in arg0 ignoring overflow
{name: "SumBytes4", argLength: 1, typ: "UInt8"}, // sum the rightmost 4 bytes in arg0 ignoring overflow
OpS390XLoweredAtomicExchange64
OpS390XFLOGR
OpS390XPOPCNT
+ OpS390XMLGR
OpS390XSumBytes2
OpS390XSumBytes4
OpS390XSumBytes8
},
},
},
+ {
+ name: "MLGR",
+ argLen: 2,
+ asm: s390x.AMLGR,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {1, 8}, // R3
+ {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
+ },
+ outputs: []outputInfo{
+ {0, 4}, // R2
+ {1, 8}, // R3
+ },
+ },
+ },
{
name: "SumBytes2",
argLen: 1,
return rewriteValueS390X_OpMul64_0(v)
case OpMul64F:
return rewriteValueS390X_OpMul64F_0(v)
+ case OpMul64uhilo:
+ return rewriteValueS390X_OpMul64uhilo_0(v)
case OpMul8:
return rewriteValueS390X_OpMul8_0(v)
case OpNeg16:
return true
}
}
+func rewriteValueS390X_OpMul64uhilo_0(v *Value) bool {
+ // match: (Mul64uhilo x y)
+ // cond:
+ // result: (MLGR x y)
+ for {
+ y := v.Args[1]
+ x := v.Args[0]
+ v.reset(OpS390XMLGR)
+ v.AddArg(x)
+ v.AddArg(y)
+ return true
+ }
+}
func rewriteValueS390X_OpMul8_0(v *Value) bool {
// match: (Mul8 x y)
// cond:
AMULLD
AMULHD
AMULHDU
+ AMLGR
ASUB
ASUBC
ASUBV
"MULLD",
"MULHD",
"MULHDU",
+ "MLGR",
"SUB",
"SUBC",
"SUBV",
{i: 12, as: ASUB, a1: C_LAUTO, a6: C_REG},
{i: 4, as: AMULHD, a1: C_REG, a6: C_REG},
{i: 4, as: AMULHD, a1: C_REG, a2: C_REG, a6: C_REG},
+ {i: 62, as: AMLGR, a1: C_REG, a6: C_REG},
{i: 2, as: ADIVW, a1: C_REG, a2: C_REG, a6: C_REG},
{i: 2, as: ADIVW, a1: C_REG, a6: C_REG},
{i: 10, as: ASUB, a1: C_REG, a2: C_REG, a6: C_REG},
d2 := c.regoff(&p.To)
zRXE(opcode, uint32(p.From.Reg), 0, 0, uint32(d2), 0, asm)
+ case 62: // equivalent of Mul64 in math/bits
+ zRRE(op_MLGR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
+
case 66:
zRR(op_BCR, 0, 0, asm)
// arm64:"UMULH","MUL"
// ppc64:"MULHDU","MULLD"
// ppc64le:"MULHDU","MULLD"
+ // s390x:"MLGR"
return bits.Mul(x, y)
}
// arm64:"UMULH","MUL"
// ppc64:"MULHDU","MULLD"
// ppc64le:"MULHDU","MULLD"
+ // s390x:"MLGR"
return bits.Mul64(x, y)
}