1
0
mirror of https://github.com/golang/go synced 2024-11-05 16:26:11 -07:00

cmd/asm, cmd/internal/obj/s390x: add new s390x instructions for SSA

This commit adds the following instructions to support the new SSA
backend for s390x:

32-bit operations:
ADDW
SUBW
NEGW
FNEGS

Conditional moves:
MOVDEQ
MOVDGE
MOVDGT
MOVDLE
MOVDLT
MOVDNE

Unordered branches (for floating point comparisons):
BLEU
BLTU

Modulo operations:
MODW
MODWU
MODD
MODDU

The modulo operations might be removed in a future commit because
I'd like to change DIV to produce a tuple once the old backend is
removed.

This commit also removes uses of REGZERO from the assembler. They
aren't necessary and R0 will be used as a GPR by SSA.

Change-Id: I05756c1cbb74bf4a35fc492f8f0cd34b50763dc9
Reviewed-on: https://go-review.googlesource.com/29075
Run-TryBot: Michael Munday <munday@ca.ibm.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Michael Munday 2016-09-12 12:13:34 -04:00
parent dfc56a4cd3
commit 43bdfa9337
5 changed files with 188 additions and 63 deletions

View File

@ -13,6 +13,13 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
MOVDBR R1, R2 // b90f0021 MOVDBR R1, R2 // b90f0021
MOVWBR R3, R4 // b91f0043 MOVWBR R3, R4 // b91f0043
MOVDEQ R0, R1 // b9e28010
MOVDGE R2, R3 // b9e2a032
MOVDGT R4, R5 // b9e22054
MOVDLE R6, R7 // b9e2c076
MOVDLT R8, R9 // b9e24098
MOVDNE R10, R11 // b9e270ba
MOVD (R15), R1 // e310f0000004 MOVD (R15), R1 // e310f0000004
MOVW (R15), R2 // e320f0000014 MOVW (R15), R2 // e320f0000014
MOVH (R15), R3 // e330f0000015 MOVH (R15), R3 // e330f0000015
@ -50,6 +57,10 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
ADDC R1, R2 // b9ea1022 ADDC R1, R2 // b9ea1022
ADDC $1, R1, R2 // b9040021c22a00000001 ADDC $1, R1, R2 // b9040021c22a00000001
ADDC R1, R2, R3 // b9ea1032 ADDC R1, R2, R3 // b9ea1032
ADDW R1, R2 // 1a21
ADDW R1, R2, R3 // b9f81032
ADDW $8192, R1 // c21900002000
ADDW $8192, R1, R2 // ec21200000d8
SUB R3, R4 // b9090043 SUB R3, R4 // b9090043
SUB R3, R4, R5 // b9e93054 SUB R3, R4, R5 // b9e93054
SUB $8192, R3 // c238ffffe000 SUB $8192, R3 // c238ffffe000
@ -57,6 +68,10 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
SUBC R1, R2 // b90b0021 SUBC R1, R2 // b90b0021
SUBC $1, R1, R2 // b9040021c22affffffff SUBC $1, R1, R2 // b9040021c22affffffff
SUBC R2, R3, R4 // b9eb2043 SUBC R2, R3, R4 // b9eb2043
SUBW R3, R4 // 1b43
SUBW R3, R4, R5 // b9f93054
SUBW $8192, R1 // c21500002000
SUBW $8192, R1, R2 // 1821c22500002000
MULLW R6, R7 // b91c0076 MULLW R6, R7 // b91c0076
MULLW R6, R7, R8 // b9040087b91c0086 MULLW R6, R7, R8 // b9040087b91c0086
MULLW $8192, R6 // a76d2000 MULLW $8192, R6 // a76d2000
@ -73,10 +88,22 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
DIVD R1, R2, R3 // b90400b2b90d00a1b904003b DIVD R1, R2, R3 // b90400b2b90d00a1b904003b
DIVW R4, R5 // b90400b5b91d00a4b904005b DIVW R4, R5 // b90400b5b91d00a4b904005b
DIVW R4, R5, R6 // b90400b5b91d00a4b904006b DIVW R4, R5, R6 // b90400b5b91d00a4b904006b
DIVDU R7, R8 // b90400a0b90400b8b98700a7b904008b DIVDU R7, R8 // a7a90000b90400b8b98700a7b904008b
DIVDU R7, R8, R9 // b90400a0b90400b8b98700a7b904009b DIVDU R7, R8, R9 // a7a90000b90400b8b98700a7b904009b
DIVWU R1, R2 // b90400a0b90400b2b99700a1b904002b DIVWU R1, R2 // a7a90000b90400b2b99700a1b904002b
DIVWU R1, R2, R3 // b90400a0b90400b2b99700a1b904003b DIVWU R1, R2, R3 // a7a90000b90400b2b99700a1b904003b
MODD R1, R2 // b90400b2b90d00a1b904002a
MODD R1, R2, R3 // b90400b2b90d00a1b904003a
MODW R4, R5 // b90400b5b91d00a4b904005a
MODW R4, R5, R6 // b90400b5b91d00a4b904006a
MODDU R7, R8 // a7a90000b90400b8b98700a7b904008a
MODDU R7, R8, R9 // a7a90000b90400b8b98700a7b904009a
MODWU R1, R2 // a7a90000b90400b2b99700a1b904002a
MODWU R1, R2, R3 // a7a90000b90400b2b99700a1b904003a
NEG R1 // b9030011
NEG R1, R2 // b9030021
NEGW R1 // b9130011
NEGW R1, R2 // b9130021
LAA R1, R2, 524287(R3) // eb213fff7ff8 LAA R1, R2, 524287(R3) // eb213fff7ff8
LAAG R4, R5, -524288(R6) // eb54600080e8 LAAG R4, R5, -524288(R6) // eb54600080e8

View File

@ -212,10 +212,15 @@ const (
AADDME AADDME
AADDE AADDE
AADDZE AADDZE
AADDW
ADIVW ADIVW
ADIVWU ADIVWU
ADIVD ADIVD
ADIVDU ADIVDU
AMODW
AMODWU
AMODD
AMODDU
AMULLW AMULLW
AMULLD AMULLD
AMULHD AMULHD
@ -226,7 +231,9 @@ const (
ASUBV ASUBV
ASUBE ASUBE
ASUBZE ASUBZE
ASUBW
ANEG ANEG
ANEGW
// integer moves // integer moves
AMOVWBR AMOVWBR
@ -240,6 +247,14 @@ const (
AMOVD AMOVD
AMOVDBR AMOVDBR
// conditional moves
AMOVDEQ
AMOVDGE
AMOVDGT
AMOVDLE
AMOVDLT
AMOVDNE
// integer bitwise // integer bitwise
AAND AAND
AANDN AANDN
@ -276,6 +291,7 @@ const (
AFMULS AFMULS
AFNABS AFNABS
AFNEG AFNEG
AFNEGS
AFNMADD AFNMADD
AFNMADDS AFNMADDS
AFNMSUB AFNMSUB
@ -334,6 +350,8 @@ const (
ABGT ABGT
ABLE ABLE
ABLT ABLT
ABLEU
ABLTU
ABNE ABNE
ABVC ABVC
ABVS ABVS

View File

@ -11,10 +11,15 @@ var Anames = []string{
"ADDME", "ADDME",
"ADDE", "ADDE",
"ADDZE", "ADDZE",
"ADDW",
"DIVW", "DIVW",
"DIVWU", "DIVWU",
"DIVD", "DIVD",
"DIVDU", "DIVDU",
"MODW",
"MODWU",
"MODD",
"MODDU",
"MULLW", "MULLW",
"MULLD", "MULLD",
"MULHD", "MULHD",
@ -25,7 +30,9 @@ var Anames = []string{
"SUBV", "SUBV",
"SUBE", "SUBE",
"SUBZE", "SUBZE",
"SUBW",
"NEG", "NEG",
"NEGW",
"MOVWBR", "MOVWBR",
"MOVB", "MOVB",
"MOVBZ", "MOVBZ",
@ -36,6 +43,12 @@ var Anames = []string{
"MOVWZ", "MOVWZ",
"MOVD", "MOVD",
"MOVDBR", "MOVDBR",
"MOVDEQ",
"MOVDGE",
"MOVDGT",
"MOVDLE",
"MOVDLT",
"MOVDNE",
"AND", "AND",
"ANDN", "ANDN",
"NAND", "NAND",
@ -69,6 +82,7 @@ var Anames = []string{
"FMULS", "FMULS",
"FNABS", "FNABS",
"FNEG", "FNEG",
"FNEGS",
"FNMADD", "FNMADD",
"FNMADDS", "FNMADDS",
"FNMSUB", "FNMSUB",
@ -111,6 +125,8 @@ var Anames = []string{
"BGT", "BGT",
"BLE", "BLE",
"BLT", "BLT",
"BLEU",
"BLTU",
"BNE", "BNE",
"BVC", "BVC",
"BVS", "BVS",

View File

@ -145,10 +145,10 @@ var optab = []Optab{
Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 0}, Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 0},
Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 0}, Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 0},
Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 0}, Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 0},
Optab{ASUB, C_LCON, C_REG, C_NONE, C_REG, 22, 0},
Optab{ASUB, 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_NONE, C_NONE, C_REG, 4, 0},
Optab{AMULHD, C_REG, C_REG, 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}, Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 0},
Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 0}, Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 0},
Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 0}, Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 0},
@ -217,6 +217,9 @@ var optab = []Optab{
Optab{ACMPUBEQ, C_REG, C_REG, C_NONE, C_SBRA, 89, 0}, Optab{ACMPUBEQ, C_REG, C_REG, C_NONE, C_SBRA, 89, 0},
Optab{ACMPUBEQ, C_REG, C_NONE, C_ANDCON, C_SBRA, 90, 0}, Optab{ACMPUBEQ, C_REG, C_NONE, C_ANDCON, C_SBRA, 90, 0},
// move on condition
Optab{AMOVDEQ, C_REG, C_NONE, C_NONE, C_REG, 17, 0},
// compare // compare
Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 0}, Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 0},
Optab{ACMP, C_REG, C_NONE, C_NONE, C_LCON, 71, 0}, Optab{ACMP, C_REG, C_NONE, C_NONE, C_LCON, 71, 0},
@ -790,6 +793,7 @@ func buildop(ctxt *obj.Link) {
switch r { switch r {
case AADD: case AADD:
opset(AADDC, r) opset(AADDC, r)
opset(AADDW, r)
opset(AMULLD, r) opset(AMULLD, r)
opset(AMULLW, r) opset(AMULLW, r)
case ADIVW: case ADIVW:
@ -797,6 +801,10 @@ func buildop(ctxt *obj.Link) {
opset(ADIVD, r) opset(ADIVD, r)
opset(ADIVDU, r) opset(ADIVDU, r)
opset(ADIVWU, r) opset(ADIVWU, r)
opset(AMODD, r)
opset(AMODDU, r)
opset(AMODW, r)
opset(AMODWU, r)
case AMULHD: case AMULHD:
opset(AMULHDU, r) opset(AMULHDU, r)
case AMOVBZ: case AMOVBZ:
@ -844,6 +852,8 @@ func buildop(ctxt *obj.Link) {
opset(ABNE, r) opset(ABNE, r)
opset(ABVC, r) opset(ABVC, r)
opset(ABVS, r) opset(ABVS, r)
opset(ABLEU, r)
opset(ABLTU, r)
case ABR: case ABR:
opset(ABL, r) opset(ABL, r)
case ABC: case ABC:
@ -851,6 +861,7 @@ func buildop(ctxt *obj.Link) {
case AFABS: case AFABS:
opset(AFNABS, r) opset(AFNABS, r)
opset(AFNEG, r) opset(AFNEG, r)
opset(AFNEGS, r)
opset(ALEDBR, r) opset(ALEDBR, r)
opset(ALDEBR, r) opset(ALDEBR, r)
opset(AFSQRT, r) opset(AFSQRT, r)
@ -889,6 +900,9 @@ func buildop(ctxt *obj.Link) {
case ASUB: case ASUB:
opset(ASUBC, r) opset(ASUBC, r)
opset(ASUBE, r) opset(ASUBE, r)
opset(ASUBW, r)
case ANEG:
opset(ANEGW, r)
case AFMOVD: case AFMOVD:
opset(AFMOVS, r) opset(AFMOVS, r)
case AMOVDBR: case AMOVDBR:
@ -927,6 +941,12 @@ func buildop(ctxt *obj.Link) {
opset(ACMPUBLE, r) opset(ACMPUBLE, r)
opset(ACMPUBLT, r) opset(ACMPUBLT, r)
opset(ACMPUBNE, r) opset(ACMPUBNE, r)
case AMOVDEQ:
opset(AMOVDGE, r)
opset(AMOVDGT, r)
opset(AMOVDLE, r)
opset(AMOVDLT, r)
opset(AMOVDNE, r)
case AVL: case AVL:
opset(AVLLEZB, r) opset(AVLLEZB, r)
opset(AVLLEZH, r) opset(AVLLEZH, r)
@ -2510,22 +2530,26 @@ func addcallreloc(ctxt *obj.Link, sym *obj.LSym, add int64) *obj.Reloc {
func branchMask(ctxt *obj.Link, p *obj.Prog) uint32 { func branchMask(ctxt *obj.Link, p *obj.Prog) uint32 {
switch p.As { switch p.As {
case ABEQ, ACMPBEQ, ACMPUBEQ: case ABEQ, ACMPBEQ, ACMPUBEQ, AMOVDEQ:
return 0x8 return 0x8
case ABGE, ACMPBGE, ACMPUBGE: case ABGE, ACMPBGE, ACMPUBGE, AMOVDGE:
return 0xA return 0xA
case ABGT, ACMPBGT, ACMPUBGT: case ABGT, ACMPBGT, ACMPUBGT, AMOVDGT:
return 0x2 return 0x2
case ABLE, ACMPBLE, ACMPUBLE: case ABLE, ACMPBLE, ACMPUBLE, AMOVDLE:
return 0xC return 0xC
case ABLT, ACMPBLT, ACMPUBLT: case ABLT, ACMPBLT, ACMPUBLT, AMOVDLT:
return 0x4 return 0x4
case ABNE, ACMPBNE, ACMPUBNE: case ABNE, ACMPBNE, ACMPUBNE, AMOVDNE:
return 0x7 return 0x7
case ABLEU: // LE or unordered
return 0xD
case ABLTU: // LT or unordered
return 0x5
case ABVC: case ABVC:
return 0x0 //needs extra instruction return 0x0 // needs extra instruction
case ABVS: case ABVS:
return 0x1 return 0x1 // unordered
} }
ctxt.Diag("unknown conditional branch %v", p.As) ctxt.Diag("unknown conditional branch %v", p.As)
return 0xF return 0xF
@ -2574,9 +2598,9 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
} }
case 2: // arithmetic op reg [reg] reg case 2: // arithmetic op reg [reg] reg
r := int(p.Reg) r := p.Reg
if r == 0 { if r == 0 {
r = int(p.To.Reg) r = p.To.Reg
} }
var opcode uint32 var opcode uint32
@ -2590,17 +2614,19 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
opcode = op_ALGRK opcode = op_ALGRK
case AADDE: case AADDE:
opcode = op_ALCGR opcode = op_ALCGR
case AADDW:
opcode = op_ARK
case AMULLW: case AMULLW:
opcode = op_MSGFR opcode = op_MSGFR
case AMULLD: case AMULLD:
opcode = op_MSGR opcode = op_MSGR
case ADIVW: case ADIVW, AMODW:
opcode = op_DSGFR opcode = op_DSGFR
case ADIVWU: case ADIVWU, AMODWU:
opcode = op_DLR opcode = op_DLR
case ADIVD: case ADIVD, AMODD:
opcode = op_DSGR opcode = op_DSGR
case ADIVDU: case ADIVDU, AMODDU:
opcode = op_DLGR opcode = op_DLGR
case AFADD: case AFADD:
opcode = op_ADBR opcode = op_ADBR
@ -2619,11 +2645,15 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
switch p.As { switch p.As {
default: default:
case AADD, AADDC: case AADD, AADDC, AADDW:
zRRF(opcode, uint32(p.From.Reg), 0, uint32(p.To.Reg), uint32(r), asm) if p.As == AADDW && r == p.To.Reg {
zRR(op_AR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
} else {
zRRF(opcode, uint32(p.From.Reg), 0, uint32(p.To.Reg), uint32(r), asm)
}
case AADDE, AMULLW, AMULLD: case AADDE, AMULLW, AMULLD:
if r == int(p.To.Reg) { if r == p.To.Reg {
zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm) zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm)
} else if p.From.Reg == p.To.Reg { } else if p.From.Reg == p.To.Reg {
zRRE(opcode, uint32(p.To.Reg), uint32(r), asm) zRRE(opcode, uint32(p.To.Reg), uint32(r), asm)
@ -2634,14 +2664,22 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
case ADIVW, ADIVWU, ADIVD, ADIVDU: case ADIVW, ADIVWU, ADIVD, ADIVDU:
if p.As == ADIVWU || p.As == ADIVDU { if p.As == ADIVWU || p.As == ADIVDU {
zRRE(op_LGR, REGTMP, REGZERO, asm) zRI(op_LGHI, REGTMP, 0, asm)
} }
zRRE(op_LGR, REGTMP2, uint32(r), asm) zRRE(op_LGR, REGTMP2, uint32(r), asm)
zRRE(opcode, REGTMP, uint32(p.From.Reg), asm) zRRE(opcode, REGTMP, uint32(p.From.Reg), asm)
zRRE(op_LGR, uint32(p.To.Reg), REGTMP2, asm) zRRE(op_LGR, uint32(p.To.Reg), REGTMP2, asm)
case AMODW, AMODWU, AMODD, AMODDU:
if p.As == AMODWU || p.As == AMODDU {
zRI(op_LGHI, REGTMP, 0, asm)
}
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: case AFADD, AFADDS:
if r == int(p.To.Reg) { if r == p.To.Reg {
zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm) zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm)
} else if p.From.Reg == p.To.Reg { } else if p.From.Reg == p.To.Reg {
zRRE(opcode, uint32(p.To.Reg), uint32(r), asm) zRRE(opcode, uint32(p.To.Reg), uint32(r), asm)
@ -2651,7 +2689,7 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
} }
case AFSUB, AFSUBS, AFDIV, AFDIVS: case AFSUB, AFSUBS, AFDIV, AFDIVS:
if r == int(p.To.Reg) { if r == p.To.Reg {
zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm) zRRE(opcode, uint32(p.To.Reg), uint32(p.From.Reg), asm)
} else if p.From.Reg == p.To.Reg { } else if p.From.Reg == p.To.Reg {
zRRE(op_LGDR, REGTMP, uint32(r), asm) zRRE(op_LGDR, REGTMP, uint32(r), asm)
@ -2681,16 +2719,14 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
case AMOVW: case AMOVW:
v = int64(int32(v)) v = int64(int32(v))
} }
if v&0xffff == v { if int64(int16(v)) == v {
zRI(op_LLILL, uint32(p.To.Reg), uint32(v), asm) zRI(op_LGHI, uint32(p.To.Reg), uint32(v), asm)
} else if v&0xffff0000 == v { } else if v&0xffff0000 == v {
zRI(op_LLILH, uint32(p.To.Reg), uint32(v>>16), asm) zRI(op_LLILH, uint32(p.To.Reg), uint32(v>>16), asm)
} else if v&0xffff00000000 == v { } else if v&0xffff00000000 == v {
zRI(op_LLIHL, uint32(p.To.Reg), uint32(v>>32), asm) zRI(op_LLIHL, uint32(p.To.Reg), uint32(v>>32), asm)
} else if uint64(v)&0xffff000000000000 == uint64(v) { } else if uint64(v)&0xffff000000000000 == uint64(v) {
zRI(op_LLIHH, uint32(p.To.Reg), uint32(v>>48), asm) zRI(op_LLIHH, uint32(p.To.Reg), uint32(v>>48), asm)
} else if int64(int16(v)) == v {
zRI(op_LGHI, uint32(p.To.Reg), uint32(v), asm)
} else if int64(int32(v)) == v { } else if int64(int32(v)) == v {
zRIL(_a, op_LGFI, uint32(p.To.Reg), uint32(v), asm) zRIL(_a, op_LGFI, uint32(p.To.Reg), uint32(v), asm)
} else if int64(uint32(v)) == v { } else if int64(uint32(v)) == v {
@ -2845,7 +2881,6 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
} else { } else {
zRRF(op_SLGRK, uint32(p.From.Reg), 0, uint32(p.To.Reg), uint32(r), asm) zRRF(op_SLGRK, uint32(p.From.Reg), 0, uint32(p.To.Reg), uint32(r), asm)
} }
case ASUBE: case ASUBE:
if r == 0 { if r == 0 {
r = int(p.To.Reg) r = int(p.To.Reg)
@ -2860,6 +2895,12 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
zRRE(op_LGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_LGR, uint32(p.To.Reg), uint32(r), asm)
zRRE(op_SLBGR, uint32(p.To.Reg), uint32(p.From.Reg), asm) zRRE(op_SLBGR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
} }
case ASUBW:
if r == 0 {
zRR(op_SR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
} else {
zRRF(op_SRK, uint32(p.From.Reg), 0, uint32(p.To.Reg), uint32(r), asm)
}
} }
case 11: // br/bl case 11: // br/bl
@ -2905,6 +2946,10 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
addrilreloc(ctxt, p.To.Sym, p.To.Offset) addrilreloc(ctxt, p.To.Sym, p.To.Offset)
} }
case 17: // move on condition
m3 := branchMask(ctxt, p)
zRRF(op_LOCGR, m3, 0, uint32(p.To.Reg), uint32(p.From.Reg), asm)
case 18: // br/bl reg case 18: // br/bl reg
if p.As == ABL { if p.As == ABL {
zRR(op_BASR, uint32(REG_LR), uint32(p.To.Reg), asm) zRR(op_BASR, uint32(REG_LR), uint32(p.To.Reg), asm)
@ -2946,6 +2991,29 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
zRRE(op_LGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_LGR, uint32(p.To.Reg), uint32(r), asm)
} }
zRIL(_a, op_ALGFI, uint32(p.To.Reg), uint32(v), asm) zRIL(_a, op_ALGFI, uint32(p.To.Reg), uint32(v), asm)
case AADDW:
i2 := int32(v)
if r == p.To.Reg {
zRIL(_a, op_AFI, uint32(p.To.Reg), uint32(i2), asm)
} else if int32(int16(i2)) == i2 {
zRIE(_d, op_AHIK, uint32(p.To.Reg), uint32(r), uint32(i2), 0, 0, 0, 0, asm)
} else {
zRR(op_LR, uint32(p.To.Reg), uint32(r), asm)
zRIL(_a, op_AFI, uint32(p.To.Reg), uint32(i2), asm)
}
case ASUB:
zRIL(_a, op_LGFI, uint32(REGTMP), uint32(v), asm)
zRRF(op_SLGRK, uint32(REGTMP), 0, uint32(p.To.Reg), uint32(r), asm)
case ASUBC:
if r != p.To.Reg {
zRRE(op_LGR, uint32(p.To.Reg), uint32(r), asm)
}
zRIL(_a, op_SLGFI, uint32(p.To.Reg), uint32(v), asm)
case ASUBW:
if r != p.To.Reg {
zRR(op_LR, uint32(p.To.Reg), uint32(r), asm)
}
zRIL(_a, op_SLFI, uint32(p.To.Reg), uint32(v), asm)
case AMULLW, AMULLD: case AMULLW, AMULLD:
if r != p.To.Reg { if r != p.To.Reg {
zRRE(op_LGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_LGR, uint32(p.To.Reg), uint32(r), asm)
@ -3009,19 +3077,20 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
zRRF(opcode, uint32(r), 0, uint32(p.To.Reg), REGTMP, asm) zRRF(opcode, uint32(r), 0, uint32(p.To.Reg), REGTMP, asm)
} }
case 26: // mov $addr/sym reg case 26: // MOVD $offset(base)(index), reg
v := regoff(ctxt, &p.From) v := regoff(ctxt, &p.From)
r := p.From.Reg r := p.From.Reg
if r == 0 { if r == 0 {
r = o.param r = o.param
} }
i := p.From.Index
if v >= 0 && v < DISP12 { if v >= 0 && v < DISP12 {
zRX(op_LA, uint32(p.To.Reg), uint32(r), 0, uint32(v), asm) zRX(op_LA, uint32(p.To.Reg), uint32(r), uint32(i), uint32(v), asm)
} else if v >= -DISP20/2 && v < DISP20/2 { } else if v >= -DISP20/2 && v < DISP20/2 {
zRXY(op_LAY, uint32(p.To.Reg), uint32(r), 0, uint32(v), asm) zRXY(op_LAY, uint32(p.To.Reg), uint32(r), uint32(i), uint32(v), asm)
} else { } else {
zRIL(_a, op_LGFI, REGTMP, uint32(v), asm) zRIL(_a, op_LGFI, REGTMP, uint32(v), asm)
zRX(op_LA, uint32(p.To.Reg), uint32(r), REGTMP, 0, asm) zRX(op_LA, uint32(p.To.Reg), uint32(r), REGTMP, uint32(i), asm)
} }
case 31: // dword case 31: // dword
@ -3076,6 +3145,8 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
opcode = op_LNDBR opcode = op_LNDBR
case AFNEG: case AFNEG:
opcode = op_LCDFR opcode = op_LCDFR
case AFNEGS:
opcode = op_LCEBR
case ALEDBR: case ALEDBR:
opcode = op_LEDBR opcode = op_LEDBR
case ALDEBR: case ALDEBR:
@ -3161,51 +3232,49 @@ func asmout(ctxt *obj.Link, asm *[]byte) {
} }
case 47: // arithmetic op (carry) reg [reg] reg case 47: // arithmetic op (carry) reg [reg] reg
r := p.From.Reg
switch p.As { switch p.As {
default: default:
case AADDME: case AADDME:
r := int(p.From.Reg)
if p.To.Reg == p.From.Reg { if p.To.Reg == p.From.Reg {
zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm) zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm)
r = REGTMP r = REGTMP
} }
zRIL(_a, op_LGFI, uint32(p.To.Reg), 0xffffffff, asm) // p.To.Reg <- -1 zRIL(_a, op_LGFI, uint32(p.To.Reg), 0xffffffff, asm) // p.To.Reg <- -1
zRRE(op_ALCGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_ALCGR, uint32(p.To.Reg), uint32(r), asm)
case AADDZE: case AADDZE:
r := int(p.From.Reg)
if p.To.Reg == p.From.Reg { if p.To.Reg == p.From.Reg {
zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm) zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm)
r = REGTMP r = REGTMP
} }
zRRE(op_LGR, uint32(p.To.Reg), REGZERO, asm) // p.To.Reg <- 0 zRI(op_LGHI, uint32(p.To.Reg), 0, asm)
zRRE(op_ALCGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_ALCGR, uint32(p.To.Reg), uint32(r), asm)
case ASUBME: case ASUBME:
r := int(p.From.Reg)
if p.To.Reg == p.From.Reg { if p.To.Reg == p.From.Reg {
zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm) zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm)
r = REGTMP r = REGTMP
} }
zRIL(_a, op_LGFI, uint32(p.To.Reg), 0xffffffff, asm) // p.To.Reg <- -1 zRIL(_a, op_LGFI, uint32(p.To.Reg), 0xffffffff, asm) // p.To.Reg <- -1
zRRE(op_SLBGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_SLBGR, uint32(p.To.Reg), uint32(r), asm)
case ASUBZE: case ASUBZE:
r := int(p.From.Reg)
if p.To.Reg == p.From.Reg { if p.To.Reg == p.From.Reg {
zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm) zRRE(op_LGR, REGTMP, uint32(p.From.Reg), asm)
r = REGTMP r = REGTMP
} }
zRRE(op_LGR, uint32(p.To.Reg), REGZERO, asm) // p.To.Reg <- 0 zRI(op_LGHI, uint32(p.To.Reg), 0, asm)
zRRE(op_SLBGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_SLBGR, uint32(p.To.Reg), uint32(r), asm)
case ANEG: case ANEG:
r := int(p.From.Reg) r := p.From.Reg
if r == 0 { if r == 0 {
r = int(p.To.Reg) r = p.To.Reg
} }
zRRE(op_LCGR, uint32(p.To.Reg), uint32(r), asm) zRRE(op_LCGR, uint32(p.To.Reg), uint32(r), asm)
case ANEGW:
r := p.From.Reg
if r == 0 {
r = p.To.Reg
}
zRRE(op_LCGFR, uint32(p.To.Reg), uint32(r), asm)
} }
case 48: // floating-point round to integer case 48: // floating-point round to integer

