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

cmd/compile/internal/s390x: add s390x support

s390x does not require duffzero/duffcopy since it has
storage-to-storage instructions that can copy/clear up to 256
bytes at a time.

peep contains several new passes to optimize instruction
sequences that match s390x instructions such as the
compare-and-branch and load/store multiple instructions.

copyprop and subprop have been extended to work with moves that
require sign/zero extension. This work could be ported to other
architectures that do not used sized math however it does add
complexity and will probably be rendered unnecessary by ssa in
the near future.

Change-Id: I1b64b281b452ed82a85655a0df69cb224d2a6941
Reviewed-on: https://go-review.googlesource.com/20873
Run-TryBot: Michael Munday <munday@ca.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBill O'Farrell <billotosyr@gmail.com>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 944a0859
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package s390x
import (
"cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/s390x"
)
type direction int
const (
_FORWARDS direction = iota
_BACKWARDS
)
// blockcopy copies w bytes from &n to &res
func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
var dst gc.Node
var src gc.Node
if n.Ullman >= res.Ullman {
gc.Agenr(n, &dst, res) // temporarily use dst
gc.Regalloc(&src, gc.Types[gc.Tptr], nil)
gins(s390x.AMOVD, &dst, &src)
if res.Op == gc.ONAME {
gc.Gvardef(res)
}
gc.Agen(res, &dst)
} else {
if res.Op == gc.ONAME {
gc.Gvardef(res)
}
gc.Agenr(res, &dst, res)
gc.Agenr(n, &src, nil)
}
defer gc.Regfree(&src)
defer gc.Regfree(&dst)
var tmp gc.Node
gc.Regalloc(&tmp, gc.Types[gc.Tptr], nil)
defer gc.Regfree(&tmp)
offset := int64(0)
dir := _FORWARDS
if osrc < odst && odst < osrc+w {
// Reverse. Can't use MVC, fall back onto basic moves.
dir = _BACKWARDS
const copiesPerIter = 2
if w >= 8*copiesPerIter {
cnt := w - (w % (8 * copiesPerIter))
ginscon(s390x.AADD, w, &src)
ginscon(s390x.AADD, w, &dst)
var end gc.Node
gc.Regalloc(&end, gc.Types[gc.Tptr], nil)
p := gins(s390x.ASUB, nil, &end)
p.From.Type = obj.TYPE_CONST
p.From.Offset = cnt
p.Reg = src.Reg
var label *obj.Prog
for i := 0; i < copiesPerIter; i++ {
offset := int64(-8 * (i + 1))
p := gins(s390x.AMOVD, &src, &tmp)
p.From.Type = obj.TYPE_MEM
p.From.Offset = offset
if i == 0 {
label = p
}
p = gins(s390x.AMOVD, &tmp, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = offset
}
ginscon(s390x.ASUB, 8*copiesPerIter, &src)
ginscon(s390x.ASUB, 8*copiesPerIter, &dst)
gins(s390x.ACMP, &src, &end)
gc.Patch(gc.Gbranch(s390x.ABNE, nil, 0), label)
gc.Regfree(&end)
w -= cnt
} else {
offset = w
}
}
if dir == _FORWARDS && w > 1024 {
// Loop over MVCs
cnt := w - (w % 256)
var end gc.Node
gc.Regalloc(&end, gc.Types[gc.Tptr], nil)
add := gins(s390x.AADD, nil, &end)
add.From.Type = obj.TYPE_CONST
add.From.Offset = cnt
add.Reg = src.Reg
mvc := gins(s390x.AMVC, &src, &dst)
mvc.From.Type = obj.TYPE_MEM
mvc.From.Offset = 0
mvc.To.Type = obj.TYPE_MEM
mvc.To.Offset = 0
mvc.From3 = new(obj.Addr)
mvc.From3.Type = obj.TYPE_CONST
mvc.From3.Offset = 256
ginscon(s390x.AADD, 256, &src)
ginscon(s390x.AADD, 256, &dst)
gins(s390x.ACMP, &src, &end)
gc.Patch(gc.Gbranch(s390x.ABNE, nil, 0), mvc)
gc.Regfree(&end)
w -= cnt
}
for w > 0 {
cnt := w
// If in reverse we can only do 8, 4, 2 or 1 bytes at a time.
if dir == _BACKWARDS {
switch {
case cnt >= 8:
cnt = 8
case cnt >= 4:
cnt = 4
case cnt >= 2:
cnt = 2
}
} else if cnt > 256 {
cnt = 256
}
switch cnt {
case 8, 4, 2, 1:
op := s390x.AMOVB
switch cnt {
case 8:
op = s390x.AMOVD
case 4:
op = s390x.AMOVW
case 2:
op = s390x.AMOVH
}
load := gins(op, &src, &tmp)
load.From.Type = obj.TYPE_MEM
load.From.Offset = offset
store := gins(op, &tmp, &dst)
store.To.Type = obj.TYPE_MEM
store.To.Offset = offset
if dir == _BACKWARDS {
load.From.Offset -= cnt
store.To.Offset -= cnt
}
default:
p := gins(s390x.AMVC, &src, &dst)
p.From.Type = obj.TYPE_MEM
p.From.Offset = offset
p.To.Type = obj.TYPE_MEM
p.To.Offset = offset
p.From3 = new(obj.Addr)
p.From3.Type = obj.TYPE_CONST
p.From3.Offset = cnt
}
switch dir {
case _FORWARDS:
offset += cnt
case _BACKWARDS:
offset -= cnt
}
w -= cnt
}
}
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package s390x
import (
"cmd/compile/internal/gc"
"cmd/internal/obj/s390x"
)
func betypeinit() {
gc.Widthptr = 8
gc.Widthint = 8
gc.Widthreg = 8
}
func Main() {
gc.Thearch.LinkArch = &s390x.Links390x
gc.Thearch.REGSP = s390x.REGSP
gc.Thearch.REGCTXT = s390x.REGCTXT
gc.Thearch.REGCALLX = s390x.REG_R3
gc.Thearch.REGCALLX2 = s390x.REG_R4
gc.Thearch.REGRETURN = s390x.REG_R3
gc.Thearch.REGMIN = s390x.REG_R0
gc.Thearch.REGMAX = s390x.REG_R15
gc.Thearch.FREGMIN = s390x.REG_F0
gc.Thearch.FREGMAX = s390x.REG_F15
gc.Thearch.MAXWIDTH = 1 << 50
gc.Thearch.ReservedRegs = resvd
gc.Thearch.Betypeinit = betypeinit
gc.Thearch.Cgen_hmul = cgen_hmul
gc.Thearch.Cgen_shift = cgen_shift
gc.Thearch.Clearfat = clearfat
gc.Thearch.Defframe = defframe
gc.Thearch.Dodiv = dodiv
gc.Thearch.Excise = excise
gc.Thearch.Expandchecks = expandchecks
gc.Thearch.Getg = getg
gc.Thearch.Gins = gins
gc.Thearch.Ginscmp = ginscmp
gc.Thearch.Ginscon = ginscon
gc.Thearch.Ginsnop = ginsnop
gc.Thearch.Gmove = gmove
gc.Thearch.Peep = peep
gc.Thearch.Proginfo = proginfo
gc.Thearch.Regtyp = isReg
gc.Thearch.Sameaddr = sameaddr
gc.Thearch.Smallindir = smallindir
gc.Thearch.Stackaddr = stackaddr
gc.Thearch.Blockcopy = blockcopy
gc.Thearch.Sudoaddable = sudoaddable
gc.Thearch.Sudoclean = sudoclean
gc.Thearch.Excludedregs = excludedregs
gc.Thearch.RtoB = RtoB
gc.Thearch.FtoB = RtoB
gc.Thearch.BtoR = BtoR
gc.Thearch.BtoF = BtoF
gc.Thearch.Optoas = optoas
gc.Thearch.Doregbits = doregbits
gc.Thearch.Regnames = regnames
gc.Main()
gc.Exit(0)
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package s390x
import (
"cmd/compile/internal/gc"
"cmd/internal/obj"
"cmd/internal/obj/s390x"
)
// This table gives the basic information about instruction
// generated by the compiler and processed in the optimizer.
// See opt.h for bit definitions.
//
// Instructions not generated need not be listed.
// As an exception to that rule, we typically write down all the
// size variants of an operation even if we just use a subset.
var progtable = [s390x.ALAST & obj.AMask]obj.ProgInfo{
obj.ATYPE & obj.AMask: {Flags: gc.Pseudo | gc.Skip},
obj.ATEXT & obj.AMask: {Flags: gc.Pseudo},
obj.AFUNCDATA & obj.AMask: {Flags: gc.Pseudo},
obj.APCDATA & obj.AMask: {Flags: gc.Pseudo},
obj.AUNDEF & obj.AMask: {Flags: gc.Break},
obj.AUSEFIELD & obj.AMask: {Flags: gc.OK},
obj.ACHECKNIL & obj.AMask: {Flags: gc.LeftRead},
obj.AVARDEF & obj.AMask: {Flags: gc.Pseudo | gc.RightWrite},
obj.AVARKILL & obj.AMask: {Flags: gc.Pseudo | gc.RightWrite},
obj.AVARLIVE & obj.AMask: {Flags: gc.Pseudo | gc.LeftRead},
// NOP is an internal no-op that also stands
// for USED and SET annotations.
obj.ANOP & obj.AMask: {Flags: gc.LeftRead | gc.RightWrite},
// Integer
s390x.AADD & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ASUB & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ANEG & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AAND & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AOR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AXOR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AMULLD & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AMULLW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AMULHD & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AMULHDU & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ADIVD & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ADIVDU & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ASLD & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ASRD & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ASRAD & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ARLL & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ARLLG & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.ACMP & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
s390x.ACMPU & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
// Floating point.
s390x.AFADD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFADDS & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFSUB & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFSUBS & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFMUL & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFMULS & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFDIV & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFDIVS & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
s390x.AFCMPU & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
s390x.ACEBR & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightRead},
s390x.ALEDBR & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ALDEBR & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.AFSQRT & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
// Conversions
s390x.ACEFBRA & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACDFBRA & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACEGBRA & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACDGBRA & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACFEBRA & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACFDBRA & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACGEBRA & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACGDBRA & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACELFBR & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACDLFBR & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACELGBR & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACDLGBR & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACLFEBR & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACLFDBR & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACLGEBR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
s390x.ACLGDBR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
// Moves
s390x.AMOVB & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
s390x.AMOVBZ & obj.AMask: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
s390x.AMOVH & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
s390x.AMOVHZ & obj.AMask: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
s390x.AMOVW & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
s390x.AMOVWZ & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
s390x.AMOVD & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
s390x.AFMOVS & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
s390x.AFMOVD & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
// Storage operations
s390x.AMVC & obj.AMask: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
s390x.ACLC & obj.AMask: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightRead | gc.RightAddr},
s390x.AXC & obj.AMask: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
s390x.AOC & obj.AMask: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
s390x.ANC & obj.AMask: {Flags: gc.LeftRead | gc.LeftAddr | gc.RightWrite | gc.RightAddr},
// Jumps
s390x.ABR & obj.AMask: {Flags: gc.Jump | gc.Break},
s390x.ABL & obj.AMask: {Flags: gc.Call},
s390x.ABEQ & obj.AMask: {Flags: gc.Cjmp},
s390x.ABNE & obj.AMask: {Flags: gc.Cjmp},
s390x.ABGE & obj.AMask: {Flags: gc.Cjmp},
s390x.ABLT & obj.AMask: {Flags: gc.Cjmp},
s390x.ABGT & obj.AMask: {Flags: gc.Cjmp},
s390x.ABLE & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPBEQ & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPBNE & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPBGE & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPBLT & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPBGT & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPBLE & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPUBEQ & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPUBNE & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPUBGE & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPUBLT & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPUBGT & obj.AMask: {Flags: gc.Cjmp},
s390x.ACMPUBLE & obj.AMask: {Flags: gc.Cjmp},
// Macros
s390x.ACLEAR & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightAddr | gc.RightWrite},
// Load/store multiple
s390x.ASTMG & obj.AMask: {Flags: gc.SizeQ | gc.LeftRead | gc.RightAddr | gc.RightWrite},
s390x.ASTMY & obj.AMask: {Flags: gc.SizeL | gc.LeftRead | gc.RightAddr | gc.RightWrite},
s390x.ALMG & obj.AMask: {Flags: gc.SizeQ | gc.LeftAddr | gc.LeftRead | gc.RightWrite},
s390x.ALMY & obj.AMask: {Flags: gc.SizeL | gc.LeftAddr | gc.LeftRead | gc.RightWrite},
obj.ARET & obj.AMask: {Flags: gc.Break},
}
func proginfo(p *obj.Prog) {
info := &p.Info
*info = progtable[p.As&obj.AMask]
if info.Flags == 0 {
gc.Fatalf("proginfo: unknown instruction %v", p)
}
if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
info.Flags &^= gc.RegRead
info.Flags |= gc.RightRead /*CanRegRead |*/
}
if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR) && p.From.Reg != 0 {
info.Regindex |= RtoB(int(p.From.Reg))
}
if (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
info.Regindex |= RtoB(int(p.To.Reg))
}
if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
info.Flags &^= gc.LeftRead
info.Flags |= gc.LeftAddr
}
switch p.As {
// load multiple sets a range of registers
case s390x.ALMG, s390x.ALMY:
for r := p.Reg; r <= p.To.Reg; r++ {
info.Regset |= RtoB(int(r))
}
// store multiple reads a range of registers
case s390x.ASTMG, s390x.ASTMY:
for r := p.From.Reg; r <= p.Reg; r++ {
info.Reguse |= RtoB(int(r))
}
}
}
// Derived from Inferno utils/6c/reg.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package s390x
import "cmd/internal/obj/s390x"
import "cmd/compile/internal/gc"
const (
NREGVAR = 32 /* 16 general + 16 floating */
)
var regname = []string{
".R0",
".R1",
".R2",
".R3",
".R4",
".R5",
".R6",
".R7",
".R8",
".R9",
".R10",
".R11",
".R12",
".R13",
".R14",
".R15",
".F0",
".F1",
".F2",
".F3",
".F4",
".F5",
".F6",
".F7",
".F8",
".F9",
".F10",
".F11",
".F12",
".F13",
".F14",
".F15",
}
func regnames(n *int) []string {
*n = NREGVAR
return regname
}
func excludedregs() uint64 {
// Exclude registers with fixed functions
return RtoB(s390x.REG_R0) |
RtoB(s390x.REGSP) |
RtoB(s390x.REGG) |
RtoB(s390x.REGTMP) |
RtoB(s390x.REGTMP2) |
RtoB(s390x.REG_LR)
}
func doregbits(r int) uint64 {
return 0
}
/*
* track register variables including external registers:
* bit reg
* 0 R0
* ... ...
* 15 R15
* 16+0 F0
* 16+1 F1
* ... ...
* 16+15 F15
*/
func RtoB(r int) uint64 {
if r >= s390x.REG_R0 && r <= s390x.REG_R15 {
return 1 << uint(r-s390x.REG_R0)
}
if r >= s390x.REG_F0 && r <= s390x.REG_F15 {
return 1 << uint(16+r-s390x.REG_F0)
}
return 0
}
func BtoR(b uint64) int {
b &= 0xffff
if b == 0 {
return 0
}
return gc.Bitno(b) + s390x.REG_R0
}
func BtoF(b uint64) int {
b >>= 16
b &= 0xffff
if b == 0 {
return 0
}
return gc.Bitno(b) + s390x.REG_F0
}
......@@ -10,6 +10,7 @@ import (
"cmd/compile/internal/arm64"
"cmd/compile/internal/mips64"
"cmd/compile/internal/ppc64"
"cmd/compile/internal/s390x"
"cmd/compile/internal/x86"
"cmd/internal/obj"
"fmt"
......@@ -38,5 +39,7 @@ func main() {
mips64.Main()
case "ppc64", "ppc64le":
ppc64.Main()
case "s390x":
s390x.Main()
}
}
......@@ -38,6 +38,7 @@ var bootstrapDirs = []string{
"compile/internal/ppc64",
"compile/internal/ssa",
"compile/internal/x86",
"compile/internal/s390x",
"internal/bio",
"internal/gcprog",
"internal/obj",
......
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