"Readme.md" did not exist on "bddf7657442e92caeec41eb8c0fbf38dbafab648"
cgen64.c 14.1 KB
Newer Older
Kai Backman's avatar
Kai Backman committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "gg.h"

/*
 * attempt to generate 64-bit
 *	res = n
 * return 1 on success, 0 if op not handled.
 */
void
cgen64(Node *n, Node *res)
{
	Node t1, t2, *l, *r;
	Node lo1, lo2, hi1, hi2;
17
	Node al, ah, bl, bh, cl, ch, s, n1, creg;
18
	Prog *p1, *p2, *p3, *p4, *p5, *p6;
19

Kai Backman's avatar
Kai Backman committed
20
	uint64 v;
Kai Backman's avatar
Kai Backman committed
21 22 23 24 25 26

	if(res->op != OINDREG && res->op != ONAME) {
		dump("n", n);
		dump("res", res);
		fatal("cgen64 %O of %O", n->op, res->op);
	}
27 28 29

	l = n->left;
	if(!l->addable) {
30
		tempname(&t1, l->type);
31 32 33 34 35
		cgen(l, &t1);
		l = &t1;
	}

	split64(l, &lo1, &hi1);
Kai Backman's avatar
Kai Backman committed
36 37 38 39
	switch(n->op) {
	default:
		fatal("cgen64 %O", n->op);

40 41 42 43 44 45 46 47 48 49 50
	case OMINUS:
		split64(res, &lo2, &hi2);

		regalloc(&t1, lo1.type, N);
		regalloc(&al, lo1.type, N);
		regalloc(&ah, hi1.type, N);

		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);

		gmove(ncon(0), &t1);
51
		p1 = gins(ASUB, &al, &t1);
52
		p1->scond |= C_SBIT;
53
		gins(AMOVW, &t1, &lo2);
54

55 56 57
		gmove(ncon(0), &t1);
		gins(ASBC, &ah, &t1);
		gins(AMOVW, &t1, &hi2);
58 59 60 61 62 63 64

		regfree(&t1);
		regfree(&al);
		regfree(&ah);
		splitclean();
		splitclean();
		return;
Kai Backman's avatar
Kai Backman committed
65

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
	case OCOM:
		split64(res, &lo2, &hi2);
		regalloc(&n1, lo1.type, N);

		gins(AMOVW, &lo1, &n1);
		gins(AMVN, &n1, &n1);
		gins(AMOVW, &n1, &lo2);

		gins(AMOVW, &hi1, &n1);
		gins(AMVN, &n1, &n1);
		gins(AMOVW, &n1, &hi2);

		regfree(&n1);
		splitclean();
		splitclean();
		return;
Kai Backman's avatar
Kai Backman committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95

	case OADD:
	case OSUB:
	case OMUL:
	case OLSH:
	case ORSH:
	case OAND:
	case OOR:
	case OXOR:
		// binary operators.
		// common setup below.
		break;
	}

96
	// setup for binary operators
Kai Backman's avatar
Kai Backman committed
97 98
	r = n->right;
	if(r != N && !r->addable) {
99
		tempname(&t2, r->type);
Kai Backman's avatar
Kai Backman committed
100 101 102 103 104 105 106 107
		cgen(r, &t2);
		r = &t2;
	}
	if(is64(r->type))
		split64(r, &lo2, &hi2);

	regalloc(&al, lo1.type, N);
	regalloc(&ah, hi1.type, N);
108

Kai Backman's avatar
Kai Backman committed
109 110 111 112 113 114 115 116 117 118 119 120 121
	// Do op.  Leave result in ah:al.
	switch(n->op) {
	default:
		fatal("cgen64: not implemented: %N\n", n);

	case OADD:
		// TODO: Constants
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
		gins(AMOVW, &hi1, &ah);
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi2, &bh);
		gins(AMOVW, &lo2, &bl);
122 123
		p1 = gins(AADD, &bl, &al);
		p1->scond |= C_SBIT;
Kai Backman's avatar
Kai Backman committed
124 125 126 127 128
		gins(AADC, &bh, &ah);
		regfree(&bl);
		regfree(&bh);
		break;

129 130
	case OSUB:
		// TODO: Constants.
131 132
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
133 134
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);
135 136
		gins(AMOVW, &lo2, &bl);
		gins(AMOVW, &hi2, &bh);
137 138
		p1 = gins(ASUB, &bl, &al);
		p1->scond |= C_SBIT;
139 140 141
		gins(ASBC, &bh, &ah);
		regfree(&bl);
		regfree(&bh);
142
		break;
