Commit cd6b2b74 authored by Michael Munday's avatar Michael Munday Committed by Brad Fitzpatrick

cmd/internal/obj/s390x: add MULHD instruction

Emulate 64-bit signed high multiplication ((a*b)>>64). To do this
we use the 64-bit unsigned high multiplication method and then
fix the result as shown in Hacker's Delight 2nd ed., chapter 8-3.

Required to enable some division optimizations.

Change-Id: I9194f428e09d3d029cb1afb4715cd5424b5d922e
Reviewed-on: https://go-review.googlesource.com/21774Reviewed-by: 's avatarBill O'Farrell <billotosyr@gmail.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent cabb1402
......@@ -61,6 +61,10 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
MULLW R6, R7, R8 // b9040087b91c0086
MULLW $8192, R6 // c26000002000
MULLW $8192, R6, R7 // b9040076c27000002000
MULHD R9, R8 // b90400b8b98600a9ebb9003f000ab98000b8b90900abebb8003f000ab98000b9b9e9b08a
MULHD R7, R2, R1 // b90400b2b98600a7ebb7003f000ab98000b2b90900abebb2003f000ab98000b7b9e9b01a
MULHDU R3, R4 // b90400b4b98600a3b904004a
MULHDU R5, R6, R7 // b90400b6b98600a5b904007a
DIVD R1, R2 // b90400b2b90d00a1b904002b
DIVD R1, R2, R3 // b90400b2b90d00a1b904003b
DIVW R4, R5 // b90400b5b91d00a4b904005b
......
......@@ -218,6 +218,7 @@ const (
ADIVDU
AMULLW
AMULLD
AMULHD
AMULHDU
ASUB
ASUBC
......
......@@ -17,6 +17,7 @@ var Anames = []string{
"DIVDU",
"MULLW",
"MULLD",
"MULHD",
"MULHDU",
"SUB",
"SUBC",
......
......@@ -150,6 +150,8 @@ var optab = []Optab{
Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 0},
Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 0},
Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 0},
Optab{AMULHD, C_REG, C_NONE, C_NONE, C_REG, 4, 0},
Optab{AMULHD, C_REG, C_REG, C_NONE, C_REG, 4, 0},
Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 0},
Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 0},
Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 0},
......@@ -793,10 +795,11 @@ func buildop(ctxt *obj.Link) {
case ADIVW:
opset(AADDE, r)
opset(AMULLD, r)
opset(AMULHDU, r)
opset(ADIVD, r)
opset(ADIVDU, r)
opset(ADIVWU, r)
case AMULHD:
opset(AMULHDU, r)
case AMOVBZ:
opset(AMOVH, r)
opset(AMOVHZ, r)
......@@ -2580,8 +2583,6 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
opcode = op_MSGFR
case AMULLD:
opcode = op_MSGR
case AMULHDU:
opcode = op_MLGR
case ADIVW:
opcode = op_DSGFR
case ADIVWU:
......@@ -2628,11 +2629,6 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
zRRE(opcode, REGTMP, uint32(p.From.Reg), asm)
zRRE(op_LGR, uint32(p.To.Reg), REGTMP2, asm)
case AMULHDU:
zRRE(op_LGR, REGTMP2, uint32(r), asm)
zRRE(opcode, REGTMP, uint32(p.From.Reg), asm)
zRRE(op_LGR, uint32(p.To.Reg), REGTMP, asm)
case AFADD, AFADDS:
if r == int(p.To.Reg) {
zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm)
......@@ -2695,6 +2691,28 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
zRIL(_a, op_IIHF, uint32(p.To.Reg), uint32(v>>32), asm)
}
case 4: // multiply high (a*b)>>64
r := p.Reg
if r == 0 {
r = p.To.Reg
}
zRRE(op_LGR, REGTMP2, uint32(r), asm)
zRRE(op_MLGR, REGTMP, uint32(p.From.Reg), asm)
switch p.As {
case AMULHDU:
// Unsigned: move result into correct register.
zRRE(op_LGR, uint32(p.To.Reg), REGTMP, asm)
case AMULHD:
// Signed: need to convert result.
// See Hacker's Delight 8-3.
zRSY(op_SRAG, REGTMP2, uint32(p.From.Reg), 0, 63, asm)
zRRE(op_NGR, REGTMP2, uint32(r), asm)
zRRE(op_SGR, REGTMP, REGTMP2, asm)
zRSY(op_SRAG, REGTMP2, uint32(r), 0, 63, asm)
zRRE(op_NGR, REGTMP2, uint32(p.From.Reg), asm)
zRRF(op_SGRK, REGTMP2, 0, uint32(p.To.Reg), REGTMP, asm)
}
case 5: // syscall
zI(op_SVC, 0, asm)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment