system/corennnnn
Revisión | 52dddc6149cde8e4bb2b3cbca53f77fcc4e62e95 (tree) |
---|---|
Tiempo | 2009-07-09 12:42:06 |
Autor | Android (Google) Code Review <android-gerrit@goog...> |
Commiter | Android (Google) Code Review |
Merge change 6597
* changes:
@@ -316,7 +316,7 @@ class Compiler : public ErrorSink { | ||
316 | 316 | * Pops TOS. |
317 | 317 | * op specifies the comparison. |
318 | 318 | */ |
319 | - virtual void gcmp(int op) = 0; | |
319 | + virtual void gcmp(int op, Type* pResultType) = 0; | |
320 | 320 | |
321 | 321 | /* Perform the arithmetic op specified by op. TOS is the |
322 | 322 | * left argument, R0 is the right argument. |
@@ -327,7 +327,7 @@ class Compiler : public ErrorSink { | ||
327 | 327 | /* Compare 0 against R0, and store the boolean result in R0. |
328 | 328 | * op specifies the comparison. |
329 | 329 | */ |
330 | - virtual void gUnaryCmp(int op) = 0; | |
330 | + virtual void gUnaryCmp(int op, Type* pResultType) = 0; | |
331 | 331 | |
332 | 332 | /* Perform the arithmetic op specified by op. 0 is the |
333 | 333 | * left argument, R0 is the right argument. |
@@ -647,7 +647,7 @@ class Compiler : public ErrorSink { | ||
647 | 647 | return o4(branch | encodeAddress(t)); |
648 | 648 | } |
649 | 649 | |
650 | - virtual void gcmp(int op) { | |
650 | + virtual void gcmp(int op, Type* pResultType) { | |
651 | 651 | LOG_API("gcmp(%d);\n", op); |
652 | 652 | o4(0xE8BD0002); // ldmfd sp!,{r1} |
653 | 653 | mStackUse -= 4; |
@@ -729,12 +729,12 @@ class Compiler : public ErrorSink { | ||
729 | 729 | popType(); |
730 | 730 | } |
731 | 731 | |
732 | - virtual void gUnaryCmp(int op) { | |
733 | - LOG_API("gcmp(%d);\n", op); | |
732 | + virtual void gUnaryCmp(int op, Type* pResultType) { | |
733 | + LOG_API("gUnaryCmp(%d);\n", op); | |
734 | 734 | o4(0xE3A01000); // mov r1, #0 |
735 | 735 | o4(0xE1510000); // cmp r1, r1 |
736 | 736 | switch(op) { |
737 | - case OP_NOT_EQUALS: | |
737 | + case OP_LOGICAL_NOT: | |
738 | 738 | o4(0x03A00000); // moveq r0,#0 |
739 | 739 | o4(0x13A00001); // movne r0,#1 |
740 | 740 | break; |
@@ -742,14 +742,12 @@ class Compiler : public ErrorSink { | ||
742 | 742 | error("Unknown unary comparison op %d", op); |
743 | 743 | break; |
744 | 744 | } |
745 | + setR0Type(pResultType); | |
745 | 746 | } |
746 | 747 | |
747 | 748 | virtual void genUnaryOp(int op) { |
748 | 749 | LOG_API("genOp(%d);\n", op); |
749 | 750 | switch(op) { |
750 | - case OP_PLUS: | |
751 | - // Do nothing | |
752 | - break; | |
753 | 751 | case OP_MINUS: |
754 | 752 | o4(0xE3A01000); // mov r1, #0 |
755 | 753 | o4(0xE0410000); // sub r0,r1,r0 |
@@ -1219,38 +1217,181 @@ class Compiler : public ErrorSink { | ||
1219 | 1217 | return psym(0x84 + l, t); |
1220 | 1218 | } |
1221 | 1219 | |
1222 | - virtual void gcmp(int op) { | |
1223 | - int t = decodeOp(op); | |
1224 | - o(0x59); /* pop %ecx */ | |
1225 | - o(0xc139); /* cmp %eax,%ecx */ | |
1226 | - li(0, NULL); | |
1227 | - o(0x0f); /* setxx %al */ | |
1228 | - o(t + 0x90); | |
1229 | - o(0xc0); | |
1230 | - popType(); | |
1220 | + virtual void gcmp(int op, Type* pResultType) { | |
1221 | + Type* pR0Type = getR0Type(); | |
1222 | + Type* pTOSType = getTOSType(); | |
1223 | + TypeTag tagR0 = pR0Type->tag; | |
1224 | + TypeTag tagTOS = pTOSType->tag; | |
1225 | + bool isFloatR0 = isFloatTag(tagR0); | |
1226 | + bool isFloatTOS = isFloatTag(tagTOS); | |
1227 | + if (!isFloatR0 && !isFloatTOS) { | |
1228 | + int t = decodeOp(op); | |
1229 | + o(0x59); /* pop %ecx */ | |
1230 | + o(0xc139); /* cmp %eax,%ecx */ | |
1231 | + li(0, NULL); | |
1232 | + o(0x0f); /* setxx %al */ | |
1233 | + o(t + 0x90); | |
1234 | + o(0xc0); | |
1235 | + popType(); | |
1236 | + } else { | |
1237 | + setupFloatOperands(); | |
1238 | + switch (op) { | |
1239 | + case OP_EQUALS: | |
1240 | + o(0xe9da); // fucompp | |
1241 | + o(0xe0df); // fnstsw %ax | |
1242 | + o(0x9e); // sahf | |
1243 | + o(0xc0940f); // sete %al | |
1244 | + o(0xc29b0f); // setnp %dl | |
1245 | + o(0xd021); // andl %edx, %eax | |
1246 | + break; | |
1247 | + case OP_NOT_EQUALS: | |
1248 | + o(0xe9da); // fucompp | |
1249 | + o(0xe0df); // fnstsw %ax | |
1250 | + o(0x9e); // sahf | |
1251 | + o(0xc0950f); // setne %al | |
1252 | + o(0xc29a0f); // setp %dl | |
1253 | + o(0xd009); // orl %edx, %eax | |
1254 | + break; | |
1255 | + case OP_GREATER_EQUAL: | |
1256 | + o(0xe9da); // fucompp | |
1257 | + o(0xe0df); // fnstsw %ax | |
1258 | + o(0x05c4f6); // testb $5, %ah | |
1259 | + o(0xc0940f); // sete %al | |
1260 | + break; | |
1261 | + case OP_LESS: | |
1262 | + o(0xc9d9); // fxch %st(1) | |
1263 | + o(0xe9da); // fucompp | |
1264 | + o(0xe0df); // fnstsw %ax | |
1265 | + o(0x9e); // sahf | |
1266 | + o(0xc0970f); // seta %al | |
1267 | + break; | |
1268 | + case OP_LESS_EQUAL: | |
1269 | + o(0xc9d9); // fxch %st(1) | |
1270 | + o(0xe9da); // fucompp | |
1271 | + o(0xe0df); // fnstsw %ax | |
1272 | + o(0x9e); // sahf | |
1273 | + o(0xc0930f); // setea %al | |
1274 | + break; | |
1275 | + case OP_GREATER: | |
1276 | + o(0xe9da); // fucompp | |
1277 | + o(0xe0df); // fnstsw %ax | |
1278 | + o(0x45c4f6); // testb $69, %ah | |
1279 | + o(0xc0940f); // sete %al | |
1280 | + break; | |
1281 | + default: | |
1282 | + error("Unknown comparison op"); | |
1283 | + } | |
1284 | + o(0xc0b60f); // movzbl %al, %eax | |
1285 | + } | |
1286 | + setR0Type(pResultType); | |
1231 | 1287 | } |
1232 | 1288 | |
1233 | 1289 | virtual void genOp(int op) { |
1234 | - o(0x59); /* pop %ecx */ | |
1235 | - o(decodeOp(op)); | |
1236 | - if (op == OP_MOD) | |
1237 | - o(0x92); /* xchg %edx, %eax */ | |
1238 | - popType(); | |
1290 | + Type* pR0Type = getR0Type(); | |
1291 | + Type* pTOSType = getTOSType(); | |
1292 | + TypeTag tagR0 = pR0Type->tag; | |
1293 | + TypeTag tagTOS = pTOSType->tag; | |
1294 | + bool isFloatR0 = isFloatTag(tagR0); | |
1295 | + bool isFloatTOS = isFloatTag(tagTOS); | |
1296 | + if (!isFloatR0 && !isFloatTOS) { | |
1297 | + // TODO: Deal with pointer arithmetic | |
1298 | + o(0x59); /* pop %ecx */ | |
1299 | + o(decodeOp(op)); | |
1300 | + if (op == OP_MOD) | |
1301 | + o(0x92); /* xchg %edx, %eax */ | |
1302 | + popType(); | |
1303 | + } else { | |
1304 | + Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; | |
1305 | + setupFloatOperands(); | |
1306 | + // Both float. x87 R0 == left hand, x87 R1 == right hand | |
1307 | + switch (op) { | |
1308 | + case OP_MUL: | |
1309 | + o(0xc9de); // fmulp | |
1310 | + break; | |
1311 | + case OP_DIV: | |
1312 | + o(0xf1de); // fdivp | |
1313 | + break; | |
1314 | + case OP_PLUS: | |
1315 | + o(0xc1de); // faddp | |
1316 | + break; | |
1317 | + case OP_MINUS: | |
1318 | + o(0xe1de); // fsubp | |
1319 | + break; | |
1320 | + default: | |
1321 | + error("Unsupported binary floating operation."); | |
1322 | + break; | |
1323 | + } | |
1324 | + popType(); | |
1325 | + setR0Type(pResultType); | |
1326 | + printf("genop: result type %d\n", pResultType->tag); | |
1327 | + } | |
1239 | 1328 | } |
1240 | 1329 | |
1241 | - virtual void gUnaryCmp(int op) { | |
1242 | - oad(0xb9, 0); /* movl $0, %ecx */ | |
1243 | - int t = decodeOp(op); | |
1244 | - o(0xc139); /* cmp %eax,%ecx */ | |
1245 | - li(0, NULL); | |
1246 | - o(0x0f); /* setxx %al */ | |
1247 | - o(t + 0x90); | |
1248 | - o(0xc0); | |
1330 | + | |
1331 | + | |
1332 | + virtual void gUnaryCmp(int op, Type* pResultType) { | |
1333 | + if (op != OP_LOGICAL_NOT) { | |
1334 | + error("Unknown unary cmp %d", op); | |
1335 | + } else { | |
1336 | + Type* pR0Type = getR0Type(); | |
1337 | + TypeTag tag = collapseType(pR0Type->tag); | |
1338 | + switch(tag) { | |
1339 | + case TY_INT: { | |
1340 | + oad(0xb9, 0); /* movl $0, %ecx */ | |
1341 | + int t = decodeOp(op); | |
1342 | + o(0xc139); /* cmp %eax,%ecx */ | |
1343 | + li(0, NULL); | |
1344 | + o(0x0f); /* setxx %al */ | |
1345 | + o(t + 0x90); | |
1346 | + o(0xc0); | |
1347 | + } | |
1348 | + break; | |
1349 | + case TY_FLOAT: | |
1350 | + case TY_DOUBLE: | |
1351 | + o(0xeed9); // fldz | |
1352 | + o(0xe9da); // fucompp | |
1353 | + o(0xe0df); // fnstsw %ax | |
1354 | + o(0x9e); // sahf | |
1355 | + o(0xc0950f); // setne %al | |
1356 | + o(0xc29a0f); // setp %dl | |
1357 | + o(0xd009); // orl %edx, %eax | |
1358 | + o(0xc0b60f); // movzbl %al, %eax | |
1359 | + o(0x01f083); // xorl $1, %eax | |
1360 | + break; | |
1361 | + default: | |
1362 | + error("genUnaryCmp unsupported type"); | |
1363 | + break; | |
1364 | + } | |
1365 | + } | |
1366 | + setR0Type(pResultType); | |
1249 | 1367 | } |
1250 | 1368 | |
1251 | 1369 | virtual void genUnaryOp(int op) { |
1252 | - oad(0xb9, 0); /* movl $0, %ecx */ | |
1253 | - o(decodeOp(op)); | |
1370 | + Type* pR0Type = getR0Type(); | |
1371 | + TypeTag tag = collapseType(pR0Type->tag); | |
1372 | + switch(tag) { | |
1373 | + case TY_INT: | |
1374 | + oad(0xb9, 0); /* movl $0, %ecx */ | |
1375 | + o(decodeOp(op)); | |
1376 | + break; | |
1377 | + case TY_FLOAT: | |
1378 | + case TY_DOUBLE: | |
1379 | + switch (op) { | |
1380 | + case OP_MINUS: | |
1381 | + o(0xe0d9); // fchs | |
1382 | + break; | |
1383 | + case OP_BIT_NOT: | |
1384 | + error("Can't apply '~' operator to a float or double."); | |
1385 | + break; | |
1386 | + default: | |
1387 | + error("Unknown unary op %d\n", op); | |
1388 | + break; | |
1389 | + } | |
1390 | + break; | |
1391 | + default: | |
1392 | + error("genUnaryOp unsupported type"); | |
1393 | + break; | |
1394 | + } | |
1254 | 1395 | } |
1255 | 1396 | |
1256 | 1397 | virtual void pushR0() { |
@@ -1592,6 +1733,34 @@ class Compiler : public ErrorSink { | ||
1592 | 1733 | o(l + 0x83); |
1593 | 1734 | oad((t > -LOCAL && t < LOCAL) << 7 | 5, t); |
1594 | 1735 | } |
1736 | + | |
1737 | + void setupFloatOperands() { | |
1738 | + Type* pR0Type = getR0Type(); | |
1739 | + Type* pTOSType = getTOSType(); | |
1740 | + TypeTag tagR0 = pR0Type->tag; | |
1741 | + TypeTag tagTOS = pTOSType->tag; | |
1742 | + bool isFloatR0 = isFloatTag(tagR0); | |
1743 | + bool isFloatTOS = isFloatTag(tagTOS); | |
1744 | + if (! isFloatR0) { | |
1745 | + // Convert R0 from int to float | |
1746 | + o(0x50); // push %eax | |
1747 | + o(0x2404DB); // fildl 0(%esp) | |
1748 | + o(0x58); // pop %eax | |
1749 | + } | |
1750 | + if (! isFloatTOS){ | |
1751 | + o(0x2404DB); // fildl 0(%esp); | |
1752 | + o(0x58); // pop %eax | |
1753 | + } else { | |
1754 | + if (tagTOS == TY_FLOAT) { | |
1755 | + o(0x2404d9); // flds (%esp) | |
1756 | + o(0x58); // pop %eax | |
1757 | + } else { | |
1758 | + o(0x2404dd); // fldl (%esp) | |
1759 | + o(0x58); // pop %eax | |
1760 | + o(0x58); // pop %eax | |
1761 | + } | |
1762 | + } | |
1763 | + } | |
1595 | 1764 | }; |
1596 | 1765 | |
1597 | 1766 | #endif // PROVIDE_X86_CODEGEN |
@@ -1656,9 +1825,9 @@ class Compiler : public ErrorSink { | ||
1656 | 1825 | return result; |
1657 | 1826 | } |
1658 | 1827 | |
1659 | - virtual void gcmp(int op) { | |
1660 | - fprintf(stderr, "gcmp(%d)\n", op); | |
1661 | - mpBase->gcmp(op); | |
1828 | + virtual void gcmp(int op, Type* pResultType) { | |
1829 | + fprintf(stderr, "gcmp(%d, pResultType)\n", op); | |
1830 | + mpBase->gcmp(op, pResultType); | |
1662 | 1831 | } |
1663 | 1832 | |
1664 | 1833 | virtual void genOp(int op) { |
@@ -1667,9 +1836,9 @@ class Compiler : public ErrorSink { | ||
1667 | 1836 | } |
1668 | 1837 | |
1669 | 1838 | |
1670 | - virtual void gUnaryCmp(int op) { | |
1671 | - fprintf(stderr, "gUnaryCmp(%d)\n", op); | |
1672 | - mpBase->gUnaryCmp(op); | |
1839 | + virtual void gUnaryCmp(int op, Type* pResultType) { | |
1840 | + fprintf(stderr, "gUnaryCmp(%d, pResultType)\n", op); | |
1841 | + mpBase->gUnaryCmp(op, pResultType); | |
1673 | 1842 | } |
1674 | 1843 | |
1675 | 1844 | virtual void genUnaryOp(int op) { |
@@ -2923,9 +3092,12 @@ class Compiler : public ErrorSink { | ||
2923 | 3092 | /* -, +, !, ~ */ |
2924 | 3093 | unary(false); |
2925 | 3094 | if (t == '!') |
2926 | - pGen->gUnaryCmp(a); | |
2927 | - else | |
3095 | + pGen->gUnaryCmp(a, mkpInt); | |
3096 | + else if (t == '+') { | |
3097 | + // ignore unary plus. | |
3098 | + } else { | |
2928 | 3099 | pGen->genUnaryOp(a); |
3100 | + } | |
2929 | 3101 | } else if (t == '(') { |
2930 | 3102 | expr(); |
2931 | 3103 | skip(')'); |
@@ -3090,7 +3262,7 @@ class Compiler : public ErrorSink { | ||
3090 | 3262 | binaryOp(level); |
3091 | 3263 | |
3092 | 3264 | if ((level == 4) | (level == 5)) { |
3093 | - pGen->gcmp(t); | |
3265 | + pGen->gcmp(t, mkpInt); | |
3094 | 3266 | } else { |
3095 | 3267 | pGen->genOp(t); |
3096 | 3268 | } |
@@ -3665,7 +3837,7 @@ class Compiler : public ErrorSink { | ||
3665 | 3837 | char* allocGlobalSpace(size_t alignment, size_t bytes) { |
3666 | 3838 | size_t base = (((size_t) glo) + alignment - 1) & ~(alignment-1); |
3667 | 3839 | size_t end = base + bytes; |
3668 | - if ((end - (size_t) pGlobalBase) > ALLOC_SIZE) { | |
3840 | + if ((end - (size_t) pGlobalBase) > (size_t) ALLOC_SIZE) { | |
3669 | 3841 | error("Global space exhausted"); |
3670 | 3842 | return NULL; |
3671 | 3843 | } |
@@ -0,0 +1,115 @@ | ||
1 | +// Test floating point operations. | |
2 | + | |
3 | +void unaryOps() { | |
4 | + // Unary ops | |
5 | + printf("-%g = %g\n", 1.1, -1.1); | |
6 | + printf("!%g = %d\n", 1.2, !1.2); | |
7 | + printf("!%g = %d\n", 0.0, !0,0); | |
8 | +} | |
9 | + | |
10 | +void binaryOps() { | |
11 | + printf("double op double:\n"); | |
12 | + printf("%g + %g = %g\n", 1.0, 2.0, 1.0 + 2.0); | |
13 | + printf("%g - %g = %g\n", 1.0, 2.0, 1.0 - 2.0); | |
14 | + printf("%g * %g = %g\n", 1.0, 2.0, 1.0 * 2.0); | |
15 | + printf("%g / %g = %g\n", 1.0, 2.0, 1.0 / 2.0); | |
16 | + | |
17 | + printf("float op float:\n"); | |
18 | + printf("%g + %g = %g\n", 1.0f, 2.0f, 1.0f + 2.0f); | |
19 | + printf("%g - %g = %g\n", 1.0f, 2.0f, 1.0f - 2.0f); | |
20 | + printf("%g * %g = %g\n", 1.0f, 2.0f, 1.0f * 2.0f); | |
21 | + printf("%g / %g = %g\n", 1.0f, 2.0f, 1.0f / 2.0f); | |
22 | + | |
23 | + printf("double op float:\n"); | |
24 | + printf("%g + %g = %g\n", 1.0, 2.0f, 1.0 + 2.0f); | |
25 | + printf("%g - %g = %g\n", 1.0, 2.0f, 1.0 - 2.0f); | |
26 | + printf("%g * %g = %g\n", 1.0, 2.0f, 1.0 * 2.0f); | |
27 | + printf("%g / %g = %g\n", 1.0, 2.0f, 1.0 / 2.0f); | |
28 | + | |
29 | + printf("double op int:\n"); | |
30 | + printf("%g + %d = %g\n", 1.0, 2, 1.0 + 2); | |
31 | + printf("%g - %d = %g\n", 1.0, 2, 1.0 - 2); | |
32 | + printf("%g * %d = %g\n", 1.0, 2, 1.0 * 2); | |
33 | + printf("%g / %d = %g\n", 1.0, 2, 1.0 / 2); | |
34 | + | |
35 | + printf("int op double:\n"); | |
36 | + printf("%d + %g = %g\n", 1, 2.0, 1 + 2.0); | |
37 | + printf("%d - %g = %g\n", 1, 2.0, 1 - 2.0); | |
38 | + printf("%d * %g = %g\n", 1, 2.0, 1 * 2.0); | |
39 | + printf("%d / %g = %g\n", 1, 2.0, 1 / 2.0); | |
40 | +} | |
41 | + | |
42 | +void comparisonTestdd(double a, double b) { | |
43 | + printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", | |
44 | + a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); | |
45 | +} | |
46 | + | |
47 | +void comparisonOpsdd() { | |
48 | + printf("double op double:\n"); | |
49 | + comparisonTestdd(1.0, 2.0); | |
50 | + comparisonTestdd(1.0, 1.0); | |
51 | + comparisonTestdd(2.0, 1.0); | |
52 | +} | |
53 | + | |
54 | + | |
55 | +void comparisonTestdf(double a, float b) { | |
56 | + printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", | |
57 | + a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); | |
58 | +} | |
59 | + | |
60 | +void comparisonOpsdf() { | |
61 | + printf("double op float:\n"); | |
62 | + comparisonTestdf(1.0, 2.0f); | |
63 | + comparisonTestdf(1.0, 1.0f); | |
64 | + comparisonTestdf(2.0, 1.0f); | |
65 | +} | |
66 | + | |
67 | +void comparisonTestff(float a, float b) { | |
68 | + printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", | |
69 | + a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); | |
70 | +} | |
71 | + | |
72 | +void comparisonOpsff() { | |
73 | + printf("float op float:\n"); | |
74 | + comparisonTestff(1.0f, 2.0f); | |
75 | + comparisonTestff(1.0f, 1.0f); | |
76 | + comparisonTestff(2.0f, 1.0f); | |
77 | +} | |
78 | +void comparisonTestid(int a, double b) { | |
79 | + printf("%d op %g: < %d <= %d == %d >= %d > %d != %d\n", | |
80 | + a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); | |
81 | +} | |
82 | + | |
83 | +void comparisonOpsid() { | |
84 | + printf("int op double:\n"); | |
85 | + comparisonTestid(1, 2.0f); | |
86 | + comparisonTestid(1, 1.0f); | |
87 | + comparisonTestid(2, 1.0f); | |
88 | +} | |
89 | +void comparisonTestdi(double a, int b) { | |
90 | + printf("%g op %d: < %d <= %d == %d >= %d > %d != %d\n", | |
91 | + a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); | |
92 | +} | |
93 | + | |
94 | +void comparisonOpsdi() { | |
95 | + printf("double op int:\n"); | |
96 | + comparisonTestdi(1.0f, 2); | |
97 | + comparisonTestdi(1.0f, 1); | |
98 | + comparisonTestdi(2.0f, 1); | |
99 | +} | |
100 | + | |
101 | +void comparisonOps() { | |
102 | + comparisonOpsdd(); | |
103 | + comparisonOpsdf(); | |
104 | + comparisonOpsff(); | |
105 | + comparisonOpsid(); | |
106 | + comparisonOpsdi(); | |
107 | +} | |
108 | + | |
109 | + | |
110 | +int main() { | |
111 | + unaryOps(); | |
112 | + binaryOps(); | |
113 | + comparisonOps(); | |
114 | + return 0; | |
115 | +} |