Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(523)

Delta Between Two Patch Sets: src/cmd/8g/gsubr.c

Issue 6962043: code review 6962043: cmd/dist, cmd/8g: implement GO386=387/sse to choose FPU... (Closed)
Left Patch Set: Created 12 years, 3 months ago
Right Patch Set: diff -r b2bc77ca3160 https://go.googlecode.com/hg/ Created 12 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/cmd/8g/ggen.c ('k') | src/cmd/8g/list.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Derived from Inferno utils/8c/txt.c 1 // Derived from Inferno utils/8c/txt.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/txt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/txt.c
3 // 3 //
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6 // Portions Copyright © 1997-1999 Vita Nuova Limited 6 // Portions Copyright © 1997-1999 Vita Nuova Limited
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov a.com) 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov a.com)
8 // Portions Copyright © 2004,2006 Bruce Ellis 8 // Portions Copyright © 2004,2006 Bruce Ellis
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 a = ACDQ; 683 a = ACDQ;
684 break; 684 break;
685 } 685 }
686 return a; 686 return a;
687 } 687 }
688 688
689 #define FCASE(a, b, c) (((a)<<16)|((b)<<8)|(c)) 689 #define FCASE(a, b, c) (((a)<<16)|((b)<<8)|(c))
690 int 690 int
691 foptoas(int op, Type *t, int flg) 691 foptoas(int op, Type *t, int flg)
692 { 692 {
693 » int et; 693 » int et, a;
694 694
695 et = simtype[t->etype]; 695 et = simtype[t->etype];
696
697 if(use_sse)
698 goto sse;
696 699
697 // If we need Fpop, it means we're working on 700 // If we need Fpop, it means we're working on
698 // two different floating-point registers, not memory. 701 // two different floating-point registers, not memory.
699 // There the instruction only has a float64 form. 702 // There the instruction only has a float64 form.
700 if(flg & Fpop) 703 if(flg & Fpop)
701 et = TFLOAT64; 704 et = TFLOAT64;
702 705
703 // clear Frev if unneeded 706 // clear Frev if unneeded
704 switch(op) { 707 switch(op) {
705 case OADD: 708 case OADD:
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 return AFCOMDPP; 766 return AFCOMDPP;
764 ········ 767 ········
765 case FCASE(OMINUS, TFLOAT32, 0): 768 case FCASE(OMINUS, TFLOAT32, 0):
766 return AFCHS; 769 return AFCHS;
767 case FCASE(OMINUS, TFLOAT64, 0): 770 case FCASE(OMINUS, TFLOAT64, 0):
768 return AFCHS; 771 return AFCHS;
769 } 772 }
770 773
771 fatal("foptoas %O %T %#x", op, t, flg); 774 fatal("foptoas %O %T %#x", op, t, flg);
772 return 0; 775 return 0;
773 } 776
777 sse:
778 » switch(CASE(op, et)) {
779 » default:
780 » » fatal("foptoas-sse: no entry %O-%T", op, t);
781 » » break;
782
783 » case CASE(OCMP, TFLOAT32):
784 » » a = AUCOMISS;
785 » » break;
786
787 » case CASE(OCMP, TFLOAT64):
788 » » a = AUCOMISD;
789 » » break;
790
791 » case CASE(OAS, TFLOAT32):
792 » » a = AMOVSS;
793 » » break;
794
795 » case CASE(OAS, TFLOAT64):
796 » » a = AMOVSD;
797 » » break;
798
799 » case CASE(OADD, TFLOAT32):
800 » » a = AADDSS;
801 » » break;
802
803 » case CASE(OADD, TFLOAT64):
804 » » a = AADDSD;
805 » » break;
806
807 » case CASE(OSUB, TFLOAT32):
808 » » a = ASUBSS;
809 » » break;
810
811 » case CASE(OSUB, TFLOAT64):
812 » » a = ASUBSD;
813 » » break;
814
815 » case CASE(OMUL, TFLOAT32):
816 » » a = AMULSS;
817 » » break;
818
819 » case CASE(OMUL, TFLOAT64):
820 » » a = AMULSD;
821 » » break;
822
823 » case CASE(ODIV, TFLOAT32):
824 » » a = ADIVSS;
825 » » break;
826
827 » case CASE(ODIV, TFLOAT64):
828 » » a = ADIVSD;
829 » » break;
830 » }
831 » return a;
832 }
833
774 834
775 static int resvd[] = 835 static int resvd[] =
776 { 836 {
777 // D_DI, // for movstring 837 // D_DI, // for movstring
778 // D_SI, // for movstring 838 // D_SI, // for movstring
779 839
780 D_AX, // for divide 840 D_AX, // for divide
781 D_CX, // for shift 841 D_CX, // for shift
782 D_DX, // for divide 842 D_DX, // for divide
783 D_SP, // for stack 843 D_SP, // for stack
784 844
785 D_BL, // because D_BX can be allocated 845 D_BL, // because D_BX can be allocated
786 D_BH, 846 D_BH,
787 }; 847 };
788 848
789 void 849 void
790 ginit(void) 850 ginit(void)
791 { 851 {
792 int i; 852 int i;
793 853
794 for(i=0; i<nelem(reg); i++) 854 for(i=0; i<nelem(reg); i++)
795 reg[i] = 1; 855 reg[i] = 1;
796 for(i=D_AX; i<=D_DI; i++) 856 for(i=D_AX; i<=D_DI; i++)
797 reg[i] = 0; 857 reg[i] = 0;
858 for(i=D_X0; i<=D_X7; i++)
859 reg[i] = 0;
798 for(i=0; i<nelem(resvd); i++) 860 for(i=0; i<nelem(resvd); i++)
799 reg[resvd[i]]++; 861 reg[resvd[i]]++;
800 } 862 }
801 863
802 uintptr regpc[D_NONE]; 864 uintptr regpc[D_NONE];
803 865
804 void 866 void
805 gclean(void) 867 gclean(void)
806 { 868 {
807 int i; 869 int i;
808 870
809 for(i=0; i<nelem(resvd); i++) 871 for(i=0; i<nelem(resvd); i++)
810 reg[resvd[i]]--; 872 reg[resvd[i]]--;
811 873
812 for(i=D_AX; i<=D_DI; i++) 874 for(i=D_AX; i<=D_DI; i++)
813 if(reg[i]) 875 if(reg[i])
814 yyerror("reg %R left allocated at %ux", i, regpc[i]); 876 yyerror("reg %R left allocated at %ux", i, regpc[i]);
877 for(i=D_X0; i<=D_X7; i++)
878 if(reg[i])
879 yyerror("reg %R left allocated\n", i);
815 } 880 }
816 881
817 int32 882 int32
818 anyregalloc(void) 883 anyregalloc(void)
819 { 884 {
820 int i, j; 885 int i, j;
821 886
822 for(i=D_AX; i<=D_DI; i++) { 887 for(i=D_AX; i<=D_DI; i++) {
823 if(reg[i] == 0) 888 if(reg[i] == 0)
824 goto ok; 889 goto ok;
825 for(j=0; j<nelem(resvd); j++) 890 for(j=0; j<nelem(resvd); j++)
826 if(resvd[j] == i) 891 if(resvd[j] == i)
827 goto ok; 892 goto ok;
828 return 1; 893 return 1;
829 ok:; 894 ok:;
830 } 895 }
896 for(i=D_X0; i<=D_X7; i++)
897 if(reg[i])
898 return 1;
831 return 0; 899 return 0;
832 } 900 }
833 901
834 /* 902 /*
835 * allocate register of type t, leave in n. 903 * allocate register of type t, leave in n.
836 * if o != N, o is desired fixed register. 904 * if o != N, o is desired fixed register.
837 * caller must regfree(n). 905 * caller must regfree(n).
838 */ 906 */
839 void 907 void
840 regalloc(Node *n, Type *t, Node *o) 908 regalloc(Node *n, Type *t, Node *o)
841 { 909 {
842 int i, et; 910 int i, et;
843 911
844 if(t == T) 912 if(t == T)
845 fatal("regalloc: t nil"); 913 fatal("regalloc: t nil");
846 et = simtype[t->etype]; 914 et = simtype[t->etype];
847 915
848 switch(et) { 916 switch(et) {
917 case TINT64:
918 case TUINT64:
919 fatal("regalloc64");
920
849 case TINT8: 921 case TINT8:
850 case TUINT8: 922 case TUINT8:
851 case TINT16: 923 case TINT16:
852 case TUINT16: 924 case TUINT16:
853 case TINT32: 925 case TINT32:
854 case TUINT32: 926 case TUINT32:
855 case TINT64:
856 case TUINT64:
857 case TPTR32: 927 case TPTR32:
858 case TPTR64: 928 case TPTR64:
859 case TBOOL: 929 case TBOOL:
860 if(o != N && o->op == OREGISTER) { 930 if(o != N && o->op == OREGISTER) {
861 i = o->val.u.reg; 931 i = o->val.u.reg;
862 if(i >= D_AX && i <= D_DI) 932 if(i >= D_AX && i <= D_DI)
863 goto out; 933 goto out;
864 } 934 }
865 for(i=D_AX; i<=D_DI; i++) 935 for(i=D_AX; i<=D_DI; i++)
866 if(reg[i] == 0) 936 if(reg[i] == 0)
867 goto out; 937 goto out;
868 938
869 fprint(2, "registers allocated at\n"); 939 fprint(2, "registers allocated at\n");
870 for(i=D_AX; i<=D_DI; i++) 940 for(i=D_AX; i<=D_DI; i++)
871 fprint(2, "\t%R\t%#lux\n", i, regpc[i]); 941 fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
872 yyerror("out of fixed registers"); 942 yyerror("out of fixed registers");
873 goto err; 943 goto err;
874 944
875 case TFLOAT32: 945 case TFLOAT32:
876 case TFLOAT64: 946 case TFLOAT64:
877 » » i = D_F0; 947 » » if(!use_sse) {
878 » » goto out; 948 » » » i = D_F0;
949 » » » goto out;
950 » » }
951 » » if(o != N && o->op == OREGISTER) {
952 » » » i = o->val.u.reg;
953 » » » if(i >= D_X0 && i <= D_X7)
954 » » » » goto out;
955 » » }
956 » » for(i=D_X0; i<=D_X7; i++)
957 » » » if(reg[i] == 0)
958 » » » » goto out;
959 » » fprint(2, "registers allocated at\n");
960 » » for(i=D_X0; i<=D_X7; i++)
961 » » » fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
962 » » fatal("out of floating registers");
879 } 963 }
880 yyerror("regalloc: unknown type %T", t); 964 yyerror("regalloc: unknown type %T", t);
881 965
882 err: 966 err:
883 nodreg(n, t, 0); 967 nodreg(n, t, 0);
884 return; 968 return;
885 969
886 out: 970 out:
887 if (i == D_SP) 971 if (i == D_SP)
888 print("alloc SP\n"); 972 print("alloc SP\n");
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 void 1256 void
1173 memname(Node *n, Type *t) 1257 memname(Node *n, Type *t)
1174 { 1258 {
1175 tempname(n, t); 1259 tempname(n, t);
1176 strcpy(namebuf, n->sym->name); 1260 strcpy(namebuf, n->sym->name);
1177 namebuf[0] = '.'; // keep optimizer from registerizing 1261 namebuf[0] = '.'; // keep optimizer from registerizing
1178 n->sym = lookup(namebuf); 1262 n->sym = lookup(namebuf);
1179 n->orig->sym = n->sym; 1263 n->orig->sym = n->sym;
1180 } 1264 }
1181 1265
1266 static void floatmove(Node *f, Node *t);
1267 static void floatmove_387(Node *f, Node *t);
1268 static void floatmove_sse(Node *f, Node *t);
1269
1182 void 1270 void
1183 gmove(Node *f, Node *t) 1271 gmove(Node *f, Node *t)
1184 { 1272 {
1185 int a, ft, tt; 1273 int a, ft, tt;
1186 Type *cvt; 1274 Type *cvt;
1187 » Node r1, r2, t1, t2, flo, fhi, tlo, thi, con, f0, f1, ax, dx, cx; 1275 » Node r1, r2, flo, fhi, tlo, thi, con;
1188 » Prog *p1, *p2, *p3;
1189 1276
1190 if(debug['M']) 1277 if(debug['M'])
1191 print("gmove %N -> %N\n", f, t); 1278 print("gmove %N -> %N\n", f, t);
1192 1279
1193 ft = simsimtype(f->type); 1280 ft = simsimtype(f->type);
1194 tt = simsimtype(t->type); 1281 tt = simsimtype(t->type);
1195 cvt = t->type; 1282 cvt = t->type;
1196 1283 »
1197 if(iscomplex[ft] || iscomplex[tt]) { 1284 if(iscomplex[ft] || iscomplex[tt]) {
1198 complexmove(f, t); 1285 complexmove(f, t);
1286 return;
1287 }
1288 if(isfloat[ft] || isfloat[tt]) {
1289 floatmove(f, t);
1199 return; 1290 return;
1200 } 1291 }
1201 1292
1202 // cannot have two integer memory operands; 1293 // cannot have two integer memory operands;
1203 // except 64-bit, which always copies via registers anyway. 1294 // except 64-bit, which always copies via registers anyway.
1204 if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f ) && ismem(t)) 1295 if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f ) && ismem(t))
1205 goto hard; 1296 goto hard;
1206 1297
1207 // convert constant to desired type 1298 // convert constant to desired type
1208 if(f->op == OLITERAL) { 1299 if(f->op == OLITERAL) {
1209 » » if(tt == TFLOAT32) 1300 » » convconst(&con, t->type, &f->val);
1210 » » » convconst(&con, types[TFLOAT64], &f->val);
1211 » » else
1212 » » » convconst(&con, t->type, &f->val);
1213 f = &con; 1301 f = &con;
1214 ft = simsimtype(con.type); 1302 ft = simsimtype(con.type);
1215
1216 // some constants can't move directly to memory.
1217 if(ismem(t)) {
1218 // float constants come from memory.
1219 if(isfloat[tt])
1220 goto hard;
1221 }
1222 } 1303 }
1223 1304
1224 // value -> value copy, only one memory operand. 1305 // value -> value copy, only one memory operand.
1225 // figure out the instruction to use. 1306 // figure out the instruction to use.
1226 // break out of switch for one-instruction gins. 1307 // break out of switch for one-instruction gins.
1227 // goto rdst for "destination must be register". 1308 // goto rdst for "destination must be register".
1228 // goto hard for "convert to cvt type first". 1309 // goto hard for "convert to cvt type first".
1229 // otherwise handle and return. 1310 // otherwise handle and return.
1230 1311
1231 switch(CASE(ft, tt)) { 1312 switch(CASE(ft, tt)) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 splitclean(); 1468 splitclean();
1388 return; 1469 return;
1389 1470
1390 case CASE(TUINT32, TINT64): // zero extend uint32 1471 case CASE(TUINT32, TINT64): // zero extend uint32
1391 case CASE(TUINT32, TUINT64): 1472 case CASE(TUINT32, TUINT64):
1392 split64(t, &tlo, &thi); 1473 split64(t, &tlo, &thi);
1393 gmove(f, &tlo); 1474 gmove(f, &tlo);
1394 gins(AMOVL, ncon(0), &thi); 1475 gins(AMOVL, ncon(0), &thi);
1395 splitclean(); 1476 splitclean();
1396 return; 1477 return;
1478 }
1479
1480 gins(a, f, t);
1481 return;
1482
1483 rsrc:
1484 // requires register source
1485 regalloc(&r1, f->type, t);
1486 gmove(f, &r1);
1487 gins(a, &r1, t);
1488 regfree(&r1);
1489 return;
1490
1491 rdst:
1492 // requires register destination
1493 regalloc(&r1, t->type, t);
1494 gins(a, f, &r1);
1495 gmove(&r1, t);
1496 regfree(&r1);
1497 return;
1498
1499 hard:
1500 // requires register intermediate
1501 regalloc(&r1, cvt, t);
1502 gmove(f, &r1);
1503 gmove(&r1, t);
1504 regfree(&r1);
1505 return;
1506
1507 fatal:
1508 // should not happen
1509 fatal("gmove %N -> %N", f, t);
1510 }
1511
1512 static void
1513 floatmove(Node *f, Node *t)
1514 {
1515 Node r1, r2, t1, t2, tlo, thi, con, f0, f1, ax, dx, cx;
1516 Type *cvt;
1517 int a, ft, tt;
1518 Prog *p1, *p2, *p3;
1519
1520 ft = simsimtype(f->type);
1521 tt = simsimtype(t->type);
1522 cvt = t->type;
1523
1524 // cannot have two floating point memory operands.
1525 if(isfloat[ft] && isfloat[tt] && ismem(f) && ismem(t))
1526 goto hard;
1527
1528 // convert constant to desired type
1529 if(f->op == OLITERAL) {
1530 convconst(&con, t->type, &f->val);
1531 f = &con;
1532 ft = simsimtype(con.type);
1533
1534 // some constants can't move directly to memory.
1535 if(ismem(t)) {
1536 // float constants come from memory.
1537 if(isfloat[tt])
1538 goto hard;
1539 }
1540 }
1541
1542 // value -> value copy, only one memory operand.
1543 // figure out the instruction to use.
1544 // break out of switch for one-instruction gins.
1545 // goto rdst for "destination must be register".
1546 // goto hard for "convert to cvt type first".
1547 // otherwise handle and return.
1548
1549 switch(CASE(ft, tt)) {
1550 default:
1551 if(use_sse)
1552 floatmove_sse(f, t);
1553 else
1554 floatmove_387(f, t);
1555 return;
1556
1557 // float to very long integer.
1558 case CASE(TFLOAT32, TINT64):
1559 case CASE(TFLOAT64, TINT64):
1560 if(f->op == OREGISTER) {
1561 cvt = f->type;
1562 goto hardmem;
1563 }
1564 nodreg(&r1, types[ft], D_F0);
1565 if(ft == TFLOAT32)
1566 gins(AFMOVF, f, &r1);
1567 else
1568 gins(AFMOVD, f, &r1);
1569
1570 // set round to zero mode during conversion
1571 memname(&t1, types[TUINT16]);
1572 memname(&t2, types[TUINT16]);
1573 gins(AFSTCW, N, &t1);
1574 gins(AMOVW, ncon(0xf7f), &t2);
1575 gins(AFLDCW, &t2, N);
1576 if(tt == TINT16)
1577 gins(AFMOVWP, &r1, t);
1578 else if(tt == TINT32)
1579 gins(AFMOVLP, &r1, t);
1580 else
1581 gins(AFMOVVP, &r1, t);
1582 gins(AFLDCW, &t1, N);
1583 return;
1584
1585 case CASE(TFLOAT32, TUINT64):
1586 case CASE(TFLOAT64, TUINT64):
1587 if(!ismem(f)) {
1588 cvt = f->type;
1589 goto hardmem;
1590 }
1591 bignodes();
1592 nodreg(&f0, types[ft], D_F0);
1593 nodreg(&f1, types[ft], D_F0 + 1);
1594 nodreg(&ax, types[TUINT16], D_AX);
1595
1596 if(ft == TFLOAT32)
1597 gins(AFMOVF, f, &f0);
1598 else
1599 gins(AFMOVD, f, &f0);
1600
1601 // if 0 > v { answer = 0 }
1602 gins(AFMOVD, &zerof, &f0);
1603 gins(AFUCOMIP, &f0, &f1);
1604 p1 = gbranch(optoas(OGT, types[tt]), T, 0);
1605 // if 1<<64 <= v { answer = 0 too }
1606 gins(AFMOVD, &two64f, &f0);
1607 gins(AFUCOMIP, &f0, &f1);
1608 p2 = gbranch(optoas(OGT, types[tt]), T, 0);
1609 patch(p1, pc);
1610 gins(AFMOVVP, &f0, t); // don't care about t, but will pop the stack
1611 split64(t, &tlo, &thi);
1612 gins(AMOVL, ncon(0), &tlo);
1613 gins(AMOVL, ncon(0), &thi);
1614 splitclean();
1615 p1 = gbranch(AJMP, T, 0);
1616 patch(p2, pc);
1617
1618 // in range; algorithm is:
1619 // if small enough, use native float64 -> int64 conversion.
1620 // otherwise, subtract 2^63, convert, and add it back.
1621
1622 // set round to zero mode during conversion
1623 memname(&t1, types[TUINT16]);
1624 memname(&t2, types[TUINT16]);
1625 gins(AFSTCW, N, &t1);
1626 gins(AMOVW, ncon(0xf7f), &t2);
1627 gins(AFLDCW, &t2, N);
1628
1629 // actual work
1630 gins(AFMOVD, &two63f, &f0);
1631 gins(AFUCOMIP, &f0, &f1);
1632 p2 = gbranch(optoas(OLE, types[tt]), T, 0);
1633 gins(AFMOVVP, &f0, t);
1634 p3 = gbranch(AJMP, T, 0);
1635 patch(p2, pc);
1636 gins(AFMOVD, &two63f, &f0);
1637 gins(AFSUBDP, &f0, &f1);
1638 gins(AFMOVVP, &f0, t);
1639 split64(t, &tlo, &thi);
1640 gins(AXORL, ncon(0x80000000), &thi); // + 2^63
1641 patch(p3, pc);
1642 splitclean();
1643 // restore rounding mode
1644 gins(AFLDCW, &t1, N);
1645
1646 patch(p1, pc);
1647 return;
1648
1649 /*
1650 * integer to float
1651 */
1652 case CASE(TINT64, TFLOAT32):
1653 case CASE(TINT64, TFLOAT64):
1654 if(t->op == OREGISTER)
1655 goto hardmem;
1656 nodreg(&f0, t->type, D_F0);
1657 gins(AFMOVV, f, &f0);
1658 if(tt == TFLOAT32)
1659 gins(AFMOVFP, &f0, t);
1660 else
1661 gins(AFMOVDP, &f0, t);
1662 return;
1663
1664 case CASE(TUINT64, TFLOAT32):
1665 case CASE(TUINT64, TFLOAT64):
1666 // algorithm is:
1667 // if small enough, use native int64 -> float64 conversion.
1668 // otherwise, halve (rounding to odd?), convert, and double .
1669 nodreg(&ax, types[TUINT32], D_AX);
1670 nodreg(&dx, types[TUINT32], D_DX);
1671 nodreg(&cx, types[TUINT32], D_CX);
1672 tempname(&t1, f->type);
1673 split64(&t1, &tlo, &thi);
1674 gmove(f, &t1);
1675 gins(ACMPL, &thi, ncon(0));
1676 p1 = gbranch(AJLT, T, 0);
1677 // native
1678 t1.type = types[TINT64];
1679 nodreg(&r1, types[tt], D_F0);
1680 gins(AFMOVV, &t1, &r1);
1681 if(tt == TFLOAT32)
1682 gins(AFMOVFP, &r1, t);
1683 else
1684 gins(AFMOVDP, &r1, t);
1685 p2 = gbranch(AJMP, T, 0);
1686 // simulated
1687 patch(p1, pc);
1688 gmove(&tlo, &ax);
1689 gmove(&thi, &dx);
1690 p1 = gins(ASHRL, ncon(1), &ax);
1691 p1->from.index = D_DX; // double-width shift DX -> AX
1692 p1->from.scale = 0;
1693 gins(AMOVL, ncon(0), &cx);
1694 gins(ASETCC, N, &cx);
1695 gins(AORL, &cx, &ax);
1696 gins(ASHRL, ncon(1), &dx);
1697 gmove(&dx, &thi);
1698 gmove(&ax, &tlo);
1699 nodreg(&r1, types[tt], D_F0);
1700 nodreg(&r2, types[tt], D_F0 + 1);
1701 gins(AFMOVV, &t1, &r1);
1702 gins(AFMOVD, &r1, &r1);
1703 gins(AFADDDP, &r1, &r2);
1704 if(tt == TFLOAT32)
1705 gins(AFMOVFP, &r1, t);
1706 else
1707 gins(AFMOVDP, &r1, t);
1708 patch(p2, pc);
1709 splitclean();
1710 return;
1711 }
1712
1713 gins(a, f, t);
1714 return;
1715
1716 hard:
1717 // requires register intermediate
1718 regalloc(&r1, cvt, t);
1719 gmove(f, &r1);
1720 gmove(&r1, t);
1721 regfree(&r1);
1722 return;
1723
1724 hardmem:
1725 // requires memory intermediate
1726 tempname(&r1, cvt);
1727 gmove(f, &r1);
1728 gmove(&r1, t);
1729 return;
1730 }
1731
1732 static void
1733 floatmove_387(Node *f, Node *t)
1734 {
1735 Node r1, t1, t2;
1736 Type *cvt;
1737 Prog *p1, *p2, *p3;
1738 int a, ft, tt;
1739
1740 ft = simsimtype(f->type);
1741 tt = simsimtype(t->type);
1742 cvt = t->type;
1743
1744 switch(CASE(ft, tt)) {
1745 default:
1746 goto fatal;
1397 1747
1398 /* 1748 /*
1399 * float to integer 1749 * float to integer
1400 */ 1750 */
1401 case CASE(TFLOAT32, TINT16): 1751 case CASE(TFLOAT32, TINT16):
1402 case CASE(TFLOAT32, TINT32): 1752 case CASE(TFLOAT32, TINT32):
1403 case CASE(TFLOAT32, TINT64): 1753 case CASE(TFLOAT32, TINT64):
1404 case CASE(TFLOAT64, TINT16): 1754 case CASE(TFLOAT64, TINT16):
1405 case CASE(TFLOAT64, TINT32): 1755 case CASE(TFLOAT64, TINT32):
1406 case CASE(TFLOAT64, TINT64): 1756 case CASE(TFLOAT64, TINT64):
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1466 gins(AMOVL, ncon(0), &t1); 1816 gins(AMOVL, ncon(0), &t1);
1467 patch(p1, pc); 1817 patch(p1, pc);
1468 gmove(&t1, t); 1818 gmove(&t1, t);
1469 break; 1819 break;
1470 } 1820 }
1471 return; 1821 return;
1472 1822
1473 case CASE(TFLOAT32, TUINT32): 1823 case CASE(TFLOAT32, TUINT32):
1474 case CASE(TFLOAT64, TUINT32): 1824 case CASE(TFLOAT64, TUINT32):
1475 // convert via int64. 1825 // convert via int64.
1476 » » tempname(&t1, types[TINT64]); 1826 » » cvt = types[TINT64];
1477 » » gmove(f, &t1); 1827 » » goto hardmem;
1478 » » split64(&t1, &tlo, &thi);
1479 » » gins(ACMPL, &thi, ncon(0));
1480 » » p1 = gbranch(AJEQ, T, +1);
1481 » » gins(AMOVL, ncon(0), &tlo);
1482 » » patch(p1, pc);
1483 » » gmove(&tlo, t);
1484 » » splitclean();
1485 » » return;
1486
1487 » case CASE(TFLOAT32, TUINT64):
1488 » case CASE(TFLOAT64, TUINT64):
1489 » » bignodes();
1490 » » nodreg(&f0, types[ft], D_F0);
1491 » » nodreg(&f1, types[ft], D_F0 + 1);
1492 » » nodreg(&ax, types[TUINT16], D_AX);
1493
1494 » » gmove(f, &f0);
1495
1496 » » // if 0 > v { answer = 0 }
1497 » » gmove(&zerof, &f0);
1498 » » gins(AFUCOMIP, &f0, &f1);
1499 » » p1 = gbranch(optoas(OGT, types[tt]), T, 0);
1500 » » // if 1<<64 <= v { answer = 0 too }
1501 » » gmove(&two64f, &f0);
1502 » » gins(AFUCOMIP, &f0, &f1);
1503 » » p2 = gbranch(optoas(OGT, types[tt]), T, 0);
1504 » » patch(p1, pc);
1505 » » gins(AFMOVVP, &f0, t);» // don't care about t, but will pop the stack
1506 » » split64(t, &tlo, &thi);
1507 » » gins(AMOVL, ncon(0), &tlo);
1508 » » gins(AMOVL, ncon(0), &thi);
1509 » » splitclean();
1510 » » p1 = gbranch(AJMP, T, 0);
1511 » » patch(p2, pc);
1512
1513 » » // in range; algorithm is:
1514 » » //» if small enough, use native float64 -> int64 conversion.
1515 » » //» otherwise, subtract 2^63, convert, and add it back.
1516
1517 » » // set round to zero mode during conversion
1518 » » memname(&t1, types[TUINT16]);
1519 » » memname(&t2, types[TUINT16]);
1520 » » gins(AFSTCW, N, &t1);
1521 » » gins(AMOVW, ncon(0xf7f), &t2);
1522 » » gins(AFLDCW, &t2, N);
1523
1524 » » // actual work
1525 » » gmove(&two63f, &f0);
1526 » » gins(AFUCOMIP, &f0, &f1);
1527 » » p2 = gbranch(optoas(OLE, types[tt]), T, 0);
1528 » » gins(AFMOVVP, &f0, t);
1529 » » p3 = gbranch(AJMP, T, 0);
1530 » » patch(p2, pc);
1531 » » gmove(&two63f, &f0);
1532 » » gins(AFSUBDP, &f0, &f1);
1533 » » gins(AFMOVVP, &f0, t);
1534 » » split64(t, &tlo, &thi);
1535 » » gins(AXORL, ncon(0x80000000), &thi);» // + 2^63
1536 » » patch(p3, pc);
1537 » » splitclean();
1538 » » // restore rounding mode
1539 » » gins(AFLDCW, &t1, N);
1540
1541 » » patch(p1, pc);
1542 » » return;
1543 1828
1544 /* 1829 /*
1545 * integer to float 1830 * integer to float
1546 */ 1831 */
1547 case CASE(TINT16, TFLOAT32): 1832 case CASE(TINT16, TFLOAT32):
1548 case CASE(TINT16, TFLOAT64): 1833 case CASE(TINT16, TFLOAT64):
1549 case CASE(TINT32, TFLOAT32): 1834 case CASE(TINT32, TFLOAT32):
1550 case CASE(TINT32, TFLOAT64): 1835 case CASE(TINT32, TFLOAT64):
1551 case CASE(TINT64, TFLOAT32): 1836 case CASE(TINT64, TFLOAT32):
1552 case CASE(TINT64, TFLOAT64): 1837 case CASE(TINT64, TFLOAT64):
(...skipping 24 matching lines...) Expand all
1577 case CASE(TUINT8, TFLOAT64): 1862 case CASE(TUINT8, TFLOAT64):
1578 // convert via int32 memory 1863 // convert via int32 memory
1579 cvt = types[TINT32]; 1864 cvt = types[TINT32];
1580 goto hardmem; 1865 goto hardmem;
1581 1866
1582 case CASE(TUINT32, TFLOAT32): 1867 case CASE(TUINT32, TFLOAT32):
1583 case CASE(TUINT32, TFLOAT64): 1868 case CASE(TUINT32, TFLOAT64):
1584 // convert via int64 memory 1869 // convert via int64 memory
1585 cvt = types[TINT64]; 1870 cvt = types[TINT64];
1586 goto hardmem; 1871 goto hardmem;
1587
1588 case CASE(TUINT64, TFLOAT32):
1589 case CASE(TUINT64, TFLOAT64):
1590 // algorithm is:
1591 // if small enough, use native int64 -> uint64 conversion.
1592 // otherwise, halve (rounding to odd?), convert, and double .
1593 nodreg(&ax, types[TUINT32], D_AX);
1594 nodreg(&dx, types[TUINT32], D_DX);
1595 nodreg(&cx, types[TUINT32], D_CX);
1596 tempname(&t1, f->type);
1597 split64(&t1, &tlo, &thi);
1598 gmove(f, &t1);
1599 gins(ACMPL, &thi, ncon(0));
1600 p1 = gbranch(AJLT, T, 0);
1601 // native
1602 t1.type = types[TINT64];
1603 gmove(&t1, t);
1604 p2 = gbranch(AJMP, T, 0);
1605 // simulated
1606 patch(p1, pc);
1607 gmove(&tlo, &ax);
1608 gmove(&thi, &dx);
1609 p1 = gins(ASHRL, ncon(1), &ax);
1610 p1->from.index = D_DX; // double-width shift DX -> AX
1611 p1->from.scale = 0;
1612 gins(AMOVL, ncon(0), &cx);
1613 gins(ASETCC, N, &cx);
1614 gins(AORL, &cx, &ax);
1615 gins(ASHRL, ncon(1), &dx);
1616 gmove(&dx, &thi);
1617 gmove(&ax, &tlo);
1618 nodreg(&r1, types[tt], D_F0);
1619 nodreg(&r2, types[tt], D_F0 + 1);
1620 gmove(&t1, &r1); // t1.type is TINT64 now, set above
1621 gins(AFMOVD, &r1, &r1);
1622 gins(AFADDDP, &r1, &r2);
1623 gmove(&r1, t);
1624 patch(p2, pc);
1625 splitclean();
1626 return;
1627 1872
1628 /* 1873 /*
1629 * float to float 1874 * float to float
1630 */ 1875 */
1631 case CASE(TFLOAT32, TFLOAT32): 1876 case CASE(TFLOAT32, TFLOAT32):
1632 case CASE(TFLOAT64, TFLOAT64): 1877 case CASE(TFLOAT64, TFLOAT64):
1633 // The way the code generator uses floating-point 1878 // The way the code generator uses floating-point
1634 // registers, a move from F0 to F0 is intended as a no-op. 1879 // registers, a move from F0 to F0 is intended as a no-op.
1635 // On the x86, it's not: it pushes a second copy of F0 1880 // On the x86, it's not: it pushes a second copy of F0
1636 // on the floating point stack. So toss it away here. 1881 // on the floating point stack. So toss it away here.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 if(f->op == OREGISTER) 1926 if(f->op == OREGISTER)
1682 gins(AFMOVFP, f, t); 1927 gins(AFMOVFP, f, t);
1683 else 1928 else
1684 gins(AFMOVD, f, t); 1929 gins(AFMOVD, f, t);
1685 return; 1930 return;
1686 } 1931 }
1687 1932
1688 gins(a, f, t); 1933 gins(a, f, t);
1689 return; 1934 return;
1690 1935
1691 rsrc: 1936 hard:
1692 » // requires register source 1937 » // requires register intermediate
1693 » regalloc(&r1, f->type, t); 1938 » regalloc(&r1, cvt, t);
1694 gmove(f, &r1); 1939 gmove(f, &r1);
1695 » gins(a, &r1, t); 1940 » gmove(&r1, t);
1696 regfree(&r1); 1941 regfree(&r1);
1942 return;
1943
1944 hardmem:
1945 // requires memory intermediate
1946 tempname(&r1, cvt);
1947 gmove(f, &r1);
1948 gmove(&r1, t);
1949 return;
1950
1951 fatal:
1952 // should not happen
1953 fatal("gmove %lN -> %lN", f, t);
1954 return;
1955 }
1956
1957 static void
1958 floatmove_sse(Node *f, Node *t)
1959 {
1960 Node r1;
1961 Type *cvt;
1962 int a, ft, tt;
1963
1964 ft = simsimtype(f->type);
1965 tt = simsimtype(t->type);
1966
1967 switch(CASE(ft, tt)) {
1968 default:
1969 // should not happen
1970 fatal("gmove %N -> %N", f, t);
1971 return;
1972 /*
1973 * float to integer
1974 */
1975 case CASE(TFLOAT32, TINT16):
1976 case CASE(TFLOAT32, TINT8):
1977 case CASE(TFLOAT32, TUINT16):
1978 case CASE(TFLOAT32, TUINT8):
1979 case CASE(TFLOAT64, TINT16):
1980 case CASE(TFLOAT64, TINT8):
1981 case CASE(TFLOAT64, TUINT16):
1982 case CASE(TFLOAT64, TUINT8):
1983 // convert via int32.
1984 cvt = types[TINT32];
1985 goto hard;
1986
1987 case CASE(TFLOAT32, TUINT32):
1988 case CASE(TFLOAT64, TUINT32):
1989 // convert via int64.
1990 cvt = types[TINT64];
1991 goto hardmem;
1992
1993 case CASE(TFLOAT32, TINT32):
1994 a = ACVTTSS2SL;
1995 goto rdst;
1996
1997 case CASE(TFLOAT64, TINT32):
1998 a = ACVTTSD2SL;
1999 goto rdst;
2000
2001 /*
2002 * integer to float
2003 */
2004 case CASE(TINT8, TFLOAT32):
2005 case CASE(TINT8, TFLOAT64):
2006 case CASE(TINT16, TFLOAT32):
2007 case CASE(TINT16, TFLOAT64):
2008 case CASE(TUINT16, TFLOAT32):
2009 case CASE(TUINT16, TFLOAT64):
2010 case CASE(TUINT8, TFLOAT32):
2011 case CASE(TUINT8, TFLOAT64):
2012 // convert via int32 memory
2013 cvt = types[TINT32];
2014 goto hard;
2015
2016 case CASE(TUINT32, TFLOAT32):
2017 case CASE(TUINT32, TFLOAT64):
2018 // convert via int64 memory
2019 cvt = types[TINT64];
2020 goto hardmem;
2021
2022 case CASE(TINT32, TFLOAT32):
2023 a = ACVTSL2SS;
2024 goto rdst;
2025
2026 case CASE(TINT32, TFLOAT64):
2027 a = ACVTSL2SD;
2028 goto rdst;
2029
2030 /*
2031 * float to float
2032 */
2033 case CASE(TFLOAT32, TFLOAT32):
2034 a = AMOVSS;
2035 break;
2036
2037 case CASE(TFLOAT64, TFLOAT64):
2038 a = AMOVSD;
2039 break;
2040
2041 case CASE(TFLOAT32, TFLOAT64):
2042 a = ACVTSS2SD;
2043 goto rdst;
2044
2045 case CASE(TFLOAT64, TFLOAT32):
2046 a = ACVTSD2SS;
2047 goto rdst;
2048 }
2049
2050 gins(a, f, t);
2051 return;
2052
2053 hard:
2054 // requires register intermediate
2055 regalloc(&r1, cvt, t);
2056 gmove(f, &r1);
2057 gmove(&r1, t);
2058 regfree(&r1);
2059 return;
2060
2061 hardmem:
2062 // requires memory intermediate
2063 tempname(&r1, cvt);
2064 gmove(f, &r1);
2065 gmove(&r1, t);
1697 return; 2066 return;
1698 2067
1699 rdst: 2068 rdst:
1700 // requires register destination 2069 // requires register destination
1701 regalloc(&r1, t->type, t); 2070 regalloc(&r1, t->type, t);
1702 gins(a, f, &r1); 2071 gins(a, f, &r1);
1703 gmove(&r1, t); 2072 gmove(&r1, t);
1704 regfree(&r1); 2073 regfree(&r1);
1705 return; 2074 return;
1706
1707 hard:
1708 // requires register intermediate
1709 regalloc(&r1, cvt, t);
1710 gmove(f, &r1);
1711 gmove(&r1, t);
1712 regfree(&r1);
1713 return;
1714
1715 hardmem:
1716 // requires memory intermediate
1717 tempname(&r1, cvt);
1718 gmove(f, &r1);
1719 gmove(&r1, t);
1720 return;
1721
1722 fatal:
1723 // should not happen
1724 fatal("gmove %N -> %N", f, t);
1725 } 2075 }
1726 2076
1727 int 2077 int
1728 samaddr(Node *f, Node *t) 2078 samaddr(Node *f, Node *t)
1729 { 2079 {
1730 2080
1731 if(f->op != t->op) 2081 if(f->op != t->op)
1732 return 0; 2082 return 0;
1733 2083
1734 switch(f->op) { 2084 switch(f->op) {
(...skipping 10 matching lines...) Expand all
1745 */ 2095 */
1746 Prog* 2096 Prog*
1747 gins(int as, Node *f, Node *t) 2097 gins(int as, Node *f, Node *t)
1748 { 2098 {
1749 Prog *p; 2099 Prog *p;
1750 Addr af, at; 2100 Addr af, at;
1751 int w; 2101 int w;
1752 2102
1753 if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER) 2103 if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER)
1754 fatal("gins MOVF reg, reg"); 2104 fatal("gins MOVF reg, reg");
2105 if(as == ACVTSD2SS && f && f->op == OLITERAL)
2106 fatal("gins CVTSD2SS const");
2107 if(as == AMOVSD && t && t->op == OREGISTER && t->val.u.reg == D_F0)
2108 fatal("gins MOVSD into F0");
1755 2109
1756 switch(as) { 2110 switch(as) {
1757 case AMOVB: 2111 case AMOVB:
1758 case AMOVW: 2112 case AMOVW:
1759 case AMOVL: 2113 case AMOVL:
1760 if(f != N && t != N && samaddr(f, t)) 2114 if(f != N && t != N && samaddr(f, t))
1761 return nil; 2115 return nil;
1762 break; 2116 break;
1763 ········ 2117 ········
1764 case ALEAL: 2118 case ALEAL:
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
2048 2402
2049 int 2403 int
2050 sudoaddable(int as, Node *n, Addr *a) 2404 sudoaddable(int as, Node *n, Addr *a)
2051 { 2405 {
2052 USED(as); 2406 USED(as);
2053 USED(n); 2407 USED(n);
2054 USED(a); 2408 USED(a);
2055 2409
2056 return 0; 2410 return 0;
2057 } 2411 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b