Kai Backman's avatar
Kai Backman committed
143 144 145 146

	case OMUL:
		// TODO(kaib): this can be done with 4 regs and does not need 6
		regalloc(&bl, types[TPTR32], N);
147
		regalloc(&bh, types[TPTR32], N);
Kai Backman's avatar
Kai Backman committed
148
		regalloc(&cl, types[TPTR32], N);
149
		regalloc(&ch, types[TPTR32], N);
Kai Backman's avatar
Kai Backman committed
150 151 152 153 154 155 156 157 158 159 160 161 162

		// load args into bh:bl and bh:bl.
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);
		gins(AMOVW, &hi2, &ch);
		gins(AMOVW, &lo2, &cl);

		// bl * cl
		p1 = gins(AMULLU, N, N);
		p1->from.type = D_REG;
		p1->from.reg = bl.val.u.reg;
		p1->reg = cl.val.u.reg;
		p1->to.type = D_REGREG;
163 164
		p1->to.reg = ah.val.u.reg;
		p1->to.offset = al.val.u.reg;
Kai Backman's avatar
Kai Backman committed
165 166 167
//print("%P\n", p1);

		// bl * ch
168
		p1 = gins(AMULA, N, N);
Kai Backman's avatar
Kai Backman committed
169
		p1->from.type = D_REG;
170 171
		p1->from.reg = bl.val.u.reg;
		p1->reg = ch.val.u.reg;
Kai Backman's avatar
Kai Backman committed
172
		p1->to.type = D_REGREG;
173
		p1->to.reg = ah.val.u.reg;
Kai Backman's avatar
Kai Backman committed
174 175 176 177
		p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);

		// bh * cl
178
		p1 = gins(AMULA, N, N);
Kai Backman's avatar
Kai Backman committed
179
		p1->from.type = D_REG;
180 181
		p1->from.reg = bh.val.u.reg;
		p1->reg = cl.val.u.reg;
Kai Backman's avatar
Kai Backman committed
182
		p1->to.type = D_REGREG;
183
		p1->to.reg = ah.val.u.reg;
Kai Backman's avatar
Kai Backman committed
184 185 186 187 188 189 190 191 192 193
		p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);

		regfree(&bh);
		regfree(&bl);
		regfree(&ch);
		regfree(&cl);

		break;

194
	case OLSH:
195
		regalloc(&bl, lo1.type, N);
196
		regalloc(&bh, hi1.type, N);
197 198 199
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);

200 201 202 203 204 205 206
		if(r->op == OLITERAL) {
			v = mpgetfix(r->val.u.xval);
			if(v >= 64) {
				// TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
				// here and below (verify it optimizes to EOR)
				gins(AEOR, &al, &al);
				gins(AEOR, &ah, &ah);
207
			} else if(v > 32) {
208
				gins(AEOR, &al, &al);
209
				//	MOVW	bl<<(v-32), ah
210 211 212 213 214 215 216
				gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
			} else if(v == 32) {
				gins(AEOR, &al, &al);
				gins(AMOVW, &bl, &ah);
			} else if(v > 0) {
				//	MOVW	bl<<v, al
				gshift(AMOVW, &bl, SHIFT_LL, v, &al);
Kai Backman's avatar
Kai Backman committed
217

218 219
				//	MOVW	bh<<v, ah
				gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
220

221 222 223 224 225 226
				//	OR		bl>>(32-v), ah
				gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
			} else {
				gins(AMOVW, &bl, &al);
				gins(AMOVW, &bh, &ah);
			}
227
			goto olsh_break;
228 229
		}

230 231
		regalloc(&s, types[TUINT32], N);
		regalloc(&creg, types[TUINT32], N);
232 233 234 235
		if (is64(r->type)) {
			// shift is >= 1<<32
			split64(r, &cl, &ch);
			gmove(&ch, &s);
Ken Thompson's avatar
Ken Thompson committed
236
			p1 = gins(ATST, &s, N);
237 238 239 240 241 242 243
			p6 = gbranch(ABNE, T);
			gmove(&cl, &s);
			splitclean();
		} else {
			gmove(r, &s);
			p6 = P;
		}
Ken Thompson's avatar
Ken Thompson committed
244
		p1 = gins(ATST, &s, N);
245

246 247 248 249 250 251 252 253
		// shift == 0
		p1 = gins(AMOVW, &bl, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &ah);
		p1->scond = C_SCOND_EQ;
		p2 = gbranch(ABEQ, T);

		// shift is < 32
254 255 256 257
		nodconst(&n1, types[TUINT32], 32);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

258
		//	MOVW.LO		bl<<s, al
