github.com/euank/go@v0.0.0-20160829210321-495514729181/src/cmd/compile/internal/ppc64/gsubr.go (about)

     1  // Derived from Inferno utils/6c/txt.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/default/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 ppc64
    32  
    33  import (
    34  	"cmd/compile/internal/big"
    35  	"cmd/compile/internal/gc"
    36  	"cmd/internal/obj"
    37  	"cmd/internal/obj/ppc64"
    38  	"fmt"
    39  )
    40  
    41  var resvd = []int{
    42  	ppc64.REGZERO,
    43  	ppc64.REGSP, // reserved for SP
    44  	// We need to preserve the C ABI TLS pointer because sigtramp
    45  	// may happen during C code and needs to access the g. C
    46  	// clobbers REGG, so if Go were to clobber REGTLS, sigtramp
    47  	// won't know which convention to use. By preserving REGTLS,
    48  	// we can just retrieve g from TLS when we aren't sure.
    49  	ppc64.REGTLS,
    50  
    51  	// TODO(austin): Consolidate REGTLS and REGG?
    52  	ppc64.REGG,
    53  	ppc64.REGTMP, // REGTMP
    54  	ppc64.FREGCVI,
    55  	ppc64.FREGZERO,
    56  	ppc64.FREGHALF,
    57  	ppc64.FREGONE,
    58  	ppc64.FREGTWO,
    59  }
    60  
    61  /*
    62   * generate
    63   *	as $c, n
    64   */
    65  func ginscon(as obj.As, c int64, n2 *gc.Node) {
    66  	var n1 gc.Node
    67  
    68  	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
    69  
    70  	if as != ppc64.AMOVD && (c < -ppc64.BIG || c > ppc64.BIG) || n2.Op != gc.OREGISTER || as == ppc64.AMULLD {
    71  		// cannot have more than 16-bit of immediate in ADD, etc.
    72  		// instead, MOV into register first.
    73  		var ntmp gc.Node
    74  		gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
    75  
    76  		rawgins(ppc64.AMOVD, &n1, &ntmp)
    77  		rawgins(as, &ntmp, n2)
    78  		gc.Regfree(&ntmp)
    79  		return
    80  	}
    81  
    82  	rawgins(as, &n1, n2)
    83  }
    84  
    85  /*
    86   * generate
    87   *	as n, $c (CMP/CMPU)
    88   */
    89  func ginscon2(as obj.As, n2 *gc.Node, c int64) {
    90  	var n1 gc.Node
    91  
    92  	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
    93  
    94  	switch as {
    95  	default:
    96  		gc.Fatalf("ginscon2")
    97  
    98  	case ppc64.ACMP:
    99  		if -ppc64.BIG <= c && c <= ppc64.BIG {
   100  			rawgins(as, n2, &n1)
   101  			return
   102  		}
   103  
   104  	case ppc64.ACMPU:
   105  		if 0 <= c && c <= 2*ppc64.BIG {
   106  			rawgins(as, n2, &n1)
   107  			return
   108  		}
   109  	}
   110  
   111  	// MOV n1 into register first
   112  	var ntmp gc.Node
   113  	gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
   114  
   115  	rawgins(ppc64.AMOVD, &n1, &ntmp)
   116  	rawgins(as, n2, &ntmp)
   117  	gc.Regfree(&ntmp)
   118  }
   119  
   120  func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
   121  	if t.IsInteger() && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
   122  		// Reverse comparison to place constant last.
   123  		op = gc.Brrev(op)
   124  		n1, n2 = n2, n1
   125  	}
   126  
   127  	var r1, r2, g1, g2 gc.Node
   128  	gc.Regalloc(&r1, t, n1)
   129  	gc.Regalloc(&g1, n1.Type, &r1)
   130  	gc.Cgen(n1, &g1)
   131  	gmove(&g1, &r1)
   132  	if t.IsInteger() && gc.Isconst(n2, gc.CTINT) {
   133  		ginscon2(optoas(gc.OCMP, t), &r1, n2.Int64())
   134  	} else {
   135  		gc.Regalloc(&r2, t, n2)
   136  		gc.Regalloc(&g2, n1.Type, &r2)
   137  		gc.Cgen(n2, &g2)
   138  		gmove(&g2, &r2)
   139  		rawgins(optoas(gc.OCMP, t), &r1, &r2)
   140  		gc.Regfree(&g2)
   141  		gc.Regfree(&r2)
   142  	}
   143  	gc.Regfree(&g1)
   144  	gc.Regfree(&r1)
   145  	return gc.Gbranch(optoas(op, t), nil, likely)
   146  }
   147  
   148  // set up nodes representing 2^63
   149  var (
   150  	bigi         gc.Node
   151  	bigf         gc.Node
   152  	bignodes_did bool
   153  )
   154  
   155  func bignodes() {
   156  	if bignodes_did {
   157  		return
   158  	}
   159  	bignodes_did = true
   160  
   161  	var i big.Int
   162  	i.SetInt64(1)
   163  	i.Lsh(&i, 63)
   164  
   165  	gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
   166  	bigi.SetBigInt(&i)
   167  
   168  	bigi.Convconst(&bigf, gc.Types[gc.TFLOAT64])
   169  }
   170  
   171  /*
   172   * generate move:
   173   *	t = f
   174   * hard part is conversions.
   175   */
   176  func gmove(f *gc.Node, t *gc.Node) {
   177  	if gc.Debug['M'] != 0 {
   178  		fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, gc.FmtLong), gc.Nconv(t, gc.FmtLong))
   179  	}
   180  
   181  	ft := int(gc.Simsimtype(f.Type))
   182  	tt := int(gc.Simsimtype(t.Type))
   183  	cvt := t.Type
   184  
   185  	if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
   186  		gc.Complexmove(f, t)
   187  		return
   188  	}
   189  
   190  	// cannot have two memory operands
   191  	var r2 gc.Node
   192  	var r1 gc.Node
   193  	var a obj.As
   194  	if gc.Ismem(f) && gc.Ismem(t) {
   195  		goto hard
   196  	}
   197  
   198  	// convert constant to desired type
   199  	if f.Op == gc.OLITERAL {
   200  		var con gc.Node
   201  		switch tt {
   202  		default:
   203  			f.Convconst(&con, t.Type)
   204  
   205  		case gc.TINT32,
   206  			gc.TINT16,
   207  			gc.TINT8:
   208  			var con gc.Node
   209  			f.Convconst(&con, gc.Types[gc.TINT64])
   210  			var r1 gc.Node
   211  			gc.Regalloc(&r1, con.Type, t)
   212  			gins(ppc64.AMOVD, &con, &r1)
   213  			gmove(&r1, t)
   214  			gc.Regfree(&r1)
   215  			return
   216  
   217  		case gc.TUINT32,
   218  			gc.TUINT16,
   219  			gc.TUINT8:
   220  			var con gc.Node
   221  			f.Convconst(&con, gc.Types[gc.TUINT64])
   222  			var r1 gc.Node
   223  			gc.Regalloc(&r1, con.Type, t)
   224  			gins(ppc64.AMOVD, &con, &r1)
   225  			gmove(&r1, t)
   226  			gc.Regfree(&r1)
   227  			return
   228  		}
   229  
   230  		f = &con
   231  		ft = tt // so big switch will choose a simple mov
   232  
   233  		// constants can't move directly to memory.
   234  		if gc.Ismem(t) {
   235  			goto hard
   236  		}
   237  	}
   238  
   239  	// float constants come from memory.
   240  	//if(isfloat[tt])
   241  	//	goto hard;
   242  
   243  	// 64-bit immediates are also from memory.
   244  	//if(isint[tt])
   245  	//	goto hard;
   246  	//// 64-bit immediates are really 32-bit sign-extended
   247  	//// unless moving into a register.
   248  	//if(isint[tt]) {
   249  	//	if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
   250  	//		goto hard;
   251  	//	if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
   252  	//		goto hard;
   253  	//}
   254  
   255  	// value -> value copy, only one memory operand.
   256  	// figure out the instruction to use.
   257  	// break out of switch for one-instruction gins.
   258  	// goto rdst for "destination must be register".
   259  	// goto hard for "convert to cvt type first".
   260  	// otherwise handle and return.
   261  
   262  	switch uint32(ft)<<16 | uint32(tt) {
   263  	default:
   264  		gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, gc.FmtLong), gc.Tconv(t.Type, gc.FmtLong))
   265  
   266  		/*
   267  		 * integer copy and truncate
   268  		 */
   269  	case gc.TINT8<<16 | gc.TINT8, // same size
   270  		gc.TUINT8<<16 | gc.TINT8,
   271  		gc.TINT16<<16 | gc.TINT8,
   272  		// truncate
   273  		gc.TUINT16<<16 | gc.TINT8,
   274  		gc.TINT32<<16 | gc.TINT8,
   275  		gc.TUINT32<<16 | gc.TINT8,
   276  		gc.TINT64<<16 | gc.TINT8,
   277  		gc.TUINT64<<16 | gc.TINT8:
   278  		a = ppc64.AMOVB
   279  
   280  	case gc.TINT8<<16 | gc.TUINT8, // same size
   281  		gc.TUINT8<<16 | gc.TUINT8,
   282  		gc.TINT16<<16 | gc.TUINT8,
   283  		// truncate
   284  		gc.TUINT16<<16 | gc.TUINT8,
   285  		gc.TINT32<<16 | gc.TUINT8,
   286  		gc.TUINT32<<16 | gc.TUINT8,
   287  		gc.TINT64<<16 | gc.TUINT8,
   288  		gc.TUINT64<<16 | gc.TUINT8:
   289  		a = ppc64.AMOVBZ
   290  
   291  	case gc.TINT16<<16 | gc.TINT16, // same size
   292  		gc.TUINT16<<16 | gc.TINT16,
   293  		gc.TINT32<<16 | gc.TINT16,
   294  		// truncate
   295  		gc.TUINT32<<16 | gc.TINT16,
   296  		gc.TINT64<<16 | gc.TINT16,
   297  		gc.TUINT64<<16 | gc.TINT16:
   298  		a = ppc64.AMOVH
   299  
   300  	case gc.TINT16<<16 | gc.TUINT16, // same size
   301  		gc.TUINT16<<16 | gc.TUINT16,
   302  		gc.TINT32<<16 | gc.TUINT16,
   303  		// truncate
   304  		gc.TUINT32<<16 | gc.TUINT16,
   305  		gc.TINT64<<16 | gc.TUINT16,
   306  		gc.TUINT64<<16 | gc.TUINT16:
   307  		a = ppc64.AMOVHZ
   308  
   309  	case gc.TINT32<<16 | gc.TINT32, // same size
   310  		gc.TUINT32<<16 | gc.TINT32,
   311  		gc.TINT64<<16 | gc.TINT32,
   312  		// truncate
   313  		gc.TUINT64<<16 | gc.TINT32:
   314  		a = ppc64.AMOVW
   315  
   316  	case gc.TINT32<<16 | gc.TUINT32, // same size
   317  		gc.TUINT32<<16 | gc.TUINT32,
   318  		gc.TINT64<<16 | gc.TUINT32,
   319  		gc.TUINT64<<16 | gc.TUINT32:
   320  		a = ppc64.AMOVWZ
   321  
   322  	case gc.TINT64<<16 | gc.TINT64, // same size
   323  		gc.TINT64<<16 | gc.TUINT64,
   324  		gc.TUINT64<<16 | gc.TINT64,
   325  		gc.TUINT64<<16 | gc.TUINT64:
   326  		a = ppc64.AMOVD
   327  
   328  		/*
   329  		 * integer up-conversions
   330  		 */
   331  	case gc.TINT8<<16 | gc.TINT16, // sign extend int8
   332  		gc.TINT8<<16 | gc.TUINT16,
   333  		gc.TINT8<<16 | gc.TINT32,
   334  		gc.TINT8<<16 | gc.TUINT32,
   335  		gc.TINT8<<16 | gc.TINT64,
   336  		gc.TINT8<<16 | gc.TUINT64:
   337  		a = ppc64.AMOVB
   338  
   339  		goto rdst
   340  
   341  	case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8
   342  		gc.TUINT8<<16 | gc.TUINT16,
   343  		gc.TUINT8<<16 | gc.TINT32,
   344  		gc.TUINT8<<16 | gc.TUINT32,
   345  		gc.TUINT8<<16 | gc.TINT64,
   346  		gc.TUINT8<<16 | gc.TUINT64:
   347  		a = ppc64.AMOVBZ
   348  
   349  		goto rdst
   350  
   351  	case gc.TINT16<<16 | gc.TINT32, // sign extend int16
   352  		gc.TINT16<<16 | gc.TUINT32,
   353  		gc.TINT16<<16 | gc.TINT64,
   354  		gc.TINT16<<16 | gc.TUINT64:
   355  		a = ppc64.AMOVH
   356  
   357  		goto rdst
   358  
   359  	case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16
   360  		gc.TUINT16<<16 | gc.TUINT32,
   361  		gc.TUINT16<<16 | gc.TINT64,
   362  		gc.TUINT16<<16 | gc.TUINT64:
   363  		a = ppc64.AMOVHZ
   364  
   365  		goto rdst
   366  
   367  	case gc.TINT32<<16 | gc.TINT64, // sign extend int32
   368  		gc.TINT32<<16 | gc.TUINT64:
   369  		a = ppc64.AMOVW
   370  
   371  		goto rdst
   372  
   373  	case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
   374  		gc.TUINT32<<16 | gc.TUINT64:
   375  		a = ppc64.AMOVWZ
   376  
   377  		goto rdst
   378  
   379  		//warn("gmove: convert float to int not implemented: %N -> %N\n", f, t);
   380  	//return;
   381  	// algorithm is:
   382  	//	if small enough, use native float64 -> int64 conversion.
   383  	//	otherwise, subtract 2^63, convert, and add it back.
   384  	/*
   385  	* float to integer
   386  	 */
   387  	case gc.TFLOAT32<<16 | gc.TINT32,
   388  		gc.TFLOAT64<<16 | gc.TINT32,
   389  		gc.TFLOAT32<<16 | gc.TINT64,
   390  		gc.TFLOAT64<<16 | gc.TINT64,
   391  		gc.TFLOAT32<<16 | gc.TINT16,
   392  		gc.TFLOAT32<<16 | gc.TINT8,
   393  		gc.TFLOAT32<<16 | gc.TUINT16,
   394  		gc.TFLOAT32<<16 | gc.TUINT8,
   395  		gc.TFLOAT64<<16 | gc.TINT16,
   396  		gc.TFLOAT64<<16 | gc.TINT8,
   397  		gc.TFLOAT64<<16 | gc.TUINT16,
   398  		gc.TFLOAT64<<16 | gc.TUINT8,
   399  		gc.TFLOAT32<<16 | gc.TUINT32,
   400  		gc.TFLOAT64<<16 | gc.TUINT32,
   401  		gc.TFLOAT32<<16 | gc.TUINT64,
   402  		gc.TFLOAT64<<16 | gc.TUINT64:
   403  		bignodes()
   404  
   405  		var r1 gc.Node
   406  		gc.Regalloc(&r1, gc.Types[ft], f)
   407  		gmove(f, &r1)
   408  		if tt == gc.TUINT64 {
   409  			gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], nil)
   410  			gmove(&bigf, &r2)
   411  			gins(ppc64.AFCMPU, &r1, &r2)
   412  			p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TFLOAT64]), nil, +1)
   413  			gins(ppc64.AFSUB, &r2, &r1)
   414  			gc.Patch(p1, gc.Pc)
   415  			gc.Regfree(&r2)
   416  		}
   417  
   418  		gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], nil)
   419  		var r3 gc.Node
   420  		gc.Regalloc(&r3, gc.Types[gc.TINT64], t)
   421  		gins(ppc64.AFCTIDZ, &r1, &r2)
   422  		p1 := gins(ppc64.AFMOVD, &r2, nil)
   423  		p1.To.Type = obj.TYPE_MEM
   424  		p1.To.Reg = ppc64.REGSP
   425  		p1.To.Offset = -8
   426  		p1 = gins(ppc64.AMOVD, nil, &r3)
   427  		p1.From.Type = obj.TYPE_MEM
   428  		p1.From.Reg = ppc64.REGSP
   429  		p1.From.Offset = -8
   430  		gc.Regfree(&r2)
   431  		gc.Regfree(&r1)
   432  		if tt == gc.TUINT64 {
   433  			p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TFLOAT64]), nil, +1) // use CR0 here again
   434  			gc.Nodreg(&r1, gc.Types[gc.TINT64], ppc64.REGTMP)
   435  			gins(ppc64.AMOVD, &bigi, &r1)
   436  			gins(ppc64.AADD, &r1, &r3)
   437  			gc.Patch(p1, gc.Pc)
   438  		}
   439  
   440  		gmove(&r3, t)
   441  		gc.Regfree(&r3)
   442  		return
   443  
   444  	/*
   445  	 * integer to float
   446  	 */
   447  	case gc.TINT32<<16 | gc.TFLOAT32,
   448  		gc.TINT32<<16 | gc.TFLOAT64,
   449  		gc.TINT64<<16 | gc.TFLOAT32,
   450  		gc.TINT64<<16 | gc.TFLOAT64,
   451  		gc.TINT16<<16 | gc.TFLOAT32,
   452  		gc.TINT16<<16 | gc.TFLOAT64,
   453  		gc.TINT8<<16 | gc.TFLOAT32,
   454  		gc.TINT8<<16 | gc.TFLOAT64,
   455  		gc.TUINT16<<16 | gc.TFLOAT32,
   456  		gc.TUINT16<<16 | gc.TFLOAT64,
   457  		gc.TUINT8<<16 | gc.TFLOAT32,
   458  		gc.TUINT8<<16 | gc.TFLOAT64,
   459  		gc.TUINT32<<16 | gc.TFLOAT32,
   460  		gc.TUINT32<<16 | gc.TFLOAT64,
   461  		gc.TUINT64<<16 | gc.TFLOAT32,
   462  		gc.TUINT64<<16 | gc.TFLOAT64:
   463  		bignodes()
   464  
   465  		// The algorithm is:
   466  		//	if small enough, use native int64 -> float64 conversion,
   467  		//	otherwise halve (x -> (x>>1)|(x&1)), convert, and double.
   468  		// Note: could use FCFIDU instead if target supports it.
   469  		var r1 gc.Node
   470  		gc.Regalloc(&r1, gc.Types[gc.TINT64], nil)
   471  		gmove(f, &r1)
   472  		if ft == gc.TUINT64 {
   473  			gc.Nodreg(&r2, gc.Types[gc.TUINT64], ppc64.REGTMP)
   474  			gmove(&bigi, &r2)
   475  			gins(ppc64.ACMPU, &r1, &r2)
   476  			p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1)
   477  			var r3 gc.Node
   478  			gc.Regalloc(&r3, gc.Types[gc.TUINT64], nil)
   479  			p2 := gins(ppc64.AANDCC, nil, &r3) // andi.
   480  			p2.Reg = r1.Reg
   481  			p2.From.Type = obj.TYPE_CONST
   482  			p2.From.Offset = 1
   483  			p3 := gins(ppc64.ASRD, nil, &r1)
   484  			p3.From.Type = obj.TYPE_CONST
   485  			p3.From.Offset = 1
   486  			gins(ppc64.AOR, &r3, &r1)
   487  			gc.Regfree(&r3)
   488  			gc.Patch(p1, gc.Pc)
   489  		}
   490  		gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
   491  		p1 := gins(ppc64.AMOVD, &r1, nil)
   492  		p1.To.Type = obj.TYPE_MEM
   493  		p1.To.Reg = ppc64.REGSP
   494  		p1.To.Offset = -8
   495  		p1 = gins(ppc64.AFMOVD, nil, &r2)
   496  		p1.From.Type = obj.TYPE_MEM
   497  		p1.From.Reg = ppc64.REGSP
   498  		p1.From.Offset = -8
   499  		gins(ppc64.AFCFID, &r2, &r2)
   500  		gc.Regfree(&r1)
   501  		if ft == gc.TUINT64 {
   502  			p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1) // use CR0 here again
   503  			gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], ppc64.FREGTWO)
   504  			gins(ppc64.AFMUL, &r1, &r2)
   505  			gc.Patch(p1, gc.Pc)
   506  		}
   507  		gmove(&r2, t)
   508  		gc.Regfree(&r2)
   509  		return
   510  
   511  		/*
   512  		 * float to float
   513  		 */
   514  	case gc.TFLOAT32<<16 | gc.TFLOAT32:
   515  		a = ppc64.AFMOVS
   516  
   517  	case gc.TFLOAT64<<16 | gc.TFLOAT64:
   518  		a = ppc64.AFMOVD
   519  
   520  	case gc.TFLOAT32<<16 | gc.TFLOAT64:
   521  		a = ppc64.AFMOVS
   522  		goto rdst
   523  
   524  	case gc.TFLOAT64<<16 | gc.TFLOAT32:
   525  		a = ppc64.AFRSP
   526  		goto rdst
   527  	}
   528  
   529  	gins(a, f, t)
   530  	return
   531  
   532  	// requires register destination
   533  rdst:
   534  	{
   535  		gc.Regalloc(&r1, t.Type, t)
   536  
   537  		gins(a, f, &r1)
   538  		gmove(&r1, t)
   539  		gc.Regfree(&r1)
   540  		return
   541  	}
   542  
   543  	// requires register intermediate
   544  hard:
   545  	gc.Regalloc(&r1, cvt, t)
   546  
   547  	gmove(f, &r1)
   548  	gmove(&r1, t)
   549  	gc.Regfree(&r1)
   550  	return
   551  }
   552  
   553  // gins is called by the front end.
   554  // It synthesizes some multiple-instruction sequences
   555  // so the front end can stay simpler.
   556  func gins(as obj.As, f, t *gc.Node) *obj.Prog {
   557  	if as >= obj.A_ARCHSPECIFIC {
   558  		if x, ok := f.IntLiteral(); ok {
   559  			ginscon(as, x, t)
   560  			return nil // caller must not use
   561  		}
   562  	}
   563  	if as == ppc64.ACMP || as == ppc64.ACMPU {
   564  		if x, ok := t.IntLiteral(); ok {
   565  			ginscon2(as, f, x)
   566  			return nil // caller must not use
   567  		}
   568  	}
   569  	return rawgins(as, f, t)
   570  }
   571  
   572  /*
   573   * generate one instruction:
   574   *	as f, t
   575   */
   576  func rawgins(as obj.As, f *gc.Node, t *gc.Node) *obj.Prog {
   577  	// TODO(austin): Add self-move test like in 6g (but be careful
   578  	// of truncation moves)
   579  
   580  	p := gc.Prog(as)
   581  	gc.Naddr(&p.From, f)
   582  	gc.Naddr(&p.To, t)
   583  
   584  	switch as {
   585  	case obj.ACALL:
   586  		if p.To.Type == obj.TYPE_REG && p.To.Reg != ppc64.REG_CTR {
   587  			// Allow front end to emit CALL REG, and rewrite into MOV REG, CTR; CALL CTR.
   588  			if gc.Ctxt.Flag_shared {
   589  				// Make sure function pointer is in R12 as well when
   590  				// compiling Go into PIC.
   591  				// TODO(mwhudson): it would obviously be better to
   592  				// change the register allocation to put the value in
   593  				// R12 already, but I don't know how to do that.
   594  				q := gc.Prog(as)
   595  				q.As = ppc64.AMOVD
   596  				q.From = p.To
   597  				q.To.Type = obj.TYPE_REG
   598  				q.To.Reg = ppc64.REG_R12
   599  			}
   600  			pp := gc.Prog(as)
   601  			pp.From = p.From
   602  			pp.To.Type = obj.TYPE_REG
   603  			pp.To.Reg = ppc64.REG_CTR
   604  
   605  			p.As = ppc64.AMOVD
   606  			p.From = p.To
   607  			p.To.Type = obj.TYPE_REG
   608  			p.To.Reg = ppc64.REG_CTR
   609  
   610  			if gc.Ctxt.Flag_shared {
   611  				// When compiling Go into PIC, the function we just
   612  				// called via pointer might have been implemented in
   613  				// a separate module and so overwritten the TOC
   614  				// pointer in R2; reload it.
   615  				q := gc.Prog(ppc64.AMOVD)
   616  				q.From.Type = obj.TYPE_MEM
   617  				q.From.Offset = 24
   618  				q.From.Reg = ppc64.REGSP
   619  				q.To.Type = obj.TYPE_REG
   620  				q.To.Reg = ppc64.REG_R2
   621  			}
   622  
   623  			if gc.Debug['g'] != 0 {
   624  				fmt.Printf("%v\n", p)
   625  				fmt.Printf("%v\n", pp)
   626  			}
   627  
   628  			return pp
   629  		}
   630  
   631  	// Bad things the front end has done to us. Crash to find call stack.
   632  	case ppc64.AAND, ppc64.AMULLD:
   633  		if p.From.Type == obj.TYPE_CONST {
   634  			gc.Debug['h'] = 1
   635  			gc.Fatalf("bad inst: %v", p)
   636  		}
   637  	case ppc64.ACMP, ppc64.ACMPU:
   638  		if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
   639  			gc.Debug['h'] = 1
   640  			gc.Fatalf("bad inst: %v", p)
   641  		}
   642  	}
   643  
   644  	if gc.Debug['g'] != 0 {
   645  		fmt.Printf("%v\n", p)
   646  	}
   647  
   648  	w := int32(0)
   649  	switch as {
   650  	case ppc64.AMOVB,
   651  		ppc64.AMOVBU,
   652  		ppc64.AMOVBZ,
   653  		ppc64.AMOVBZU:
   654  		w = 1
   655  
   656  	case ppc64.AMOVH,
   657  		ppc64.AMOVHU,
   658  		ppc64.AMOVHZ,
   659  		ppc64.AMOVHZU:
   660  		w = 2
   661  
   662  	case ppc64.AMOVW,
   663  		ppc64.AMOVWU,
   664  		ppc64.AMOVWZ,
   665  		ppc64.AMOVWZU:
   666  		w = 4
   667  
   668  	case ppc64.AMOVD,
   669  		ppc64.AMOVDU:
   670  		if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR {
   671  			break
   672  		}
   673  		w = 8
   674  	}
   675  
   676  	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) {
   677  		gc.Dump("f", f)
   678  		gc.Dump("t", t)
   679  		gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
   680  	}
   681  
   682  	return p
   683  }
   684  
   685  /*
   686   * return Axxx for Oxxx on type t.
   687   */
   688  func optoas(op gc.Op, t *gc.Type) obj.As {
   689  	if t == nil {
   690  		gc.Fatalf("optoas: t is nil")
   691  	}
   692  
   693  	// avoid constant conversions in switches below
   694  	const (
   695  		OMINUS_ = uint32(gc.OMINUS) << 16
   696  		OLSH_   = uint32(gc.OLSH) << 16
   697  		ORSH_   = uint32(gc.ORSH) << 16
   698  		OADD_   = uint32(gc.OADD) << 16
   699  		OSUB_   = uint32(gc.OSUB) << 16
   700  		OMUL_   = uint32(gc.OMUL) << 16
   701  		ODIV_   = uint32(gc.ODIV) << 16
   702  		OOR_    = uint32(gc.OOR) << 16
   703  		OAND_   = uint32(gc.OAND) << 16
   704  		OXOR_   = uint32(gc.OXOR) << 16
   705  		OEQ_    = uint32(gc.OEQ) << 16
   706  		ONE_    = uint32(gc.ONE) << 16
   707  		OLT_    = uint32(gc.OLT) << 16
   708  		OLE_    = uint32(gc.OLE) << 16
   709  		OGE_    = uint32(gc.OGE) << 16
   710  		OGT_    = uint32(gc.OGT) << 16
   711  		OCMP_   = uint32(gc.OCMP) << 16
   712  		OAS_    = uint32(gc.OAS) << 16
   713  		OHMUL_  = uint32(gc.OHMUL) << 16
   714  		OSQRT_  = uint32(gc.OSQRT) << 16
   715  	)
   716  
   717  	a := obj.AXXX
   718  	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
   719  	default:
   720  		gc.Fatalf("optoas: no entry for op=%v type=%v", op, t)
   721  
   722  	case OEQ_ | gc.TBOOL,
   723  		OEQ_ | gc.TINT8,
   724  		OEQ_ | gc.TUINT8,
   725  		OEQ_ | gc.TINT16,
   726  		OEQ_ | gc.TUINT16,
   727  		OEQ_ | gc.TINT32,
   728  		OEQ_ | gc.TUINT32,
   729  		OEQ_ | gc.TINT64,
   730  		OEQ_ | gc.TUINT64,
   731  		OEQ_ | gc.TPTR32,
   732  		OEQ_ | gc.TPTR64,
   733  		OEQ_ | gc.TFLOAT32,
   734  		OEQ_ | gc.TFLOAT64:
   735  		a = ppc64.ABEQ
   736  
   737  	case ONE_ | gc.TBOOL,
   738  		ONE_ | gc.TINT8,
   739  		ONE_ | gc.TUINT8,
   740  		ONE_ | gc.TINT16,
   741  		ONE_ | gc.TUINT16,
   742  		ONE_ | gc.TINT32,
   743  		ONE_ | gc.TUINT32,
   744  		ONE_ | gc.TINT64,
   745  		ONE_ | gc.TUINT64,
   746  		ONE_ | gc.TPTR32,
   747  		ONE_ | gc.TPTR64,
   748  		ONE_ | gc.TFLOAT32,
   749  		ONE_ | gc.TFLOAT64:
   750  		a = ppc64.ABNE
   751  
   752  	case OLT_ | gc.TINT8, // ACMP
   753  		OLT_ | gc.TINT16,
   754  		OLT_ | gc.TINT32,
   755  		OLT_ | gc.TINT64,
   756  		OLT_ | gc.TUINT8,
   757  		// ACMPU
   758  		OLT_ | gc.TUINT16,
   759  		OLT_ | gc.TUINT32,
   760  		OLT_ | gc.TUINT64,
   761  		OLT_ | gc.TFLOAT32,
   762  		// AFCMPU
   763  		OLT_ | gc.TFLOAT64:
   764  		a = ppc64.ABLT
   765  
   766  	case OLE_ | gc.TINT8, // ACMP
   767  		OLE_ | gc.TINT16,
   768  		OLE_ | gc.TINT32,
   769  		OLE_ | gc.TINT64,
   770  		OLE_ | gc.TUINT8,
   771  		// ACMPU
   772  		OLE_ | gc.TUINT16,
   773  		OLE_ | gc.TUINT32,
   774  		OLE_ | gc.TUINT64:
   775  		// No OLE for floats, because it mishandles NaN.
   776  		// Front end must reverse comparison or use OLT and OEQ together.
   777  		a = ppc64.ABLE
   778  
   779  	case OGT_ | gc.TINT8,
   780  		OGT_ | gc.TINT16,
   781  		OGT_ | gc.TINT32,
   782  		OGT_ | gc.TINT64,
   783  		OGT_ | gc.TUINT8,
   784  		OGT_ | gc.TUINT16,
   785  		OGT_ | gc.TUINT32,
   786  		OGT_ | gc.TUINT64,
   787  		OGT_ | gc.TFLOAT32,
   788  		OGT_ | gc.TFLOAT64:
   789  		a = ppc64.ABGT
   790  
   791  	case OGE_ | gc.TINT8,
   792  		OGE_ | gc.TINT16,
   793  		OGE_ | gc.TINT32,
   794  		OGE_ | gc.TINT64,
   795  		OGE_ | gc.TUINT8,
   796  		OGE_ | gc.TUINT16,
   797  		OGE_ | gc.TUINT32,
   798  		OGE_ | gc.TUINT64:
   799  		// No OGE for floats, because it mishandles NaN.
   800  		// Front end must reverse comparison or use OLT and OEQ together.
   801  		a = ppc64.ABGE
   802  
   803  	case OCMP_ | gc.TBOOL,
   804  		OCMP_ | gc.TINT8,
   805  		OCMP_ | gc.TINT16,
   806  		OCMP_ | gc.TINT32,
   807  		OCMP_ | gc.TPTR32,
   808  		OCMP_ | gc.TINT64:
   809  		a = ppc64.ACMP
   810  
   811  	case OCMP_ | gc.TUINT8,
   812  		OCMP_ | gc.TUINT16,
   813  		OCMP_ | gc.TUINT32,
   814  		OCMP_ | gc.TUINT64,
   815  		OCMP_ | gc.TPTR64:
   816  		a = ppc64.ACMPU
   817  
   818  	case OCMP_ | gc.TFLOAT32,
   819  		OCMP_ | gc.TFLOAT64:
   820  		a = ppc64.AFCMPU
   821  
   822  	case OAS_ | gc.TBOOL,
   823  		OAS_ | gc.TINT8:
   824  		a = ppc64.AMOVB
   825  
   826  	case OAS_ | gc.TUINT8:
   827  		a = ppc64.AMOVBZ
   828  
   829  	case OAS_ | gc.TINT16:
   830  		a = ppc64.AMOVH
   831  
   832  	case OAS_ | gc.TUINT16:
   833  		a = ppc64.AMOVHZ
   834  
   835  	case OAS_ | gc.TINT32:
   836  		a = ppc64.AMOVW
   837  
   838  	case OAS_ | gc.TUINT32,
   839  		OAS_ | gc.TPTR32:
   840  		a = ppc64.AMOVWZ
   841  
   842  	case OAS_ | gc.TINT64,
   843  		OAS_ | gc.TUINT64,
   844  		OAS_ | gc.TPTR64:
   845  		a = ppc64.AMOVD
   846  
   847  	case OAS_ | gc.TFLOAT32:
   848  		a = ppc64.AFMOVS
   849  
   850  	case OAS_ | gc.TFLOAT64:
   851  		a = ppc64.AFMOVD
   852  
   853  	case OADD_ | gc.TINT8,
   854  		OADD_ | gc.TUINT8,
   855  		OADD_ | gc.TINT16,
   856  		OADD_ | gc.TUINT16,
   857  		OADD_ | gc.TINT32,
   858  		OADD_ | gc.TUINT32,
   859  		OADD_ | gc.TPTR32,
   860  		OADD_ | gc.TINT64,
   861  		OADD_ | gc.TUINT64,
   862  		OADD_ | gc.TPTR64:
   863  		a = ppc64.AADD
   864  
   865  	case OADD_ | gc.TFLOAT32:
   866  		a = ppc64.AFADDS
   867  
   868  	case OADD_ | gc.TFLOAT64:
   869  		a = ppc64.AFADD
   870  
   871  	case OSUB_ | gc.TINT8,
   872  		OSUB_ | gc.TUINT8,
   873  		OSUB_ | gc.TINT16,
   874  		OSUB_ | gc.TUINT16,
   875  		OSUB_ | gc.TINT32,
   876  		OSUB_ | gc.TUINT32,
   877  		OSUB_ | gc.TPTR32,
   878  		OSUB_ | gc.TINT64,
   879  		OSUB_ | gc.TUINT64,
   880  		OSUB_ | gc.TPTR64:
   881  		a = ppc64.ASUB
   882  
   883  	case OSUB_ | gc.TFLOAT32:
   884  		a = ppc64.AFSUBS
   885  
   886  	case OSUB_ | gc.TFLOAT64:
   887  		a = ppc64.AFSUB
   888  
   889  	case OMINUS_ | gc.TINT8,
   890  		OMINUS_ | gc.TUINT8,
   891  		OMINUS_ | gc.TINT16,
   892  		OMINUS_ | gc.TUINT16,
   893  		OMINUS_ | gc.TINT32,
   894  		OMINUS_ | gc.TUINT32,
   895  		OMINUS_ | gc.TPTR32,
   896  		OMINUS_ | gc.TINT64,
   897  		OMINUS_ | gc.TUINT64,
   898  		OMINUS_ | gc.TPTR64:
   899  		a = ppc64.ANEG
   900  
   901  	case OAND_ | gc.TINT8,
   902  		OAND_ | gc.TUINT8,
   903  		OAND_ | gc.TINT16,
   904  		OAND_ | gc.TUINT16,
   905  		OAND_ | gc.TINT32,
   906  		OAND_ | gc.TUINT32,
   907  		OAND_ | gc.TPTR32,
   908  		OAND_ | gc.TINT64,
   909  		OAND_ | gc.TUINT64,
   910  		OAND_ | gc.TPTR64:
   911  		a = ppc64.AAND
   912  
   913  	case OOR_ | gc.TINT8,
   914  		OOR_ | gc.TUINT8,
   915  		OOR_ | gc.TINT16,
   916  		OOR_ | gc.TUINT16,
   917  		OOR_ | gc.TINT32,
   918  		OOR_ | gc.TUINT32,
   919  		OOR_ | gc.TPTR32,
   920  		OOR_ | gc.TINT64,
   921  		OOR_ | gc.TUINT64,
   922  		OOR_ | gc.TPTR64:
   923  		a = ppc64.AOR
   924  
   925  	case OXOR_ | gc.TINT8,
   926  		OXOR_ | gc.TUINT8,
   927  		OXOR_ | gc.TINT16,
   928  		OXOR_ | gc.TUINT16,
   929  		OXOR_ | gc.TINT32,
   930  		OXOR_ | gc.TUINT32,
   931  		OXOR_ | gc.TPTR32,
   932  		OXOR_ | gc.TINT64,
   933  		OXOR_ | gc.TUINT64,
   934  		OXOR_ | gc.TPTR64:
   935  		a = ppc64.AXOR
   936  
   937  		// TODO(minux): handle rotates
   938  	//case CASE(OLROT, TINT8):
   939  	//case CASE(OLROT, TUINT8):
   940  	//case CASE(OLROT, TINT16):
   941  	//case CASE(OLROT, TUINT16):
   942  	//case CASE(OLROT, TINT32):
   943  	//case CASE(OLROT, TUINT32):
   944  	//case CASE(OLROT, TPTR32):
   945  	//case CASE(OLROT, TINT64):
   946  	//case CASE(OLROT, TUINT64):
   947  	//case CASE(OLROT, TPTR64):
   948  	//	a = 0//???; RLDC?
   949  	//	break;
   950  
   951  	case OLSH_ | gc.TINT8,
   952  		OLSH_ | gc.TUINT8,
   953  		OLSH_ | gc.TINT16,
   954  		OLSH_ | gc.TUINT16,
   955  		OLSH_ | gc.TINT32,
   956  		OLSH_ | gc.TUINT32,
   957  		OLSH_ | gc.TPTR32,
   958  		OLSH_ | gc.TINT64,
   959  		OLSH_ | gc.TUINT64,
   960  		OLSH_ | gc.TPTR64:
   961  		a = ppc64.ASLD
   962  
   963  	case ORSH_ | gc.TUINT8,
   964  		ORSH_ | gc.TUINT16,
   965  		ORSH_ | gc.TUINT32,
   966  		ORSH_ | gc.TPTR32,
   967  		ORSH_ | gc.TUINT64,
   968  		ORSH_ | gc.TPTR64:
   969  		a = ppc64.ASRD
   970  
   971  	case ORSH_ | gc.TINT8,
   972  		ORSH_ | gc.TINT16,
   973  		ORSH_ | gc.TINT32,
   974  		ORSH_ | gc.TINT64:
   975  		a = ppc64.ASRAD
   976  
   977  		// TODO(minux): handle rotates
   978  	//case CASE(ORROTC, TINT8):
   979  	//case CASE(ORROTC, TUINT8):
   980  	//case CASE(ORROTC, TINT16):
   981  	//case CASE(ORROTC, TUINT16):
   982  	//case CASE(ORROTC, TINT32):
   983  	//case CASE(ORROTC, TUINT32):
   984  	//case CASE(ORROTC, TINT64):
   985  	//case CASE(ORROTC, TUINT64):
   986  	//	a = 0//??? RLDC??
   987  	//	break;
   988  
   989  	case OHMUL_ | gc.TINT64:
   990  		a = ppc64.AMULHD
   991  
   992  	case OHMUL_ | gc.TUINT64,
   993  		OHMUL_ | gc.TPTR64:
   994  		a = ppc64.AMULHDU
   995  
   996  	case OMUL_ | gc.TINT8,
   997  		OMUL_ | gc.TINT16,
   998  		OMUL_ | gc.TINT32,
   999  		OMUL_ | gc.TINT64:
  1000  		a = ppc64.AMULLD
  1001  
  1002  	case OMUL_ | gc.TUINT8,
  1003  		OMUL_ | gc.TUINT16,
  1004  		OMUL_ | gc.TUINT32,
  1005  		OMUL_ | gc.TPTR32,
  1006  		// don't use word multiply, the high 32-bit are undefined.
  1007  		OMUL_ | gc.TUINT64,
  1008  		OMUL_ | gc.TPTR64:
  1009  		// for 64-bit multiplies, signedness doesn't matter.
  1010  		a = ppc64.AMULLD
  1011  
  1012  	case OMUL_ | gc.TFLOAT32:
  1013  		a = ppc64.AFMULS
  1014  
  1015  	case OMUL_ | gc.TFLOAT64:
  1016  		a = ppc64.AFMUL
  1017  
  1018  	case ODIV_ | gc.TINT8,
  1019  		ODIV_ | gc.TINT16,
  1020  		ODIV_ | gc.TINT32,
  1021  		ODIV_ | gc.TINT64:
  1022  		a = ppc64.ADIVD
  1023  
  1024  	case ODIV_ | gc.TUINT8,
  1025  		ODIV_ | gc.TUINT16,
  1026  		ODIV_ | gc.TUINT32,
  1027  		ODIV_ | gc.TPTR32,
  1028  		ODIV_ | gc.TUINT64,
  1029  		ODIV_ | gc.TPTR64:
  1030  		a = ppc64.ADIVDU
  1031  
  1032  	case ODIV_ | gc.TFLOAT32:
  1033  		a = ppc64.AFDIVS
  1034  
  1035  	case ODIV_ | gc.TFLOAT64:
  1036  		a = ppc64.AFDIV
  1037  
  1038  	case OSQRT_ | gc.TFLOAT64:
  1039  		a = ppc64.AFSQRT
  1040  	}
  1041  
  1042  	return a
  1043  }
  1044  
  1045  const (
  1046  	ODynam   = 1 << 0
  1047  	OAddable = 1 << 1
  1048  )
  1049  
  1050  func xgen(n *gc.Node, a *gc.Node, o int) bool {
  1051  	// TODO(minux)
  1052  
  1053  	return -1 != 0 /*TypeKind(100016)*/
  1054  }
  1055  
  1056  func sudoclean() {
  1057  	return
  1058  }
  1059  
  1060  /*
  1061   * generate code to compute address of n,
  1062   * a reference to a (perhaps nested) field inside
  1063   * an array or struct.
  1064   * return 0 on failure, 1 on success.
  1065   * on success, leaves usable address in a.
  1066   *
  1067   * caller is responsible for calling sudoclean
  1068   * after successful sudoaddable,
  1069   * to release the register used for a.
  1070   */
  1071  func sudoaddable(as obj.As, n *gc.Node, a *obj.Addr) bool {
  1072  	// TODO(minux)
  1073  
  1074  	*a = obj.Addr{}
  1075  	return false
  1076  }