View File

@ -109,13 +109,13 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
// Rewrite SUB constants into ADD. // Rewrite SUB constants into ADD.
switch p.As { switch p.As {
case ASUBC: case ASUBC:
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST && isint32(-p.From.Offset) {
p.From.Offset = -p.From.Offset p.From.Offset = -p.From.Offset
p.As = AADDC p.As = AADDC
} }
case ASUB: case ASUB:
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST && isint32(-p.From.Offset) {
p.From.Offset = -p.From.Offset p.From.Offset = -p.From.Offset
p.As = AADD p.As = AADD
} }
@ -258,14 +258,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p.Link.Mark |= LABEL p.Link.Mark |= LABEL
} }
case ANOR:
q = p
if p.To.Type == obj.TYPE_REG {
if p.To.Reg == REGZERO {
p.Mark |= LABEL | SYNC
}
}
case ASYNC, case ASYNC,
AWORD: AWORD:
q = p q = p
@ -312,6 +304,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
ABGT, ABGT,
ABLE, ABLE,
ABLT, ABLT,
ABLEU,
ABLTU,
ABNE, ABNE,
ABR, ABR,
ABVC, ABVC,
@ -401,7 +395,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
q = p q = p
if p.From3.Offset&obj.NOSPLIT == 0 { if p.From3.Offset&obj.NOSPLIT == 0 && p.From3.Offset&obj.NOFRAME == 0 {
p, pPreempt = stacksplitPre(ctxt, p, autosize) // emit pre part of split check p, pPreempt = stacksplitPre(ctxt, p, autosize) // emit pre part of split check
pPre = p pPre = p
wasSplit = true //need post part of split wasSplit = true //need post part of split
@ -440,7 +434,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
// //
// MOVD g_panic(g), R3 // MOVD g_panic(g), R3
// CMP R0, R3 // CMP R3, $0
// BEQ end // BEQ end
// MOVD panic_argp(R3), R4 // MOVD panic_argp(R3), R4
// ADD $(autosize+8), R1, R5 // ADD $(autosize+8), R1, R5
@ -466,9 +460,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
q = obj.Appendp(ctxt, q) q = obj.Appendp(ctxt, q)
q.As = ACMP q.As = ACMP
q.From.Type = obj.TYPE_REG q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R0 q.From.Reg = REG_R3
q.To.Type = obj.TYPE_REG q.To.Type = obj.TYPE_CONST
q.To.Reg = REG_R3 q.To.Offset = 0
q = obj.Appendp(ctxt, q) q = obj.Appendp(ctxt, q)
q.As = ABEQ q.As = ABEQ
@ -993,6 +987,7 @@ var unaryDst = map[obj.As]bool{
ASTCKE: true, ASTCKE: true,
ASTCKF: true, ASTCKF: true,
ANEG: true, ANEG: true,
ANEGW: true,
AVONE: true, AVONE: true,
AVZERO: true, AVZERO: true,
} }