259
		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
260
		p1->scond = C_SCOND_LO;
261

262
		//	MOVW.LO		bh<<s, ah
263
		p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
264
		p1->scond = C_SCOND_LO;
265

266 267 268
		//	SUB.LO		s, creg
		p1 = gins(ASUB, &s, &creg);
		p1->scond = C_SCOND_LO;
269

270
		//	OR.LO		bl>>creg, ah
271
		p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
272
		p1->scond = C_SCOND_LO;
273

274 275
		//	BLO	end
		p3 = gbranch(ABLO, T);
276

277 278 279 280 281 282 283 284
		// shift == 32
		p1 = gins(AEOR, &al, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bl, &ah);
		p1->scond = C_SCOND_EQ;
		p4 = gbranch(ABEQ, T);

		// shift is < 64
285 286 287 288
		nodconst(&n1, types[TUINT32], 64);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

289
		//	EOR.LO	al, al
290
		p1 = gins(AEOR, &al, &al);
291
		p1->scond = C_SCOND_LO;
292

293
		//	MOVW.LO		creg>>1, creg
294
		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
295
		p1->scond = C_SCOND_LO;
296

297 298 299
		//	SUB.LO		creg, s
		p1 = gins(ASUB, &creg, &s);
		p1->scond = C_SCOND_LO;
300

301 302
		//	MOVW	bl<<s, ah
		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
303
		p1->scond = C_SCOND_LO;
304

305
		p5 = gbranch(ABLO, T);
306

307 308
		// shift >= 64
		if (p6 != P) patch(p6, pc);
309 310 311 312 313
		gins(AEOR, &al, &al);
		gins(AEOR, &ah, &ah);

		patch(p2, pc);
		patch(p3, pc);
314 315
		patch(p4, pc);
		patch(p5, pc);
316 317 318 319 320 321
		regfree(&s);
		regfree(&creg);

olsh_break:
		regfree(&bl);
		regfree(&bh);
322
		break;
Kai Backman's avatar
Kai Backman committed
323 324


Kai Backman's avatar
Kai Backman committed
325
	case ORSH:
326
		regalloc(&bl, lo1.type, N);
327
		regalloc(&bh, hi1.type, N);
328 329 330
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);

Kai Backman's avatar
Kai Backman committed
331 332 333
		if(r->op == OLITERAL) {
			v = mpgetfix(r->val.u.xval);
			if(v >= 64) {
334 335
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->31, al
336
					gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
Kai Backman's avatar
Kai Backman committed
337

338
					//	MOVW	bh->31, ah
339
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
Kai Backman's avatar
Kai Backman committed
340 341 342 343
				} else {
					gins(AEOR, &al, &al);
					gins(AEOR, &ah, &ah);
				}
344
			} else if(v > 32) {
345 346
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->(v-32), al
347
					gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);
Kai Backman's avatar
Kai Backman committed
348

349
					//	MOVW	bh->31, ah
350
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
Kai Backman's avatar
Kai Backman committed
351
				} else {
352
					//	MOVW	bh>>(v-32), al
353
					gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
Kai Backman's avatar
Kai Backman committed
354 355
					gins(AEOR, &ah, &ah);
				}
356 357 358 359 360 361 362 363 364 365 366 367 368 369
			} else if(v == 32) {
				gins(AMOVW, &bh, &al);
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->31, ah
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
				} else {
					gins(AEOR, &ah, &ah);
				}
			} else if( v > 0) {
				//	MOVW	bl>>v, al
				gshift(AMOVW, &bl, SHIFT_LR, v, &al);
	
				//	OR		bh<<(32-v), al
				gshift(AORR, &bh, SHIFT_LL, 32-v, &al);
Kai Backman's avatar
Kai Backman committed
370

371 372 373 374 375 376 377
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->v, ah
					gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
				} else {
					//	MOVW	bh>>v, ah
					gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
				}
Kai Backman's avatar
Kai Backman committed
378
			} else {
379 380
				gins(AMOVW, &bl, &al);
				gins(AMOVW, &bh, &ah);
Kai Backman's avatar
Kai Backman committed
381
			}
382
			goto orsh_break;
Kai Backman's avatar
Kai Backman committed
383
		}
Kai Backman's avatar
Kai Backman committed
384

385 386
		regalloc(&s, types[TUINT32], N);
		regalloc(&creg, types[TUINT32], N);
