Mercurial > projects > ldc
comparison gen/asm-x86-64.h @ 1091:20d96c148b39
Fix for fmul/div/add/sub with no operands. Revert explicit ST0 definition since a typo
had caused the need for that.
author | Kelly Wilson <wilsonk cpsc.ucalgary.ca> |
---|---|
date | Tue, 10 Mar 2009 18:34:19 -0600 |
parents | 8cb5b746500c |
children | cb868105a6b5 |
comparison
equal
deleted
inserted
replaced
1090:6a19c36fc4a6 | 1091:20d96c148b39 |
---|---|
15 Reg_EDX, | 15 Reg_EDX, |
16 Reg_ESI, | 16 Reg_ESI, |
17 Reg_EDI, | 17 Reg_EDI, |
18 Reg_EBP, | 18 Reg_EBP, |
19 Reg_ESP, | 19 Reg_ESP, |
20 Reg_ST, Reg_ST0, | 20 Reg_ST, |
21 Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7, | 21 Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7, |
22 Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7, | 22 Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7, |
23 Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7, | 23 Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7, |
24 | 24 |
25 Reg_RAX, Reg_RBX, Reg_RCX, Reg_RDX, Reg_RSI, Reg_RDI, Reg_RBP, Reg_RSP, | 25 Reg_RAX, Reg_RBX, Reg_RCX, Reg_RDX, Reg_RSI, Reg_RDI, Reg_RBP, Reg_RSP, |
43 Reg_CR0, Reg_CR2, Reg_CR3, Reg_CR4, | 43 Reg_CR0, Reg_CR2, Reg_CR3, Reg_CR4, |
44 Reg_DR0, Reg_DR1, Reg_DR2, Reg_DR3, Reg_DR6, Reg_DR7, | 44 Reg_DR0, Reg_DR1, Reg_DR2, Reg_DR3, Reg_DR6, Reg_DR7, |
45 Reg_TR3, Reg_TR4, Reg_TR5, Reg_TR6, Reg_TR7 | 45 Reg_TR3, Reg_TR4, Reg_TR5, Reg_TR6, Reg_TR7 |
46 } Reg; | 46 } Reg; |
47 | 47 |
48 static const int N_Regs = /*gp*/ 8 + /*fp*/ 9 + /*mmx*/ 8 + /*sse*/ 8 + | 48 static const int N_Regs = /*gp*/ 8 + /*fp*/ 8 + /*mmx*/ 8 + /*sse*/ 8 + |
49 /*seg*/ 6 + /*16bit*/ 8 + /*8bit*/ 8 + /*sys*/ 4+6+5 + /*flags*/ + 1 | 49 /*seg*/ 6 + /*16bit*/ 8 + /*8bit*/ 8 + /*sys*/ 4+6+5 + /*flags*/ + 1 |
50 + 8 /*RAX, etc*/ | 50 + 8 /*RAX, etc*/ |
51 + 8 /*R8-15*/ | 51 + 8 /*R8-15*/ |
52 + 4 /*SIL, etc. 8-bit*/ | 52 + 4 /*SIL, etc. 8-bit*/ |
53 + 8 /*R8-15B*/ | 53 + 8 /*R8-15B*/ |
76 { "ESI", NULL_TREE, NULL, 4, Reg_ESI }, | 76 { "ESI", NULL_TREE, NULL, 4, Reg_ESI }, |
77 { "EDI", NULL_TREE, NULL, 4, Reg_EDI }, | 77 { "EDI", NULL_TREE, NULL, 4, Reg_EDI }, |
78 { "EBP", NULL_TREE, NULL, 4, Reg_EBP }, | 78 { "EBP", NULL_TREE, NULL, 4, Reg_EBP }, |
79 { "ESP", NULL_TREE, NULL, 4, Reg_ESP }, | 79 { "ESP", NULL_TREE, NULL, 4, Reg_ESP }, |
80 { "ST", NULL_TREE, NULL, 10, Reg_ST }, | 80 { "ST", NULL_TREE, NULL, 10, Reg_ST }, |
81 { "ST(0)", NULL_TREE, NULL, 10, Reg_ST0 }, | |
82 { "ST(1)", NULL_TREE, NULL,10, Reg_ST1 }, | 81 { "ST(1)", NULL_TREE, NULL,10, Reg_ST1 }, |
83 { "ST(2)", NULL_TREE, NULL,10, Reg_ST2 }, | 82 { "ST(2)", NULL_TREE, NULL,10, Reg_ST2 }, |
84 { "ST(3)", NULL_TREE, NULL,10, Reg_ST3 }, | 83 { "ST(3)", NULL_TREE, NULL,10, Reg_ST3 }, |
85 { "ST(4)", NULL_TREE, NULL,10, Reg_ST4 }, | 84 { "ST(4)", NULL_TREE, NULL,10, Reg_ST4 }, |
86 { "ST(5)", NULL_TREE, NULL,10, Reg_ST5 }, | 85 { "ST(5)", NULL_TREE, NULL,10, Reg_ST5 }, |
291 Op_FfdR_P, | 290 Op_FfdR_P, |
292 Op_FfdRR_P, | 291 Op_FfdRR_P, |
293 Op_Fd_P, | 292 Op_Fd_P, |
294 Op_FdST, | 293 Op_FdST, |
295 Op_FMath, | 294 Op_FMath, |
295 Op_FMath0, | |
296 Op_FMath2, | |
296 Op_FdSTiSTi, | 297 Op_FdSTiSTi, |
298 Op_FdST0ST1, | |
297 Op_FPMath, | 299 Op_FPMath, |
298 Op_FCmp, | 300 Op_FCmp, |
299 Op_FCmp1, | 301 Op_FCmp1, |
300 Op_FCmpP, | 302 Op_FCmpP, |
301 Op_FCmpP1, | 303 Op_FCmpP1, |
532 /* Op_Ffd_P */ { D|mfp, 0, 0, FP_Types, Clb_ST, Next_Form, Op_FfdR_P }, // pop, fld so also 80 bit, " | 534 /* Op_Ffd_P */ { D|mfp, 0, 0, FP_Types, Clb_ST, Next_Form, Op_FfdR_P }, // pop, fld so also 80 bit, " |
533 /* Op_FfdR_P */ { D|rfp, 0, 0, 0, Clb_ST, Next_Form, Op_FfdRR_P }, | 535 /* Op_FfdR_P */ { D|rfp, 0, 0, 0, Clb_ST, Next_Form, Op_FfdRR_P }, |
534 /* Op_FfdRR_P */ { D|mfp|rfp,rfp,0, 0, Clb_ST }, | 536 /* Op_FfdRR_P */ { D|mfp|rfp,rfp,0, 0, Clb_ST }, |
535 /* Op_Fd_P */ { D|mem, 0, 0, 0, Clb_ST }, // " | 537 /* Op_Fd_P */ { D|mem, 0, 0, 0, Clb_ST }, // " |
536 /* Op_FdST */ { D|rfp, 0, 0 }, | 538 /* Op_FdST */ { D|rfp, 0, 0 }, |
537 /* Op_FMath */ { mfp, 0, 0, FP_Types, Clb_ST, Next_Form, Op_FdSTiSTi }, // and only single or double prec | 539 /* Op_FMath */ { mfp, 0, 0, FP_Types, Clb_ST, Next_Form, Op_FMath0 }, // and only single or double prec |
540 /* Op_FMath0 */ { 0, 0, 0, 0, Clb_ST, Next_Form, Op_FMath2 }, // pops | |
541 /* Op_FMath2 */ { D|rfp, rfp, 0, 0, Clb_ST, Next_Form, Op_FdST0ST1 }, // and only single or double prec | |
538 /* Op_FdSTiSTi */ { D|rfp, rfp, 0, }, | 542 /* Op_FdSTiSTi */ { D|rfp, rfp, 0, }, |
543 /* Op_FdST0ST1 */ { 0, 0, 0, }, | |
539 /* Op_FPMath */ { D|rfp, rfp, 0, 0, Clb_ST, Next_Form, Op_F0_P }, // pops | 544 /* Op_FPMath */ { D|rfp, rfp, 0, 0, Clb_ST, Next_Form, Op_F0_P }, // pops |
540 /* Op_FCmp */ { mfp, 0, 0, FP_Types, 0, Next_Form, Op_FCmp1 }, // DMD defaults to float ptr | 545 /* Op_FCmp */ { mfp, 0, 0, FP_Types, 0, Next_Form, Op_FCmp1 }, // DMD defaults to float ptr |
541 /* Op_FCmp1 */ { rfp, 0, 0, 0, 0, Next_Form, Op_0 }, | 546 /* Op_FCmp1 */ { rfp, 0, 0, 0, 0, Next_Form, Op_0 }, |
542 /* Op_FCmpP */ { mfp, 0, 0, FP_Types, 0, Next_Form, Op_FCmpP1 }, // pops | 547 /* Op_FCmpP */ { mfp, 0, 0, FP_Types, 0, Next_Form, Op_FCmpP1 }, // pops |
543 /* Op_FCmpP1 */ { rfp, 0, 0, 0, 0, Next_Form, Op_F0_P }, // pops | 548 /* Op_FCmpP1 */ { rfp, 0, 0, 0, 0, Next_Form, Op_F0_P }, // pops |
1482 unsigned operand_i = 0; | 1487 unsigned operand_i = 0; |
1483 | 1488 |
1484 opInfo = & asmOpInfo[op]; | 1489 opInfo = & asmOpInfo[op]; |
1485 memset ( operands, 0, sizeof ( operands ) ); | 1490 memset ( operands, 0, sizeof ( operands ) ); |
1486 | 1491 |
1492 if ( token->value == TOKeof && ( op == Op_FMath0) ) | |
1493 { | |
1494 for ( operand_i = 0; operand_i < 1; operand_i++) | |
1495 { | |
1496 operand = & operands[operand_i]; | |
1497 operand->reg = operand->baseReg = operand->indexReg = | |
1498 operand->segmentPrefix = Reg_Invalid; | |
1499 | |
1500 operand->cls = Opr_Reg; | |
1501 if ( operand_i == 0) | |
1502 { | |
1503 operand->reg = Reg_ST; | |
1504 } | |
1505 else | |
1506 { | |
1507 operand->reg = Reg_ST1; | |
1508 } | |
1509 operand->hasNumber = 0; | |
1510 operand->constDisplacement = 0; | |
1511 parseOperand(); | |
1512 | |
1513 if ( matchOperands ( operand_i ) ) | |
1514 { | |
1515 AsmCode * asmcode = new AsmCode ( N_Regs ); | |
1516 | |
1517 if ( formatInstruction ( operand_i, asmcode ) ) | |
1518 stmt->asmcode = ( code * ) asmcode; | |
1519 } | |
1520 } | |
1521 return; | |
1522 } | |
1523 | |
1487 while ( token->value != TOKeof ) | 1524 while ( token->value != TOKeof ) |
1488 { | 1525 { |
1489 if ( operand_i < Max_Operands ) | 1526 if ( operand_i < Max_Operands ) |
1490 { | 1527 { |
1491 operand = & operands[operand_i]; | 1528 operand = & operands[operand_i]; |
1547 | 1584 |
1548 for ( unsigned i = 0; i < nOperands; i++ ) | 1585 for ( unsigned i = 0; i < nOperands; i++ ) |
1549 classifyOperand ( & operands[i] ); | 1586 classifyOperand ( & operands[i] ); |
1550 | 1587 |
1551 while ( 1 ) | 1588 while ( 1 ) |
1552 { | 1589 { |
1553 if ( nOperands == opInfo->nOperands() ) | 1590 if ( nOperands == opInfo->nOperands() ) |
1554 { | 1591 { |
1555 wrong_number = false; | 1592 wrong_number = false; |
1556 /* Cases in which number of operands is not | 1593 /* Cases in which number of operands is not |
1557 enough for a match: Op_FCmp/Op_FCmp1, | 1594 enough for a match: Op_FCmp/Op_FCmp1, |
1708 return Opr_Invalid; | 1745 return Opr_Invalid; |
1709 } | 1746 } |
1710 | 1747 |
1711 return Opr_Mem; | 1748 return Opr_Mem; |
1712 } | 1749 } |
1713 | 1750 |
1714 if ( operand->reg != Reg_Invalid && ! operand->hasNumber ) | 1751 if ( operand->reg != Reg_Invalid && ! operand->hasNumber ) |
1715 return Opr_Reg; | 1752 return Opr_Reg; |
1716 | 1753 |
1717 // should check immediate given (operand->hasNumber); | 1754 // should check immediate given (operand->hasNumber); |
1718 // | 1755 // |
1819 // %% todo: special case for something.. | 1856 // %% todo: special case for something.. |
1820 if ( opInfo->linkType == Out_Mnemonic ) | 1857 if ( opInfo->linkType == Out_Mnemonic ) |
1821 mnemonic = alternateMnemonics[opInfo->link]; | 1858 mnemonic = alternateMnemonics[opInfo->link]; |
1822 else | 1859 else |
1823 mnemonic = opIdent->string; | 1860 mnemonic = opIdent->string; |
1824 | 1861 |
1825 if ( opInfo->needsType ) | 1862 if ( opInfo->needsType ) |
1826 { | 1863 { |
1827 PtrType exact_type = Default_Ptr; | 1864 PtrType exact_type = Default_Ptr; |
1828 PtrType min_type = Default_Ptr; | 1865 PtrType min_type = Default_Ptr; |
1829 PtrType hint_type = Default_Ptr; | 1866 PtrType hint_type = Default_Ptr; |
1895 // gas won't accept the two-operand form | 1932 // gas won't accept the two-operand form |
1896 else if ( operands[1].cls == Opr_Reg && operands[1].reg == Reg_ST ) | 1933 else if ( operands[1].cls == Opr_Reg && operands[1].reg == Reg_ST ) |
1897 { | 1934 { |
1898 nOperands = 1; | 1935 nOperands = 1; |
1899 } | 1936 } |
1900 else if ( operands[0].cls == Opr_Reg && (operands[0].reg == Reg_ST1 || operands[0].reg == Reg_ST || operands[0].reg == Reg_ST0 )) | 1937 else if ( operands[0].cls == Opr_Reg && (operands[0].reg == Reg_ST1 || operands[0].reg == Reg_ST )) |
1901 { | 1938 { |
1902 //fix previous update to to allow single operand form of fstp | 1939 //fix previous update to allow single operand form of fstp |
1903 } | 1940 } |
1904 else | 1941 else |
1905 { | 1942 { |
1906 stmt->error ( "invalid operands" ); | 1943 stmt->error ( "invalid operands" ); |
1907 return false; | 1944 return false; |
1908 } | 1945 } |
1946 } | |
1947 else if ( op == Op_FMath0 || op == Op_FdST0ST1 ) | |
1948 { | |
1949 operands[0].cls = Opr_Reg; | |
1950 operands[0].reg = Reg_ST; | |
1951 operands[1].cls = Opr_Reg; | |
1952 operands[1].reg = Reg_ST1; | |
1953 nOperands = 2; | |
1909 } | 1954 } |
1910 | 1955 |
1911 switch ( op ) | 1956 switch ( op ) |
1912 { | 1957 { |
1913 case Op_SizedStack: | 1958 case Op_SizedStack: |
2007 asm statement leaves an arg pushed on the stack. | 2052 asm statement leaves an arg pushed on the stack. |
2008 Maybe if the statment had and input or output | 2053 Maybe if the statment had and input or output |
2009 operand it would work... In any case, clobbering | 2054 operand it would work... In any case, clobbering |
2010 all FP prevents incorrect code generation. */ | 2055 all FP prevents incorrect code generation. */ |
2011 asmcode->regs[Reg_ST] = true; | 2056 asmcode->regs[Reg_ST] = true; |
2012 asmcode->regs[Reg_ST0] = true; | |
2013 asmcode->regs[Reg_ST1] = true; | 2057 asmcode->regs[Reg_ST1] = true; |
2014 asmcode->regs[Reg_ST2] = true; | 2058 asmcode->regs[Reg_ST2] = true; |
2015 asmcode->regs[Reg_ST3] = true; | 2059 asmcode->regs[Reg_ST3] = true; |
2016 asmcode->regs[Reg_ST4] = true; | 2060 asmcode->regs[Reg_ST4] = true; |
2017 asmcode->regs[Reg_ST5] = true; | 2061 asmcode->regs[Reg_ST5] = true; |
2936 case TOKint64: | 2980 case TOKint64: |
2937 //This is for the 'short' in "jle short Label;" | 2981 //This is for the 'short' in "jle short Label;" |
2938 return Handled; | 2982 return Handled; |
2939 break; | 2983 break; |
2940 default: | 2984 default: |
2985 if ( op == Op_FMath0 || op == Op_FdST0ST1 || op == Op_FMath ) | |
2986 return Handled; | |
2941 invalidExpression(); | 2987 invalidExpression(); |
2942 return Handled; | 2988 return Handled; |
2943 } | 2989 } |
2944 return e; | 2990 return e; |
2945 } | 2991 } |