• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


Commit MetaInfo

Revisão52dddc6149cde8e4bb2b3cbca53f77fcc4e62e95 (tree)
Hora2009-07-09 12:42:06
AutorAndroid (Google) Code Review <android-gerrit@goog...>
CommiterAndroid (Google) Code Review

Mensagem de Log

Merge change 6597

* changes:

Implement x86 floating point operations

Mudança Sumário

Diff

--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -316,7 +316,7 @@ class Compiler : public ErrorSink {
316316 * Pops TOS.
317317 * op specifies the comparison.
318318 */
319- virtual void gcmp(int op) = 0;
319+ virtual void gcmp(int op, Type* pResultType) = 0;
320320
321321 /* Perform the arithmetic op specified by op. TOS is the
322322 * left argument, R0 is the right argument.
@@ -327,7 +327,7 @@ class Compiler : public ErrorSink {
327327 /* Compare 0 against R0, and store the boolean result in R0.
328328 * op specifies the comparison.
329329 */
330- virtual void gUnaryCmp(int op) = 0;
330+ virtual void gUnaryCmp(int op, Type* pResultType) = 0;
331331
332332 /* Perform the arithmetic op specified by op. 0 is the
333333 * left argument, R0 is the right argument.
@@ -647,7 +647,7 @@ class Compiler : public ErrorSink {
647647 return o4(branch | encodeAddress(t));
648648 }
649649
650- virtual void gcmp(int op) {
650+ virtual void gcmp(int op, Type* pResultType) {
651651 LOG_API("gcmp(%d);\n", op);
652652 o4(0xE8BD0002); // ldmfd sp!,{r1}
653653 mStackUse -= 4;
@@ -729,12 +729,12 @@ class Compiler : public ErrorSink {
729729 popType();
730730 }
731731
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);
734734 o4(0xE3A01000); // mov r1, #0
735735 o4(0xE1510000); // cmp r1, r1
736736 switch(op) {
737- case OP_NOT_EQUALS:
737+ case OP_LOGICAL_NOT:
738738 o4(0x03A00000); // moveq r0,#0
739739 o4(0x13A00001); // movne r0,#1
740740 break;
@@ -742,14 +742,12 @@ class Compiler : public ErrorSink {
742742 error("Unknown unary comparison op %d", op);
743743 break;
744744 }
745+ setR0Type(pResultType);
745746 }
746747
747748 virtual void genUnaryOp(int op) {
748749 LOG_API("genOp(%d);\n", op);
749750 switch(op) {
750- case OP_PLUS:
751- // Do nothing
752- break;
753751 case OP_MINUS:
754752 o4(0xE3A01000); // mov r1, #0
755753 o4(0xE0410000); // sub r0,r1,r0
@@ -1219,38 +1217,181 @@ class Compiler : public ErrorSink {
12191217 return psym(0x84 + l, t);
12201218 }
12211219
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);
12311287 }
12321288
12331289 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+ }
12391328 }
12401329
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);
12491367 }
12501368
12511369 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+ }
12541395 }
12551396
12561397 virtual void pushR0() {
@@ -1592,6 +1733,34 @@ class Compiler : public ErrorSink {
15921733 o(l + 0x83);
15931734 oad((t > -LOCAL && t < LOCAL) << 7 | 5, t);
15941735 }
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+ }
15951764 };
15961765
15971766 #endif // PROVIDE_X86_CODEGEN
@@ -1656,9 +1825,9 @@ class Compiler : public ErrorSink {
16561825 return result;
16571826 }
16581827
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);
16621831 }
16631832
16641833 virtual void genOp(int op) {
@@ -1667,9 +1836,9 @@ class Compiler : public ErrorSink {
16671836 }
16681837
16691838
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);
16731842 }
16741843
16751844 virtual void genUnaryOp(int op) {
@@ -2923,9 +3092,12 @@ class Compiler : public ErrorSink {
29233092 /* -, +, !, ~ */
29243093 unary(false);
29253094 if (t == '!')
2926- pGen->gUnaryCmp(a);
2927- else
3095+ pGen->gUnaryCmp(a, mkpInt);
3096+ else if (t == '+') {
3097+ // ignore unary plus.
3098+ } else {
29283099 pGen->genUnaryOp(a);
3100+ }
29293101 } else if (t == '(') {
29303102 expr();
29313103 skip(')');
@@ -3090,7 +3262,7 @@ class Compiler : public ErrorSink {
30903262 binaryOp(level);
30913263
30923264 if ((level == 4) | (level == 5)) {
3093- pGen->gcmp(t);
3265+ pGen->gcmp(t, mkpInt);
30943266 } else {
30953267 pGen->genOp(t);
30963268 }
@@ -3665,7 +3837,7 @@ class Compiler : public ErrorSink {
36653837 char* allocGlobalSpace(size_t alignment, size_t bytes) {
36663838 size_t base = (((size_t) glo) + alignment - 1) & ~(alignment-1);
36673839 size_t end = base + bytes;
3668- if ((end - (size_t) pGlobalBase) > ALLOC_SIZE) {
3840+ if ((end - (size_t) pGlobalBase) > (size_t) ALLOC_SIZE) {
36693841 error("Global space exhausted");
36703842 return NULL;
36713843 }
--- /dev/null
+++ b/libacc/tests/data/flops.c
@@ -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+}