387 388 389 390
		if (is64(r->type)) {
			// shift is >= 1<<32
			split64(r, &cl, &ch);
			gmove(&ch, &s);
Ken Thompson's avatar
Ken Thompson committed
391
			p1 = gins(ATST, &s, N);
392 393 394 395 396 397 398
			p6 = gbranch(ABNE, T);
			gmove(&cl, &s);
			splitclean();
		} else {
			gmove(r, &s);
			p6 = P;
		}
Ken Thompson's avatar
Ken Thompson committed
399
		p1 = gins(ATST, &s, N);
400 401 402 403 404 405 406

		// shift == 0
		p1 = gins(AMOVW, &bl, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &ah);
		p1->scond = C_SCOND_EQ;
		p2 = gbranch(ABEQ, T);
407 408 409 410 411 412

		// check if shift is < 32
		nodconst(&n1, types[TUINT32], 32);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

413 414 415
		//	MOVW.LO		bl>>s, al
		p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
		p1->scond = C_SCOND_LO;
416

417 418 419
		//	SUB.LO		s,creg
		p1 = gins(ASUB, &s, &creg);
		p1->scond = C_SCOND_LO;
420

421 422 423
		//	OR.LO		bh<<(32-s), al
		p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
		p1->scond = C_SCOND_LO;
424 425 426

		if(bh.type->etype == TINT32) {
			//	MOVW	bh->s, ah
427
			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
428 429
		} else {
			//	MOVW	bh>>s, ah
430
			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
431
		}
432 433 434 435
		p1->scond = C_SCOND_LO;

		//	BLO	end
		p3 = gbranch(ABLO, T);
436

437
		// shift == 32
Ken Thompson's avatar
Ken Thompson committed
438 439
		p1 = gins(AMOVW, &bh, &al);
		p1->scond = C_SCOND_EQ;
440 441 442
		if(bh.type->etype == TINT32)
			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
		else
Ken Thompson's avatar
Ken Thompson committed
443
			p1 = gins(AEOR, &ah, &ah);
444 445
		p1->scond = C_SCOND_EQ;
		p4 = gbranch(ABEQ, T);
446 447 448 449 450 451

		// check if shift is < 64
		nodconst(&n1, types[TUINT32], 64);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

452 453 454
		//	MOVW.LO		creg>>1, creg
		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
		p1->scond = C_SCOND_LO;
455

456 457 458
		//	SUB.LO		creg, s
		p1 = gins(ASUB, &creg, &s);
		p1->scond = C_SCOND_LO;
459 460 461

		if(bh.type->etype == TINT32) {
			//	MOVW	bh->(s-32), al
462 463
			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
			p1->scond = C_SCOND_LO;
464 465

			//	MOVW	bh->31, ah
466 467
			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
			p1->scond = C_SCOND_LO;
468 469
		} else {
			//	MOVW	bh>>(v-32), al
470 471
			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
			p1->scond = C_SCOND_LO;
472 473

			p1 = gins(AEOR, &ah, &ah);
474
			p1->scond = C_SCOND_LO;
475 476
		}

477 478
		//	BLO	end
		p5 = gbranch(ABLO, T);
479 480

		// s >= 64
481
		if (p6 != P) patch(p6, pc);
482 483
		if(bh.type->etype == TINT32) {
			//	MOVW	bh->31, al
484
			gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
485 486

			//	MOVW	bh->31, ah
487
			gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
488 489 490 491 492 493 494
		} else {
			gins(AEOR, &al, &al);
			gins(AEOR, &ah, &ah);
		}

		patch(p2, pc);
		patch(p3, pc);
495 496
		patch(p4, pc);
		patch(p5, pc);
497 498 499 500 501 502 503 504
		regfree(&s);
		regfree(&creg);


orsh_break:
		regfree(&bl);
		regfree(&bh);
		break;
Kai Backman's avatar
Kai Backman committed
505

506 507 508 509 510
	case OXOR:
	case OAND:
	case OOR:
		// TODO(kaib): literal optimizations
		// make constant the right side (it usually is anyway).
Kai Backman's avatar
Kai Backman committed
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
//		if(lo1.op == OLITERAL) {
//			nswap(&lo1, &lo2);
//			nswap(&hi1, &hi2);
//		}
//		if(lo2.op == OLITERAL) {
//			// special cases for constants.
//			lv = mpgetfix(lo2.val.u.xval);
//			hv = mpgetfix(hi2.val.u.xval);
//			splitclean();	// right side
//			split64(res, &lo2, &hi2);
//			switch(n->op) {
//			case OXOR:
//				gmove(&lo1, &lo2);
//				gmove(&hi1, &hi2);
//				switch(lv) {
//				case 0:
//					break;
//				case 0xffffffffu:
//					gins(ANOTL, N, &lo2);
//					break;
//				default:
//					gins(AXORL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					break;
//				case 0xffffffffu:
//					gins(ANOTL, N, &hi2);
//					break;
//				default:
//					gins(AXORL, ncon(hv), &hi2);
//					break;
//				}
//				break;

