Home | History | Annotate | Download | only in amd64
      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 (a] 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 (a] 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 amd64
     32 
     33 import (
     34 	"cmd/compile/internal/big"
     35 	"cmd/compile/internal/gc"
     36 	"cmd/internal/obj"
     37 	"cmd/internal/obj/x86"
     38 	"fmt"
     39 )
     40 
     41 var resvd = []int{
     42 	x86.REG_DI, // for movstring
     43 	x86.REG_SI, // for movstring
     44 
     45 	x86.REG_AX, // for divide
     46 	x86.REG_CX, // for shift
     47 	x86.REG_DX, // for divide
     48 	x86.REG_SP, // for stack
     49 }
     50 
     51 /*
     52  * generate
     53  *	as $c, reg
     54  */
     55 func gconreg(as int, c int64, reg int) {
     56 	var nr gc.Node
     57 
     58 	switch as {
     59 	case x86.AADDL,
     60 		x86.AMOVL,
     61 		x86.ALEAL:
     62 		gc.Nodreg(&nr, gc.Types[gc.TINT32], reg)
     63 
     64 	default:
     65 		gc.Nodreg(&nr, gc.Types[gc.TINT64], reg)
     66 	}
     67 
     68 	ginscon(as, c, &nr)
     69 }
     70 
     71 /*
     72  * generate
     73  *	as $c, n
     74  */
     75 func ginscon(as int, c int64, n2 *gc.Node) {
     76 	var n1 gc.Node
     77 
     78 	switch as {
     79 	case x86.AADDL,
     80 		x86.AMOVL,
     81 		x86.ALEAL:
     82 		gc.Nodconst(&n1, gc.Types[gc.TINT32], c)
     83 
     84 	default:
     85 		gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
     86 	}
     87 
     88 	if as != x86.AMOVQ && (c < -(1<<31) || c >= 1<<31) {
     89 		// cannot have 64-bit immediate in ADD, etc.
     90 		// instead, MOV into register first.
     91 		var ntmp gc.Node
     92 		gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
     93 
     94 		gins(x86.AMOVQ, &n1, &ntmp)
     95 		gins(as, &ntmp, n2)
     96 		gc.Regfree(&ntmp)
     97 		return
     98 	}
     99 
    100 	gins(as, &n1, n2)
    101 }
    102 
    103 func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
    104 	if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && gc.Smallintconst(n1) && n2.Op != gc.OLITERAL {
    105 		// Reverse comparison to place constant last.
    106 		op = gc.Brrev(op)
    107 		n1, n2 = n2, n1
    108 	}
    109 	// General case.
    110 	var r1, r2, g1, g2 gc.Node
    111 	if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
    112 		r1 = *n1
    113 	} else {
    114 		gc.Regalloc(&r1, t, n1)
    115 		gc.Regalloc(&g1, n1.Type, &r1)
    116 		gc.Cgen(n1, &g1)
    117 		gmove(&g1, &r1)
    118 	}
    119 	if n2.Op == gc.OLITERAL && gc.Isint[t.Etype] && gc.Smallintconst(n2) {
    120 		r2 = *n2
    121 	} else {
    122 		gc.Regalloc(&r2, t, n2)
    123 		gc.Regalloc(&g2, n1.Type, &r2)
    124 		gc.Cgen(n2, &g2)
    125 		gmove(&g2, &r2)
    126 	}
    127 	gins(optoas(gc.OCMP, t), &r1, &r2)
    128 	if r1.Op == gc.OREGISTER {
    129 		gc.Regfree(&g1)
    130 		gc.Regfree(&r1)
    131 	}
    132 	if r2.Op == gc.OREGISTER {
    133 		gc.Regfree(&g2)
    134 		gc.Regfree(&r2)
    135 	}
    136 	return gc.Gbranch(optoas(op, t), nil, likely)
    137 }
    138 
    139 func ginsboolval(a int, n *gc.Node) {
    140 	gins(jmptoset(a), nil, n)
    141 }
    142 
    143 // set up nodes representing 2^63
    144 var (
    145 	bigi         gc.Node
    146 	bigf         gc.Node
    147 	bignodes_did bool
    148 )
    149 
    150 func bignodes() {
    151 	if bignodes_did {
    152 		return
    153 	}
    154 	bignodes_did = true
    155 
    156 	var i big.Int
    157 	i.SetInt64(1)
    158 	i.Lsh(&i, 63)
    159 
    160 	gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
    161 	bigi.SetBigInt(&i)
    162 
    163 	bigi.Convconst(&bigf, gc.Types[gc.TFLOAT64])
    164 }
    165 
    166 /*
    167  * generate move:
    168  *	t = f
    169  * hard part is conversions.
    170  */
    171 func gmove(f *gc.Node, t *gc.Node) {
    172 	if gc.Debug['M'] != 0 {
    173 		fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
    174 	}
    175 
    176 	ft := gc.Simsimtype(f.Type)
    177 	tt := gc.Simsimtype(t.Type)
    178 	cvt := t.Type
    179 
    180 	if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
    181 		gc.Complexmove(f, t)
    182 		return
    183 	}
    184 
    185 	// cannot have two memory operands
    186 	var a int
    187 	if gc.Ismem(f) && gc.Ismem(t) {
    188 		goto hard
    189 	}
    190 
    191 	// convert constant to desired type
    192 	if f.Op == gc.OLITERAL {
    193 		var con gc.Node
    194 		f.Convconst(&con, t.Type)
    195 		f = &con
    196 		ft = tt // so big switch will choose a simple mov
    197 
    198 		// some constants can't move directly to memory.
    199 		if gc.Ismem(t) {
    200 			// float constants come from memory.
    201 			if gc.Isfloat[tt] {
    202 				goto hard
    203 			}
    204 
    205 			// 64-bit immediates are really 32-bit sign-extended
    206 			// unless moving into a register.
    207 			if gc.Isint[tt] {
    208 				if i := con.Int(); int64(int32(i)) != i {
    209 					goto hard
    210 				}
    211 			}
    212 		}
    213 	}
    214 
    215 	// value -> value copy, only one memory operand.
    216 	// figure out the instruction to use.
    217 	// break out of switch for one-instruction gins.
    218 	// goto rdst for "destination must be register".
    219 	// goto hard for "convert to cvt type first".
    220 	// otherwise handle and return.
    221 
    222 	switch uint32(ft)<<16 | uint32(tt) {
    223 	default:
    224 		gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
    225 
    226 		/*
    227 		 * integer copy and truncate
    228 		 */
    229 	case gc.TINT8<<16 | gc.TINT8, // same size
    230 		gc.TINT8<<16 | gc.TUINT8,
    231 		gc.TUINT8<<16 | gc.TINT8,
    232 		gc.TUINT8<<16 | gc.TUINT8,
    233 		gc.TINT16<<16 | gc.TINT8,
    234 		// truncate
    235 		gc.TUINT16<<16 | gc.TINT8,
    236 		gc.TINT32<<16 | gc.TINT8,
    237 		gc.TUINT32<<16 | gc.TINT8,
    238 		gc.TINT64<<16 | gc.TINT8,
    239 		gc.TUINT64<<16 | gc.TINT8,
    240 		gc.TINT16<<16 | gc.TUINT8,
    241 		gc.TUINT16<<16 | gc.TUINT8,
    242 		gc.TINT32<<16 | gc.TUINT8,
    243 		gc.TUINT32<<16 | gc.TUINT8,
    244 		gc.TINT64<<16 | gc.TUINT8,
    245 		gc.TUINT64<<16 | gc.TUINT8:
    246 		a = x86.AMOVB
    247 
    248 	case gc.TINT16<<16 | gc.TINT16, // same size
    249 		gc.TINT16<<16 | gc.TUINT16,
    250 		gc.TUINT16<<16 | gc.TINT16,
    251 		gc.TUINT16<<16 | gc.TUINT16,
    252 		gc.TINT32<<16 | gc.TINT16,
    253 		// truncate
    254 		gc.TUINT32<<16 | gc.TINT16,
    255 		gc.TINT64<<16 | gc.TINT16,
    256 		gc.TUINT64<<16 | gc.TINT16,
    257 		gc.TINT32<<16 | gc.TUINT16,
    258 		gc.TUINT32<<16 | gc.TUINT16,
    259 		gc.TINT64<<16 | gc.TUINT16,
    260 		gc.TUINT64<<16 | gc.TUINT16:
    261 		a = x86.AMOVW
    262 
    263 	case gc.TINT32<<16 | gc.TINT32, // same size
    264 		gc.TINT32<<16 | gc.TUINT32,
    265 		gc.TUINT32<<16 | gc.TINT32,
    266 		gc.TUINT32<<16 | gc.TUINT32:
    267 		a = x86.AMOVL
    268 
    269 	case gc.TINT64<<16 | gc.TINT32, // truncate
    270 		gc.TUINT64<<16 | gc.TINT32,
    271 		gc.TINT64<<16 | gc.TUINT32,
    272 		gc.TUINT64<<16 | gc.TUINT32:
    273 		a = x86.AMOVQL
    274 
    275 	case gc.TINT64<<16 | gc.TINT64, // same size
    276 		gc.TINT64<<16 | gc.TUINT64,
    277 		gc.TUINT64<<16 | gc.TINT64,
    278 		gc.TUINT64<<16 | gc.TUINT64:
    279 		a = x86.AMOVQ
    280 
    281 		/*
    282 		 * integer up-conversions
    283 		 */
    284 	case gc.TINT8<<16 | gc.TINT16, // sign extend int8
    285 		gc.TINT8<<16 | gc.TUINT16:
    286 		a = x86.AMOVBWSX
    287 
    288 		goto rdst
    289 
    290 	case gc.TINT8<<16 | gc.TINT32,
    291 		gc.TINT8<<16 | gc.TUINT32:
    292 		a = x86.AMOVBLSX
    293 		goto rdst
    294 
    295 	case gc.TINT8<<16 | gc.TINT64,
    296 		gc.TINT8<<16 | gc.TUINT64:
    297 		a = x86.AMOVBQSX
    298 		goto rdst
    299 
    300 	case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8
    301 		gc.TUINT8<<16 | gc.TUINT16:
    302 		a = x86.AMOVBWZX
    303 
    304 		goto rdst
    305 
    306 	case gc.TUINT8<<16 | gc.TINT32,
    307 		gc.TUINT8<<16 | gc.TUINT32:
    308 		a = x86.AMOVBLZX
    309 		goto rdst
    310 
    311 	case gc.TUINT8<<16 | gc.TINT64,
    312 		gc.TUINT8<<16 | gc.TUINT64:
    313 		a = x86.AMOVBQZX
    314 		goto rdst
    315 
    316 	case gc.TINT16<<16 | gc.TINT32, // sign extend int16
    317 		gc.TINT16<<16 | gc.TUINT32:
    318 		a = x86.AMOVWLSX
    319 
    320 		goto rdst
    321 
    322 	case gc.TINT16<<16 | gc.TINT64,
    323 		gc.TINT16<<16 | gc.TUINT64:
    324 		a = x86.AMOVWQSX
    325 		goto rdst
    326 
    327 	case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16
    328 		gc.TUINT16<<16 | gc.TUINT32:
    329 		a = x86.AMOVWLZX
    330 
    331 		goto rdst
    332 
    333 	case gc.TUINT16<<16 | gc.TINT64,
    334 		gc.TUINT16<<16 | gc.TUINT64:
    335 		a = x86.AMOVWQZX
    336 		goto rdst
    337 
    338 	case gc.TINT32<<16 | gc.TINT64, // sign extend int32
    339 		gc.TINT32<<16 | gc.TUINT64:
    340 		a = x86.AMOVLQSX
    341 
    342 		goto rdst
    343 
    344 		// AMOVL into a register zeros the top of the register,
    345 	// so this is not always necessary, but if we rely on AMOVL
    346 	// the optimizer is almost certain to screw with us.
    347 	case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
    348 		gc.TUINT32<<16 | gc.TUINT64:
    349 		a = x86.AMOVLQZX
    350 
    351 		goto rdst
    352 
    353 		/*
    354 		* float to integer
    355 		 */
    356 	case gc.TFLOAT32<<16 | gc.TINT32:
    357 		a = x86.ACVTTSS2SL
    358 
    359 		goto rdst
    360 
    361 	case gc.TFLOAT64<<16 | gc.TINT32:
    362 		a = x86.ACVTTSD2SL
    363 		goto rdst
    364 
    365 	case gc.TFLOAT32<<16 | gc.TINT64:
    366 		a = x86.ACVTTSS2SQ
    367 		goto rdst
    368 
    369 	case gc.TFLOAT64<<16 | gc.TINT64:
    370 		a = x86.ACVTTSD2SQ
    371 		goto rdst
    372 
    373 		// convert via int32.
    374 	case gc.TFLOAT32<<16 | gc.TINT16,
    375 		gc.TFLOAT32<<16 | gc.TINT8,
    376 		gc.TFLOAT32<<16 | gc.TUINT16,
    377 		gc.TFLOAT32<<16 | gc.TUINT8,
    378 		gc.TFLOAT64<<16 | gc.TINT16,
    379 		gc.TFLOAT64<<16 | gc.TINT8,
    380 		gc.TFLOAT64<<16 | gc.TUINT16,
    381 		gc.TFLOAT64<<16 | gc.TUINT8:
    382 		cvt = gc.Types[gc.TINT32]
    383 
    384 		goto hard
    385 
    386 		// convert via int64.
    387 	case gc.TFLOAT32<<16 | gc.TUINT32,
    388 		gc.TFLOAT64<<16 | gc.TUINT32:
    389 		cvt = gc.Types[gc.TINT64]
    390 
    391 		goto hard
    392 
    393 		// algorithm is:
    394 	//	if small enough, use native float64 -> int64 conversion.
    395 	//	otherwise, subtract 2^63, convert, and add it back.
    396 	case gc.TFLOAT32<<16 | gc.TUINT64,
    397 		gc.TFLOAT64<<16 | gc.TUINT64:
    398 		a := x86.ACVTTSS2SQ
    399 
    400 		if ft == gc.TFLOAT64 {
    401 			a = x86.ACVTTSD2SQ
    402 		}
    403 		bignodes()
    404 		var r1 gc.Node
    405 		gc.Regalloc(&r1, gc.Types[ft], nil)
    406 		var r2 gc.Node
    407 		gc.Regalloc(&r2, gc.Types[tt], t)
    408 		var r3 gc.Node
    409 		gc.Regalloc(&r3, gc.Types[ft], nil)
    410 		var r4 gc.Node
    411 		gc.Regalloc(&r4, gc.Types[tt], nil)
    412 		gins(optoas(gc.OAS, f.Type), f, &r1)
    413 		gins(optoas(gc.OCMP, f.Type), &bigf, &r1)
    414 		p1 := gc.Gbranch(optoas(gc.OLE, f.Type), nil, +1)
    415 		gins(a, &r1, &r2)
    416 		p2 := gc.Gbranch(obj.AJMP, nil, 0)
    417 		gc.Patch(p1, gc.Pc)
    418 		gins(optoas(gc.OAS, f.Type), &bigf, &r3)
    419 		gins(optoas(gc.OSUB, f.Type), &r3, &r1)
    420 		gins(a, &r1, &r2)
    421 		gins(x86.AMOVQ, &bigi, &r4)
    422 		gins(x86.AXORQ, &r4, &r2)
    423 		gc.Patch(p2, gc.Pc)
    424 		gmove(&r2, t)
    425 		gc.Regfree(&r4)
    426 		gc.Regfree(&r3)
    427 		gc.Regfree(&r2)
    428 		gc.Regfree(&r1)
    429 		return
    430 
    431 		/*
    432 		 * integer to float
    433 		 */
    434 	case gc.TINT32<<16 | gc.TFLOAT32:
    435 		a = x86.ACVTSL2SS
    436 
    437 		goto rdst
    438 
    439 	case gc.TINT32<<16 | gc.TFLOAT64:
    440 		a = x86.ACVTSL2SD
    441 		goto rdst
    442 
    443 	case gc.TINT64<<16 | gc.TFLOAT32:
    444 		a = x86.ACVTSQ2SS
    445 		goto rdst
    446 
    447 	case gc.TINT64<<16 | gc.TFLOAT64:
    448 		a = x86.ACVTSQ2SD
    449 		goto rdst
    450 
    451 		// convert via int32
    452 	case gc.TINT16<<16 | gc.TFLOAT32,
    453 		gc.TINT16<<16 | gc.TFLOAT64,
    454 		gc.TINT8<<16 | gc.TFLOAT32,
    455 		gc.TINT8<<16 | gc.TFLOAT64,
    456 		gc.TUINT16<<16 | gc.TFLOAT32,
    457 		gc.TUINT16<<16 | gc.TFLOAT64,
    458 		gc.TUINT8<<16 | gc.TFLOAT32,
    459 		gc.TUINT8<<16 | gc.TFLOAT64:
    460 		cvt = gc.Types[gc.TINT32]
    461 
    462 		goto hard
    463 
    464 		// convert via int64.
    465 	case gc.TUINT32<<16 | gc.TFLOAT32,
    466 		gc.TUINT32<<16 | gc.TFLOAT64:
    467 		cvt = gc.Types[gc.TINT64]
    468 
    469 		goto hard
    470 
    471 		// algorithm is:
    472 	//	if small enough, use native int64 -> uint64 conversion.
    473 	//	otherwise, halve (rounding to odd?), convert, and double.
    474 	case gc.TUINT64<<16 | gc.TFLOAT32,
    475 		gc.TUINT64<<16 | gc.TFLOAT64:
    476 		a := x86.ACVTSQ2SS
    477 
    478 		if tt == gc.TFLOAT64 {
    479 			a = x86.ACVTSQ2SD
    480 		}
    481 		var zero gc.Node
    482 		gc.Nodconst(&zero, gc.Types[gc.TUINT64], 0)
    483 		var one gc.Node
    484 		gc.Nodconst(&one, gc.Types[gc.TUINT64], 1)
    485 		var r1 gc.Node
    486 		gc.Regalloc(&r1, f.Type, f)
    487 		var r2 gc.Node
    488 		gc.Regalloc(&r2, t.Type, t)
    489 		var r3 gc.Node
    490 		gc.Regalloc(&r3, f.Type, nil)
    491 		var r4 gc.Node
    492 		gc.Regalloc(&r4, f.Type, nil)
    493 		gmove(f, &r1)
    494 		gins(x86.ACMPQ, &r1, &zero)
    495 		p1 := gc.Gbranch(x86.AJLT, nil, +1)
    496 		gins(a, &r1, &r2)
    497 		p2 := gc.Gbranch(obj.AJMP, nil, 0)
    498 		gc.Patch(p1, gc.Pc)
    499 		gmove(&r1, &r3)
    500 		gins(x86.ASHRQ, &one, &r3)
    501 		gmove(&r1, &r4)
    502 		gins(x86.AANDL, &one, &r4)
    503 		gins(x86.AORQ, &r4, &r3)
    504 		gins(a, &r3, &r2)
    505 		gins(optoas(gc.OADD, t.Type), &r2, &r2)
    506 		gc.Patch(p2, gc.Pc)
    507 		gmove(&r2, t)
    508 		gc.Regfree(&r4)
    509 		gc.Regfree(&r3)
    510 		gc.Regfree(&r2)
    511 		gc.Regfree(&r1)
    512 		return
    513 
    514 		/*
    515 		 * float to float
    516 		 */
    517 	case gc.TFLOAT32<<16 | gc.TFLOAT32:
    518 		a = x86.AMOVSS
    519 
    520 	case gc.TFLOAT64<<16 | gc.TFLOAT64:
    521 		a = x86.AMOVSD
    522 
    523 	case gc.TFLOAT32<<16 | gc.TFLOAT64:
    524 		a = x86.ACVTSS2SD
    525 		goto rdst
    526 
    527 	case gc.TFLOAT64<<16 | gc.TFLOAT32:
    528 		a = x86.ACVTSD2SS
    529 		goto rdst
    530 	}
    531 
    532 	gins(a, f, t)
    533 	return
    534 
    535 	// requires register destination
    536 rdst:
    537 	{
    538 		var r1 gc.Node
    539 		gc.Regalloc(&r1, t.Type, t)
    540 
    541 		gins(a, f, &r1)
    542 		gmove(&r1, t)
    543 		gc.Regfree(&r1)
    544 		return
    545 	}
    546 
    547 	// requires register intermediate
    548 hard:
    549 	var r1 gc.Node
    550 	gc.Regalloc(&r1, cvt, t)
    551 
    552 	gmove(f, &r1)
    553 	gmove(&r1, t)
    554 	gc.Regfree(&r1)
    555 	return
    556 }
    557 
    558 func samaddr(f *gc.Node, t *gc.Node) bool {
    559 	if f.Op != t.Op {
    560 		return false
    561 	}
    562 
    563 	switch f.Op {
    564 	case gc.OREGISTER:
    565 		if f.Reg != t.Reg {
    566 			break
    567 		}
    568 		return true
    569 	}
    570 
    571 	return false
    572 }
    573 
    574 /*
    575  * generate one instruction:
    576  *	as f, t
    577  */
    578 func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
    579 	//	Node nod;
    580 
    581 	//	if(f != N && f->op == OINDEX) {
    582 	//		gc.Regalloc(&nod, &regnode, Z);
    583 	//		v = constnode.vconst;
    584 	//		gc.Cgen(f->right, &nod);
    585 	//		constnode.vconst = v;
    586 	//		idx.reg = nod.reg;
    587 	//		gc.Regfree(&nod);
    588 	//	}
    589 	//	if(t != N && t->op == OINDEX) {
    590 	//		gc.Regalloc(&nod, &regnode, Z);
    591 	//		v = constnode.vconst;
    592 	//		gc.Cgen(t->right, &nod);
    593 	//		constnode.vconst = v;
    594 	//		idx.reg = nod.reg;
    595 	//		gc.Regfree(&nod);
    596 	//	}
    597 
    598 	if f != nil && f.Op == gc.OADDR && (as == x86.AMOVL || as == x86.AMOVQ) {
    599 		// Turn MOVL $xxx into LEAL xxx.
    600 		// These should be equivalent but most of the backend
    601 		// only expects to see LEAL, because that's what we had
    602 		// historically generated. Various hidden assumptions are baked in by now.
    603 		if as == x86.AMOVL {
    604 			as = x86.ALEAL
    605 		} else {
    606 			as = x86.ALEAQ
    607 		}
    608 		f = f.Left
    609 	}
    610 
    611 	switch as {
    612 	case x86.AMOVB,
    613 		x86.AMOVW,
    614 		x86.AMOVL,
    615 		x86.AMOVQ,
    616 		x86.AMOVSS,
    617 		x86.AMOVSD:
    618 		if f != nil && t != nil && samaddr(f, t) {
    619 			return nil
    620 		}
    621 
    622 	case x86.ALEAQ:
    623 		if f != nil && gc.Isconst(f, gc.CTNIL) {
    624 			gc.Fatal("gins LEAQ nil %v", f.Type)
    625 		}
    626 	}
    627 
    628 	p := gc.Prog(as)
    629 	gc.Naddr(&p.From, f)
    630 	gc.Naddr(&p.To, t)
    631 
    632 	if gc.Debug['g'] != 0 {
    633 		fmt.Printf("%v\n", p)
    634 	}
    635 
    636 	w := int32(0)
    637 	switch as {
    638 	case x86.AMOVB:
    639 		w = 1
    640 
    641 	case x86.AMOVW:
    642 		w = 2
    643 
    644 	case x86.AMOVL:
    645 		w = 4
    646 
    647 	case x86.AMOVQ:
    648 		w = 8
    649 	}
    650 
    651 	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Width > int64(w))) {
    652 		gc.Dump("f", f)
    653 		gc.Dump("t", t)
    654 		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
    655 	}
    656 
    657 	if p.To.Type == obj.TYPE_ADDR && w > 0 {
    658 		gc.Fatal("bad use of addr: %v", p)
    659 	}
    660 
    661 	return p
    662 }
    663 
    664 func ginsnop() {
    665 	// This is actually not the x86 NOP anymore,
    666 	// but at the point where it gets used, AX is dead
    667 	// so it's okay if we lose the high bits.
    668 	var reg gc.Node
    669 	gc.Nodreg(&reg, gc.Types[gc.TINT], x86.REG_AX)
    670 	gins(x86.AXCHGL, &reg, &reg)
    671 }
    672 
    673 /*
    674  * return Axxx for Oxxx on type t.
    675  */
    676 func optoas(op int, t *gc.Type) int {
    677 	if t == nil {
    678 		gc.Fatal("optoas: t is nil")
    679 	}
    680 
    681 	a := obj.AXXX
    682 	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
    683 	default:
    684 		gc.Fatal("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
    685 
    686 	case gc.OADDR<<16 | gc.TPTR32:
    687 		a = x86.ALEAL
    688 
    689 	case gc.OADDR<<16 | gc.TPTR64:
    690 		a = x86.ALEAQ
    691 
    692 	case gc.OEQ<<16 | gc.TBOOL,
    693 		gc.OEQ<<16 | gc.TINT8,
    694 		gc.OEQ<<16 | gc.TUINT8,
    695 		gc.OEQ<<16 | gc.TINT16,
    696 		gc.OEQ<<16 | gc.TUINT16,
    697 		gc.OEQ<<16 | gc.TINT32,
    698 		gc.OEQ<<16 | gc.TUINT32,
    699 		gc.OEQ<<16 | gc.TINT64,
    700 		gc.OEQ<<16 | gc.TUINT64,
    701 		gc.OEQ<<16 | gc.TPTR32,
    702 		gc.OEQ<<16 | gc.TPTR64,
    703 		gc.OEQ<<16 | gc.TFLOAT32,
    704 		gc.OEQ<<16 | gc.TFLOAT64:
    705 		a = x86.AJEQ
    706 
    707 	case gc.ONE<<16 | gc.TBOOL,
    708 		gc.ONE<<16 | gc.TINT8,
    709 		gc.ONE<<16 | gc.TUINT8,
    710 		gc.ONE<<16 | gc.TINT16,
    711 		gc.ONE<<16 | gc.TUINT16,
    712 		gc.ONE<<16 | gc.TINT32,
    713 		gc.ONE<<16 | gc.TUINT32,
    714 		gc.ONE<<16 | gc.TINT64,
    715 		gc.ONE<<16 | gc.TUINT64,
    716 		gc.ONE<<16 | gc.TPTR32,
    717 		gc.ONE<<16 | gc.TPTR64,
    718 		gc.ONE<<16 | gc.TFLOAT32,
    719 		gc.ONE<<16 | gc.TFLOAT64:
    720 		a = x86.AJNE
    721 
    722 	case gc.OPS<<16 | gc.TBOOL,
    723 		gc.OPS<<16 | gc.TINT8,
    724 		gc.OPS<<16 | gc.TUINT8,
    725 		gc.OPS<<16 | gc.TINT16,
    726 		gc.OPS<<16 | gc.TUINT16,
    727 		gc.OPS<<16 | gc.TINT32,
    728 		gc.OPS<<16 | gc.TUINT32,
    729 		gc.OPS<<16 | gc.TINT64,
    730 		gc.OPS<<16 | gc.TUINT64,
    731 		gc.OPS<<16 | gc.TPTR32,
    732 		gc.OPS<<16 | gc.TPTR64,
    733 		gc.OPS<<16 | gc.TFLOAT32,
    734 		gc.OPS<<16 | gc.TFLOAT64:
    735 		a = x86.AJPS
    736 
    737 	case gc.OPC<<16 | gc.TBOOL,
    738 		gc.OPC<<16 | gc.TINT8,
    739 		gc.OPC<<16 | gc.TUINT8,
    740 		gc.OPC<<16 | gc.TINT16,
    741 		gc.OPC<<16 | gc.TUINT16,
    742 		gc.OPC<<16 | gc.TINT32,
    743 		gc.OPC<<16 | gc.TUINT32,
    744 		gc.OPC<<16 | gc.TINT64,
    745 		gc.OPC<<16 | gc.TUINT64,
    746 		gc.OPC<<16 | gc.TPTR32,
    747 		gc.OPC<<16 | gc.TPTR64,
    748 		gc.OPC<<16 | gc.TFLOAT32,
    749 		gc.OPC<<16 | gc.TFLOAT64:
    750 		a = x86.AJPC
    751 
    752 	case gc.OLT<<16 | gc.TINT8,
    753 		gc.OLT<<16 | gc.TINT16,
    754 		gc.OLT<<16 | gc.TINT32,
    755 		gc.OLT<<16 | gc.TINT64:
    756 		a = x86.AJLT
    757 
    758 	case gc.OLT<<16 | gc.TUINT8,
    759 		gc.OLT<<16 | gc.TUINT16,
    760 		gc.OLT<<16 | gc.TUINT32,
    761 		gc.OLT<<16 | gc.TUINT64:
    762 		a = x86.AJCS
    763 
    764 	case gc.OLE<<16 | gc.TINT8,
    765 		gc.OLE<<16 | gc.TINT16,
    766 		gc.OLE<<16 | gc.TINT32,
    767 		gc.OLE<<16 | gc.TINT64:
    768 		a = x86.AJLE
    769 
    770 	case gc.OLE<<16 | gc.TUINT8,
    771 		gc.OLE<<16 | gc.TUINT16,
    772 		gc.OLE<<16 | gc.TUINT32,
    773 		gc.OLE<<16 | gc.TUINT64:
    774 		a = x86.AJLS
    775 
    776 	case gc.OGT<<16 | gc.TINT8,
    777 		gc.OGT<<16 | gc.TINT16,
    778 		gc.OGT<<16 | gc.TINT32,
    779 		gc.OGT<<16 | gc.TINT64:
    780 		a = x86.AJGT
    781 
    782 	case gc.OGT<<16 | gc.TUINT8,
    783 		gc.OGT<<16 | gc.TUINT16,
    784 		gc.OGT<<16 | gc.TUINT32,
    785 		gc.OGT<<16 | gc.TUINT64,
    786 		gc.OLT<<16 | gc.TFLOAT32,
    787 		gc.OLT<<16 | gc.TFLOAT64:
    788 		a = x86.AJHI
    789 
    790 	case gc.OGE<<16 | gc.TINT8,
    791 		gc.OGE<<16 | gc.TINT16,
    792 		gc.OGE<<16 | gc.TINT32,
    793 		gc.OGE<<16 | gc.TINT64:
    794 		a = x86.AJGE
    795 
    796 	case gc.OGE<<16 | gc.TUINT8,
    797 		gc.OGE<<16 | gc.TUINT16,
    798 		gc.OGE<<16 | gc.TUINT32,
    799 		gc.OGE<<16 | gc.TUINT64,
    800 		gc.OLE<<16 | gc.TFLOAT32,
    801 		gc.OLE<<16 | gc.TFLOAT64:
    802 		a = x86.AJCC
    803 
    804 	case gc.OCMP<<16 | gc.TBOOL,
    805 		gc.OCMP<<16 | gc.TINT8,
    806 		gc.OCMP<<16 | gc.TUINT8:
    807 		a = x86.ACMPB
    808 
    809 	case gc.OCMP<<16 | gc.TINT16,
    810 		gc.OCMP<<16 | gc.TUINT16:
    811 		a = x86.ACMPW
    812 
    813 	case gc.OCMP<<16 | gc.TINT32,
    814 		gc.OCMP<<16 | gc.TUINT32,
    815 		gc.OCMP<<16 | gc.TPTR32:
    816 		a = x86.ACMPL
    817 
    818 	case gc.OCMP<<16 | gc.TINT64,
    819 		gc.OCMP<<16 | gc.TUINT64,
    820 		gc.OCMP<<16 | gc.TPTR64:
    821 		a = x86.ACMPQ
    822 
    823 	case gc.OCMP<<16 | gc.TFLOAT32:
    824 		a = x86.AUCOMISS
    825 
    826 	case gc.OCMP<<16 | gc.TFLOAT64:
    827 		a = x86.AUCOMISD
    828 
    829 	case gc.OAS<<16 | gc.TBOOL,
    830 		gc.OAS<<16 | gc.TINT8,
    831 		gc.OAS<<16 | gc.TUINT8:
    832 		a = x86.AMOVB
    833 
    834 	case gc.OAS<<16 | gc.TINT16,
    835 		gc.OAS<<16 | gc.TUINT16:
    836 		a = x86.AMOVW
    837 
    838 	case gc.OAS<<16 | gc.TINT32,
    839 		gc.OAS<<16 | gc.TUINT32,
    840 		gc.OAS<<16 | gc.TPTR32:
    841 		a = x86.AMOVL
    842 
    843 	case gc.OAS<<16 | gc.TINT64,
    844 		gc.OAS<<16 | gc.TUINT64,
    845 		gc.OAS<<16 | gc.TPTR64:
    846 		a = x86.AMOVQ
    847 
    848 	case gc.OAS<<16 | gc.TFLOAT32:
    849 		a = x86.AMOVSS
    850 
    851 	case gc.OAS<<16 | gc.TFLOAT64:
    852 		a = x86.AMOVSD
    853 
    854 	case gc.OADD<<16 | gc.TINT8,
    855 		gc.OADD<<16 | gc.TUINT8:
    856 		a = x86.AADDB
    857 
    858 	case gc.OADD<<16 | gc.TINT16,
    859 		gc.OADD<<16 | gc.TUINT16:
    860 		a = x86.AADDW
    861 
    862 	case gc.OADD<<16 | gc.TINT32,
    863 		gc.OADD<<16 | gc.TUINT32,
    864 		gc.OADD<<16 | gc.TPTR32:
    865 		a = x86.AADDL
    866 
    867 	case gc.OADD<<16 | gc.TINT64,
    868 		gc.OADD<<16 | gc.TUINT64,
    869 		gc.OADD<<16 | gc.TPTR64:
    870 		a = x86.AADDQ
    871 
    872 	case gc.OADD<<16 | gc.TFLOAT32:
    873 		a = x86.AADDSS
    874 
    875 	case gc.OADD<<16 | gc.TFLOAT64:
    876 		a = x86.AADDSD
    877 
    878 	case gc.OSUB<<16 | gc.TINT8,
    879 		gc.OSUB<<16 | gc.TUINT8:
    880 		a = x86.ASUBB
    881 
    882 	case gc.OSUB<<16 | gc.TINT16,
    883 		gc.OSUB<<16 | gc.TUINT16:
    884 		a = x86.ASUBW
    885 
    886 	case gc.OSUB<<16 | gc.TINT32,
    887 		gc.OSUB<<16 | gc.TUINT32,
    888 		gc.OSUB<<16 | gc.TPTR32:
    889 		a = x86.ASUBL
    890 
    891 	case gc.OSUB<<16 | gc.TINT64,
    892 		gc.OSUB<<16 | gc.TUINT64,
    893 		gc.OSUB<<16 | gc.TPTR64:
    894 		a = x86.ASUBQ
    895 
    896 	case gc.OSUB<<16 | gc.TFLOAT32:
    897 		a = x86.ASUBSS
    898 
    899 	case gc.OSUB<<16 | gc.TFLOAT64:
    900 		a = x86.ASUBSD
    901 
    902 	case gc.OINC<<16 | gc.TINT8,
    903 		gc.OINC<<16 | gc.TUINT8:
    904 		a = x86.AINCB
    905 
    906 	case gc.OINC<<16 | gc.TINT16,
    907 		gc.OINC<<16 | gc.TUINT16:
    908 		a = x86.AINCW
    909 
    910 	case gc.OINC<<16 | gc.TINT32,
    911 		gc.OINC<<16 | gc.TUINT32,
    912 		gc.OINC<<16 | gc.TPTR32:
    913 		a = x86.AINCL
    914 
    915 	case gc.OINC<<16 | gc.TINT64,
    916 		gc.OINC<<16 | gc.TUINT64,
    917 		gc.OINC<<16 | gc.TPTR64:
    918 		a = x86.AINCQ
    919 
    920 	case gc.ODEC<<16 | gc.TINT8,
    921 		gc.ODEC<<16 | gc.TUINT8:
    922 		a = x86.ADECB
    923 
    924 	case gc.ODEC<<16 | gc.TINT16,
    925 		gc.ODEC<<16 | gc.TUINT16:
    926 		a = x86.ADECW
    927 
    928 	case gc.ODEC<<16 | gc.TINT32,
    929 		gc.ODEC<<16 | gc.TUINT32,
    930 		gc.ODEC<<16 | gc.TPTR32:
    931 		a = x86.ADECL
    932 
    933 	case gc.ODEC<<16 | gc.TINT64,
    934 		gc.ODEC<<16 | gc.TUINT64,
    935 		gc.ODEC<<16 | gc.TPTR64:
    936 		a = x86.ADECQ
    937 
    938 	case gc.OMINUS<<16 | gc.TINT8,
    939 		gc.OMINUS<<16 | gc.TUINT8:
    940 		a = x86.ANEGB
    941 
    942 	case gc.OMINUS<<16 | gc.TINT16,
    943 		gc.OMINUS<<16 | gc.TUINT16:
    944 		a = x86.ANEGW
    945 
    946 	case gc.OMINUS<<16 | gc.TINT32,
    947 		gc.OMINUS<<16 | gc.TUINT32,
    948 		gc.OMINUS<<16 | gc.TPTR32:
    949 		a = x86.ANEGL
    950 
    951 	case gc.OMINUS<<16 | gc.TINT64,
    952 		gc.OMINUS<<16 | gc.TUINT64,
    953 		gc.OMINUS<<16 | gc.TPTR64:
    954 		a = x86.ANEGQ
    955 
    956 	case gc.OAND<<16 | gc.TBOOL,
    957 		gc.OAND<<16 | gc.TINT8,
    958 		gc.OAND<<16 | gc.TUINT8:
    959 		a = x86.AANDB
    960 
    961 	case gc.OAND<<16 | gc.TINT16,
    962 		gc.OAND<<16 | gc.TUINT16:
    963 		a = x86.AANDW
    964 
    965 	case gc.OAND<<16 | gc.TINT32,
    966 		gc.OAND<<16 | gc.TUINT32,
    967 		gc.OAND<<16 | gc.TPTR32:
    968 		a = x86.AANDL
    969 
    970 	case gc.OAND<<16 | gc.TINT64,
    971 		gc.OAND<<16 | gc.TUINT64,
    972 		gc.OAND<<16 | gc.TPTR64:
    973 		a = x86.AANDQ
    974 
    975 	case gc.OOR<<16 | gc.TBOOL,
    976 		gc.OOR<<16 | gc.TINT8,
    977 		gc.OOR<<16 | gc.TUINT8:
    978 		a = x86.AORB
    979 
    980 	case gc.OOR<<16 | gc.TINT16,
    981 		gc.OOR<<16 | gc.TUINT16:
    982 		a = x86.AORW
    983 
    984 	case gc.OOR<<16 | gc.TINT32,
    985 		gc.OOR<<16 | gc.TUINT32,
    986 		gc.OOR<<16 | gc.TPTR32:
    987 		a = x86.AORL
    988 
    989 	case gc.OOR<<16 | gc.TINT64,
    990 		gc.OOR<<16 | gc.TUINT64,
    991 		gc.OOR<<16 | gc.TPTR64:
    992 		a = x86.AORQ
    993 
    994 	case gc.OXOR<<16 | gc.TINT8,
    995 		gc.OXOR<<16 | gc.TUINT8:
    996 		a = x86.AXORB
    997 
    998 	case gc.OXOR<<16 | gc.TINT16,
    999 		gc.OXOR<<16 | gc.TUINT16:
   1000 		a = x86.AXORW
   1001 
   1002 	case gc.OXOR<<16 | gc.TINT32,
   1003 		gc.OXOR<<16 | gc.TUINT32,
   1004 		gc.OXOR<<16 | gc.TPTR32:
   1005 		a = x86.AXORL
   1006 
   1007 	case gc.OXOR<<16 | gc.TINT64,
   1008 		gc.OXOR<<16 | gc.TUINT64,
   1009 		gc.OXOR<<16 | gc.TPTR64:
   1010 		a = x86.AXORQ
   1011 
   1012 	case gc.OLROT<<16 | gc.TINT8,
   1013 		gc.OLROT<<16 | gc.TUINT8:
   1014 		a = x86.AROLB
   1015 
   1016 	case gc.OLROT<<16 | gc.TINT16,
   1017 		gc.OLROT<<16 | gc.TUINT16:
   1018 		a = x86.AROLW
   1019 
   1020 	case gc.OLROT<<16 | gc.TINT32,
   1021 		gc.OLROT<<16 | gc.TUINT32,
   1022 		gc.OLROT<<16 | gc.TPTR32:
   1023 		a = x86.AROLL
   1024 
   1025 	case gc.OLROT<<16 | gc.TINT64,
   1026 		gc.OLROT<<16 | gc.TUINT64,
   1027 		gc.OLROT<<16 | gc.TPTR64:
   1028 		a = x86.AROLQ
   1029 
   1030 	case gc.OLSH<<16 | gc.TINT8,
   1031 		gc.OLSH<<16 | gc.TUINT8:
   1032 		a = x86.ASHLB
   1033 
   1034 	case gc.OLSH<<16 | gc.TINT16,
   1035 		gc.OLSH<<16 | gc.TUINT16:
   1036 		a = x86.ASHLW
   1037 
   1038 	case gc.OLSH<<16 | gc.TINT32,
   1039 		gc.OLSH<<16 | gc.TUINT32,
   1040 		gc.OLSH<<16 | gc.TPTR32:
   1041 		a = x86.ASHLL
   1042 
   1043 	case gc.OLSH<<16 | gc.TINT64,
   1044 		gc.OLSH<<16 | gc.TUINT64,
   1045 		gc.OLSH<<16 | gc.TPTR64:
   1046 		a = x86.ASHLQ
   1047 
   1048 	case gc.ORSH<<16 | gc.TUINT8:
   1049 		a = x86.ASHRB
   1050 
   1051 	case gc.ORSH<<16 | gc.TUINT16:
   1052 		a = x86.ASHRW
   1053 
   1054 	case gc.ORSH<<16 | gc.TUINT32,
   1055 		gc.ORSH<<16 | gc.TPTR32:
   1056 		a = x86.ASHRL
   1057 
   1058 	case gc.ORSH<<16 | gc.TUINT64,
   1059 		gc.ORSH<<16 | gc.TPTR64:
   1060 		a = x86.ASHRQ
   1061 
   1062 	case gc.ORSH<<16 | gc.TINT8:
   1063 		a = x86.ASARB
   1064 
   1065 	case gc.ORSH<<16 | gc.TINT16:
   1066 		a = x86.ASARW
   1067 
   1068 	case gc.ORSH<<16 | gc.TINT32:
   1069 		a = x86.ASARL
   1070 
   1071 	case gc.ORSH<<16 | gc.TINT64:
   1072 		a = x86.ASARQ
   1073 
   1074 	case gc.ORROTC<<16 | gc.TINT8,
   1075 		gc.ORROTC<<16 | gc.TUINT8:
   1076 		a = x86.ARCRB
   1077 
   1078 	case gc.ORROTC<<16 | gc.TINT16,
   1079 		gc.ORROTC<<16 | gc.TUINT16:
   1080 		a = x86.ARCRW
   1081 
   1082 	case gc.ORROTC<<16 | gc.TINT32,
   1083 		gc.ORROTC<<16 | gc.TUINT32:
   1084 		a = x86.ARCRL
   1085 
   1086 	case gc.ORROTC<<16 | gc.TINT64,
   1087 		gc.ORROTC<<16 | gc.TUINT64:
   1088 		a = x86.ARCRQ
   1089 
   1090 	case gc.OHMUL<<16 | gc.TINT8,
   1091 		gc.OMUL<<16 | gc.TINT8,
   1092 		gc.OMUL<<16 | gc.TUINT8:
   1093 		a = x86.AIMULB
   1094 
   1095 	case gc.OHMUL<<16 | gc.TINT16,
   1096 		gc.OMUL<<16 | gc.TINT16,
   1097 		gc.OMUL<<16 | gc.TUINT16:
   1098 		a = x86.AIMULW
   1099 
   1100 	case gc.OHMUL<<16 | gc.TINT32,
   1101 		gc.OMUL<<16 | gc.TINT32,
   1102 		gc.OMUL<<16 | gc.TUINT32,
   1103 		gc.OMUL<<16 | gc.TPTR32:
   1104 		a = x86.AIMULL
   1105 
   1106 	case gc.OHMUL<<16 | gc.TINT64,
   1107 		gc.OMUL<<16 | gc.TINT64,
   1108 		gc.OMUL<<16 | gc.TUINT64,
   1109 		gc.OMUL<<16 | gc.TPTR64:
   1110 		a = x86.AIMULQ
   1111 
   1112 	case gc.OHMUL<<16 | gc.TUINT8:
   1113 		a = x86.AMULB
   1114 
   1115 	case gc.OHMUL<<16 | gc.TUINT16:
   1116 		a = x86.AMULW
   1117 
   1118 	case gc.OHMUL<<16 | gc.TUINT32,
   1119 		gc.OHMUL<<16 | gc.TPTR32:
   1120 		a = x86.AMULL
   1121 
   1122 	case gc.OHMUL<<16 | gc.TUINT64,
   1123 		gc.OHMUL<<16 | gc.TPTR64:
   1124 		a = x86.AMULQ
   1125 
   1126 	case gc.OMUL<<16 | gc.TFLOAT32:
   1127 		a = x86.AMULSS
   1128 
   1129 	case gc.OMUL<<16 | gc.TFLOAT64:
   1130 		a = x86.AMULSD
   1131 
   1132 	case gc.ODIV<<16 | gc.TINT8,
   1133 		gc.OMOD<<16 | gc.TINT8:
   1134 		a = x86.AIDIVB
   1135 
   1136 	case gc.ODIV<<16 | gc.TUINT8,
   1137 		gc.OMOD<<16 | gc.TUINT8:
   1138 		a = x86.ADIVB
   1139 
   1140 	case gc.ODIV<<16 | gc.TINT16,
   1141 		gc.OMOD<<16 | gc.TINT16:
   1142 		a = x86.AIDIVW
   1143 
   1144 	case gc.ODIV<<16 | gc.TUINT16,
   1145 		gc.OMOD<<16 | gc.TUINT16:
   1146 		a = x86.ADIVW
   1147 
   1148 	case gc.ODIV<<16 | gc.TINT32,
   1149 		gc.OMOD<<16 | gc.TINT32:
   1150 		a = x86.AIDIVL
   1151 
   1152 	case gc.ODIV<<16 | gc.TUINT32,
   1153 		gc.ODIV<<16 | gc.TPTR32,
   1154 		gc.OMOD<<16 | gc.TUINT32,
   1155 		gc.OMOD<<16 | gc.TPTR32:
   1156 		a = x86.ADIVL
   1157 
   1158 	case gc.ODIV<<16 | gc.TINT64,
   1159 		gc.OMOD<<16 | gc.TINT64:
   1160 		a = x86.AIDIVQ
   1161 
   1162 	case gc.ODIV<<16 | gc.TUINT64,
   1163 		gc.ODIV<<16 | gc.TPTR64,
   1164 		gc.OMOD<<16 | gc.TUINT64,
   1165 		gc.OMOD<<16 | gc.TPTR64:
   1166 		a = x86.ADIVQ
   1167 
   1168 	case gc.OEXTEND<<16 | gc.TINT16:
   1169 		a = x86.ACWD
   1170 
   1171 	case gc.OEXTEND<<16 | gc.TINT32:
   1172 		a = x86.ACDQ
   1173 
   1174 	case gc.OEXTEND<<16 | gc.TINT64:
   1175 		a = x86.ACQO
   1176 
   1177 	case gc.ODIV<<16 | gc.TFLOAT32:
   1178 		a = x86.ADIVSS
   1179 
   1180 	case gc.ODIV<<16 | gc.TFLOAT64:
   1181 		a = x86.ADIVSD
   1182 
   1183 	case gc.OSQRT<<16 | gc.TFLOAT64:
   1184 		a = x86.ASQRTSD
   1185 	}
   1186 
   1187 	return a
   1188 }
   1189 
   1190 // jmptoset returns ASETxx for AJxx.
   1191 func jmptoset(jmp int) int {
   1192 	switch jmp {
   1193 	case x86.AJEQ:
   1194 		return x86.ASETEQ
   1195 	case x86.AJNE:
   1196 		return x86.ASETNE
   1197 	case x86.AJLT:
   1198 		return x86.ASETLT
   1199 	case x86.AJCS:
   1200 		return x86.ASETCS
   1201 	case x86.AJLE:
   1202 		return x86.ASETLE
   1203 	case x86.AJLS:
   1204 		return x86.ASETLS
   1205 	case x86.AJGT:
   1206 		return x86.ASETGT
   1207 	case x86.AJHI:
   1208 		return x86.ASETHI
   1209 	case x86.AJGE:
   1210 		return x86.ASETGE
   1211 	case x86.AJCC:
   1212 		return x86.ASETCC
   1213 	case x86.AJMI:
   1214 		return x86.ASETMI
   1215 	case x86.AJOC:
   1216 		return x86.ASETOC
   1217 	case x86.AJOS:
   1218 		return x86.ASETOS
   1219 	case x86.AJPC:
   1220 		return x86.ASETPC
   1221 	case x86.AJPL:
   1222 		return x86.ASETPL
   1223 	case x86.AJPS:
   1224 		return x86.ASETPS
   1225 	}
   1226 	gc.Fatal("jmptoset: no entry for %v", gc.Oconv(jmp, 0))
   1227 	panic("unreachable")
   1228 }
   1229 
   1230 const (
   1231 	ODynam   = 1 << 0
   1232 	OAddable = 1 << 1
   1233 )
   1234 
   1235 var clean [20]gc.Node
   1236 
   1237 var cleani int = 0
   1238 
   1239 func sudoclean() {
   1240 	if clean[cleani-1].Op != gc.OEMPTY {
   1241 		gc.Regfree(&clean[cleani-1])
   1242 	}
   1243 	if clean[cleani-2].Op != gc.OEMPTY {
   1244 		gc.Regfree(&clean[cleani-2])
   1245 	}
   1246 	cleani -= 2
   1247 }
   1248 
   1249 /*
   1250  * generate code to compute address of n,
   1251  * a reference to a (perhaps nested) field inside
   1252  * an array or struct.
   1253  * return 0 on failure, 1 on success.
   1254  * on success, leaves usable address in a.
   1255  *
   1256  * caller is responsible for calling sudoclean
   1257  * after successful sudoaddable,
   1258  * to release the register used for a.
   1259  */
   1260 func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
   1261 	if n.Type == nil {
   1262 		return false
   1263 	}
   1264 
   1265 	*a = obj.Addr{}
   1266 
   1267 	switch n.Op {
   1268 	case gc.OLITERAL:
   1269 		if !gc.Isconst(n, gc.CTINT) {
   1270 			break
   1271 		}
   1272 		v := n.Int()
   1273 		if v >= 32000 || v <= -32000 {
   1274 			break
   1275 		}
   1276 		switch as {
   1277 		default:
   1278 			return false
   1279 
   1280 		case x86.AADDB,
   1281 			x86.AADDW,
   1282 			x86.AADDL,
   1283 			x86.AADDQ,
   1284 			x86.ASUBB,
   1285 			x86.ASUBW,
   1286 			x86.ASUBL,
   1287 			x86.ASUBQ,
   1288 			x86.AANDB,
   1289 			x86.AANDW,
   1290 			x86.AANDL,
   1291 			x86.AANDQ,
   1292 			x86.AORB,
   1293 			x86.AORW,
   1294 			x86.AORL,
   1295 			x86.AORQ,
   1296 			x86.AXORB,
   1297 			x86.AXORW,
   1298 			x86.AXORL,
   1299 			x86.AXORQ,
   1300 			x86.AINCB,
   1301 			x86.AINCW,
   1302 			x86.AINCL,
   1303 			x86.AINCQ,
   1304 			x86.ADECB,
   1305 			x86.ADECW,
   1306 			x86.ADECL,
   1307 			x86.ADECQ,
   1308 			x86.AMOVB,
   1309 			x86.AMOVW,
   1310 			x86.AMOVL,
   1311 			x86.AMOVQ:
   1312 			break
   1313 		}
   1314 
   1315 		cleani += 2
   1316 		reg := &clean[cleani-1]
   1317 		reg1 := &clean[cleani-2]
   1318 		reg.Op = gc.OEMPTY
   1319 		reg1.Op = gc.OEMPTY
   1320 		gc.Naddr(a, n)
   1321 		return true
   1322 
   1323 	case gc.ODOT,
   1324 		gc.ODOTPTR:
   1325 		cleani += 2
   1326 		reg := &clean[cleani-1]
   1327 		reg1 := &clean[cleani-2]
   1328 		reg.Op = gc.OEMPTY
   1329 		reg1.Op = gc.OEMPTY
   1330 		var nn *gc.Node
   1331 		var oary [10]int64
   1332 		o := gc.Dotoffset(n, oary[:], &nn)
   1333 		if nn == nil {
   1334 			sudoclean()
   1335 			return false
   1336 		}
   1337 
   1338 		if nn.Addable && o == 1 && oary[0] >= 0 {
   1339 			// directly addressable set of DOTs
   1340 			n1 := *nn
   1341 
   1342 			n1.Type = n.Type
   1343 			n1.Xoffset += oary[0]
   1344 			gc.Naddr(a, &n1)
   1345 			return true
   1346 		}
   1347 
   1348 		gc.Regalloc(reg, gc.Types[gc.Tptr], nil)
   1349 		n1 := *reg
   1350 		n1.Op = gc.OINDREG
   1351 		if oary[0] >= 0 {
   1352 			gc.Agen(nn, reg)
   1353 			n1.Xoffset = oary[0]
   1354 		} else {
   1355 			gc.Cgen(nn, reg)
   1356 			gc.Cgen_checknil(reg)
   1357 			n1.Xoffset = -(oary[0] + 1)
   1358 		}
   1359 
   1360 		for i := 1; i < o; i++ {
   1361 			if oary[i] >= 0 {
   1362 				gc.Fatal("can't happen")
   1363 			}
   1364 			gins(movptr, &n1, reg)
   1365 			gc.Cgen_checknil(reg)
   1366 			n1.Xoffset = -(oary[i] + 1)
   1367 		}
   1368 
   1369 		a.Type = obj.TYPE_NONE
   1370 		a.Index = obj.TYPE_NONE
   1371 		gc.Fixlargeoffset(&n1)
   1372 		gc.Naddr(a, &n1)
   1373 		return true
   1374 
   1375 	case gc.OINDEX:
   1376 		return false
   1377 	}
   1378 
   1379 	return false
   1380 }
   1381