405
flt: // floating-point. 387 (not SSE2) to interoperate with 8c
406
nodreg(&f0, nl->type, D_F0);
407
nodreg(&f1, n->type, D_F0+1);
413
if(n->op != OCONV && n->op != OPLUS)
414
gins(foptoas(n->op, n->type, 0), N, N);
419
if(nl->ullman >= nr->ullman) {
422
gins(foptoas(n->op, n->type, 0), nr, &f0);
425
gins(foptoas(n->op, n->type, Fpop), &f0, &f1);
430
gins(foptoas(n->op, n->type, Frev), nl, &f0);
433
gins(foptoas(n->op, n->type, Frev|Fpop), &f0, &f1);
441
* generate array index into res.
442
* n might be any size; res is 32-bit.
439
* generate an addressable node in res, containing the value of n.
440
* n is an array index, and might be any size; res width is <= 32-bit.
443
441
* returns Prog* to patch to panic call.
446
cgenindex(Node *n, Node *res)
444
igenindex(Node *n, Node *res, int bounded)
448
446
Node tmp, lo, hi, zero;
450
448
if(!is64(n->type)) {
453
tempname(res, types[TUINT32]);
455
459
tempname(&tmp, types[TINT64]);
457
461
split64(&tmp, &lo, &hi);
462
tempname(res, types[TUINT32]);
463
468
nodconst(&zero, types[TINT32], 0);
464
469
gins(ACMPL, &hi, &zero);
466
return gbranch(AJNE, T);
471
return gbranch(AJNE, T, +1);
524
544
cgen_aret(n, res);
550
tempname(&n1, n->type);
556
tempname(&n1, n->type);
528
562
p2 = nil; // to be patched to panicindex.
529
563
w = n->type->width;
564
bounded = debug['B'] || n->bounded;
530
565
if(nr->addable) {
531
if(!isconst(nr, CTINT))
532
tempname(&tmp, types[TINT32]);
566
// Generate &nl first, and move nr into register.
533
567
if(!isconst(nl, CTSTR))
535
569
if(!isconst(nr, CTINT)) {
536
p2 = cgenindex(nr, &tmp);
570
p2 = igenindex(nr, &tmp, bounded);
537
571
regalloc(&n1, tmp.type, N);
538
572
gmove(&tmp, &n1);
540
574
} else if(nl->addable) {
575
// Generate nr first, and move &nl into register.
541
576
if(!isconst(nr, CTINT)) {
542
tempname(&tmp, types[TINT32]);
543
p2 = cgenindex(nr, &tmp);
577
p2 = igenindex(nr, &tmp, bounded);
544
578
regalloc(&n1, tmp.type, N);
545
579
gmove(&tmp, &n1);
547
if(!isconst(nl, CTSTR)) {
548
regalloc(&n3, types[tptr], res);
581
if(!isconst(nl, CTSTR))
552
tempname(&tmp, types[TINT32]);
553
p2 = cgenindex(nr, &tmp);
584
p2 = igenindex(nr, &tmp, bounded);
555
586
if(!isconst(nl, CTSTR))
557
588
regalloc(&n1, tmp.type, N);
558
589
gins(optoas(OAS, tmp.type), &tmp, &n1);
561
// &a is in &n3 (allocated in res)
562
// i is in &n1 (if not constant)
592
// For fixed array we really want the pointer in n3.
593
if(isfixedarray(nl->type)) {
594
regalloc(&n2, types[tptr], &n3);
600
// &a[0] is in n3 (allocated in res)
601
// i is in n1 (if not constant)
602
// len(a) is in nlen (if needed)
565
605
// explicit check for nil if array is large enough
566
606
// that we might derive too big a pointer.
567
607
if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
568
regalloc(&n4, types[tptr], &n3);
571
610
n4.type = types[TUINT8];
573
612
gins(ATESTB, nodintconst(0), &n4);
577
615
// constant index
578
616
if(isconst(nr, CTINT)) {
579
617
if(isconst(nl, CTSTR))
580
fatal("constant string constant index");
618
fatal("constant string constant index"); // front end should handle
581
619
v = mpgetfix(nr->val.u.xval);
582
620
if(isslice(nl->type) || nl->type->etype == TSTRING) {
583
if(!debug['B'] && !n->etype) {
586
n1.type = types[tptr];
587
n1.xoffset = Array_nel;
621
if(!debug['B'] && !n->bounded) {
623
nlen.type = types[TUINT32];
624
nlen.xoffset += Array_nel;
588
625
nodconst(&n2, types[TUINT32], v);
589
gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
590
p1 = gbranch(optoas(OGT, types[TUINT32]), T);
591
ginscall(panicindex, 0);
626
gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
627
p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
628
ginscall(panicindex, -1);
597
n1.type = types[tptr];
598
n1.xoffset = Array_array;
633
// Load base pointer in n2 = n3.
634
regalloc(&n2, types[tptr], &n3);
635
n3.type = types[tptr];
636
n3.xoffset += Array_array;
603
nodconst(&n2, types[tptr], v*w);
604
gins(optoas(OADD, types[tptr]), &n2, &n3);
640
nodconst(&n1, types[tptr], v*w);
641
gins(optoas(OADD, types[tptr]), &n1, &n2);
611
regalloc(&n2, types[TINT32], &n1); // i
648
// i is in register n1, extend to 32 bits.
650
if(issigned[n1.type->etype])
653
regalloc(&n2, t, &n1); // i
615
if(!debug['B'] && !n->etype) {
657
if(!debug['B'] && !n->bounded) {
617
if(isconst(nl, CTSTR))
618
nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
619
else if(isslice(nl->type) || nl->type->etype == TSTRING) {
622
n1.type = types[tptr];
623
n1.xoffset = Array_nel;
625
nodconst(&n1, types[TUINT32], nl->type->bound);
626
gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
627
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
660
if(isconst(nl, CTSTR)) {
661
nodconst(&nlen, t, nl->val.u.sval->len);
662
} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
665
nlen.xoffset += Array_nel;
667
nodconst(&nlen, t, nl->type->bound);
669
gins(optoas(OCMP, t), &n2, &nlen);
670
p1 = gbranch(optoas(OLT, t), T, +1);
630
ginscall(panicindex, 0);
673
ginscall(panicindex, -1);
634
677
if(isconst(nl, CTSTR)) {
635
678
regalloc(&n3, types[tptr], res);
636
679
p1 = gins(ALEAL, N, &n3);
686
// Load base pointer in n3.
687
regalloc(&tmp, types[tptr], &n3);
643
688
if(isslice(nl->type) || nl->type->etype == TSTRING) {
646
n1.type = types[tptr];
647
n1.xoffset = Array_array;
689
n3.type = types[tptr];
690
n3.xoffset += Array_array;
653
698
} else if(w == 1 || w == 2 || w == 4 || w == 8) {
699
// LEAL (n3)(n2*w), n3
654
700
p1 = gins(ALEAL, &n2, &n3);
655
701
p1->from.scale = w;
656
702
p1->from.index = p1->from.type;
657
703
p1->from.type = p1->to.type + D_INDIR;
659
nodconst(&n1, types[TUINT32], w);
660
gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
705
nodconst(&tmp, types[TUINT32], w);
706
gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
661
707
gins(optoas(OADD, types[tptr]), &n2, &n3);
936
1030
if(isslice(nl->type)) {
937
1031
// front end should only leave cmp to literal nil
938
1032
if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
939
yyerror("illegal array comparison");
1033
yyerror("illegal slice comparison");
942
1036
a = optoas(a, types[tptr]);
943
regalloc(&n1, types[tptr], N);
947
n2.xoffset = Array_array;
948
n2.type = types[tptr];
1038
n1.xoffset += Array_array;
1039
n1.type = types[tptr];
949
1040
nodconst(&tmp, types[tptr], 0);
950
gins(optoas(OCMP, types[tptr]), &n2, &tmp);
951
patch(gbranch(a, types[tptr]), to);
1041
gins(optoas(OCMP, types[tptr]), &n1, &tmp);
1042
patch(gbranch(a, types[tptr], likely), to);
962
1053
a = optoas(a, types[tptr]);
963
regalloc(&n1, types[tptr], N);
1055
n1.type = types[tptr];
968
1056
nodconst(&tmp, types[tptr], 0);
969
gins(optoas(OCMP, types[tptr]), &n2, &tmp);
970
patch(gbranch(a, types[tptr]), to);
1057
gins(optoas(OCMP, types[tptr]), &n1, &tmp);
1058
patch(gbranch(a, types[tptr], likely), to);
975
if(isfloat[nr->type->etype]) {
976
a = brrev(a); // because the args are stacked
977
if(a == OGE || a == OGT) {
978
// only < and <= work right with NaN; reverse if needed
984
nodreg(&tmp, nr->type, D_F0);
985
nodreg(&n2, nr->type, D_F0 + 1);
986
nodreg(&ax, types[TUINT16], D_AX);
987
et = simsimtype(nr->type);
989
if(nl->ullman > nr->ullman) {
992
gins(AFXCHD, &tmp, &n2);
997
gins(AFUCOMIP, &tmp, &n2);
998
gins(AFMOVDP, &tmp, &tmp); // annoying pop but still better than STSW+SAHF
1000
// TODO(rsc): The moves back and forth to memory
1001
// here are for truncating the value to 32 bits.
1002
// This handles 32-bit comparison but presumably
1003
// all the other ops have the same problem.
1004
// We need to figure out what the right general
1005
// solution is, besides telling people to use float64.
1006
tempname(&t1, types[TFLOAT32]);
1007
tempname(&t2, types[TFLOAT32]);
1011
gins(AFCOMFP, &t1, &tmp);
1012
gins(AFSTSW, N, &ax);
1017
p1 = gbranch(AJNE, T);
1018
p2 = gbranch(AJPS, T);
1019
patch(gbranch(AJMP, T), to);
1022
} else if(a == ONE) {
1024
patch(gbranch(AJNE, T), to);
1025
patch(gbranch(AJPS, T), to);
1027
patch(gbranch(optoas(a, nr->type), T), to);
1030
1063
if(iscomplex[nl->type->etype]) {
1031
complexbool(a, nl, nr, true, to);
1064
complexbool(a, nl, nr, true, likely, to);
1035
1068
if(is64(nr->type)) {
1069
if(!nl->addable || isconst(nl, CTINT)) {
1037
1070
tempname(&n1, nl->type);
1046
cmp64(nl, nr, a, to);
1079
cmp64(nl, nr, a, likely, to);
1050
a = optoas(a, nr->type);
1052
1083
if(nr->ullman >= UINF) {
1085
tempname(&n1, nl->type);
1090
tempname(&tmp, nr->type);
1094
regalloc(&n2, nr->type, N);
1053
1101
tempname(&n1, nl->type);
1106
if(smallintconst(nr)) {
1107
gins(optoas(OCMP, nr->type), nl, nr);
1108
patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
1054
1113
tempname(&tmp, nr->type);
1056
1114
cgen(nr, &tmp);
1057
regalloc(&n2, nr->type, N);
1062
tempname(&n1, nl->type);
1065
if(smallintconst(nr)) {
1066
gins(optoas(OCMP, nr->type), &n1, nr);
1067
patch(gbranch(a, nr->type), to);
1071
tempname(&tmp, nr->type);
1073
1117
regalloc(&n2, nr->type, N);
1077
gins(optoas(OCMP, nr->type), &n1, &n2);
1078
patch(gbranch(a, nr->type), to);
1122
gins(optoas(OCMP, nr->type), nl, nr);
1123
patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
1125
if(nl->op == OREGISTER)
1306
// dont know how it happens,
1319
* copy a composite value by moving its individual components.
1320
* Slices, strings and interfaces are supported.
1321
* nr is N when assigning a zero value.
1322
* return 1 if can do, 0 if cant.
1325
componentgen(Node *nr, Node *nl)
1333
switch(nl->type->etype) {
1338
if(!isslice(nl->type))
1347
if(nr == N || !cadable(nr))
1361
switch(nl->type->etype) {
1363
nodl.xoffset += Array_array;
1364
nodl.type = ptrto(nl->type->type);
1367
nodr.xoffset += Array_array;
1368
nodr.type = nodl.type;
1370
nodconst(&nodr, nodl.type, 0);
1371
gmove(&nodr, &nodl);
1373
nodl.xoffset += Array_nel-Array_array;
1374
nodl.type = types[TUINT32];
1377
nodr.xoffset += Array_nel-Array_array;
1378
nodr.type = nodl.type;
1380
nodconst(&nodr, nodl.type, 0);
1381
gmove(&nodr, &nodl);
1383
nodl.xoffset += Array_cap-Array_nel;
1384
nodl.type = types[TUINT32];
1387
nodr.xoffset += Array_cap-Array_nel;
1388
nodr.type = nodl.type;
1390
nodconst(&nodr, nodl.type, 0);
1391
gmove(&nodr, &nodl);
1396
nodl.xoffset += Array_array;
1397
nodl.type = ptrto(types[TUINT8]);
1400
nodr.xoffset += Array_array;
1401
nodr.type = nodl.type;
1403
nodconst(&nodr, nodl.type, 0);
1404
gmove(&nodr, &nodl);
1406
nodl.xoffset += Array_nel-Array_array;
1407
nodl.type = types[TUINT32];
1410
nodr.xoffset += Array_nel-Array_array;
1411
nodr.type = nodl.type;
1413
nodconst(&nodr, nodl.type, 0);
1414
gmove(&nodr, &nodl);
1419
nodl.xoffset += Array_array;
1420
nodl.type = ptrto(types[TUINT8]);
1423
nodr.xoffset += Array_array;
1424
nodr.type = nodl.type;
1426
nodconst(&nodr, nodl.type, 0);
1427
gmove(&nodr, &nodl);
1429
nodl.xoffset += Array_nel-Array_array;
1430
nodl.type = ptrto(types[TUINT8]);
1433
nodr.xoffset += Array_nel-Array_array;
1434
nodr.type = nodl.type;
1436
nodconst(&nodr, nodl.type, 0);
1437
gmove(&nodr, &nodl);