OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // TODO(rsc): | 5 // TODO(rsc): |
6 // assume CLD? | 6 // assume CLD? |
7 | 7 |
8 #include <u.h> | 8 #include <u.h> |
9 #include <libc.h> | 9 #include <libc.h> |
10 #include "gg.h" | 10 #include "gg.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 * generate: | 42 * generate: |
43 * res = n; | 43 * res = n; |
44 * simplifies and calls gmove. | 44 * simplifies and calls gmove. |
45 * | 45 * |
46 * TODO: | 46 * TODO: |
47 * sudoaddable | 47 * sudoaddable |
48 */ | 48 */ |
49 void | 49 void |
50 cgen(Node *n, Node *res) | 50 cgen(Node *n, Node *res) |
51 { | 51 { |
52 » Node *nl, *nr, *r, n1, n2, nt, f0, f1; | 52 » Node *nl, *nr, *r, n1, n2, nt; |
53 Prog *p1, *p2, *p3; | 53 Prog *p1, *p2, *p3; |
54 int a; | 54 int a; |
55 | 55 |
56 if(debug['g']) { | 56 if(debug['g']) { |
57 dump("\ncgen-n", n); | 57 dump("\ncgen-n", n); |
58 dump("cgen-res", res); | 58 dump("cgen-res", res); |
59 } | 59 } |
60 | 60 |
61 if(n == N || n->type == T) | 61 if(n == N || n->type == T) |
62 fatal("cgen: n nil"); | 62 fatal("cgen: n nil"); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 case OLSH: | 181 case OLSH: |
182 case ORSH: | 182 case ORSH: |
183 case OAND: | 183 case OAND: |
184 case OOR: | 184 case OOR: |
185 case OXOR: | 185 case OXOR: |
186 cgen64(n, res); | 186 cgen64(n, res); |
187 return; | 187 return; |
188 } | 188 } |
189 } | 189 } |
190 | 190 |
191 » if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) | 191 » if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) { |
192 » » goto flt; | 192 » » cgen_float(n, res); |
| 193 » » return; |
| 194 » } |
193 | 195 |
194 switch(n->op) { | 196 switch(n->op) { |
195 default: | 197 default: |
196 dump("cgen", n); | 198 dump("cgen", n); |
197 fatal("cgen %O", n->op); | 199 fatal("cgen %O", n->op); |
198 break; | 200 break; |
199 | 201 |
200 case OREAL: | 202 case OREAL: |
201 case OIMAG: | 203 case OIMAG: |
202 case OCOMPLEX: | 204 case OCOMPLEX: |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 regfree(&n1); | 426 regfree(&n1); |
425 } | 427 } |
426 return; | 428 return; |
427 | 429 |
428 uop: // unary | 430 uop: // unary |
429 tempname(&n1, nl->type); | 431 tempname(&n1, nl->type); |
430 cgen(nl, &n1); | 432 cgen(nl, &n1); |
431 gins(a, N, &n1); | 433 gins(a, N, &n1); |
432 gmove(&n1, res); | 434 gmove(&n1, res); |
433 return; | 435 return; |
434 | |
435 flt: // floating-point. 387 (not SSE2) to interoperate with 8c | |
436 nodreg(&f0, nl->type, D_F0); | |
437 nodreg(&f1, n->type, D_F0+1); | |
438 if(nr != N) | |
439 goto flt2; | |
440 | |
441 // unary | |
442 cgen(nl, &f0); | |
443 if(n->op != OCONV && n->op != OPLUS) | |
444 gins(foptoas(n->op, n->type, 0), N, N); | |
445 gmove(&f0, res); | |
446 return; | |
447 | |
448 flt2: // binary | |
449 if(nl->ullman >= nr->ullman) { | |
450 cgen(nl, &f0); | |
451 if(nr->addable) | |
452 gins(foptoas(n->op, n->type, 0), nr, &f0); | |
453 else { | |
454 cgen(nr, &f0); | |
455 gins(foptoas(n->op, n->type, Fpop), &f0, &f1); | |
456 } | |
457 } else { | |
458 cgen(nr, &f0); | |
459 if(nl->addable) | |
460 gins(foptoas(n->op, n->type, Frev), nl, &f0); | |
461 else { | |
462 cgen(nl, &f0); | |
463 gins(foptoas(n->op, n->type, Frev|Fpop), &f0, &f1); | |
464 } | |
465 } | |
466 gmove(&f0, res); | |
467 return; | |
468 } | 436 } |
469 | 437 |
470 /* | 438 /* |
471 * generate an addressable node in res, containing the value of n. | 439 * generate an addressable node in res, containing the value of n. |
472 * n is an array index, and might be any size; res width is <= 32-bit. | 440 * n is an array index, and might be any size; res width is <= 32-bit. |
473 * returns Prog* to patch to panic call. | 441 * returns Prog* to patch to panic call. |
474 */ | 442 */ |
475 static Prog* | 443 static Prog* |
476 igenindex(Node *n, Node *res, int bounded) | 444 igenindex(Node *n, Node *res, int bounded) |
477 { | 445 { |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 | 880 |
913 /* | 881 /* |
914 * branch gen | 882 * branch gen |
915 * if(n == true) goto to; | 883 * if(n == true) goto to; |
916 */ | 884 */ |
917 void | 885 void |
918 bgen(Node *n, int true, int likely, Prog *to) | 886 bgen(Node *n, int true, int likely, Prog *to) |
919 { | 887 { |
920 int et, a; | 888 int et, a; |
921 Node *nl, *nr, *r; | 889 Node *nl, *nr, *r; |
922 » Node n1, n2, tmp, t1, t2, ax; | 890 » Node n1, n2, tmp; |
923 » NodeList *ll; | |
924 Prog *p1, *p2; | 891 Prog *p1, *p2; |
925 | 892 |
926 if(debug['g']) { | 893 if(debug['g']) { |
927 dump("\nbgen", n); | 894 dump("\nbgen", n); |
928 } | 895 } |
929 | 896 |
930 if(n == N) | 897 if(n == N) |
931 n = nodbool(1); | 898 n = nodbool(1); |
932 | 899 |
933 if(n->ninit != nil) | 900 if(n->ninit != nil) |
934 genlist(n->ninit); | 901 genlist(n->ninit); |
935 | 902 |
936 if(n->type == T) { | 903 if(n->type == T) { |
937 convlit(&n, types[TBOOL]); | 904 convlit(&n, types[TBOOL]); |
938 if(n->type == T) | 905 if(n->type == T) |
939 return; | 906 return; |
940 } | 907 } |
941 | 908 |
942 et = n->type->etype; | 909 et = n->type->etype; |
943 if(et != TBOOL) { | 910 if(et != TBOOL) { |
944 yyerror("cgen: bad type %T for %O", n->type, n->op); | 911 yyerror("cgen: bad type %T for %O", n->type, n->op); |
945 patch(gins(AEND, N, N), to); | 912 patch(gins(AEND, N, N), to); |
946 return; | 913 return; |
947 } | 914 } |
| 915 nl = n->left; |
948 nr = N; | 916 nr = N; |
949 | 917 |
| 918 if(nl != N && isfloat[nl->type->etype]) { |
| 919 bgen_float(n, true, likely, to); |
| 920 return; |
| 921 } |
| 922 |
950 switch(n->op) { | 923 switch(n->op) { |
951 default: | 924 default: |
952 def: | 925 def: |
953 regalloc(&n1, n->type, N); | 926 regalloc(&n1, n->type, N); |
954 cgen(n, &n1); | 927 cgen(n, &n1); |
955 nodconst(&n2, n->type, 0); | 928 nodconst(&n2, n->type, 0); |
956 gins(optoas(OCMP, n->type), &n1, &n2); | 929 gins(optoas(OCMP, n->type), &n1, &n2); |
957 a = AJNE; | 930 a = AJNE; |
958 if(!true) | 931 if(!true) |
959 a = AJEQ; | 932 a = AJEQ; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 break; | 997 break; |
1025 | 998 |
1026 case OEQ: | 999 case OEQ: |
1027 case ONE: | 1000 case ONE: |
1028 case OLT: | 1001 case OLT: |
1029 case OGT: | 1002 case OGT: |
1030 case OLE: | 1003 case OLE: |
1031 case OGE: | 1004 case OGE: |
1032 a = n->op; | 1005 a = n->op; |
1033 if(!true) { | 1006 if(!true) { |
1034 if(isfloat[nl->type->etype]) { | |
1035 // brcom is not valid on floats when NaN is invo
lved. | |
1036 p1 = gbranch(AJMP, T, 0); | |
1037 p2 = gbranch(AJMP, T, 0); | |
1038 patch(p1, pc); | |
1039 ll = n->ninit; // avoid re-genning ninit | |
1040 n->ninit = nil; | |
1041 bgen(n, 1, -likely, p2); | |
1042 n->ninit = ll; | |
1043 patch(gbranch(AJMP, T, 0), to); | |
1044 patch(p2, pc); | |
1045 break; | |
1046 }······························· | |
1047 a = brcom(a); | 1007 a = brcom(a); |
1048 true = !true; | 1008 true = !true; |
1049 } | 1009 } |
1050 | 1010 |
1051 // make simplest on right | 1011 // make simplest on right |
1052 if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman
< UINF)) { | 1012 if(nl->op == OLITERAL || (nl->ullman < nr->ullman && nl->ullman
< UINF)) { |
1053 a = brrev(a); | 1013 a = brrev(a); |
1054 r = nl; | 1014 r = nl; |
1055 nl = nr; | 1015 nl = nr; |
1056 nr = r; | 1016 nr = r; |
(...skipping 25 matching lines...) Expand all Loading... |
1082 a = optoas(a, types[tptr]); | 1042 a = optoas(a, types[tptr]); |
1083 igen(nl, &n1, N); | 1043 igen(nl, &n1, N); |
1084 n1.type = types[tptr]; | 1044 n1.type = types[tptr]; |
1085 nodconst(&tmp, types[tptr], 0); | 1045 nodconst(&tmp, types[tptr], 0); |
1086 gins(optoas(OCMP, types[tptr]), &n1, &tmp); | 1046 gins(optoas(OCMP, types[tptr]), &n1, &tmp); |
1087 patch(gbranch(a, types[tptr], likely), to); | 1047 patch(gbranch(a, types[tptr], likely), to); |
1088 regfree(&n1); | 1048 regfree(&n1); |
1089 break; | 1049 break; |
1090 } | 1050 } |
1091 | 1051 |
1092 if(isfloat[nr->type->etype]) { | |
1093 a = brrev(a); // because the args are stacked | |
1094 if(a == OGE || a == OGT) { | |
1095 // only < and <= work right with NaN; reverse if
needed | |
1096 r = nr; | |
1097 nr = nl; | |
1098 nl = r; | |
1099 a = brrev(a); | |
1100 } | |
1101 nodreg(&tmp, nr->type, D_F0); | |
1102 nodreg(&n2, nr->type, D_F0 + 1); | |
1103 nodreg(&ax, types[TUINT16], D_AX); | |
1104 et = simsimtype(nr->type); | |
1105 if(et == TFLOAT64) { | |
1106 if(nl->ullman > nr->ullman) { | |
1107 cgen(nl, &tmp); | |
1108 cgen(nr, &tmp); | |
1109 gins(AFXCHD, &tmp, &n2); | |
1110 } else { | |
1111 cgen(nr, &tmp); | |
1112 cgen(nl, &tmp); | |
1113 } | |
1114 gins(AFUCOMIP, &tmp, &n2); | |
1115 gins(AFMOVDP, &tmp, &tmp); // annoying pop
but still better than STSW+SAHF | |
1116 } else { | |
1117 // TODO(rsc): The moves back and forth to memory | |
1118 // here are for truncating the value to 32 bits. | |
1119 // This handles 32-bit comparison but presumably | |
1120 // all the other ops have the same problem. | |
1121 // We need to figure out what the right general | |
1122 // solution is, besides telling people to use fl
oat64. | |
1123 tempname(&t1, types[TFLOAT32]); | |
1124 tempname(&t2, types[TFLOAT32]); | |
1125 cgen(nr, &t1); | |
1126 cgen(nl, &t2); | |
1127 gmove(&t2, &tmp); | |
1128 gins(AFCOMFP, &t1, &tmp); | |
1129 gins(AFSTSW, N, &ax); | |
1130 gins(ASAHF, N, N); | |
1131 } | |
1132 if(a == OEQ) { | |
1133 // neither NE nor P | |
1134 p1 = gbranch(AJNE, T, -likely); | |
1135 p2 = gbranch(AJPS, T, -likely); | |
1136 patch(gbranch(AJMP, T, 0), to); | |
1137 patch(p1, pc); | |
1138 patch(p2, pc); | |
1139 } else if(a == ONE) { | |
1140 // either NE or P | |
1141 patch(gbranch(AJNE, T, likely), to); | |
1142 patch(gbranch(AJPS, T, likely), to); | |
1143 } else | |
1144 patch(gbranch(optoas(a, nr->type), T, likely), t
o); | |
1145 break; | |
1146 } | |
1147 if(iscomplex[nl->type->etype]) { | 1052 if(iscomplex[nl->type->etype]) { |
1148 complexbool(a, nl, nr, true, likely, to); | 1053 complexbool(a, nl, nr, true, likely, to); |
1149 break; | 1054 break; |
1150 } | 1055 } |
1151 | 1056 |
1152 if(is64(nr->type)) { | 1057 if(is64(nr->type)) { |
1153 if(!nl->addable) { | 1058 if(!nl->addable) { |
1154 tempname(&n1, nl->type); | 1059 tempname(&n1, nl->type); |
1155 cgen(nl, &n1); | 1060 cgen(nl, &n1); |
1156 nl = &n1; | 1061 nl = &n1; |
1157 } | 1062 } |
1158 if(!nr->addable) { | 1063 if(!nr->addable) { |
1159 tempname(&n2, nr->type); | 1064 tempname(&n2, nr->type); |
1160 cgen(nr, &n2); | 1065 cgen(nr, &n2); |
1161 nr = &n2; | 1066 nr = &n2; |
1162 } | 1067 } |
1163 cmp64(nl, nr, a, likely, to); | 1068 cmp64(nl, nr, a, likely, to); |
1164 break; | 1069 break; |
1165 } | 1070 } |
1166 | 1071 |
1167 a = optoas(a, nr->type); | |
1168 | |
1169 if(nr->ullman >= UINF) { | 1072 if(nr->ullman >= UINF) { |
1170 if(!nl->addable) { | 1073 if(!nl->addable) { |
1171 tempname(&n1, nl->type); | 1074 tempname(&n1, nl->type); |
1172 cgen(nl, &n1); | 1075 cgen(nl, &n1); |
1173 nl = &n1; | 1076 nl = &n1; |
1174 } | 1077 } |
1175 if(!nr->addable) { | 1078 if(!nr->addable) { |
1176 tempname(&tmp, nr->type); | 1079 tempname(&tmp, nr->type); |
1177 cgen(nr, &tmp); | 1080 cgen(nr, &tmp); |
1178 nr = &tmp; | 1081 nr = &tmp; |
1179 } | 1082 } |
1180 regalloc(&n2, nr->type, N); | 1083 regalloc(&n2, nr->type, N); |
1181 cgen(nr, &n2); | 1084 cgen(nr, &n2); |
| 1085 nr = &n2; |
1182 goto cmp; | 1086 goto cmp; |
1183 } | 1087 } |
1184 | 1088 |
1185 if(!nl->addable) { | 1089 if(!nl->addable) { |
1186 tempname(&n1, nl->type); | 1090 tempname(&n1, nl->type); |
1187 cgen(nl, &n1); | 1091 cgen(nl, &n1); |
1188 nl = &n1; | 1092 nl = &n1; |
1189 } | 1093 } |
1190 | 1094 |
1191 if(smallintconst(nr)) { | 1095 if(smallintconst(nr)) { |
1192 gins(optoas(OCMP, nr->type), nl, nr); | 1096 gins(optoas(OCMP, nr->type), nl, nr); |
1193 » » » patch(gbranch(a, nr->type, likely), to); | 1097 » » » patch(gbranch(optoas(a, nr->type), nr->type, likely), to
); |
1194 break; | 1098 break; |
1195 } | 1099 } |
1196 | 1100 |
1197 if(!nr->addable) { | 1101 if(!nr->addable) { |
1198 tempname(&tmp, nr->type); | 1102 tempname(&tmp, nr->type); |
1199 cgen(nr, &tmp); | 1103 cgen(nr, &tmp); |
1200 nr = &tmp; | 1104 nr = &tmp; |
1201 } | 1105 } |
1202 regalloc(&n2, nr->type, N); | 1106 regalloc(&n2, nr->type, N); |
1203 gmove(nr, &n2); | 1107 gmove(nr, &n2); |
| 1108 nr = &n2; |
1204 | 1109 |
1205 cmp: | 1110 cmp: |
1206 » » gins(optoas(OCMP, nr->type), nl, &n2); | 1111 » » gins(optoas(OCMP, nr->type), nl, nr); |
1207 » » patch(gbranch(a, nr->type, likely), to); | 1112 » » patch(gbranch(optoas(a, nr->type), nr->type, likely), to); |
1208 » » regfree(&n2); | 1113 |
| 1114 » » if(nl->op == OREGISTER) |
| 1115 » » » regfree(nl); |
| 1116 » » regfree(nr); |
1209 break; | 1117 break; |
1210 } | 1118 } |
1211 } | 1119 } |
1212 | 1120 |
1213 /* | 1121 /* |
1214 * n is on stack, either local variable | 1122 * n is on stack, either local variable |
1215 * or return value from function call. | 1123 * or return value from function call. |
1216 * return n's offset from SP. | 1124 * return n's offset from SP. |
1217 */ | 1125 */ |
1218 int32 | 1126 int32 |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1527 regfree(&nodl); | 1435 regfree(&nodl); |
1528 return 0; | 1436 return 0; |
1529 | 1437 |
1530 yes: | 1438 yes: |
1531 if(freer) | 1439 if(freer) |
1532 regfree(&nodr); | 1440 regfree(&nodr); |
1533 if(freel) | 1441 if(freel) |
1534 regfree(&nodl); | 1442 regfree(&nodl); |
1535 return 1; | 1443 return 1; |
1536 } | 1444 } |
OLD | NEW |