github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/cmd/compile/internal/s390x/gsubr.go (about)

     1  // Derived from Inferno utils/6c/txt.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package s390x
    32  
    33  import (
    34  	"cmd/compile/internal/gc"
    35  	"cmd/internal/obj"
    36  	"cmd/internal/obj/s390x"
    37  	"fmt"
    38  )
    39  
    40  var resvd = []int{
    41  	s390x.REGZERO, // R0
    42  	s390x.REGTMP,  // R10
    43  	s390x.REGTMP2, // R11
    44  	s390x.REGCTXT, // R12
    45  	s390x.REGG,    // R13
    46  	s390x.REG_LR,  // R14
    47  	s390x.REGSP,   // R15
    48  }
    49  
    50  // generate
    51  //	as $c, n
    52  func ginscon(as obj.As, c int64, n2 *gc.Node) {
    53  	var n1 gc.Node
    54  
    55  	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
    56  
    57  	if as != s390x.AMOVD && (c < -s390x.BIG || c > s390x.BIG) || n2.Op != gc.OREGISTER {
    58  		// cannot have more than 16-bit of immediate in ADD, etc.
    59  		// instead, MOV into register first.
    60  		var ntmp gc.Node
    61  		gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
    62  
    63  		rawgins(s390x.AMOVD, &n1, &ntmp)
    64  		rawgins(as, &ntmp, n2)
    65  		gc.Regfree(&ntmp)
    66  		return
    67  	}
    68  
    69  	rawgins(as, &n1, n2)
    70  }
    71  
    72  // generate
    73  //	as n, $c (CMP/CMPU)
    74  func ginscon2(as obj.As, n2 *gc.Node, c int64) {
    75  	var n1 gc.Node
    76  
    77  	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
    78  
    79  	switch as {
    80  	default:
    81  		gc.Fatalf("ginscon2")
    82  
    83  	case s390x.ACMP:
    84  		if -s390x.BIG <= c && c <= s390x.BIG {
    85  			rawgins(as, n2, &n1)
    86  			return
    87  		}
    88  
    89  	case s390x.ACMPU:
    90  		if 0 <= c && c <= 2*s390x.BIG {
    91  			rawgins(as, n2, &n1)
    92  			return
    93  		}
    94  	}
    95  
    96  	// MOV n1 into register first
    97  	var ntmp gc.Node
    98  	gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
    99  
   100  	rawgins(s390x.AMOVD, &n1, &ntmp)
   101  	rawgins(as, n2, &ntmp)
   102  	gc.Regfree(&ntmp)
   103  }
   104  
   105  func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
   106  	if t.IsInteger() && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
   107  		// Reverse comparison to place constant last.
   108  		op = gc.Brrev(op)
   109  		n1, n2 = n2, n1
   110  	}
   111  
   112  	var r1, r2, g1, g2 gc.Node
   113  	gc.Regalloc(&r1, t, n1)
   114  	gc.Regalloc(&g1, n1.Type, &r1)
   115  	gc.Cgen(n1, &g1)
   116  	gmove(&g1, &r1)
   117  	if t.IsInteger() && gc.Isconst(n2, gc.CTINT) {
   118  		ginscon2(optoas(gc.OCMP, t), &r1, n2.Int64())
   119  	} else {
   120  		gc.Regalloc(&r2, t, n2)
   121  		gc.Regalloc(&g2, n1.Type, &r2)
   122  		gc.Cgen(n2, &g2)
   123  		gmove(&g2, &r2)
   124  		rawgins(optoas(gc.OCMP, t), &r1, &r2)
   125  		gc.Regfree(&g2)
   126  		gc.Regfree(&r2)
   127  	}
   128  	gc.Regfree(&g1)
   129  	gc.Regfree(&r1)
   130  	return gc.Gbranch(optoas(op, t), nil, likely)
   131  }
   132  
   133  // gmvc tries to move f to t using a mvc instruction.
   134  // If successful it returns true, otherwise it returns false.
   135  func gmvc(f, t *gc.Node) bool {
   136  	ft := int(gc.Simsimtype(f.Type))
   137  	tt := int(gc.Simsimtype(t.Type))
   138  
   139  	if ft != tt {
   140  		return false
   141  	}
   142  
   143  	if f.Op != gc.OINDREG || t.Op != gc.OINDREG {
   144  		return false
   145  	}
   146  
   147  	if f.Xoffset < 0 || f.Xoffset >= 4096-8 {
   148  		return false
   149  	}
   150  
   151  	if t.Xoffset < 0 || t.Xoffset >= 4096-8 {
   152  		return false
   153  	}
   154  
   155  	var len int64
   156  	switch ft {
   157  	case gc.TUINT8, gc.TINT8, gc.TBOOL:
   158  		len = 1
   159  	case gc.TUINT16, gc.TINT16:
   160  		len = 2
   161  	case gc.TUINT32, gc.TINT32, gc.TFLOAT32:
   162  		len = 4
   163  	case gc.TUINT64, gc.TINT64, gc.TFLOAT64, gc.TPTR64:
   164  		len = 8
   165  	case gc.TUNSAFEPTR:
   166  		len = int64(gc.Widthptr)
   167  	default:
   168  		return false
   169  	}
   170  
   171  	p := gc.Prog(s390x.AMVC)
   172  	gc.Naddr(&p.From, f)
   173  	gc.Naddr(&p.To, t)
   174  	p.From3 = new(obj.Addr)
   175  	p.From3.Offset = len
   176  	p.From3.Type = obj.TYPE_CONST
   177  	return true
   178  }
   179  
   180  // generate move:
   181  //	t = f
   182  // hard part is conversions.
   183  func gmove(f *gc.Node, t *gc.Node) {
   184  	if gc.Debug['M'] != 0 {
   185  		fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, gc.FmtLong), gc.Nconv(t, gc.FmtLong))
   186  	}
   187  
   188  	ft := int(gc.Simsimtype(f.Type))
   189  	tt := int(gc.Simsimtype(t.Type))
   190  	cvt := t.Type
   191  
   192  	if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
   193  		gc.Complexmove(f, t)
   194  		return
   195  	}
   196  
   197  	var a obj.As
   198  
   199  	// cannot have two memory operands
   200  	if gc.Ismem(f) && gc.Ismem(t) {
   201  		if gmvc(f, t) {
   202  			return
   203  		}
   204  		goto hard
   205  	}
   206  
   207  	// convert constant to desired type
   208  	if f.Op == gc.OLITERAL {
   209  		var con gc.Node
   210  		f.Convconst(&con, t.Type)
   211  		f = &con
   212  		ft = tt // so big switch will choose a simple mov
   213  
   214  		// some constants can't move directly to memory.
   215  		if gc.Ismem(t) {
   216  			// float constants come from memory.
   217  			if t.Type.IsFloat() {
   218  				goto hard
   219  			}
   220  
   221  			// all immediates are 16-bit sign-extended
   222  			// unless moving into a register.
   223  			if t.Type.IsInteger() {
   224  				if i := con.Int64(); int64(int16(i)) != i {
   225  					goto hard
   226  				}
   227  			}
   228  
   229  			// immediate moves to memory have a 12-bit unsigned displacement
   230  			if t.Xoffset < 0 || t.Xoffset >= 4096-8 {
   231  				goto hard
   232  			}
   233  		}
   234  	}
   235  
   236  	// a float-to-int or int-to-float conversion requires the source operand in a register
   237  	if gc.Ismem(f) && ((f.Type.IsFloat() && t.Type.IsInteger()) || (f.Type.IsInteger() && t.Type.IsFloat())) {
   238  		cvt = f.Type
   239  		goto hard
   240  	}
   241  
   242  	// a float32-to-float64 or float64-to-float32 conversion requires the source operand in a register
   243  	if gc.Ismem(f) && f.Type.IsFloat() && t.Type.IsFloat() && (ft != tt) {
   244  		cvt = f.Type
   245  		goto hard
   246  	}
   247  
   248  	// value -> value copy, only one memory operand.
   249  	// figure out the instruction to use.
   250  	// break out of switch for one-instruction gins.
   251  	// goto rdst for "destination must be register".
   252  	// goto hard for "convert to cvt type first".
   253  	// otherwise handle and return.
   254  	switch uint32(ft)<<16 | uint32(tt) {
   255  	default:
   256  		gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, gc.FmtLong), gc.Tconv(t.Type, gc.FmtLong))
   257  
   258  	// integer copy and truncate
   259  	case gc.TINT8<<16 | gc.TINT8,
   260  		gc.TUINT8<<16 | gc.TINT8,
   261  		gc.TINT16<<16 | gc.TINT8,
   262  		gc.TUINT16<<16 | gc.TINT8,
   263  		gc.TINT32<<16 | gc.TINT8,
   264  		gc.TUINT32<<16 | gc.TINT8,
   265  		gc.TINT64<<16 | gc.TINT8,
   266  		gc.TUINT64<<16 | gc.TINT8:
   267  		a = s390x.AMOVB
   268  
   269  	case gc.TINT8<<16 | gc.TUINT8,
   270  		gc.TUINT8<<16 | gc.TUINT8,
   271  		gc.TINT16<<16 | gc.TUINT8,
   272  		gc.TUINT16<<16 | gc.TUINT8,
   273  		gc.TINT32<<16 | gc.TUINT8,
   274  		gc.TUINT32<<16 | gc.TUINT8,
   275  		gc.TINT64<<16 | gc.TUINT8,
   276  		gc.TUINT64<<16 | gc.TUINT8:
   277  		a = s390x.AMOVBZ
   278  
   279  	case gc.TINT16<<16 | gc.TINT16,
   280  		gc.TUINT16<<16 | gc.TINT16,
   281  		gc.TINT32<<16 | gc.TINT16,
   282  		gc.TUINT32<<16 | gc.TINT16,
   283  		gc.TINT64<<16 | gc.TINT16,
   284  		gc.TUINT64<<16 | gc.TINT16:
   285  		a = s390x.AMOVH
   286  
   287  	case gc.TINT16<<16 | gc.TUINT16,
   288  		gc.TUINT16<<16 | gc.TUINT16,
   289  		gc.TINT32<<16 | gc.TUINT16,
   290  		gc.TUINT32<<16 | gc.TUINT16,
   291  		gc.TINT64<<16 | gc.TUINT16,
   292  		gc.TUINT64<<16 | gc.TUINT16:
   293  		a = s390x.AMOVHZ
   294  
   295  	case gc.TINT32<<16 | gc.TINT32,
   296  		gc.TUINT32<<16 | gc.TINT32,
   297  		gc.TINT64<<16 | gc.TINT32,
   298  		gc.TUINT64<<16 | gc.TINT32:
   299  		a = s390x.AMOVW
   300  
   301  	case gc.TINT32<<16 | gc.TUINT32,
   302  		gc.TUINT32<<16 | gc.TUINT32,
   303  		gc.TINT64<<16 | gc.TUINT32,
   304  		gc.TUINT64<<16 | gc.TUINT32:
   305  		a = s390x.AMOVWZ
   306  
   307  	case gc.TINT64<<16 | gc.TINT64,
   308  		gc.TINT64<<16 | gc.TUINT64,
   309  		gc.TUINT64<<16 | gc.TINT64,
   310  		gc.TUINT64<<16 | gc.TUINT64:
   311  		a = s390x.AMOVD
   312  
   313  	// sign extend int8
   314  	case gc.TINT8<<16 | gc.TINT16,
   315  		gc.TINT8<<16 | gc.TUINT16,
   316  		gc.TINT8<<16 | gc.TINT32,
   317  		gc.TINT8<<16 | gc.TUINT32,
   318  		gc.TINT8<<16 | gc.TINT64,
   319  		gc.TINT8<<16 | gc.TUINT64:
   320  		a = s390x.AMOVB
   321  		goto rdst
   322  
   323  	// sign extend uint8
   324  	case gc.TUINT8<<16 | gc.TINT16,
   325  		gc.TUINT8<<16 | gc.TUINT16,
   326  		gc.TUINT8<<16 | gc.TINT32,
   327  		gc.TUINT8<<16 | gc.TUINT32,
   328  		gc.TUINT8<<16 | gc.TINT64,
   329  		gc.TUINT8<<16 | gc.TUINT64:
   330  		a = s390x.AMOVBZ
   331  		goto rdst
   332  
   333  	// sign extend int16
   334  	case gc.TINT16<<16 | gc.TINT32,
   335  		gc.TINT16<<16 | gc.TUINT32,
   336  		gc.TINT16<<16 | gc.TINT64,
   337  		gc.TINT16<<16 | gc.TUINT64:
   338  		a = s390x.AMOVH
   339  		goto rdst
   340  
   341  	// zero extend uint16
   342  	case gc.TUINT16<<16 | gc.TINT32,
   343  		gc.TUINT16<<16 | gc.TUINT32,
   344  		gc.TUINT16<<16 | gc.TINT64,
   345  		gc.TUINT16<<16 | gc.TUINT64:
   346  		a = s390x.AMOVHZ
   347  		goto rdst
   348  
   349  	// sign extend int32
   350  	case gc.TINT32<<16 | gc.TINT64,
   351  		gc.TINT32<<16 | gc.TUINT64:
   352  		a = s390x.AMOVW
   353  		goto rdst
   354  
   355  	// zero extend uint32
   356  	case gc.TUINT32<<16 | gc.TINT64,
   357  		gc.TUINT32<<16 | gc.TUINT64:
   358  		a = s390x.AMOVWZ
   359  		goto rdst
   360  
   361  	// float to integer
   362  	case gc.TFLOAT32<<16 | gc.TUINT8,
   363  		gc.TFLOAT32<<16 | gc.TUINT16:
   364  		cvt = gc.Types[gc.TUINT32]
   365  		goto hard
   366  
   367  	case gc.TFLOAT32<<16 | gc.TUINT32:
   368  		a = s390x.ACLFEBR
   369  		goto rdst
   370  
   371  	case gc.TFLOAT32<<16 | gc.TUINT64:
   372  		a = s390x.ACLGEBR
   373  		goto rdst
   374  
   375  	case gc.TFLOAT64<<16 | gc.TUINT8,
   376  		gc.TFLOAT64<<16 | gc.TUINT16:
   377  		cvt = gc.Types[gc.TUINT32]
   378  		goto hard
   379  
   380  	case gc.TFLOAT64<<16 | gc.TUINT32:
   381  		a = s390x.ACLFDBR
   382  		goto rdst
   383  
   384  	case gc.TFLOAT64<<16 | gc.TUINT64:
   385  		a = s390x.ACLGDBR
   386  		goto rdst
   387  
   388  	case gc.TFLOAT32<<16 | gc.TINT8,
   389  		gc.TFLOAT32<<16 | gc.TINT16:
   390  		cvt = gc.Types[gc.TINT32]
   391  		goto hard
   392  
   393  	case gc.TFLOAT32<<16 | gc.TINT32:
   394  		a = s390x.ACFEBRA
   395  		goto rdst
   396  
   397  	case gc.TFLOAT32<<16 | gc.TINT64:
   398  		a = s390x.ACGEBRA
   399  		goto rdst
   400  
   401  	case gc.TFLOAT64<<16 | gc.TINT8,
   402  		gc.TFLOAT64<<16 | gc.TINT16:
   403  		cvt = gc.Types[gc.TINT32]
   404  		goto hard
   405  
   406  	case gc.TFLOAT64<<16 | gc.TINT32:
   407  		a = s390x.ACFDBRA
   408  		goto rdst
   409  
   410  	case gc.TFLOAT64<<16 | gc.TINT64:
   411  		a = s390x.ACGDBRA
   412  		goto rdst
   413  
   414  	// integer to float
   415  	case gc.TUINT8<<16 | gc.TFLOAT32,
   416  		gc.TUINT16<<16 | gc.TFLOAT32:
   417  		cvt = gc.Types[gc.TUINT32]
   418  		goto hard
   419  
   420  	case gc.TUINT32<<16 | gc.TFLOAT32:
   421  		a = s390x.ACELFBR
   422  		goto rdst
   423  
   424  	case gc.TUINT64<<16 | gc.TFLOAT32:
   425  		a = s390x.ACELGBR
   426  		goto rdst
   427  
   428  	case gc.TUINT8<<16 | gc.TFLOAT64,
   429  		gc.TUINT16<<16 | gc.TFLOAT64:
   430  		cvt = gc.Types[gc.TUINT32]
   431  		goto hard
   432  
   433  	case gc.TUINT32<<16 | gc.TFLOAT64:
   434  		a = s390x.ACDLFBR
   435  		goto rdst
   436  
   437  	case gc.TUINT64<<16 | gc.TFLOAT64:
   438  		a = s390x.ACDLGBR
   439  		goto rdst
   440  
   441  	case gc.TINT8<<16 | gc.TFLOAT32,
   442  		gc.TINT16<<16 | gc.TFLOAT32:
   443  		cvt = gc.Types[gc.TINT32]
   444  		goto hard
   445  
   446  	case gc.TINT32<<16 | gc.TFLOAT32:
   447  		a = s390x.ACEFBRA
   448  		goto rdst
   449  
   450  	case gc.TINT64<<16 | gc.TFLOAT32:
   451  		a = s390x.ACEGBRA
   452  		goto rdst
   453  
   454  	case gc.TINT8<<16 | gc.TFLOAT64,
   455  		gc.TINT16<<16 | gc.TFLOAT64:
   456  		cvt = gc.Types[gc.TINT32]
   457  		goto hard
   458  
   459  	case gc.TINT32<<16 | gc.TFLOAT64:
   460  		a = s390x.ACDFBRA
   461  		goto rdst
   462  
   463  	case gc.TINT64<<16 | gc.TFLOAT64:
   464  		a = s390x.ACDGBRA
   465  		goto rdst
   466  
   467  	// float to float
   468  	case gc.TFLOAT32<<16 | gc.TFLOAT32:
   469  		a = s390x.AFMOVS
   470  
   471  	case gc.TFLOAT64<<16 | gc.TFLOAT64:
   472  		a = s390x.AFMOVD
   473  
   474  	case gc.TFLOAT32<<16 | gc.TFLOAT64:
   475  		a = s390x.ALDEBR
   476  		goto rdst
   477  
   478  	case gc.TFLOAT64<<16 | gc.TFLOAT32:
   479  		a = s390x.ALEDBR
   480  		goto rdst
   481  	}
   482  
   483  	gins(a, f, t)
   484  	return
   485  
   486  	// requires register destination
   487  rdst:
   488  	if t != nil && t.Op == gc.OREGISTER {
   489  		gins(a, f, t)
   490  		return
   491  	} else {
   492  		var r1 gc.Node
   493  		gc.Regalloc(&r1, t.Type, t)
   494  
   495  		gins(a, f, &r1)
   496  		gmove(&r1, t)
   497  		gc.Regfree(&r1)
   498  		return
   499  	}
   500  
   501  	// requires register intermediate
   502  hard:
   503  	var r1 gc.Node
   504  	gc.Regalloc(&r1, cvt, t)
   505  
   506  	gmove(f, &r1)
   507  	gmove(&r1, t)
   508  	gc.Regfree(&r1)
   509  	return
   510  }
   511  
   512  func intLiteral(n *gc.Node) (x int64, ok bool) {
   513  	switch {
   514  	case n == nil:
   515  		return
   516  	case gc.Isconst(n, gc.CTINT):
   517  		return n.Int64(), true
   518  	case gc.Isconst(n, gc.CTBOOL):
   519  		return int64(obj.Bool2int(n.Bool())), true
   520  	}
   521  	return
   522  }
   523  
   524  // gins is called by the front end.
   525  // It synthesizes some multiple-instruction sequences
   526  // so the front end can stay simpler.
   527  func gins(as obj.As, f, t *gc.Node) *obj.Prog {
   528  	if t != nil {
   529  		if as >= obj.A_ARCHSPECIFIC {
   530  			if x, ok := intLiteral(f); ok {
   531  				ginscon(as, x, t)
   532  				return nil // caller must not use
   533  			}
   534  		}
   535  		if as == s390x.ACMP || as == s390x.ACMPU {
   536  			if x, ok := intLiteral(t); ok {
   537  				ginscon2(as, f, x)
   538  				return nil // caller must not use
   539  			}
   540  		}
   541  	}
   542  	return rawgins(as, f, t)
   543  }
   544  
   545  // generate one instruction:
   546  //	as f, t
   547  func rawgins(as obj.As, f *gc.Node, t *gc.Node) *obj.Prog {
   548  	// self move check
   549  	// TODO(mundaym): use sized math and extend to MOVB, MOVWZ etc.
   550  	switch as {
   551  	case s390x.AMOVD, s390x.AFMOVS, s390x.AFMOVD:
   552  		if f != nil && t != nil &&
   553  			f.Op == gc.OREGISTER && t.Op == gc.OREGISTER &&
   554  			f.Reg == t.Reg {
   555  			return nil
   556  		}
   557  	}
   558  
   559  	p := gc.Prog(as)
   560  	gc.Naddr(&p.From, f)
   561  	gc.Naddr(&p.To, t)
   562  
   563  	switch as {
   564  	// Bad things the front end has done to us. Crash to find call stack.
   565  	case s390x.ACMP, s390x.ACMPU:
   566  		if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
   567  			gc.Debug['h'] = 1
   568  			gc.Fatalf("bad inst: %v", p)
   569  		}
   570  	}
   571  
   572  	if gc.Debug['g'] != 0 {
   573  		fmt.Printf("%v\n", p)
   574  	}
   575  
   576  	w := int32(0)
   577  	switch as {
   578  	case s390x.AMOVB, s390x.AMOVBZ:
   579  		w = 1
   580  
   581  	case s390x.AMOVH, s390x.AMOVHZ:
   582  		w = 2
   583  
   584  	case s390x.AMOVW, s390x.AMOVWZ:
   585  		w = 4
   586  
   587  	case s390x.AMOVD:
   588  		if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR {
   589  			break
   590  		}
   591  		w = 8
   592  	}
   593  
   594  	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) {
   595  		gc.Dump("f", f)
   596  		gc.Dump("t", t)
   597  		gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
   598  	}
   599  
   600  	return p
   601  }
   602  
   603  // optoas returns the Axxx equivalent of Oxxx for type t
   604  func optoas(op gc.Op, t *gc.Type) obj.As {
   605  	if t == nil {
   606  		gc.Fatalf("optoas: t is nil")
   607  	}
   608  
   609  	// avoid constant conversions in switches below
   610  	const (
   611  		OMINUS_ = uint32(gc.OMINUS) << 16
   612  		OLSH_   = uint32(gc.OLSH) << 16
   613  		ORSH_   = uint32(gc.ORSH) << 16
   614  		OADD_   = uint32(gc.OADD) << 16
   615  		OSUB_   = uint32(gc.OSUB) << 16
   616  		OMUL_   = uint32(gc.OMUL) << 16
   617  		ODIV_   = uint32(gc.ODIV) << 16
   618  		OOR_    = uint32(gc.OOR) << 16
   619  		OAND_   = uint32(gc.OAND) << 16
   620  		OXOR_   = uint32(gc.OXOR) << 16
   621  		OEQ_    = uint32(gc.OEQ) << 16
   622  		ONE_    = uint32(gc.ONE) << 16
   623  		OLT_    = uint32(gc.OLT) << 16
   624  		OLE_    = uint32(gc.OLE) << 16
   625  		OGE_    = uint32(gc.OGE) << 16
   626  		OGT_    = uint32(gc.OGT) << 16
   627  		OCMP_   = uint32(gc.OCMP) << 16
   628  		OAS_    = uint32(gc.OAS) << 16
   629  		OHMUL_  = uint32(gc.OHMUL) << 16
   630  		OSQRT_  = uint32(gc.OSQRT) << 16
   631  		OLROT_  = uint32(gc.OLROT) << 16
   632  	)
   633  
   634  	a := obj.AXXX
   635  	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
   636  	default:
   637  		gc.Fatalf("optoas: no entry for op=%v type=%v", op, t)
   638  
   639  	case OEQ_ | gc.TBOOL,
   640  		OEQ_ | gc.TINT8,
   641  		OEQ_ | gc.TUINT8,
   642  		OEQ_ | gc.TINT16,
   643  		OEQ_ | gc.TUINT16,
   644  		OEQ_ | gc.TINT32,
   645  		OEQ_ | gc.TUINT32,
   646  		OEQ_ | gc.TINT64,
   647  		OEQ_ | gc.TUINT64,
   648  		OEQ_ | gc.TPTR32,
   649  		OEQ_ | gc.TPTR64,
   650  		OEQ_ | gc.TFLOAT32,
   651  		OEQ_ | gc.TFLOAT64:
   652  		a = s390x.ABEQ
   653  
   654  	case ONE_ | gc.TBOOL,
   655  		ONE_ | gc.TINT8,
   656  		ONE_ | gc.TUINT8,
   657  		ONE_ | gc.TINT16,
   658  		ONE_ | gc.TUINT16,
   659  		ONE_ | gc.TINT32,
   660  		ONE_ | gc.TUINT32,
   661  		ONE_ | gc.TINT64,
   662  		ONE_ | gc.TUINT64,
   663  		ONE_ | gc.TPTR32,
   664  		ONE_ | gc.TPTR64,
   665  		ONE_ | gc.TFLOAT32,
   666  		ONE_ | gc.TFLOAT64:
   667  		a = s390x.ABNE
   668  
   669  	case OLT_ | gc.TINT8, // ACMP
   670  		OLT_ | gc.TINT16,
   671  		OLT_ | gc.TINT32,
   672  		OLT_ | gc.TINT64,
   673  		OLT_ | gc.TUINT8,
   674  		// ACMPU
   675  		OLT_ | gc.TUINT16,
   676  		OLT_ | gc.TUINT32,
   677  		OLT_ | gc.TUINT64,
   678  		OLT_ | gc.TFLOAT32,
   679  		// AFCMPU
   680  		OLT_ | gc.TFLOAT64:
   681  		a = s390x.ABLT
   682  
   683  	case OLE_ | gc.TINT8, // ACMP
   684  		OLE_ | gc.TINT16,
   685  		OLE_ | gc.TINT32,
   686  		OLE_ | gc.TINT64,
   687  		OLE_ | gc.TUINT8,
   688  		// ACMPU
   689  		OLE_ | gc.TUINT16,
   690  		OLE_ | gc.TUINT32,
   691  		OLE_ | gc.TUINT64,
   692  		OLE_ | gc.TFLOAT32,
   693  		OLE_ | gc.TFLOAT64:
   694  		a = s390x.ABLE
   695  
   696  	case OGT_ | gc.TINT8,
   697  		OGT_ | gc.TINT16,
   698  		OGT_ | gc.TINT32,
   699  		OGT_ | gc.TINT64,
   700  		OGT_ | gc.TUINT8,
   701  		OGT_ | gc.TUINT16,
   702  		OGT_ | gc.TUINT32,
   703  		OGT_ | gc.TUINT64,
   704  		OGT_ | gc.TFLOAT32,
   705  		OGT_ | gc.TFLOAT64:
   706  		a = s390x.ABGT
   707  
   708  	case OGE_ | gc.TINT8,
   709  		OGE_ | gc.TINT16,
   710  		OGE_ | gc.TINT32,
   711  		OGE_ | gc.TINT64,
   712  		OGE_ | gc.TUINT8,
   713  		OGE_ | gc.TUINT16,
   714  		OGE_ | gc.TUINT32,
   715  		OGE_ | gc.TUINT64,
   716  		OGE_ | gc.TFLOAT32,
   717  		OGE_ | gc.TFLOAT64:
   718  		a = s390x.ABGE
   719  
   720  	case OCMP_ | gc.TBOOL,
   721  		OCMP_ | gc.TINT8,
   722  		OCMP_ | gc.TINT16,
   723  		OCMP_ | gc.TINT32,
   724  		OCMP_ | gc.TPTR32,
   725  		OCMP_ | gc.TINT64:
   726  		a = s390x.ACMP
   727  
   728  	case OCMP_ | gc.TUINT8,
   729  		OCMP_ | gc.TUINT16,
   730  		OCMP_ | gc.TUINT32,
   731  		OCMP_ | gc.TUINT64,
   732  		OCMP_ | gc.TPTR64:
   733  		a = s390x.ACMPU
   734  
   735  	case OCMP_ | gc.TFLOAT32:
   736  		a = s390x.ACEBR
   737  
   738  	case OCMP_ | gc.TFLOAT64:
   739  		a = s390x.AFCMPU
   740  
   741  	case OAS_ | gc.TBOOL,
   742  		OAS_ | gc.TINT8:
   743  		a = s390x.AMOVB
   744  
   745  	case OAS_ | gc.TUINT8:
   746  		a = s390x.AMOVBZ
   747  
   748  	case OAS_ | gc.TINT16:
   749  		a = s390x.AMOVH
   750  
   751  	case OAS_ | gc.TUINT16:
   752  		a = s390x.AMOVHZ
   753  
   754  	case OAS_ | gc.TINT32:
   755  		a = s390x.AMOVW
   756  
   757  	case OAS_ | gc.TUINT32,
   758  		OAS_ | gc.TPTR32:
   759  		a = s390x.AMOVWZ
   760  
   761  	case OAS_ | gc.TINT64,
   762  		OAS_ | gc.TUINT64,
   763  		OAS_ | gc.TPTR64:
   764  		a = s390x.AMOVD
   765  
   766  	case OAS_ | gc.TFLOAT32:
   767  		a = s390x.AFMOVS
   768  
   769  	case OAS_ | gc.TFLOAT64:
   770  		a = s390x.AFMOVD
   771  
   772  	case OADD_ | gc.TINT8,
   773  		OADD_ | gc.TUINT8,
   774  		OADD_ | gc.TINT16,
   775  		OADD_ | gc.TUINT16,
   776  		OADD_ | gc.TINT32,
   777  		OADD_ | gc.TUINT32,
   778  		OADD_ | gc.TPTR32,
   779  		OADD_ | gc.TINT64,
   780  		OADD_ | gc.TUINT64,
   781  		OADD_ | gc.TPTR64:
   782  		a = s390x.AADD
   783  
   784  	case OADD_ | gc.TFLOAT32:
   785  		a = s390x.AFADDS
   786  
   787  	case OADD_ | gc.TFLOAT64:
   788  		a = s390x.AFADD
   789  
   790  	case OSUB_ | gc.TINT8,
   791  		OSUB_ | gc.TUINT8,
   792  		OSUB_ | gc.TINT16,
   793  		OSUB_ | gc.TUINT16,
   794  		OSUB_ | gc.TINT32,
   795  		OSUB_ | gc.TUINT32,
   796  		OSUB_ | gc.TPTR32,
   797  		OSUB_ | gc.TINT64,
   798  		OSUB_ | gc.TUINT64,
   799  		OSUB_ | gc.TPTR64:
   800  		a = s390x.ASUB
   801  
   802  	case OSUB_ | gc.TFLOAT32:
   803  		a = s390x.AFSUBS
   804  
   805  	case OSUB_ | gc.TFLOAT64:
   806  		a = s390x.AFSUB
   807  
   808  	case OMINUS_ | gc.TINT8,
   809  		OMINUS_ | gc.TUINT8,
   810  		OMINUS_ | gc.TINT16,
   811  		OMINUS_ | gc.TUINT16,
   812  		OMINUS_ | gc.TINT32,
   813  		OMINUS_ | gc.TUINT32,
   814  		OMINUS_ | gc.TPTR32,
   815  		OMINUS_ | gc.TINT64,
   816  		OMINUS_ | gc.TUINT64,
   817  		OMINUS_ | gc.TPTR64:
   818  		a = s390x.ANEG
   819  
   820  	case OAND_ | gc.TINT8,
   821  		OAND_ | gc.TUINT8,
   822  		OAND_ | gc.TINT16,
   823  		OAND_ | gc.TUINT16,
   824  		OAND_ | gc.TINT32,
   825  		OAND_ | gc.TUINT32,
   826  		OAND_ | gc.TPTR32,
   827  		OAND_ | gc.TINT64,
   828  		OAND_ | gc.TUINT64,
   829  		OAND_ | gc.TPTR64:
   830  		a = s390x.AAND
   831  
   832  	case OOR_ | gc.TINT8,
   833  		OOR_ | gc.TUINT8,
   834  		OOR_ | gc.TINT16,
   835  		OOR_ | gc.TUINT16,
   836  		OOR_ | gc.TINT32,
   837  		OOR_ | gc.TUINT32,
   838  		OOR_ | gc.TPTR32,
   839  		OOR_ | gc.TINT64,
   840  		OOR_ | gc.TUINT64,
   841  		OOR_ | gc.TPTR64:
   842  		a = s390x.AOR
   843  
   844  	case OXOR_ | gc.TINT8,
   845  		OXOR_ | gc.TUINT8,
   846  		OXOR_ | gc.TINT16,
   847  		OXOR_ | gc.TUINT16,
   848  		OXOR_ | gc.TINT32,
   849  		OXOR_ | gc.TUINT32,
   850  		OXOR_ | gc.TPTR32,
   851  		OXOR_ | gc.TINT64,
   852  		OXOR_ | gc.TUINT64,
   853  		OXOR_ | gc.TPTR64:
   854  		a = s390x.AXOR
   855  
   856  	case OLSH_ | gc.TINT8,
   857  		OLSH_ | gc.TUINT8,
   858  		OLSH_ | gc.TINT16,
   859  		OLSH_ | gc.TUINT16,
   860  		OLSH_ | gc.TINT32,
   861  		OLSH_ | gc.TUINT32,
   862  		OLSH_ | gc.TPTR32,
   863  		OLSH_ | gc.TINT64,
   864  		OLSH_ | gc.TUINT64,
   865  		OLSH_ | gc.TPTR64:
   866  		a = s390x.ASLD
   867  
   868  	case ORSH_ | gc.TUINT8,
   869  		ORSH_ | gc.TUINT16,
   870  		ORSH_ | gc.TUINT32,
   871  		ORSH_ | gc.TPTR32,
   872  		ORSH_ | gc.TUINT64,
   873  		ORSH_ | gc.TPTR64:
   874  		a = s390x.ASRD
   875  
   876  	case ORSH_ | gc.TINT8,
   877  		ORSH_ | gc.TINT16,
   878  		ORSH_ | gc.TINT32,
   879  		ORSH_ | gc.TINT64:
   880  		a = s390x.ASRAD
   881  
   882  	case OHMUL_ | gc.TINT64:
   883  		a = s390x.AMULHD
   884  
   885  	case OHMUL_ | gc.TUINT64,
   886  		OHMUL_ | gc.TPTR64:
   887  		a = s390x.AMULHDU
   888  
   889  	case OMUL_ | gc.TINT8,
   890  		OMUL_ | gc.TINT16,
   891  		OMUL_ | gc.TINT32,
   892  		OMUL_ | gc.TINT64:
   893  		a = s390x.AMULLD
   894  
   895  	case OMUL_ | gc.TUINT8,
   896  		OMUL_ | gc.TUINT16,
   897  		OMUL_ | gc.TUINT32,
   898  		OMUL_ | gc.TPTR32,
   899  		// don't use word multiply, the high 32-bit are undefined.
   900  		OMUL_ | gc.TUINT64,
   901  		OMUL_ | gc.TPTR64:
   902  		// for 64-bit multiplies, signedness doesn't matter.
   903  		a = s390x.AMULLD
   904  
   905  	case OMUL_ | gc.TFLOAT32:
   906  		a = s390x.AFMULS
   907  
   908  	case OMUL_ | gc.TFLOAT64:
   909  		a = s390x.AFMUL
   910  
   911  	case ODIV_ | gc.TINT8,
   912  		ODIV_ | gc.TINT16,
   913  		ODIV_ | gc.TINT32,
   914  		ODIV_ | gc.TINT64:
   915  		a = s390x.ADIVD
   916  
   917  	case ODIV_ | gc.TUINT8,
   918  		ODIV_ | gc.TUINT16,
   919  		ODIV_ | gc.TUINT32,
   920  		ODIV_ | gc.TPTR32,
   921  		ODIV_ | gc.TUINT64,
   922  		ODIV_ | gc.TPTR64:
   923  		a = s390x.ADIVDU
   924  
   925  	case ODIV_ | gc.TFLOAT32:
   926  		a = s390x.AFDIVS
   927  
   928  	case ODIV_ | gc.TFLOAT64:
   929  		a = s390x.AFDIV
   930  
   931  	case OSQRT_ | gc.TFLOAT64:
   932  		a = s390x.AFSQRT
   933  
   934  	case OLROT_ | gc.TUINT32,
   935  		OLROT_ | gc.TPTR32,
   936  		OLROT_ | gc.TINT32:
   937  		a = s390x.ARLL
   938  
   939  	case OLROT_ | gc.TUINT64,
   940  		OLROT_ | gc.TPTR64,
   941  		OLROT_ | gc.TINT64:
   942  		a = s390x.ARLLG
   943  	}
   944  
   945  	return a
   946  }
   947  
   948  const (
   949  	ODynam   = 1 << 0
   950  	OAddable = 1 << 1
   951  )
   952  
   953  var clean [20]gc.Node
   954  
   955  var cleani int = 0
   956  
   957  func sudoclean() {
   958  	if clean[cleani-1].Op != gc.OEMPTY {
   959  		gc.Regfree(&clean[cleani-1])
   960  	}
   961  	if clean[cleani-2].Op != gc.OEMPTY {
   962  		gc.Regfree(&clean[cleani-2])
   963  	}
   964  	cleani -= 2
   965  }
   966  
   967  /*
   968   * generate code to compute address of n,
   969   * a reference to a (perhaps nested) field inside
   970   * an array or struct.
   971   * return 0 on failure, 1 on success.
   972   * on success, leaves usable address in a.
   973   *
   974   * caller is responsible for calling sudoclean
   975   * after successful sudoaddable,
   976   * to release the register used for a.
   977   */
   978  func sudoaddable(as obj.As, n *gc.Node, a *obj.Addr) bool {
   979  	if n.Type == nil {
   980  		return false
   981  	}
   982  
   983  	*a = obj.Addr{}
   984  
   985  	switch n.Op {
   986  	case gc.OLITERAL:
   987  		if !gc.Isconst(n, gc.CTINT) {
   988  			return false
   989  		}
   990  		v := n.Int64()
   991  		switch as {
   992  		default:
   993  			return false
   994  
   995  		// operations that can cope with a 32-bit immediate
   996  		// TODO(mundaym): logical operations can work on high bits
   997  		case s390x.AADD,
   998  			s390x.AADDC,
   999  			s390x.ASUB,
  1000  			s390x.AMULLW,
  1001  			s390x.AAND,
  1002  			s390x.AOR,
  1003  			s390x.AXOR,
  1004  			s390x.ASLD,
  1005  			s390x.ASLW,
  1006  			s390x.ASRAW,
  1007  			s390x.ASRAD,
  1008  			s390x.ASRW,
  1009  			s390x.ASRD,
  1010  			s390x.AMOVB,
  1011  			s390x.AMOVBZ,
  1012  			s390x.AMOVH,
  1013  			s390x.AMOVHZ,
  1014  			s390x.AMOVW,
  1015  			s390x.AMOVWZ,
  1016  			s390x.AMOVD:
  1017  			if int64(int32(v)) != v {
  1018  				return false
  1019  			}
  1020  
  1021  		// for comparisons avoid immediates unless they can
  1022  		// fit into a int8/uint8
  1023  		// this favours combined compare and branch instructions
  1024  		case s390x.ACMP:
  1025  			if int64(int8(v)) != v {
  1026  				return false
  1027  			}
  1028  		case s390x.ACMPU:
  1029  			if int64(uint8(v)) != v {
  1030  				return false
  1031  			}
  1032  		}
  1033  
  1034  		cleani += 2
  1035  		reg := &clean[cleani-1]
  1036  		reg1 := &clean[cleani-2]
  1037  		reg.Op = gc.OEMPTY
  1038  		reg1.Op = gc.OEMPTY
  1039  		gc.Naddr(a, n)
  1040  		return true
  1041  
  1042  	case gc.ODOT,
  1043  		gc.ODOTPTR:
  1044  		cleani += 2
  1045  		reg := &clean[cleani-1]
  1046  		reg1 := &clean[cleani-2]
  1047  		reg.Op = gc.OEMPTY
  1048  		reg1.Op = gc.OEMPTY
  1049  		var nn *gc.Node
  1050  		var oary [10]int64
  1051  		o := gc.Dotoffset(n, oary[:], &nn)
  1052  		if nn == nil {
  1053  			sudoclean()
  1054  			return false
  1055  		}
  1056  
  1057  		if nn.Addable && o == 1 && oary[0] >= 0 {
  1058  			// directly addressable set of DOTs
  1059  			n1 := *nn
  1060  
  1061  			n1.Type = n.Type
  1062  			n1.Xoffset += oary[0]
  1063  			// check that the offset fits into a 12-bit displacement
  1064  			if n1.Xoffset < 0 || n1.Xoffset >= (1<<12)-8 {
  1065  				sudoclean()
  1066  				return false
  1067  			}
  1068  			gc.Naddr(a, &n1)
  1069  			return true
  1070  		}
  1071  
  1072  		gc.Regalloc(reg, gc.Types[gc.Tptr], nil)
  1073  		n1 := *reg
  1074  		n1.Op = gc.OINDREG
  1075  		if oary[0] >= 0 {
  1076  			gc.Agen(nn, reg)
  1077  			n1.Xoffset = oary[0]
  1078  		} else {
  1079  			gc.Cgen(nn, reg)
  1080  			gc.Cgen_checknil(reg)
  1081  			n1.Xoffset = -(oary[0] + 1)
  1082  		}
  1083  
  1084  		for i := 1; i < o; i++ {
  1085  			if oary[i] >= 0 {
  1086  				gc.Fatalf("can't happen")
  1087  			}
  1088  			gins(s390x.AMOVD, &n1, reg)
  1089  			gc.Cgen_checknil(reg)
  1090  			n1.Xoffset = -(oary[i] + 1)
  1091  		}
  1092  
  1093  		a.Type = obj.TYPE_NONE
  1094  		a.Index = 0
  1095  		// check that the offset fits into a 12-bit displacement
  1096  		if n1.Xoffset < 0 || n1.Xoffset >= (1<<12)-8 {
  1097  			tmp := n1
  1098  			tmp.Op = gc.OREGISTER
  1099  			tmp.Type = gc.Types[gc.Tptr]
  1100  			tmp.Xoffset = 0
  1101  			gc.Cgen_checknil(&tmp)
  1102  			ginscon(s390x.AADD, n1.Xoffset, &tmp)
  1103  			n1.Xoffset = 0
  1104  		}
  1105  		gc.Naddr(a, &n1)
  1106  		return true
  1107  	}
  1108  
  1109  	return false
  1110  }