//			case OAND:
//				switch(lv) {
//				case 0:
//					gins(AMOVL, ncon(0), &lo2);
//					break;
//				default:
//					gmove(&lo1, &lo2);
//					if(lv != 0xffffffffu)
//						gins(AANDL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					gins(AMOVL, ncon(0), &hi2);
//					break;
//				default:
//					gmove(&hi1, &hi2);
//					if(hv != 0xffffffffu)
//						gins(AANDL, ncon(hv), &hi2);
//					break;
//				}
//				break;

//			case OOR:
//				switch(lv) {
//				case 0:
//					gmove(&lo1, &lo2);
//					break;
//				case 0xffffffffu:
//					gins(AMOVL, ncon(0xffffffffu), &lo2);
//					break;
//				default:
//					gmove(&lo1, &lo2);
//					gins(AORL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					gmove(&hi1, &hi2);
//					break;
//				case 0xffffffffu:
//					gins(AMOVL, ncon(0xffffffffu), &hi2);
//					break;
//				default:
//					gmove(&hi1, &hi2);
//					gins(AORL, ncon(hv), &hi2);
//					break;
//				}
//				break;
//			}
//			splitclean();
//			splitclean();
//			goto out;
//		}
601
		regalloc(&n1, lo1.type, N);
602 603
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);
604 605 606 607 608
		gins(AMOVW, &lo2, &n1);
		gins(optoas(n->op, lo1.type), &n1, &al);
		gins(AMOVW, &hi2, &n1);
		gins(optoas(n->op, lo1.type), &n1, &ah);
		regfree(&n1);
609
		break;
Kai Backman's avatar
Kai Backman committed
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
	}
	if(is64(r->type))
		splitclean();
	splitclean();

	split64(res, &lo1, &hi1);
	gins(AMOVW, &al, &lo1);
	gins(AMOVW, &ah, &hi1);
	splitclean();

//out:
	regfree(&al);
	regfree(&ah);
}

/*
 * generate comparison of nl, nr, both 64-bit.
 * nl is memory; nr is constant or memory.
 */
void
cmp64(Node *nl, Node *nr, int op, Prog *to)
{
Kai Backman's avatar
Kai Backman committed
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
	Node lo1, hi1, lo2, hi2, r1, r2;
	Prog *br;
	Type *t;

	split64(nl, &lo1, &hi1);
	split64(nr, &lo2, &hi2);

	// compare most significant word;
	// if they differ, we're done.
	t = hi1.type;
	regalloc(&r1, types[TINT32], N);
	regalloc(&r2, types[TINT32], N);
	gins(AMOVW, &hi1, &r1);
	gins(AMOVW, &hi2, &r2);
	gcmp(ACMP, &r1, &r2);
	regfree(&r1);
	regfree(&r2);

	br = P;
	switch(op) {
	default:
		fatal("cmp64 %O %T", op, t);
	case OEQ:
		// cmp hi
		// bne L
		// cmp lo
		// beq to
		// L:
		br = gbranch(ABNE, T);
		break;
	case ONE:
		// cmp hi
		// bne to
		// cmp lo
		// bne to
		patch(gbranch(ABNE, T), to);
		break;
	case OGE:
	case OGT:
		// cmp hi
		// bgt to
		// blt L
		// cmp lo
		// bge to (or bgt to)
		// L:
		patch(gbranch(optoas(OGT, t), T), to);
		br = gbranch(optoas(OLT, t), T);
		break;
	case OLE:
	case OLT:
		// cmp hi
		// blt to
		// bgt L
		// cmp lo
		// ble to (or jlt to)
		// L:
		patch(gbranch(optoas(OLT, t), T), to);
		br = gbranch(optoas(OGT, t), T);
		break;
	}

	// compare least significant word
	t = lo1.type;
	regalloc(&r1, types[TINT32], N);
	regalloc(&r2, types[TINT32], N);
	gins(AMOVW, &lo1, &r1);
	gins(AMOVW, &lo2, &r2);
	gcmp(ACMP, &r1, &r2);
	regfree(&r1);
	regfree(&r2);

	// jump again
	patch(gbranch(optoas(op, t), T), to);

	// point first branch down here if appropriate
	if(br != P)
		patch(br, pc);

	splitclean();
	splitclean();
Kai Backman's avatar
Kai Backman committed
712
}