Home | History | Annotate | Download | only in arm64
      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 arm64
     32 
     33 import (
     34 	"cmd/compile/internal/gc"
     35 	"cmd/internal/obj"
     36 	"cmd/internal/obj/arm64"
     37 	"fmt"
     38 )
     39 
     40 var resvd = []int{
     41 	arm64.REGTMP,
     42 	arm64.REGG,
     43 	arm64.REGRT1,
     44 	arm64.REGRT2,
     45 	arm64.REG_R31, // REGZERO and REGSP
     46 	arm64.FREGZERO,
     47 	arm64.FREGHALF,
     48 	arm64.FREGONE,
     49 	arm64.FREGTWO,
     50 }
     51 
     52 /*
     53  * generate
     54  *	as $c, n
     55  */
     56 func ginscon(as int, c int64, n2 *gc.Node) {
     57 	var n1 gc.Node
     58 
     59 	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
     60 
     61 	if as != arm64.AMOVD && (c < -arm64.BIG || c > arm64.BIG) || as == arm64.AMUL || n2 != nil && n2.Op != gc.OREGISTER {
     62 		// cannot have more than 16-bit of immediate in ADD, etc.
     63 		// instead, MOV into register first.
     64 		var ntmp gc.Node
     65 		gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
     66 
     67 		gins(arm64.AMOVD, &n1, &ntmp)
     68 		gins(as, &ntmp, n2)
     69 		gc.Regfree(&ntmp)
     70 		return
     71 	}
     72 
     73 	rawgins(as, &n1, n2)
     74 }
     75 
     76 /*
     77  * generate
     78  *	as n, $c (CMP)
     79  */
     80 func ginscon2(as int, n2 *gc.Node, c int64) {
     81 	var n1 gc.Node
     82 
     83 	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
     84 
     85 	switch as {
     86 	default:
     87 		gc.Fatal("ginscon2")
     88 
     89 	case arm64.ACMP:
     90 		if -arm64.BIG <= c && c <= arm64.BIG {
     91 			gcmp(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(arm64.AMOVD, &n1, &ntmp)
    101 	gcmp(as, n2, &ntmp)
    102 	gc.Regfree(&ntmp)
    103 }
    104 
    105 func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
    106 	if gc.Isint[t.Etype] && 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 gc.Isint[t.Etype] && gc.Isconst(n2, gc.CTINT) {
    118 		ginscon2(optoas(gc.OCMP, t), &r1, n2.Int())
    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 		gcmp(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 /*
    134  * generate move:
    135  *	t = f
    136  * hard part is conversions.
    137  */
    138 func gmove(f *gc.Node, t *gc.Node) {
    139 	if gc.Debug['M'] != 0 {
    140 		fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
    141 	}
    142 
    143 	ft := int(gc.Simsimtype(f.Type))
    144 	tt := int(gc.Simsimtype(t.Type))
    145 	cvt := (*gc.Type)(t.Type)
    146 
    147 	if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
    148 		gc.Complexmove(f, t)
    149 		return
    150 	}
    151 
    152 	// cannot have two memory operands
    153 	var r1 gc.Node
    154 	var a int
    155 	if gc.Ismem(f) && gc.Ismem(t) {
    156 		goto hard
    157 	}
    158 
    159 	// convert constant to desired type
    160 	if f.Op == gc.OLITERAL {
    161 		var con gc.Node
    162 		switch tt {
    163 		default:
    164 			f.Convconst(&con, t.Type)
    165 
    166 		case gc.TINT32,
    167 			gc.TINT16,
    168 			gc.TINT8:
    169 			var con gc.Node
    170 			f.Convconst(&con, gc.Types[gc.TINT64])
    171 			var r1 gc.Node
    172 			gc.Regalloc(&r1, con.Type, t)
    173 			gins(arm64.AMOVD, &con, &r1)
    174 			gmove(&r1, t)
    175 			gc.Regfree(&r1)
    176 			return
    177 
    178 		case gc.TUINT32,
    179 			gc.TUINT16,
    180 			gc.TUINT8:
    181 			var con gc.Node
    182 			f.Convconst(&con, gc.Types[gc.TUINT64])
    183 			var r1 gc.Node
    184 			gc.Regalloc(&r1, con.Type, t)
    185 			gins(arm64.AMOVD, &con, &r1)
    186 			gmove(&r1, t)
    187 			gc.Regfree(&r1)
    188 			return
    189 		}
    190 
    191 		f = &con
    192 		ft = tt // so big switch will choose a simple mov
    193 
    194 		// constants can't move directly to memory.
    195 		if gc.Ismem(t) {
    196 			goto hard
    197 		}
    198 	}
    199 
    200 	// value -> value copy, first operand in memory.
    201 	// any floating point operand requires register
    202 	// src, so goto hard to copy to register first.
    203 	if gc.Ismem(f) && ft != tt && (gc.Isfloat[ft] || gc.Isfloat[tt]) {
    204 		cvt = gc.Types[ft]
    205 		goto hard
    206 	}
    207 
    208 	// value -> value copy, only one memory operand.
    209 	// figure out the instruction to use.
    210 	// break out of switch for one-instruction gins.
    211 	// goto rdst for "destination must be register".
    212 	// goto hard for "convert to cvt type first".
    213 	// otherwise handle and return.
    214 
    215 	switch uint32(ft)<<16 | uint32(tt) {
    216 	default:
    217 		gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
    218 
    219 		/*
    220 		 * integer copy and truncate
    221 		 */
    222 	case gc.TINT8<<16 | gc.TINT8, // same size
    223 		gc.TUINT8<<16 | gc.TINT8,
    224 		gc.TINT16<<16 | gc.TINT8,
    225 		// truncate
    226 		gc.TUINT16<<16 | gc.TINT8,
    227 		gc.TINT32<<16 | gc.TINT8,
    228 		gc.TUINT32<<16 | gc.TINT8,
    229 		gc.TINT64<<16 | gc.TINT8,
    230 		gc.TUINT64<<16 | gc.TINT8:
    231 		a = arm64.AMOVB
    232 
    233 	case gc.TINT8<<16 | gc.TUINT8, // same size
    234 		gc.TUINT8<<16 | gc.TUINT8,
    235 		gc.TINT16<<16 | gc.TUINT8,
    236 		// truncate
    237 		gc.TUINT16<<16 | gc.TUINT8,
    238 		gc.TINT32<<16 | gc.TUINT8,
    239 		gc.TUINT32<<16 | gc.TUINT8,
    240 		gc.TINT64<<16 | gc.TUINT8,
    241 		gc.TUINT64<<16 | gc.TUINT8:
    242 		a = arm64.AMOVBU
    243 
    244 	case gc.TINT16<<16 | gc.TINT16, // same size
    245 		gc.TUINT16<<16 | gc.TINT16,
    246 		gc.TINT32<<16 | gc.TINT16,
    247 		// truncate
    248 		gc.TUINT32<<16 | gc.TINT16,
    249 		gc.TINT64<<16 | gc.TINT16,
    250 		gc.TUINT64<<16 | gc.TINT16:
    251 		a = arm64.AMOVH
    252 
    253 	case gc.TINT16<<16 | gc.TUINT16, // same size
    254 		gc.TUINT16<<16 | gc.TUINT16,
    255 		gc.TINT32<<16 | gc.TUINT16,
    256 		// truncate
    257 		gc.TUINT32<<16 | gc.TUINT16,
    258 		gc.TINT64<<16 | gc.TUINT16,
    259 		gc.TUINT64<<16 | gc.TUINT16:
    260 		a = arm64.AMOVHU
    261 
    262 	case gc.TINT32<<16 | gc.TINT32, // same size
    263 		gc.TUINT32<<16 | gc.TINT32,
    264 		gc.TINT64<<16 | gc.TINT32,
    265 		// truncate
    266 		gc.TUINT64<<16 | gc.TINT32:
    267 		a = arm64.AMOVW
    268 
    269 	case gc.TINT32<<16 | gc.TUINT32, // same size
    270 		gc.TUINT32<<16 | gc.TUINT32,
    271 		gc.TINT64<<16 | gc.TUINT32,
    272 		gc.TUINT64<<16 | gc.TUINT32:
    273 		a = arm64.AMOVWU
    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 = arm64.AMOVD
    280 
    281 		/*
    282 		 * integer up-conversions
    283 		 */
    284 	case gc.TINT8<<16 | gc.TINT16, // sign extend int8
    285 		gc.TINT8<<16 | gc.TUINT16,
    286 		gc.TINT8<<16 | gc.TINT32,
    287 		gc.TINT8<<16 | gc.TUINT32,
    288 		gc.TINT8<<16 | gc.TINT64,
    289 		gc.TINT8<<16 | gc.TUINT64:
    290 		a = arm64.AMOVB
    291 
    292 		goto rdst
    293 
    294 	case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8
    295 		gc.TUINT8<<16 | gc.TUINT16,
    296 		gc.TUINT8<<16 | gc.TINT32,
    297 		gc.TUINT8<<16 | gc.TUINT32,
    298 		gc.TUINT8<<16 | gc.TINT64,
    299 		gc.TUINT8<<16 | gc.TUINT64:
    300 		a = arm64.AMOVBU
    301 
    302 		goto rdst
    303 
    304 	case gc.TINT16<<16 | gc.TINT32, // sign extend int16
    305 		gc.TINT16<<16 | gc.TUINT32,
    306 		gc.TINT16<<16 | gc.TINT64,
    307 		gc.TINT16<<16 | gc.TUINT64:
    308 		a = arm64.AMOVH
    309 
    310 		goto rdst
    311 
    312 	case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16
    313 		gc.TUINT16<<16 | gc.TUINT32,
    314 		gc.TUINT16<<16 | gc.TINT64,
    315 		gc.TUINT16<<16 | gc.TUINT64:
    316 		a = arm64.AMOVHU
    317 
    318 		goto rdst
    319 
    320 	case gc.TINT32<<16 | gc.TINT64, // sign extend int32
    321 		gc.TINT32<<16 | gc.TUINT64:
    322 		a = arm64.AMOVW
    323 
    324 		goto rdst
    325 
    326 	case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
    327 		gc.TUINT32<<16 | gc.TUINT64:
    328 		a = arm64.AMOVWU
    329 
    330 		goto rdst
    331 
    332 	/*
    333 	* float to integer
    334 	 */
    335 	case gc.TFLOAT32<<16 | gc.TINT32:
    336 		a = arm64.AFCVTZSSW
    337 		goto rdst
    338 
    339 	case gc.TFLOAT64<<16 | gc.TINT32:
    340 		a = arm64.AFCVTZSDW
    341 		goto rdst
    342 
    343 	case gc.TFLOAT32<<16 | gc.TINT64:
    344 		a = arm64.AFCVTZSS
    345 		goto rdst
    346 
    347 	case gc.TFLOAT64<<16 | gc.TINT64:
    348 		a = arm64.AFCVTZSD
    349 		goto rdst
    350 
    351 	case gc.TFLOAT32<<16 | gc.TUINT32:
    352 		a = arm64.AFCVTZUSW
    353 		goto rdst
    354 
    355 	case gc.TFLOAT64<<16 | gc.TUINT32:
    356 		a = arm64.AFCVTZUDW
    357 		goto rdst
    358 
    359 	case gc.TFLOAT32<<16 | gc.TUINT64:
    360 		a = arm64.AFCVTZUS
    361 		goto rdst
    362 
    363 	case gc.TFLOAT64<<16 | gc.TUINT64:
    364 		a = arm64.AFCVTZUD
    365 		goto rdst
    366 
    367 	case gc.TFLOAT32<<16 | gc.TINT16,
    368 		gc.TFLOAT32<<16 | gc.TINT8,
    369 		gc.TFLOAT64<<16 | gc.TINT16,
    370 		gc.TFLOAT64<<16 | gc.TINT8:
    371 		cvt = gc.Types[gc.TINT32]
    372 
    373 		goto hard
    374 
    375 	case gc.TFLOAT32<<16 | gc.TUINT16,
    376 		gc.TFLOAT32<<16 | gc.TUINT8,
    377 		gc.TFLOAT64<<16 | gc.TUINT16,
    378 		gc.TFLOAT64<<16 | gc.TUINT8:
    379 		cvt = gc.Types[gc.TUINT32]
    380 
    381 		goto hard
    382 
    383 	/*
    384 	 * integer to float
    385 	 */
    386 	case gc.TINT8<<16 | gc.TFLOAT32,
    387 		gc.TINT16<<16 | gc.TFLOAT32,
    388 		gc.TINT32<<16 | gc.TFLOAT32:
    389 		a = arm64.ASCVTFWS
    390 
    391 		goto rdst
    392 
    393 	case gc.TINT8<<16 | gc.TFLOAT64,
    394 		gc.TINT16<<16 | gc.TFLOAT64,
    395 		gc.TINT32<<16 | gc.TFLOAT64:
    396 		a = arm64.ASCVTFWD
    397 
    398 		goto rdst
    399 
    400 	case gc.TINT64<<16 | gc.TFLOAT32:
    401 		a = arm64.ASCVTFS
    402 		goto rdst
    403 
    404 	case gc.TINT64<<16 | gc.TFLOAT64:
    405 		a = arm64.ASCVTFD
    406 		goto rdst
    407 
    408 	case gc.TUINT8<<16 | gc.TFLOAT32,
    409 		gc.TUINT16<<16 | gc.TFLOAT32,
    410 		gc.TUINT32<<16 | gc.TFLOAT32:
    411 		a = arm64.AUCVTFWS
    412 
    413 		goto rdst
    414 
    415 	case gc.TUINT8<<16 | gc.TFLOAT64,
    416 		gc.TUINT16<<16 | gc.TFLOAT64,
    417 		gc.TUINT32<<16 | gc.TFLOAT64:
    418 		a = arm64.AUCVTFWD
    419 
    420 		goto rdst
    421 
    422 	case gc.TUINT64<<16 | gc.TFLOAT32:
    423 		a = arm64.AUCVTFS
    424 		goto rdst
    425 
    426 	case gc.TUINT64<<16 | gc.TFLOAT64:
    427 		a = arm64.AUCVTFD
    428 		goto rdst
    429 
    430 		/*
    431 		 * float to float
    432 		 */
    433 	case gc.TFLOAT32<<16 | gc.TFLOAT32:
    434 		a = arm64.AFMOVS
    435 
    436 	case gc.TFLOAT64<<16 | gc.TFLOAT64:
    437 		a = arm64.AFMOVD
    438 
    439 	case gc.TFLOAT32<<16 | gc.TFLOAT64:
    440 		a = arm64.AFCVTSD
    441 		goto rdst
    442 
    443 	case gc.TFLOAT64<<16 | gc.TFLOAT32:
    444 		a = arm64.AFCVTDS
    445 		goto rdst
    446 	}
    447 
    448 	gins(a, f, t)
    449 	return
    450 
    451 	// requires register destination
    452 rdst:
    453 	gc.Regalloc(&r1, t.Type, t)
    454 
    455 	gins(a, f, &r1)
    456 	gmove(&r1, t)
    457 	gc.Regfree(&r1)
    458 	return
    459 
    460 	// requires register intermediate
    461 hard:
    462 	gc.Regalloc(&r1, cvt, t)
    463 
    464 	gmove(f, &r1)
    465 	gmove(&r1, t)
    466 	gc.Regfree(&r1)
    467 	return
    468 }
    469 
    470 func intLiteral(n *gc.Node) (x int64, ok bool) {
    471 	switch {
    472 	case n == nil:
    473 		return
    474 	case gc.Isconst(n, gc.CTINT):
    475 		return n.Int(), true
    476 	case gc.Isconst(n, gc.CTBOOL):
    477 		return int64(obj.Bool2int(n.Bool())), true
    478 	}
    479 	return
    480 }
    481 
    482 // gins is called by the front end.
    483 // It synthesizes some multiple-instruction sequences
    484 // so the front end can stay simpler.
    485 func gins(as int, f, t *gc.Node) *obj.Prog {
    486 	if as >= obj.A_ARCHSPECIFIC {
    487 		if x, ok := intLiteral(f); ok {
    488 			ginscon(as, x, t)
    489 			return nil // caller must not use
    490 		}
    491 	}
    492 	if as == arm64.ACMP {
    493 		if x, ok := intLiteral(t); ok {
    494 			ginscon2(as, f, x)
    495 			return nil // caller must not use
    496 		}
    497 	}
    498 	return rawgins(as, f, t)
    499 }
    500 
    501 /*
    502  * generate one instruction:
    503  *	as f, t
    504  */
    505 func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
    506 	// TODO(austin): Add self-move test like in 6g (but be careful
    507 	// of truncation moves)
    508 
    509 	p := gc.Prog(as)
    510 	gc.Naddr(&p.From, f)
    511 	gc.Naddr(&p.To, t)
    512 
    513 	switch as {
    514 	case arm64.ACMP, arm64.AFCMPS, arm64.AFCMPD:
    515 		if t != nil {
    516 			if f.Op != gc.OREGISTER {
    517 				gc.Fatal("bad operands to gcmp")
    518 			}
    519 			p.From = p.To
    520 			p.To = obj.Addr{}
    521 			raddr(f, p)
    522 		}
    523 	}
    524 
    525 	// Bad things the front end has done to us. Crash to find call stack.
    526 	switch as {
    527 	case arm64.AAND, arm64.AMUL:
    528 		if p.From.Type == obj.TYPE_CONST {
    529 			gc.Debug['h'] = 1
    530 			gc.Fatal("bad inst: %v", p)
    531 		}
    532 	case arm64.ACMP:
    533 		if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
    534 			gc.Debug['h'] = 1
    535 			gc.Fatal("bad inst: %v", p)
    536 		}
    537 	}
    538 
    539 	if gc.Debug['g'] != 0 {
    540 		fmt.Printf("%v\n", p)
    541 	}
    542 
    543 	w := int32(0)
    544 	switch as {
    545 	case arm64.AMOVB,
    546 		arm64.AMOVBU:
    547 		w = 1
    548 
    549 	case arm64.AMOVH,
    550 		arm64.AMOVHU:
    551 		w = 2
    552 
    553 	case arm64.AMOVW,
    554 		arm64.AMOVWU:
    555 		w = 4
    556 
    557 	case arm64.AMOVD:
    558 		if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR {
    559 			break
    560 		}
    561 		w = 8
    562 	}
    563 
    564 	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) {
    565 		gc.Dump("f", f)
    566 		gc.Dump("t", t)
    567 		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
    568 	}
    569 
    570 	return p
    571 }
    572 
    573 /*
    574  * insert n into reg slot of p
    575  */
    576 func raddr(n *gc.Node, p *obj.Prog) {
    577 	var a obj.Addr
    578 
    579 	gc.Naddr(&a, n)
    580 	if a.Type != obj.TYPE_REG {
    581 		if n != nil {
    582 			gc.Fatal("bad in raddr: %v", gc.Oconv(int(n.Op), 0))
    583 		} else {
    584 			gc.Fatal("bad in raddr: <null>")
    585 		}
    586 		p.Reg = 0
    587 	} else {
    588 		p.Reg = a.Reg
    589 	}
    590 }
    591 
    592 func gcmp(as int, lhs *gc.Node, rhs *gc.Node) *obj.Prog {
    593 	if lhs.Op != gc.OREGISTER {
    594 		gc.Fatal("bad operands to gcmp: %v %v", gc.Oconv(int(lhs.Op), 0), gc.Oconv(int(rhs.Op), 0))
    595 	}
    596 
    597 	p := rawgins(as, rhs, nil)
    598 	raddr(lhs, p)
    599 	return p
    600 }
    601 
    602 /*
    603  * return Axxx for Oxxx on type t.
    604  */
    605 func optoas(op int, t *gc.Type) int {
    606 	if t == nil {
    607 		gc.Fatal("optoas: t is nil")
    608 	}
    609 
    610 	a := int(obj.AXXX)
    611 	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
    612 	default:
    613 		gc.Fatal("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
    614 
    615 	case gc.OEQ<<16 | gc.TBOOL,
    616 		gc.OEQ<<16 | gc.TINT8,
    617 		gc.OEQ<<16 | gc.TUINT8,
    618 		gc.OEQ<<16 | gc.TINT16,
    619 		gc.OEQ<<16 | gc.TUINT16,
    620 		gc.OEQ<<16 | gc.TINT32,
    621 		gc.OEQ<<16 | gc.TUINT32,
    622 		gc.OEQ<<16 | gc.TINT64,
    623 		gc.OEQ<<16 | gc.TUINT64,
    624 		gc.OEQ<<16 | gc.TPTR32,
    625 		gc.OEQ<<16 | gc.TPTR64,
    626 		gc.OEQ<<16 | gc.TFLOAT32,
    627 		gc.OEQ<<16 | gc.TFLOAT64:
    628 		a = arm64.ABEQ
    629 
    630 	case gc.ONE<<16 | gc.TBOOL,
    631 		gc.ONE<<16 | gc.TINT8,
    632 		gc.ONE<<16 | gc.TUINT8,
    633 		gc.ONE<<16 | gc.TINT16,
    634 		gc.ONE<<16 | gc.TUINT16,
    635 		gc.ONE<<16 | gc.TINT32,
    636 		gc.ONE<<16 | gc.TUINT32,
    637 		gc.ONE<<16 | gc.TINT64,
    638 		gc.ONE<<16 | gc.TUINT64,
    639 		gc.ONE<<16 | gc.TPTR32,
    640 		gc.ONE<<16 | gc.TPTR64,
    641 		gc.ONE<<16 | gc.TFLOAT32,
    642 		gc.ONE<<16 | gc.TFLOAT64:
    643 		a = arm64.ABNE
    644 
    645 	case gc.OLT<<16 | gc.TINT8,
    646 		gc.OLT<<16 | gc.TINT16,
    647 		gc.OLT<<16 | gc.TINT32,
    648 		gc.OLT<<16 | gc.TINT64:
    649 		a = arm64.ABLT
    650 
    651 	case gc.OLT<<16 | gc.TUINT8,
    652 		gc.OLT<<16 | gc.TUINT16,
    653 		gc.OLT<<16 | gc.TUINT32,
    654 		gc.OLT<<16 | gc.TUINT64,
    655 		gc.OLT<<16 | gc.TFLOAT32,
    656 		gc.OLT<<16 | gc.TFLOAT64:
    657 		a = arm64.ABLO
    658 
    659 	case gc.OLE<<16 | gc.TINT8,
    660 		gc.OLE<<16 | gc.TINT16,
    661 		gc.OLE<<16 | gc.TINT32,
    662 		gc.OLE<<16 | gc.TINT64:
    663 		a = arm64.ABLE
    664 
    665 	case gc.OLE<<16 | gc.TUINT8,
    666 		gc.OLE<<16 | gc.TUINT16,
    667 		gc.OLE<<16 | gc.TUINT32,
    668 		gc.OLE<<16 | gc.TUINT64,
    669 		gc.OLE<<16 | gc.TFLOAT32,
    670 		gc.OLE<<16 | gc.TFLOAT64:
    671 		a = arm64.ABLS
    672 
    673 	case gc.OGT<<16 | gc.TINT8,
    674 		gc.OGT<<16 | gc.TINT16,
    675 		gc.OGT<<16 | gc.TINT32,
    676 		gc.OGT<<16 | gc.TINT64,
    677 		gc.OGT<<16 | gc.TFLOAT32,
    678 		gc.OGT<<16 | gc.TFLOAT64:
    679 		a = arm64.ABGT
    680 
    681 	case gc.OGT<<16 | gc.TUINT8,
    682 		gc.OGT<<16 | gc.TUINT16,
    683 		gc.OGT<<16 | gc.TUINT32,
    684 		gc.OGT<<16 | gc.TUINT64:
    685 		a = arm64.ABHI
    686 
    687 	case gc.OGE<<16 | gc.TINT8,
    688 		gc.OGE<<16 | gc.TINT16,
    689 		gc.OGE<<16 | gc.TINT32,
    690 		gc.OGE<<16 | gc.TINT64,
    691 		gc.OGE<<16 | gc.TFLOAT32,
    692 		gc.OGE<<16 | gc.TFLOAT64:
    693 		a = arm64.ABGE
    694 
    695 	case gc.OGE<<16 | gc.TUINT8,
    696 		gc.OGE<<16 | gc.TUINT16,
    697 		gc.OGE<<16 | gc.TUINT32,
    698 		gc.OGE<<16 | gc.TUINT64:
    699 		a = arm64.ABHS
    700 
    701 	case gc.OCMP<<16 | gc.TBOOL,
    702 		gc.OCMP<<16 | gc.TINT8,
    703 		gc.OCMP<<16 | gc.TINT16,
    704 		gc.OCMP<<16 | gc.TINT32,
    705 		gc.OCMP<<16 | gc.TPTR32,
    706 		gc.OCMP<<16 | gc.TINT64,
    707 		gc.OCMP<<16 | gc.TUINT8,
    708 		gc.OCMP<<16 | gc.TUINT16,
    709 		gc.OCMP<<16 | gc.TUINT32,
    710 		gc.OCMP<<16 | gc.TUINT64,
    711 		gc.OCMP<<16 | gc.TPTR64:
    712 		a = arm64.ACMP
    713 
    714 	case gc.OCMP<<16 | gc.TFLOAT32:
    715 		a = arm64.AFCMPS
    716 
    717 	case gc.OCMP<<16 | gc.TFLOAT64:
    718 		a = arm64.AFCMPD
    719 
    720 	case gc.OAS<<16 | gc.TBOOL,
    721 		gc.OAS<<16 | gc.TINT8:
    722 		a = arm64.AMOVB
    723 
    724 	case gc.OAS<<16 | gc.TUINT8:
    725 		a = arm64.AMOVBU
    726 
    727 	case gc.OAS<<16 | gc.TINT16:
    728 		a = arm64.AMOVH
    729 
    730 	case gc.OAS<<16 | gc.TUINT16:
    731 		a = arm64.AMOVHU
    732 
    733 	case gc.OAS<<16 | gc.TINT32:
    734 		a = arm64.AMOVW
    735 
    736 	case gc.OAS<<16 | gc.TUINT32,
    737 		gc.OAS<<16 | gc.TPTR32:
    738 		a = arm64.AMOVWU
    739 
    740 	case gc.OAS<<16 | gc.TINT64,
    741 		gc.OAS<<16 | gc.TUINT64,
    742 		gc.OAS<<16 | gc.TPTR64:
    743 		a = arm64.AMOVD
    744 
    745 	case gc.OAS<<16 | gc.TFLOAT32:
    746 		a = arm64.AFMOVS
    747 
    748 	case gc.OAS<<16 | gc.TFLOAT64:
    749 		a = arm64.AFMOVD
    750 
    751 	case gc.OADD<<16 | gc.TINT8,
    752 		gc.OADD<<16 | gc.TUINT8,
    753 		gc.OADD<<16 | gc.TINT16,
    754 		gc.OADD<<16 | gc.TUINT16,
    755 		gc.OADD<<16 | gc.TINT32,
    756 		gc.OADD<<16 | gc.TUINT32,
    757 		gc.OADD<<16 | gc.TPTR32,
    758 		gc.OADD<<16 | gc.TINT64,
    759 		gc.OADD<<16 | gc.TUINT64,
    760 		gc.OADD<<16 | gc.TPTR64:
    761 		a = arm64.AADD
    762 
    763 	case gc.OADD<<16 | gc.TFLOAT32:
    764 		a = arm64.AFADDS
    765 
    766 	case gc.OADD<<16 | gc.TFLOAT64:
    767 		a = arm64.AFADDD
    768 
    769 	case gc.OSUB<<16 | gc.TINT8,
    770 		gc.OSUB<<16 | gc.TUINT8,
    771 		gc.OSUB<<16 | gc.TINT16,
    772 		gc.OSUB<<16 | gc.TUINT16,
    773 		gc.OSUB<<16 | gc.TINT32,
    774 		gc.OSUB<<16 | gc.TUINT32,
    775 		gc.OSUB<<16 | gc.TPTR32,
    776 		gc.OSUB<<16 | gc.TINT64,
    777 		gc.OSUB<<16 | gc.TUINT64,
    778 		gc.OSUB<<16 | gc.TPTR64:
    779 		a = arm64.ASUB
    780 
    781 	case gc.OSUB<<16 | gc.TFLOAT32:
    782 		a = arm64.AFSUBS
    783 
    784 	case gc.OSUB<<16 | gc.TFLOAT64:
    785 		a = arm64.AFSUBD
    786 
    787 	case gc.OMINUS<<16 | gc.TINT8,
    788 		gc.OMINUS<<16 | gc.TUINT8,
    789 		gc.OMINUS<<16 | gc.TINT16,
    790 		gc.OMINUS<<16 | gc.TUINT16,
    791 		gc.OMINUS<<16 | gc.TINT32,
    792 		gc.OMINUS<<16 | gc.TUINT32,
    793 		gc.OMINUS<<16 | gc.TPTR32,
    794 		gc.OMINUS<<16 | gc.TINT64,
    795 		gc.OMINUS<<16 | gc.TUINT64,
    796 		gc.OMINUS<<16 | gc.TPTR64:
    797 		a = arm64.ANEG
    798 
    799 	case gc.OMINUS<<16 | gc.TFLOAT32:
    800 		a = arm64.AFNEGS
    801 
    802 	case gc.OMINUS<<16 | gc.TFLOAT64:
    803 		a = arm64.AFNEGD
    804 
    805 	case gc.OAND<<16 | gc.TINT8,
    806 		gc.OAND<<16 | gc.TUINT8,
    807 		gc.OAND<<16 | gc.TINT16,
    808 		gc.OAND<<16 | gc.TUINT16,
    809 		gc.OAND<<16 | gc.TINT32,
    810 		gc.OAND<<16 | gc.TUINT32,
    811 		gc.OAND<<16 | gc.TPTR32,
    812 		gc.OAND<<16 | gc.TINT64,
    813 		gc.OAND<<16 | gc.TUINT64,
    814 		gc.OAND<<16 | gc.TPTR64:
    815 		a = arm64.AAND
    816 
    817 	case gc.OOR<<16 | gc.TINT8,
    818 		gc.OOR<<16 | gc.TUINT8,
    819 		gc.OOR<<16 | gc.TINT16,
    820 		gc.OOR<<16 | gc.TUINT16,
    821 		gc.OOR<<16 | gc.TINT32,
    822 		gc.OOR<<16 | gc.TUINT32,
    823 		gc.OOR<<16 | gc.TPTR32,
    824 		gc.OOR<<16 | gc.TINT64,
    825 		gc.OOR<<16 | gc.TUINT64,
    826 		gc.OOR<<16 | gc.TPTR64:
    827 		a = arm64.AORR
    828 
    829 	case gc.OXOR<<16 | gc.TINT8,
    830 		gc.OXOR<<16 | gc.TUINT8,
    831 		gc.OXOR<<16 | gc.TINT16,
    832 		gc.OXOR<<16 | gc.TUINT16,
    833 		gc.OXOR<<16 | gc.TINT32,
    834 		gc.OXOR<<16 | gc.TUINT32,
    835 		gc.OXOR<<16 | gc.TPTR32,
    836 		gc.OXOR<<16 | gc.TINT64,
    837 		gc.OXOR<<16 | gc.TUINT64,
    838 		gc.OXOR<<16 | gc.TPTR64:
    839 		a = arm64.AEOR
    840 
    841 		// TODO(minux): handle rotates
    842 	//case CASE(OLROT, TINT8):
    843 	//case CASE(OLROT, TUINT8):
    844 	//case CASE(OLROT, TINT16):
    845 	//case CASE(OLROT, TUINT16):
    846 	//case CASE(OLROT, TINT32):
    847 	//case CASE(OLROT, TUINT32):
    848 	//case CASE(OLROT, TPTR32):
    849 	//case CASE(OLROT, TINT64):
    850 	//case CASE(OLROT, TUINT64):
    851 	//case CASE(OLROT, TPTR64):
    852 	//	a = 0//???; RLDC?
    853 	//	break;
    854 
    855 	case gc.OLSH<<16 | gc.TINT8,
    856 		gc.OLSH<<16 | gc.TUINT8,
    857 		gc.OLSH<<16 | gc.TINT16,
    858 		gc.OLSH<<16 | gc.TUINT16,
    859 		gc.OLSH<<16 | gc.TINT32,
    860 		gc.OLSH<<16 | gc.TUINT32,
    861 		gc.OLSH<<16 | gc.TPTR32,
    862 		gc.OLSH<<16 | gc.TINT64,
    863 		gc.OLSH<<16 | gc.TUINT64,
    864 		gc.OLSH<<16 | gc.TPTR64:
    865 		a = arm64.ALSL
    866 
    867 	case gc.ORSH<<16 | gc.TUINT8,
    868 		gc.ORSH<<16 | gc.TUINT16,
    869 		gc.ORSH<<16 | gc.TUINT32,
    870 		gc.ORSH<<16 | gc.TPTR32,
    871 		gc.ORSH<<16 | gc.TUINT64,
    872 		gc.ORSH<<16 | gc.TPTR64:
    873 		a = arm64.ALSR
    874 
    875 	case gc.ORSH<<16 | gc.TINT8,
    876 		gc.ORSH<<16 | gc.TINT16,
    877 		gc.ORSH<<16 | gc.TINT32,
    878 		gc.ORSH<<16 | gc.TINT64:
    879 		a = arm64.AASR
    880 
    881 		// TODO(minux): handle rotates
    882 	//case CASE(ORROTC, TINT8):
    883 	//case CASE(ORROTC, TUINT8):
    884 	//case CASE(ORROTC, TINT16):
    885 	//case CASE(ORROTC, TUINT16):
    886 	//case CASE(ORROTC, TINT32):
    887 	//case CASE(ORROTC, TUINT32):
    888 	//case CASE(ORROTC, TINT64):
    889 	//case CASE(ORROTC, TUINT64):
    890 	//	a = 0//??? RLDC??
    891 	//	break;
    892 
    893 	case gc.OHMUL<<16 | gc.TINT64:
    894 		a = arm64.ASMULH
    895 
    896 	case gc.OHMUL<<16 | gc.TUINT64,
    897 		gc.OHMUL<<16 | gc.TPTR64:
    898 		a = arm64.AUMULH
    899 
    900 	case gc.OMUL<<16 | gc.TINT8,
    901 		gc.OMUL<<16 | gc.TINT16,
    902 		gc.OMUL<<16 | gc.TINT32:
    903 		a = arm64.ASMULL
    904 
    905 	case gc.OMUL<<16 | gc.TINT64:
    906 		a = arm64.AMUL
    907 
    908 	case gc.OMUL<<16 | gc.TUINT8,
    909 		gc.OMUL<<16 | gc.TUINT16,
    910 		gc.OMUL<<16 | gc.TUINT32,
    911 		gc.OMUL<<16 | gc.TPTR32:
    912 		// don't use word multiply, the high 32-bit are undefined.
    913 		a = arm64.AUMULL
    914 
    915 	case gc.OMUL<<16 | gc.TUINT64,
    916 		gc.OMUL<<16 | gc.TPTR64:
    917 		a = arm64.AMUL // for 64-bit multiplies, signedness doesn't matter.
    918 
    919 	case gc.OMUL<<16 | gc.TFLOAT32:
    920 		a = arm64.AFMULS
    921 
    922 	case gc.OMUL<<16 | gc.TFLOAT64:
    923 		a = arm64.AFMULD
    924 
    925 	case gc.ODIV<<16 | gc.TINT8,
    926 		gc.ODIV<<16 | gc.TINT16,
    927 		gc.ODIV<<16 | gc.TINT32,
    928 		gc.ODIV<<16 | gc.TINT64:
    929 		a = arm64.ASDIV
    930 
    931 	case gc.ODIV<<16 | gc.TUINT8,
    932 		gc.ODIV<<16 | gc.TUINT16,
    933 		gc.ODIV<<16 | gc.TUINT32,
    934 		gc.ODIV<<16 | gc.TPTR32,
    935 		gc.ODIV<<16 | gc.TUINT64,
    936 		gc.ODIV<<16 | gc.TPTR64:
    937 		a = arm64.AUDIV
    938 
    939 	case gc.ODIV<<16 | gc.TFLOAT32:
    940 		a = arm64.AFDIVS
    941 
    942 	case gc.ODIV<<16 | gc.TFLOAT64:
    943 		a = arm64.AFDIVD
    944 
    945 	case gc.OSQRT<<16 | gc.TFLOAT64:
    946 		a = arm64.AFSQRTD
    947 	}
    948 
    949 	return a
    950 }
    951 
    952 const (
    953 	ODynam   = 1 << 0
    954 	OAddable = 1 << 1
    955 )
    956 
    957 func xgen(n *gc.Node, a *gc.Node, o int) bool {
    958 	// TODO(minux)
    959 
    960 	return -1 != 0 /*TypeKind(100016)*/
    961 }
    962 
    963 func sudoclean() {
    964 	return
    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 int, n *gc.Node, a *obj.Addr) bool {
    979 	// TODO(minux)
    980 
    981 	*a = obj.Addr{}
    982 	return false
    983 }
    984