Home | History | Annotate | Download | only in arm
      1 // Do not edit. Bootstrap copy of /Volumes/Android/buildbot/src/android/build-tools/out/obj/go/src/cmd/compile/internal/arm/cgen64.go
      2 
      3 //line /Volumes/Android/buildbot/src/android/build-tools/out/obj/go/src/cmd/compile/internal/arm/cgen64.go:1
      4 // Copyright 2009 The Go Authors. All rights reserved.
      5 // Use of this source code is governed by a BSD-style
      6 // license that can be found in the LICENSE file.
      7 
      8 package arm
      9 
     10 import (
     11 	"bootstrap/compile/internal/gc"
     12 	"bootstrap/internal/obj"
     13 	"bootstrap/internal/obj/arm"
     14 )
     15 
     16 /*
     17  * attempt to generate 64-bit
     18  *	res = n
     19  * return 1 on success, 0 if op not handled.
     20  */
     21 func cgen64(n *gc.Node, res *gc.Node) {
     22 	if res.Op != gc.OINDREG && res.Op != gc.ONAME {
     23 		gc.Dump("n", n)
     24 		gc.Dump("res", res)
     25 		gc.Fatal("cgen64 %v of %v", gc.Oconv(int(n.Op), 0), gc.Oconv(int(res.Op), 0))
     26 	}
     27 
     28 	l := n.Left
     29 	var t1 gc.Node
     30 	if !l.Addable {
     31 		gc.Tempname(&t1, l.Type)
     32 		gc.Cgen(l, &t1)
     33 		l = &t1
     34 	}
     35 
     36 	var hi1 gc.Node
     37 	var lo1 gc.Node
     38 	split64(l, &lo1, &hi1)
     39 	switch n.Op {
     40 	default:
     41 		gc.Fatal("cgen64 %v", gc.Oconv(int(n.Op), 0))
     42 
     43 	case gc.OMINUS:
     44 		var lo2 gc.Node
     45 		var hi2 gc.Node
     46 		split64(res, &lo2, &hi2)
     47 
     48 		gc.Regalloc(&t1, lo1.Type, nil)
     49 		var al gc.Node
     50 		gc.Regalloc(&al, lo1.Type, nil)
     51 		var ah gc.Node
     52 		gc.Regalloc(&ah, hi1.Type, nil)
     53 
     54 		gins(arm.AMOVW, &lo1, &al)
     55 		gins(arm.AMOVW, &hi1, &ah)
     56 
     57 		gmove(ncon(0), &t1)
     58 		p1 := gins(arm.ASUB, &al, &t1)
     59 		p1.Scond |= arm.C_SBIT
     60 		gins(arm.AMOVW, &t1, &lo2)
     61 
     62 		gmove(ncon(0), &t1)
     63 		gins(arm.ASBC, &ah, &t1)
     64 		gins(arm.AMOVW, &t1, &hi2)
     65 
     66 		gc.Regfree(&t1)
     67 		gc.Regfree(&al)
     68 		gc.Regfree(&ah)
     69 		splitclean()
     70 		splitclean()
     71 		return
     72 
     73 	case gc.OCOM:
     74 		gc.Regalloc(&t1, lo1.Type, nil)
     75 		gmove(ncon(^uint32(0)), &t1)
     76 
     77 		var lo2 gc.Node
     78 		var hi2 gc.Node
     79 		split64(res, &lo2, &hi2)
     80 		var n1 gc.Node
     81 		gc.Regalloc(&n1, lo1.Type, nil)
     82 
     83 		gins(arm.AMOVW, &lo1, &n1)
     84 		gins(arm.AEOR, &t1, &n1)
     85 		gins(arm.AMOVW, &n1, &lo2)
     86 
     87 		gins(arm.AMOVW, &hi1, &n1)
     88 		gins(arm.AEOR, &t1, &n1)
     89 		gins(arm.AMOVW, &n1, &hi2)
     90 
     91 		gc.Regfree(&t1)
     92 		gc.Regfree(&n1)
     93 		splitclean()
     94 		splitclean()
     95 		return
     96 
     97 		// binary operators.
     98 	// common setup below.
     99 	case gc.OADD,
    100 		gc.OSUB,
    101 		gc.OMUL,
    102 		gc.OLSH,
    103 		gc.ORSH,
    104 		gc.OAND,
    105 		gc.OOR,
    106 		gc.OXOR,
    107 		gc.OLROT:
    108 		break
    109 	}
    110 
    111 	// setup for binary operators
    112 	r := n.Right
    113 
    114 	if r != nil && !r.Addable {
    115 		var t2 gc.Node
    116 		gc.Tempname(&t2, r.Type)
    117 		gc.Cgen(r, &t2)
    118 		r = &t2
    119 	}
    120 
    121 	var hi2 gc.Node
    122 	var lo2 gc.Node
    123 	if gc.Is64(r.Type) {
    124 		split64(r, &lo2, &hi2)
    125 	}
    126 
    127 	var al gc.Node
    128 	gc.Regalloc(&al, lo1.Type, nil)
    129 	var ah gc.Node
    130 	gc.Regalloc(&ah, hi1.Type, nil)
    131 
    132 	// Do op.  Leave result in ah:al.
    133 	switch n.Op {
    134 	default:
    135 		gc.Fatal("cgen64: not implemented: %v\n", n)
    136 
    137 		// TODO: Constants
    138 	case gc.OADD:
    139 		var bl gc.Node
    140 		gc.Regalloc(&bl, gc.Types[gc.TPTR32], nil)
    141 
    142 		var bh gc.Node
    143 		gc.Regalloc(&bh, gc.Types[gc.TPTR32], nil)
    144 		gins(arm.AMOVW, &hi1, &ah)
    145 		gins(arm.AMOVW, &lo1, &al)
    146 		gins(arm.AMOVW, &hi2, &bh)
    147 		gins(arm.AMOVW, &lo2, &bl)
    148 		p1 := gins(arm.AADD, &bl, &al)
    149 		p1.Scond |= arm.C_SBIT
    150 		gins(arm.AADC, &bh, &ah)
    151 		gc.Regfree(&bl)
    152 		gc.Regfree(&bh)
    153 
    154 		// TODO: Constants.
    155 	case gc.OSUB:
    156 		var bl gc.Node
    157 		gc.Regalloc(&bl, gc.Types[gc.TPTR32], nil)
    158 
    159 		var bh gc.Node
    160 		gc.Regalloc(&bh, gc.Types[gc.TPTR32], nil)
    161 		gins(arm.AMOVW, &lo1, &al)
    162 		gins(arm.AMOVW, &hi1, &ah)
    163 		gins(arm.AMOVW, &lo2, &bl)
    164 		gins(arm.AMOVW, &hi2, &bh)
    165 		p1 := gins(arm.ASUB, &bl, &al)
    166 		p1.Scond |= arm.C_SBIT
    167 		gins(arm.ASBC, &bh, &ah)
    168 		gc.Regfree(&bl)
    169 		gc.Regfree(&bh)
    170 
    171 		// TODO(kaib): this can be done with 4 regs and does not need 6
    172 	case gc.OMUL:
    173 		var bl gc.Node
    174 		gc.Regalloc(&bl, gc.Types[gc.TPTR32], nil)
    175 
    176 		var bh gc.Node
    177 		gc.Regalloc(&bh, gc.Types[gc.TPTR32], nil)
    178 		var cl gc.Node
    179 		gc.Regalloc(&cl, gc.Types[gc.TPTR32], nil)
    180 		var ch gc.Node
    181 		gc.Regalloc(&ch, gc.Types[gc.TPTR32], nil)
    182 
    183 		// load args into bh:bl and bh:bl.
    184 		gins(arm.AMOVW, &hi1, &bh)
    185 
    186 		gins(arm.AMOVW, &lo1, &bl)
    187 		gins(arm.AMOVW, &hi2, &ch)
    188 		gins(arm.AMOVW, &lo2, &cl)
    189 
    190 		// bl * cl -> ah al
    191 		p1 := gins(arm.AMULLU, nil, nil)
    192 
    193 		p1.From.Type = obj.TYPE_REG
    194 		p1.From.Reg = bl.Reg
    195 		p1.Reg = cl.Reg
    196 		p1.To.Type = obj.TYPE_REGREG
    197 		p1.To.Reg = ah.Reg
    198 		p1.To.Offset = int64(al.Reg)
    199 
    200 		//print("%v\n", p1);
    201 
    202 		// bl * ch + ah -> ah
    203 		p1 = gins(arm.AMULA, nil, nil)
    204 
    205 		p1.From.Type = obj.TYPE_REG
    206 		p1.From.Reg = bl.Reg
    207 		p1.Reg = ch.Reg
    208 		p1.To.Type = obj.TYPE_REGREG2
    209 		p1.To.Reg = ah.Reg
    210 		p1.To.Offset = int64(ah.Reg)
    211 
    212 		//print("%v\n", p1);
    213 
    214 		// bh * cl + ah -> ah
    215 		p1 = gins(arm.AMULA, nil, nil)
    216 
    217 		p1.From.Type = obj.TYPE_REG
    218 		p1.From.Reg = bh.Reg
    219 		p1.Reg = cl.Reg
    220 		p1.To.Type = obj.TYPE_REGREG2
    221 		p1.To.Reg = ah.Reg
    222 		p1.To.Offset = int64(ah.Reg)
    223 
    224 		//print("%v\n", p1);
    225 
    226 		gc.Regfree(&bh)
    227 
    228 		gc.Regfree(&bl)
    229 		gc.Regfree(&ch)
    230 		gc.Regfree(&cl)
    231 
    232 		// We only rotate by a constant c in [0,64).
    233 	// if c >= 32:
    234 	//	lo, hi = hi, lo
    235 	//	c -= 32
    236 	// if c == 0:
    237 	//	no-op
    238 	// else:
    239 	//	t = hi
    240 	//	shld hi:lo, c
    241 	//	shld lo:t, c
    242 	case gc.OLROT:
    243 		v := uint64(r.Int())
    244 
    245 		var bl gc.Node
    246 		gc.Regalloc(&bl, lo1.Type, nil)
    247 		var bh gc.Node
    248 		gc.Regalloc(&bh, hi1.Type, nil)
    249 		if v >= 32 {
    250 			// reverse during load to do the first 32 bits of rotate
    251 			v -= 32
    252 
    253 			gins(arm.AMOVW, &hi1, &bl)
    254 			gins(arm.AMOVW, &lo1, &bh)
    255 		} else {
    256 			gins(arm.AMOVW, &hi1, &bh)
    257 			gins(arm.AMOVW, &lo1, &bl)
    258 		}
    259 
    260 		if v == 0 {
    261 			gins(arm.AMOVW, &bh, &ah)
    262 			gins(arm.AMOVW, &bl, &al)
    263 		} else {
    264 			// rotate by 1 <= v <= 31
    265 			//	MOVW	bl<<v, al
    266 			//	MOVW	bh<<v, ah
    267 			//	OR		bl>>(32-v), ah
    268 			//	OR		bh>>(32-v), al
    269 			gshift(arm.AMOVW, &bl, arm.SHIFT_LL, int32(v), &al)
    270 
    271 			gshift(arm.AMOVW, &bh, arm.SHIFT_LL, int32(v), &ah)
    272 			gshift(arm.AORR, &bl, arm.SHIFT_LR, int32(32-v), &ah)
    273 			gshift(arm.AORR, &bh, arm.SHIFT_LR, int32(32-v), &al)
    274 		}
    275 
    276 		gc.Regfree(&bl)
    277 		gc.Regfree(&bh)
    278 
    279 	case gc.OLSH:
    280 		var bl gc.Node
    281 		gc.Regalloc(&bl, lo1.Type, nil)
    282 		var bh gc.Node
    283 		gc.Regalloc(&bh, hi1.Type, nil)
    284 		gins(arm.AMOVW, &hi1, &bh)
    285 		gins(arm.AMOVW, &lo1, &bl)
    286 
    287 		var p6 *obj.Prog
    288 		var s gc.Node
    289 		var n1 gc.Node
    290 		var creg gc.Node
    291 		var p1 *obj.Prog
    292 		var p2 *obj.Prog
    293 		var p3 *obj.Prog
    294 		var p4 *obj.Prog
    295 		var p5 *obj.Prog
    296 		if r.Op == gc.OLITERAL {
    297 			v := uint64(r.Int())
    298 			if v >= 64 {
    299 				// TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
    300 				// here and below (verify it optimizes to EOR)
    301 				gins(arm.AEOR, &al, &al)
    302 
    303 				gins(arm.AEOR, &ah, &ah)
    304 			} else if v > 32 {
    305 				gins(arm.AEOR, &al, &al)
    306 
    307 				//	MOVW	bl<<(v-32), ah
    308 				gshift(arm.AMOVW, &bl, arm.SHIFT_LL, int32(v-32), &ah)
    309 			} else if v == 32 {
    310 				gins(arm.AEOR, &al, &al)
    311 				gins(arm.AMOVW, &bl, &ah)
    312 			} else if v > 0 {
    313 				//	MOVW	bl<<v, al
    314 				gshift(arm.AMOVW, &bl, arm.SHIFT_LL, int32(v), &al)
    315 
    316 				//	MOVW	bh<<v, ah
    317 				gshift(arm.AMOVW, &bh, arm.SHIFT_LL, int32(v), &ah)
    318 
    319 				//	OR		bl>>(32-v), ah
    320 				gshift(arm.AORR, &bl, arm.SHIFT_LR, int32(32-v), &ah)
    321 			} else {
    322 				gins(arm.AMOVW, &bl, &al)
    323 				gins(arm.AMOVW, &bh, &ah)
    324 			}
    325 
    326 			goto olsh_break
    327 		}
    328 
    329 		gc.Regalloc(&s, gc.Types[gc.TUINT32], nil)
    330 		gc.Regalloc(&creg, gc.Types[gc.TUINT32], nil)
    331 		if gc.Is64(r.Type) {
    332 			// shift is >= 1<<32
    333 			var cl gc.Node
    334 			var ch gc.Node
    335 			split64(r, &cl, &ch)
    336 
    337 			gmove(&ch, &s)
    338 			gins(arm.ATST, &s, nil)
    339 			p6 = gc.Gbranch(arm.ABNE, nil, 0)
    340 			gmove(&cl, &s)
    341 			splitclean()
    342 		} else {
    343 			gmove(r, &s)
    344 			p6 = nil
    345 		}
    346 
    347 		gins(arm.ATST, &s, nil)
    348 
    349 		// shift == 0
    350 		p1 = gins(arm.AMOVW, &bl, &al)
    351 
    352 		p1.Scond = arm.C_SCOND_EQ
    353 		p1 = gins(arm.AMOVW, &bh, &ah)
    354 		p1.Scond = arm.C_SCOND_EQ
    355 		p2 = gc.Gbranch(arm.ABEQ, nil, 0)
    356 
    357 		// shift is < 32
    358 		gc.Nodconst(&n1, gc.Types[gc.TUINT32], 32)
    359 
    360 		gmove(&n1, &creg)
    361 		gins(arm.ACMP, &s, &creg)
    362 
    363 		//	MOVW.LO		bl<<s, al
    364 		p1 = gregshift(arm.AMOVW, &bl, arm.SHIFT_LL, &s, &al)
    365 
    366 		p1.Scond = arm.C_SCOND_LO
    367 
    368 		//	MOVW.LO		bh<<s, ah
    369 		p1 = gregshift(arm.AMOVW, &bh, arm.SHIFT_LL, &s, &ah)
    370 
    371 		p1.Scond = arm.C_SCOND_LO
    372 
    373 		//	SUB.LO		s, creg
    374 		p1 = gins(arm.ASUB, &s, &creg)
    375 
    376 		p1.Scond = arm.C_SCOND_LO
    377 
    378 		//	OR.LO		bl>>creg, ah
    379 		p1 = gregshift(arm.AORR, &bl, arm.SHIFT_LR, &creg, &ah)
    380 
    381 		p1.Scond = arm.C_SCOND_LO
    382 
    383 		//	BLO	end
    384 		p3 = gc.Gbranch(arm.ABLO, nil, 0)
    385 
    386 		// shift == 32
    387 		p1 = gins(arm.AEOR, &al, &al)
    388 
    389 		p1.Scond = arm.C_SCOND_EQ
    390 		p1 = gins(arm.AMOVW, &bl, &ah)
    391 		p1.Scond = arm.C_SCOND_EQ
    392 		p4 = gc.Gbranch(arm.ABEQ, nil, 0)
    393 
    394 		// shift is < 64
    395 		gc.Nodconst(&n1, gc.Types[gc.TUINT32], 64)
    396 
    397 		gmove(&n1, &creg)
    398 		gins(arm.ACMP, &s, &creg)
    399 
    400 		//	EOR.LO	al, al
    401 		p1 = gins(arm.AEOR, &al, &al)
    402 
    403 		p1.Scond = arm.C_SCOND_LO
    404 
    405 		//	MOVW.LO		creg>>1, creg
    406 		p1 = gshift(arm.AMOVW, &creg, arm.SHIFT_LR, 1, &creg)
    407 
    408 		p1.Scond = arm.C_SCOND_LO
    409 
    410 		//	SUB.LO		creg, s
    411 		p1 = gins(arm.ASUB, &creg, &s)
    412 
    413 		p1.Scond = arm.C_SCOND_LO
    414 
    415 		//	MOVW	bl<<s, ah
    416 		p1 = gregshift(arm.AMOVW, &bl, arm.SHIFT_LL, &s, &ah)
    417 
    418 		p1.Scond = arm.C_SCOND_LO
    419 
    420 		p5 = gc.Gbranch(arm.ABLO, nil, 0)
    421 
    422 		// shift >= 64
    423 		if p6 != nil {
    424 			gc.Patch(p6, gc.Pc)
    425 		}
    426 		gins(arm.AEOR, &al, &al)
    427 		gins(arm.AEOR, &ah, &ah)
    428 
    429 		gc.Patch(p2, gc.Pc)
    430 		gc.Patch(p3, gc.Pc)
    431 		gc.Patch(p4, gc.Pc)
    432 		gc.Patch(p5, gc.Pc)
    433 		gc.Regfree(&s)
    434 		gc.Regfree(&creg)
    435 
    436 	olsh_break:
    437 		gc.Regfree(&bl)
    438 		gc.Regfree(&bh)
    439 
    440 	case gc.ORSH:
    441 		var bl gc.Node
    442 		gc.Regalloc(&bl, lo1.Type, nil)
    443 		var bh gc.Node
    444 		gc.Regalloc(&bh, hi1.Type, nil)
    445 		gins(arm.AMOVW, &hi1, &bh)
    446 		gins(arm.AMOVW, &lo1, &bl)
    447 
    448 		var p4 *obj.Prog
    449 		var p5 *obj.Prog
    450 		var n1 gc.Node
    451 		var p6 *obj.Prog
    452 		var s gc.Node
    453 		var p1 *obj.Prog
    454 		var p2 *obj.Prog
    455 		var creg gc.Node
    456 		var p3 *obj.Prog
    457 		if r.Op == gc.OLITERAL {
    458 			v := uint64(r.Int())
    459 			if v >= 64 {
    460 				if bh.Type.Etype == gc.TINT32 {
    461 					//	MOVW	bh->31, al
    462 					gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &al)
    463 
    464 					//	MOVW	bh->31, ah
    465 					gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah)
    466 				} else {
    467 					gins(arm.AEOR, &al, &al)
    468 					gins(arm.AEOR, &ah, &ah)
    469 				}
    470 			} else if v > 32 {
    471 				if bh.Type.Etype == gc.TINT32 {
    472 					//	MOVW	bh->(v-32), al
    473 					gshift(arm.AMOVW, &bh, arm.SHIFT_AR, int32(v-32), &al)
    474 
    475 					//	MOVW	bh->31, ah
    476 					gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah)
    477 				} else {
    478 					//	MOVW	bh>>(v-32), al
    479 					gshift(arm.AMOVW, &bh, arm.SHIFT_LR, int32(v-32), &al)
    480 
    481 					gins(arm.AEOR, &ah, &ah)
    482 				}
    483 			} else if v == 32 {
    484 				gins(arm.AMOVW, &bh, &al)
    485 				if bh.Type.Etype == gc.TINT32 {
    486 					//	MOVW	bh->31, ah
    487 					gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah)
    488 				} else {
    489 					gins(arm.AEOR, &ah, &ah)
    490 				}
    491 			} else if v > 0 {
    492 				//	MOVW	bl>>v, al
    493 				gshift(arm.AMOVW, &bl, arm.SHIFT_LR, int32(v), &al)
    494 
    495 				//	OR		bh<<(32-v), al
    496 				gshift(arm.AORR, &bh, arm.SHIFT_LL, int32(32-v), &al)
    497 
    498 				if bh.Type.Etype == gc.TINT32 {
    499 					//	MOVW	bh->v, ah
    500 					gshift(arm.AMOVW, &bh, arm.SHIFT_AR, int32(v), &ah)
    501 				} else {
    502 					//	MOVW	bh>>v, ah
    503 					gshift(arm.AMOVW, &bh, arm.SHIFT_LR, int32(v), &ah)
    504 				}
    505 			} else {
    506 				gins(arm.AMOVW, &bl, &al)
    507 				gins(arm.AMOVW, &bh, &ah)
    508 			}
    509 
    510 			goto orsh_break
    511 		}
    512 
    513 		gc.Regalloc(&s, gc.Types[gc.TUINT32], nil)
    514 		gc.Regalloc(&creg, gc.Types[gc.TUINT32], nil)
    515 		if gc.Is64(r.Type) {
    516 			// shift is >= 1<<32
    517 			var ch gc.Node
    518 			var cl gc.Node
    519 			split64(r, &cl, &ch)
    520 
    521 			gmove(&ch, &s)
    522 			gins(arm.ATST, &s, nil)
    523 			var p1 *obj.Prog
    524 			if bh.Type.Etype == gc.TINT32 {
    525 				p1 = gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah)
    526 			} else {
    527 				p1 = gins(arm.AEOR, &ah, &ah)
    528 			}
    529 			p1.Scond = arm.C_SCOND_NE
    530 			p6 = gc.Gbranch(arm.ABNE, nil, 0)
    531 			gmove(&cl, &s)
    532 			splitclean()
    533 		} else {
    534 			gmove(r, &s)
    535 			p6 = nil
    536 		}
    537 
    538 		gins(arm.ATST, &s, nil)
    539 
    540 		// shift == 0
    541 		p1 = gins(arm.AMOVW, &bl, &al)
    542 
    543 		p1.Scond = arm.C_SCOND_EQ
    544 		p1 = gins(arm.AMOVW, &bh, &ah)
    545 		p1.Scond = arm.C_SCOND_EQ
    546 		p2 = gc.Gbranch(arm.ABEQ, nil, 0)
    547 
    548 		// check if shift is < 32
    549 		gc.Nodconst(&n1, gc.Types[gc.TUINT32], 32)
    550 
    551 		gmove(&n1, &creg)
    552 		gins(arm.ACMP, &s, &creg)
    553 
    554 		//	MOVW.LO		bl>>s, al
    555 		p1 = gregshift(arm.AMOVW, &bl, arm.SHIFT_LR, &s, &al)
    556 
    557 		p1.Scond = arm.C_SCOND_LO
    558 
    559 		//	SUB.LO		s,creg
    560 		p1 = gins(arm.ASUB, &s, &creg)
    561 
    562 		p1.Scond = arm.C_SCOND_LO
    563 
    564 		//	OR.LO		bh<<(32-s), al
    565 		p1 = gregshift(arm.AORR, &bh, arm.SHIFT_LL, &creg, &al)
    566 
    567 		p1.Scond = arm.C_SCOND_LO
    568 
    569 		if bh.Type.Etype == gc.TINT32 {
    570 			//	MOVW	bh->s, ah
    571 			p1 = gregshift(arm.AMOVW, &bh, arm.SHIFT_AR, &s, &ah)
    572 		} else {
    573 			//	MOVW	bh>>s, ah
    574 			p1 = gregshift(arm.AMOVW, &bh, arm.SHIFT_LR, &s, &ah)
    575 		}
    576 
    577 		p1.Scond = arm.C_SCOND_LO
    578 
    579 		//	BLO	end
    580 		p3 = gc.Gbranch(arm.ABLO, nil, 0)
    581 
    582 		// shift == 32
    583 		p1 = gins(arm.AMOVW, &bh, &al)
    584 
    585 		p1.Scond = arm.C_SCOND_EQ
    586 		if bh.Type.Etype == gc.TINT32 {
    587 			gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &ah)
    588 		} else {
    589 			gins(arm.AEOR, &ah, &ah)
    590 		}
    591 		p4 = gc.Gbranch(arm.ABEQ, nil, 0)
    592 
    593 		// check if shift is < 64
    594 		gc.Nodconst(&n1, gc.Types[gc.TUINT32], 64)
    595 
    596 		gmove(&n1, &creg)
    597 		gins(arm.ACMP, &s, &creg)
    598 
    599 		//	MOVW.LO		creg>>1, creg
    600 		p1 = gshift(arm.AMOVW, &creg, arm.SHIFT_LR, 1, &creg)
    601 
    602 		p1.Scond = arm.C_SCOND_LO
    603 
    604 		//	SUB.LO		creg, s
    605 		p1 = gins(arm.ASUB, &creg, &s)
    606 
    607 		p1.Scond = arm.C_SCOND_LO
    608 
    609 		if bh.Type.Etype == gc.TINT32 {
    610 			//	MOVW	bh->(s-32), al
    611 			p1 := gregshift(arm.AMOVW, &bh, arm.SHIFT_AR, &s, &al)
    612 
    613 			p1.Scond = arm.C_SCOND_LO
    614 		} else {
    615 			//	MOVW	bh>>(v-32), al
    616 			p1 := gregshift(arm.AMOVW, &bh, arm.SHIFT_LR, &s, &al)
    617 
    618 			p1.Scond = arm.C_SCOND_LO
    619 		}
    620 
    621 		//	BLO	end
    622 		p5 = gc.Gbranch(arm.ABLO, nil, 0)
    623 
    624 		// s >= 64
    625 		if p6 != nil {
    626 			gc.Patch(p6, gc.Pc)
    627 		}
    628 		if bh.Type.Etype == gc.TINT32 {
    629 			//	MOVW	bh->31, al
    630 			gshift(arm.AMOVW, &bh, arm.SHIFT_AR, 31, &al)
    631 		} else {
    632 			gins(arm.AEOR, &al, &al)
    633 		}
    634 
    635 		gc.Patch(p2, gc.Pc)
    636 		gc.Patch(p3, gc.Pc)
    637 		gc.Patch(p4, gc.Pc)
    638 		gc.Patch(p5, gc.Pc)
    639 		gc.Regfree(&s)
    640 		gc.Regfree(&creg)
    641 
    642 	orsh_break:
    643 		gc.Regfree(&bl)
    644 		gc.Regfree(&bh)
    645 
    646 		// TODO(kaib): literal optimizations
    647 	// make constant the right side (it usually is anyway).
    648 	//		if(lo1.op == OLITERAL) {
    649 	//			nswap(&lo1, &lo2);
    650 	//			nswap(&hi1, &hi2);
    651 	//		}
    652 	//		if(lo2.op == OLITERAL) {
    653 	//			// special cases for constants.
    654 	//			lv = mpgetfix(lo2.val.u.xval);
    655 	//			hv = mpgetfix(hi2.val.u.xval);
    656 	//			splitclean();	// right side
    657 	//			split64(res, &lo2, &hi2);
    658 	//			switch(n->op) {
    659 	//			case OXOR:
    660 	//				gmove(&lo1, &lo2);
    661 	//				gmove(&hi1, &hi2);
    662 	//				switch(lv) {
    663 	//				case 0:
    664 	//					break;
    665 	//				case 0xffffffffu:
    666 	//					gins(ANOTL, N, &lo2);
    667 	//					break;
    668 	//				default:
    669 	//					gins(AXORL, ncon(lv), &lo2);
    670 	//					break;
    671 	//				}
    672 	//				switch(hv) {
    673 	//				case 0:
    674 	//					break;
    675 	//				case 0xffffffffu:
    676 	//					gins(ANOTL, N, &hi2);
    677 	//					break;
    678 	//				default:
    679 	//					gins(AXORL, ncon(hv), &hi2);
    680 	//					break;
    681 	//				}
    682 	//				break;
    683 
    684 	//			case OAND:
    685 	//				switch(lv) {
    686 	//				case 0:
    687 	//					gins(AMOVL, ncon(0), &lo2);
    688 	//					break;
    689 	//				default:
    690 	//					gmove(&lo1, &lo2);
    691 	//					if(lv != 0xffffffffu)
    692 	//						gins(AANDL, ncon(lv), &lo2);
    693 	//					break;
    694 	//				}
    695 	//				switch(hv) {
    696 	//				case 0:
    697 	//					gins(AMOVL, ncon(0), &hi2);
    698 	//					break;
    699 	//				default:
    700 	//					gmove(&hi1, &hi2);
    701 	//					if(hv != 0xffffffffu)
    702 	//						gins(AANDL, ncon(hv), &hi2);
    703 	//					break;
    704 	//				}
    705 	//				break;
    706 
    707 	//			case OOR:
    708 	//				switch(lv) {
    709 	//				case 0:
    710 	//					gmove(&lo1, &lo2);
    711 	//					break;
    712 	//				case 0xffffffffu:
    713 	//					gins(AMOVL, ncon(0xffffffffu), &lo2);
    714 	//					break;
    715 	//				default:
    716 	//					gmove(&lo1, &lo2);
    717 	//					gins(AORL, ncon(lv), &lo2);
    718 	//					break;
    719 	//				}
    720 	//				switch(hv) {
    721 	//				case 0:
    722 	//					gmove(&hi1, &hi2);
    723 	//					break;
    724 	//				case 0xffffffffu:
    725 	//					gins(AMOVL, ncon(0xffffffffu), &hi2);
    726 	//					break;
    727 	//				default:
    728 	//					gmove(&hi1, &hi2);
    729 	//					gins(AORL, ncon(hv), &hi2);
    730 	//					break;
    731 	//				}
    732 	//				break;
    733 	//			}
    734 	//			splitclean();
    735 	//			splitclean();
    736 	//			goto out;
    737 	//		}
    738 	case gc.OXOR,
    739 		gc.OAND,
    740 		gc.OOR:
    741 		var n1 gc.Node
    742 		gc.Regalloc(&n1, lo1.Type, nil)
    743 
    744 		gins(arm.AMOVW, &lo1, &al)
    745 		gins(arm.AMOVW, &hi1, &ah)
    746 		gins(arm.AMOVW, &lo2, &n1)
    747 		gins(optoas(int(n.Op), lo1.Type), &n1, &al)
    748 		gins(arm.AMOVW, &hi2, &n1)
    749 		gins(optoas(int(n.Op), lo1.Type), &n1, &ah)
    750 		gc.Regfree(&n1)
    751 	}
    752 
    753 	if gc.Is64(r.Type) {
    754 		splitclean()
    755 	}
    756 	splitclean()
    757 
    758 	split64(res, &lo1, &hi1)
    759 	gins(arm.AMOVW, &al, &lo1)
    760 	gins(arm.AMOVW, &ah, &hi1)
    761 	splitclean()
    762 
    763 	//out:
    764 	gc.Regfree(&al)
    765 
    766 	gc.Regfree(&ah)
    767 }
    768 
    769 /*
    770  * generate comparison of nl, nr, both 64-bit.
    771  * nl is memory; nr is constant or memory.
    772  */
    773 func cmp64(nl *gc.Node, nr *gc.Node, op int, likely int, to *obj.Prog) {
    774 	var lo1 gc.Node
    775 	var hi1 gc.Node
    776 	var lo2 gc.Node
    777 	var hi2 gc.Node
    778 	var r1 gc.Node
    779 	var r2 gc.Node
    780 
    781 	split64(nl, &lo1, &hi1)
    782 	split64(nr, &lo2, &hi2)
    783 
    784 	// compare most significant word;
    785 	// if they differ, we're done.
    786 	t := hi1.Type
    787 
    788 	gc.Regalloc(&r1, gc.Types[gc.TINT32], nil)
    789 	gc.Regalloc(&r2, gc.Types[gc.TINT32], nil)
    790 	gins(arm.AMOVW, &hi1, &r1)
    791 	gins(arm.AMOVW, &hi2, &r2)
    792 	gins(arm.ACMP, &r1, &r2)
    793 	gc.Regfree(&r1)
    794 	gc.Regfree(&r2)
    795 
    796 	var br *obj.Prog
    797 	switch op {
    798 	default:
    799 		gc.Fatal("cmp64 %v %v", gc.Oconv(int(op), 0), t)
    800 
    801 		// cmp hi
    802 	// bne L
    803 	// cmp lo
    804 	// beq to
    805 	// L:
    806 	case gc.OEQ:
    807 		br = gc.Gbranch(arm.ABNE, nil, -likely)
    808 
    809 		// cmp hi
    810 	// bne to
    811 	// cmp lo
    812 	// bne to
    813 	case gc.ONE:
    814 		gc.Patch(gc.Gbranch(arm.ABNE, nil, likely), to)
    815 
    816 		// cmp hi
    817 	// bgt to
    818 	// blt L
    819 	// cmp lo
    820 	// bge to (or bgt to)
    821 	// L:
    822 	case gc.OGE,
    823 		gc.OGT:
    824 		gc.Patch(gc.Gbranch(optoas(gc.OGT, t), nil, likely), to)
    825 
    826 		br = gc.Gbranch(optoas(gc.OLT, t), nil, -likely)
    827 
    828 		// cmp hi
    829 	// blt to
    830 	// bgt L
    831 	// cmp lo
    832 	// ble to (or jlt to)
    833 	// L:
    834 	case gc.OLE,
    835 		gc.OLT:
    836 		gc.Patch(gc.Gbranch(optoas(gc.OLT, t), nil, likely), to)
    837 
    838 		br = gc.Gbranch(optoas(gc.OGT, t), nil, -likely)
    839 	}
    840 
    841 	// compare least significant word
    842 	t = lo1.Type
    843 
    844 	gc.Regalloc(&r1, gc.Types[gc.TINT32], nil)
    845 	gc.Regalloc(&r2, gc.Types[gc.TINT32], nil)
    846 	gins(arm.AMOVW, &lo1, &r1)
    847 	gins(arm.AMOVW, &lo2, &r2)
    848 	gins(arm.ACMP, &r1, &r2)
    849 	gc.Regfree(&r1)
    850 	gc.Regfree(&r2)
    851 
    852 	// jump again
    853 	gc.Patch(gc.Gbranch(optoas(op, t), nil, likely), to)
    854 
    855 	// point first branch down here if appropriate
    856 	if br != nil {
    857 		gc.Patch(br, gc.Pc)
    858 	}
    859 
    860 	splitclean()
    861 	splitclean()
    862 }
    863