Mercurial > projects > ldc
comparison gen/asm-x86-32.h @ 1102:ae950bd712d3
Use stringstream in asm generation instead of OutBuffer.
Besides looking better, this should reduce allocations and copying.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Thu, 12 Mar 2009 14:08:57 +0100 |
parents | 8bf8b058944a |
children | cdb7e1167803 |
comparison
equal
deleted
inserted
replaced
1101:8bf8b058944a | 1102:ae950bd712d3 |
---|---|
1204 | 1204 |
1205 AsmStatement * stmt; | 1205 AsmStatement * stmt; |
1206 Scope * sc; | 1206 Scope * sc; |
1207 | 1207 |
1208 Token * token; | 1208 Token * token; |
1209 OutBuffer * insnTemplate; | 1209 std::ostringstream insnTemplate; |
1210 | 1210 |
1211 AsmOp op; | 1211 AsmOp op; |
1212 AsmOpInfo * opInfo; | 1212 AsmOpInfo * opInfo; |
1213 Operand operands[Max_Operands]; | 1213 Operand operands[Max_Operands]; |
1214 Identifier * opIdent; | 1214 Identifier * opIdent; |
1217 AsmProcessor ( Scope * sc, AsmStatement * stmt ) | 1217 AsmProcessor ( Scope * sc, AsmStatement * stmt ) |
1218 { | 1218 { |
1219 this->sc = sc; | 1219 this->sc = sc; |
1220 this->stmt = stmt; | 1220 this->stmt = stmt; |
1221 token = stmt->tokens; | 1221 token = stmt->tokens; |
1222 insnTemplate = new OutBuffer; | |
1223 | 1222 |
1224 opInfo = NULL; | 1223 opInfo = NULL; |
1225 | 1224 |
1226 if ( ! regInfo[0].ident ) | 1225 if ( ! regInfo[0].ident ) |
1227 { | 1226 { |
1448 } | 1447 } |
1449 | 1448 |
1450 void setAsmCode() | 1449 void setAsmCode() |
1451 { | 1450 { |
1452 AsmCode * asmcode = new AsmCode ( N_Regs ); | 1451 AsmCode * asmcode = new AsmCode ( N_Regs ); |
1453 asmcode->insnTemplateLen = insnTemplate->offset; | 1452 asmcode->insnTemplate = insnTemplate.str(); |
1454 asmcode->insnTemplate = ( char* ) insnTemplate->extractData(); | |
1455 stmt->asmcode = ( code* ) asmcode; | 1453 stmt->asmcode = ( code* ) asmcode; |
1456 } | 1454 } |
1457 | 1455 |
1458 // note: doesn't update AsmOp op | 1456 // note: doesn't update AsmOp op |
1459 bool matchOperands ( unsigned nOperands ) | 1457 bool matchOperands ( unsigned nOperands ) |
1511 { | 1509 { |
1512 switch ( type ) | 1510 switch ( type ) |
1513 { | 1511 { |
1514 case Arg_Integer: | 1512 case Arg_Integer: |
1515 if ( e->type->isunsigned() ) | 1513 if ( e->type->isunsigned() ) |
1516 insnTemplate->printf ( "$%llu", e->toUInteger() ); | 1514 insnTemplate << "$" << e->toUInteger(); |
1517 else | 1515 else |
1518 insnTemplate->printf ( "$%lld", e->toInteger() ); | 1516 insnTemplate << "$" << e->toInteger(); |
1519 break; | 1517 break; |
1520 | 1518 |
1521 case Arg_Pointer: | 1519 case Arg_Pointer: |
1522 stmt->error ( "unsupported pointer reference to '%s' in naked asm", e->toChars() ); | 1520 stmt->error ( "unsupported pointer reference to '%s' in naked asm", e->toChars() ); |
1523 break; | 1521 break; |
1534 break; | 1532 break; |
1535 } | 1533 } |
1536 | 1534 |
1537 // osx needs an extra underscore | 1535 // osx needs an extra underscore |
1538 if ( global.params.os == OSMacOSX ) | 1536 if ( global.params.os == OSMacOSX ) |
1539 insnTemplate->writestring ( "_" ); | 1537 insnTemplate << "_"; |
1540 | 1538 |
1541 // print out the mangle | 1539 // print out the mangle |
1542 insnTemplate->writestring ( vd->mangle() ); | 1540 insnTemplate << vd->mangle(); |
1543 vd->nakedUse = true; | 1541 vd->nakedUse = true; |
1544 break; | 1542 break; |
1545 } | 1543 } |
1546 } | 1544 } |
1547 stmt->error ( "unsupported memory reference to '%s' in naked asm", e->toChars() ); | 1545 stmt->error ( "unsupported memory reference to '%s' in naked asm", e->toChars() ); |
1552 break; | 1550 break; |
1553 } | 1551 } |
1554 } | 1552 } |
1555 else | 1553 else |
1556 { | 1554 { |
1557 insnTemplate->writestring ( ( char* ) fmt ); | 1555 insnTemplate << fmt |
1558 insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() ); | 1556 << "<<" << (mode==Mode_Input ? "in" : "out") << asmcode->args.size() << ">>"; |
1559 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); | 1557 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); |
1560 } | 1558 } |
1561 } | 1559 } |
1562 void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input ) | 1560 void addOperand2 ( const char * fmtpre, const char * fmtpost, AsmArgType type, Expression * e, AsmCode * asmcode, AsmArgMode mode = Mode_Input ) |
1563 { | 1561 { |
1564 assert ( !sc->func->naked ); | 1562 assert ( !sc->func->naked ); |
1565 insnTemplate->writestring ( ( char* ) fmtpre ); | 1563 insnTemplate << fmtpre |
1566 insnTemplate->printf ( "<<%s%d>>", ( mode==Mode_Input ) ?"in":"out", asmcode->args.size() ); | 1564 << "<<" << (mode==Mode_Input ? "in" : "out") << ">>" |
1567 insnTemplate->writestring ( ( char* ) fmtpost ); | 1565 << fmtpost; |
1568 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); | 1566 asmcode->args.push_back ( AsmArg ( type, e, mode ) ); |
1569 } | 1567 } |
1570 | 1568 |
1571 void addLabel ( char* id ) | 1569 void addLabel ( char* id ) |
1572 { | 1570 { |
1573 insnTemplate->writestring ( sc->func->mangle() ); | 1571 insnTemplate << sc->func->mangle() << "_" << id; |
1574 insnTemplate->writestring ( "_" ); | |
1575 insnTemplate->writestring ( id ); | |
1576 } | 1572 } |
1577 | 1573 |
1578 /* Determines whether the operand is a register, memory reference | 1574 /* Determines whether the operand is a register, memory reference |
1579 or immediate. Immediate addresses are currently classified as | 1575 or immediate. Immediate addresses are currently classified as |
1580 memory. This function is called before the exact instructions | 1576 memory. This function is called before the exact instructions |
1651 return Opr_Invalid; | 1647 return Opr_Invalid; |
1652 } | 1648 } |
1653 | 1649 |
1654 void writeReg ( Reg reg ) | 1650 void writeReg ( Reg reg ) |
1655 { | 1651 { |
1656 insnTemplate->writestring ( ( char* ) "%" ); | 1652 insnTemplate << "%" << regInfo[reg].gccName; |
1657 insnTemplate->write ( regInfo[reg].gccName.c_str(), regInfo[reg].gccName.length() ); | |
1658 } | 1653 } |
1659 | 1654 |
1660 bool opTakesLabel() | 1655 bool opTakesLabel() |
1661 { | 1656 { |
1662 switch ( op ) | 1657 switch ( op ) |
1724 const char *mnemonic; | 1719 const char *mnemonic; |
1725 char type_char = 0; | 1720 char type_char = 0; |
1726 bool use_star; | 1721 bool use_star; |
1727 AsmArgMode mode; | 1722 AsmArgMode mode; |
1728 | 1723 |
1729 insnTemplate = new OutBuffer; | 1724 insnTemplate.str(""); |
1730 // %% todo: special case for something.. | 1725 // %% todo: special case for something.. |
1731 if ( opInfo->linkType == Out_Mnemonic ) | 1726 if ( opInfo->linkType == Out_Mnemonic ) |
1732 mnemonic = alternateMnemonics[opInfo->link]; | 1727 mnemonic = alternateMnemonics[opInfo->link]; |
1733 else | 1728 else |
1734 mnemonic = opIdent->string; | 1729 mnemonic = opIdent->string; |
1793 } | 1788 } |
1794 } | 1789 } |
1795 else if ( op == Op_Branch ) | 1790 else if ( op == Op_Branch ) |
1796 { | 1791 { |
1797 if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that.. | 1792 if ( operands[0].dataSize == Far_Ptr ) // %% type=Far_Ptr not set by Seg:Ofss OTOH, we don't support that.. |
1798 insnTemplate->writebyte ( 'l' ); | 1793 insnTemplate << 'l'; |
1799 } | 1794 } |
1800 else if ( op == Op_fxch || op == Op_FfdRR_P || op == Op_FidR_P ) | 1795 else if ( op == Op_fxch || op == Op_FfdRR_P || op == Op_FidR_P ) |
1801 { | 1796 { |
1802 if ( operands[0].cls == Opr_Mem && op == Op_FidR_P ) | 1797 if ( operands[0].cls == Opr_Mem && op == Op_FidR_P ) |
1803 { | 1798 { |
1835 { | 1830 { |
1836 case Op_SizedStack: | 1831 case Op_SizedStack: |
1837 { | 1832 { |
1838 int mlen = strlen ( mnemonic ); | 1833 int mlen = strlen ( mnemonic ); |
1839 if ( mnemonic[mlen-1] == 'd' ) | 1834 if ( mnemonic[mlen-1] == 'd' ) |
1840 insnTemplate->write ( mnemonic, mlen-1 ); | 1835 insnTemplate.write(mnemonic, mlen-1); |
1841 else | 1836 else |
1842 { | 1837 { |
1843 insnTemplate->writestring ( ( char* ) mnemonic ); | 1838 insnTemplate << mnemonic << 'w'; |
1844 insnTemplate->writebyte ( 'w' ); | |
1845 } | 1839 } |
1846 } | 1840 } |
1847 break; | 1841 break; |
1848 case Op_cmpsd: | 1842 case Op_cmpsd: |
1849 case Op_insX: | 1843 case Op_insX: |
1854 case Op_stosX: | 1848 case Op_stosX: |
1855 { | 1849 { |
1856 int mlen = strlen ( mnemonic ); | 1850 int mlen = strlen ( mnemonic ); |
1857 if ( mnemonic[mlen-1] == 'd' ) | 1851 if ( mnemonic[mlen-1] == 'd' ) |
1858 { | 1852 { |
1859 insnTemplate->write ( mnemonic, mlen-1 ); | 1853 insnTemplate.write(mnemonic, mlen-1) << 'l'; |
1860 insnTemplate->writebyte ( 'l' ); | |
1861 } | 1854 } |
1862 else | 1855 else |
1863 { | 1856 { |
1864 insnTemplate->writestring ( ( char* ) mnemonic ); | 1857 insnTemplate << mnemonic; |
1865 } | 1858 } |
1866 } | 1859 } |
1867 break; | 1860 break; |
1868 case Op_movsx: | 1861 case Op_movsx: |
1869 case Op_movzx: | 1862 case Op_movzx: |
1886 default: | 1879 default: |
1887 stmt->error ( "invalid operand size/type" ); | 1880 stmt->error ( "invalid operand size/type" ); |
1888 return false; | 1881 return false; |
1889 } | 1882 } |
1890 assert ( type_char != 0 ); | 1883 assert ( type_char != 0 ); |
1891 insnTemplate->write ( mnemonic, mlen-1 ); | 1884 insnTemplate.write(mnemonic, mlen-1) << tc_1 << type_char; |
1892 insnTemplate->writebyte ( tc_1 ); | |
1893 insnTemplate->writebyte ( type_char ); | |
1894 } | 1885 } |
1895 break; | 1886 break; |
1896 default: | 1887 default: |
1897 insnTemplate->writestring ( ( char* ) mnemonic ); | 1888 insnTemplate << mnemonic; |
1898 if ( type_char ) | 1889 if ( type_char ) |
1899 insnTemplate->writebyte ( type_char ); | 1890 insnTemplate << type_char; |
1900 break; | 1891 break; |
1901 } | 1892 } |
1902 | 1893 |
1903 switch ( opInfo->implicitClobbers & Clb_DXAX_Mask ) | 1894 switch ( opInfo->implicitClobbers & Clb_DXAX_Mask ) |
1904 { | 1895 { |
1948 asmcode->regs[Reg_EBX] = true; | 1939 asmcode->regs[Reg_EBX] = true; |
1949 asmcode->regs[Reg_ECX] = true; | 1940 asmcode->regs[Reg_ECX] = true; |
1950 asmcode->regs[Reg_EDX] = true; | 1941 asmcode->regs[Reg_EDX] = true; |
1951 } | 1942 } |
1952 | 1943 |
1953 insnTemplate->writebyte ( ' ' ); | 1944 insnTemplate << ' '; |
1954 for ( int i__ = 0; i__ < nOperands; i__++ ) | 1945 for ( int i__ = 0; i__ < nOperands; i__++ ) |
1955 { | 1946 { |
1956 int i; | 1947 int i; |
1957 if ( i__ != 0 ) | 1948 if ( i__ != 0 ) |
1958 insnTemplate->writestring ( ( char* ) ", " ); | 1949 insnTemplate << ", "; |
1959 | 1950 |
1960 fmt = "$"; | 1951 fmt = "$"; |
1961 | 1952 |
1962 switch ( op ) | 1953 switch ( op ) |
1963 { | 1954 { |
2001 // handle __LOCAL_SIZE, which in this constant, is an immediate | 1992 // handle __LOCAL_SIZE, which in this constant, is an immediate |
2002 // should do this in slotexp.. | 1993 // should do this in slotexp.. |
2003 addOperand ( "$", Arg_LocalSize, | 1994 addOperand ( "$", Arg_LocalSize, |
2004 ( Expression * ) operand->symbolDisplacement.data[0], asmcode ); | 1995 ( Expression * ) operand->symbolDisplacement.data[0], asmcode ); |
2005 if ( operand->constDisplacement ) | 1996 if ( operand->constDisplacement ) |
2006 insnTemplate->writebyte ( '+' ); | 1997 insnTemplate << '+'; |
2007 else | 1998 else |
2008 break; | 1999 break; |
2009 } | 2000 } |
2010 | 2001 |
2011 if ( operand->symbolDisplacement.dim ) | 2002 if ( operand->symbolDisplacement.dim ) |
2014 addOperand ( "$", Arg_Pointer, | 2005 addOperand ( "$", Arg_Pointer, |
2015 ( Expression * ) operand->symbolDisplacement.data[0], | 2006 ( Expression * ) operand->symbolDisplacement.data[0], |
2016 asmcode ); | 2007 asmcode ); |
2017 | 2008 |
2018 if ( operand->constDisplacement ) | 2009 if ( operand->constDisplacement ) |
2019 insnTemplate->writebyte ( '+' ); | 2010 insnTemplate << '+'; |
2020 else | 2011 else |
2021 // skip the addOperand(fmt, Arg_Integer...) below | 2012 // skip the addOperand(fmt, Arg_Integer...) below |
2022 break; | 2013 break; |
2023 } | 2014 } |
2024 addOperand ( fmt, Arg_Integer, newIntExp ( operand->constDisplacement ), asmcode ); | 2015 addOperand ( fmt, Arg_Integer, newIntExp ( operand->constDisplacement ), asmcode ); |
2031 { | 2022 { |
2032 asmcode->regs[clbr_reg] = true; | 2023 asmcode->regs[clbr_reg] = true; |
2033 } | 2024 } |
2034 } | 2025 } |
2035 if ( opTakesLabel() /*opInfo->takesLabel()*/ ) | 2026 if ( opTakesLabel() /*opInfo->takesLabel()*/ ) |
2036 insnTemplate->writebyte ( '*' ); | 2027 insnTemplate << '*'; |
2037 writeReg ( operand->reg ); | 2028 writeReg ( operand->reg ); |
2038 /* | 2029 /* |
2039 insnTemplate->writestring("%"); | 2030 insnTemplate << "%"; |
2040 insnTemplate->writestring(regInfo[operand->reg].name); | 2031 insnTemplate << regInfo[operand->reg].name; |
2041 */ | 2032 */ |
2042 break; | 2033 break; |
2043 case Opr_Mem: | 2034 case Opr_Mem: |
2044 // better: use output operands for simple variable references | 2035 // better: use output operands for simple variable references |
2045 if ( ( opInfo->operands[i] & Opr_Update ) == Opr_Update ) | 2036 if ( ( opInfo->operands[i] & Opr_Update ) == Opr_Update ) |
2059 | 2050 |
2060 if ( operand->segmentPrefix != Reg_Invalid || operand->constDisplacement ) | 2051 if ( operand->segmentPrefix != Reg_Invalid || operand->constDisplacement ) |
2061 { | 2052 { |
2062 if ( operand->symbolDisplacement.dim ) | 2053 if ( operand->symbolDisplacement.dim ) |
2063 { | 2054 { |
2064 insnTemplate->printf ( "%d", operand->constDisplacement ); | 2055 insnTemplate << operand->constDisplacement << '+'; |
2065 insnTemplate->writebyte ( '+' ); | |
2066 } | 2056 } |
2067 //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode); | 2057 //addOperand(fmt, Arg_Integer, newIntExp(operand->constDisplacement), asmcode); |
2068 if ( opInfo->operands[i] & Opr_Dest ) | 2058 if ( opInfo->operands[i] & Opr_Dest ) |
2069 asmcode->clobbersMemory = 1; | 2059 asmcode->clobbersMemory = 1; |
2070 } | 2060 } |
2071 | 2061 |
2072 if ( operand->segmentPrefix != Reg_Invalid ) | 2062 if ( operand->segmentPrefix != Reg_Invalid ) |
2073 { | 2063 { |
2074 writeReg ( operand->segmentPrefix ); | 2064 writeReg ( operand->segmentPrefix ); |
2075 insnTemplate->writebyte ( ':' ); | 2065 insnTemplate << ':'; |
2076 } | 2066 } |
2077 if ( operand->symbolDisplacement.dim ) | 2067 if ( operand->symbolDisplacement.dim ) |
2078 { | 2068 { |
2079 Expression * e = ( Expression * ) operand->symbolDisplacement.data[0]; | 2069 Expression * e = ( Expression * ) operand->symbolDisplacement.data[0]; |
2080 Declaration * decl = 0; | 2070 Declaration * decl = 0; |
2161 { | 2151 { |
2162 use_star = false; | 2152 use_star = false; |
2163 // simply write out the mangle | 2153 // simply write out the mangle |
2164 // on osx, prepend extra _ | 2154 // on osx, prepend extra _ |
2165 if ( global.params.os == OSMacOSX ) | 2155 if ( global.params.os == OSMacOSX ) |
2166 insnTemplate->writestring ( "_" ); | 2156 insnTemplate << "_"; |
2167 insnTemplate->writestring ( decl->mangle() ); | 2157 insnTemplate << decl->mangle(); |
2168 // addOperand2("${", ":c}", Arg_Pointer, e, asmcode); | 2158 // addOperand2("${", ":c}", Arg_Pointer, e, asmcode); |
2169 } | 2159 } |
2170 else | 2160 else |
2171 { | 2161 { |
2172 if ( use_star ) | 2162 if ( use_star ) |
2173 { | 2163 { |
2174 insnTemplate->writebyte ( '*' ); | 2164 insnTemplate << '*'; |
2175 use_star = false; | 2165 use_star = false; |
2176 } | 2166 } |
2177 | 2167 |
2178 if ( !sc->func->naked ) // no addrexp in naked asm please :) | 2168 if ( !sc->func->naked ) // no addrexp in naked asm please :) |
2179 { | 2169 { |
2185 addOperand ( fmt, Arg_Memory, e, asmcode, mode ); | 2175 addOperand ( fmt, Arg_Memory, e, asmcode, mode ); |
2186 } | 2176 } |
2187 } | 2177 } |
2188 } | 2178 } |
2189 if ( use_star ) | 2179 if ( use_star ) |
2190 insnTemplate->writebyte ( '*' ); | 2180 insnTemplate << '*'; |
2191 if ( operand->segmentPrefix != Reg_Invalid && !(operand->constDisplacement) ) | 2181 if ( operand->segmentPrefix != Reg_Invalid && !(operand->constDisplacement) ) |
2192 { | 2182 { |
2193 insnTemplate->printf ( "%d", operand->constDisplacement ); | 2183 insnTemplate << operand->constDisplacement; |
2194 if ( opInfo->operands[i] & Opr_Dest ) | 2184 if ( opInfo->operands[i] & Opr_Dest ) |
2195 asmcode->clobbersMemory = 1; | 2185 asmcode->clobbersMemory = 1; |
2196 } | 2186 } |
2197 if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid ) | 2187 if ( operand->baseReg != Reg_Invalid || operand->indexReg != Reg_Invalid ) |
2198 { | 2188 { |
2199 insnTemplate->writebyte ( '(' ); | 2189 insnTemplate << '('; |
2200 if ( operand->baseReg != Reg_Invalid ) | 2190 if ( operand->baseReg != Reg_Invalid ) |
2201 writeReg ( operand->baseReg ); | 2191 writeReg ( operand->baseReg ); |
2202 if ( operand->indexReg != Reg_Invalid ) | 2192 if ( operand->indexReg != Reg_Invalid ) |
2203 { | 2193 { |
2204 insnTemplate->writebyte ( ',' ); | 2194 insnTemplate << ','; |
2205 writeReg ( operand->indexReg ); | 2195 writeReg ( operand->indexReg ); |
2206 if ( operand->scale ) | 2196 if ( operand->scale ) |
2207 { | 2197 { |
2208 insnTemplate->printf ( ",%d", operand->scale ); | 2198 insnTemplate << "," << operand->scale; |
2209 } | 2199 } |
2210 } | 2200 } |
2211 insnTemplate->writebyte ( ')' ); | 2201 insnTemplate << ')'; |
2212 if ( opInfo->operands[i] & Opr_Dest ) | 2202 if ( opInfo->operands[i] & Opr_Dest ) |
2213 asmcode->clobbersMemory = 1; | 2203 asmcode->clobbersMemory = 1; |
2214 } | 2204 } |
2215 break; | 2205 break; |
2216 case Opr_Invalid: | 2206 case Opr_Invalid: |
2217 return false; | 2207 return false; |
2218 } | 2208 } |
2219 } | 2209 } |
2220 | 2210 |
2221 asmcode->insnTemplateLen = insnTemplate->offset; | 2211 asmcode->insnTemplate = insnTemplate.str(); |
2222 asmcode->insnTemplate = ( char* ) insnTemplate->extractData(); | |
2223 return true; | 2212 return true; |
2224 } | 2213 } |
2225 | 2214 |
2226 bool isIntExp ( Expression * exp ) | 2215 bool isIntExp ( Expression * exp ) |
2227 { | 2216 { |
2889 if ( ( align & ( align - 1 ) ) == 0 ) | 2878 if ( ( align & ( align - 1 ) ) == 0 ) |
2890 { | 2879 { |
2891 //FIXME: This printf is not portable. The use of `align` varies from system to system; | 2880 //FIXME: This printf is not portable. The use of `align` varies from system to system; |
2892 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary | 2881 // on i386 using a.out, .align `n` will align on a 2^`n` boundary instead of an `n` boundary |
2893 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN | 2882 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN |
2894 insnTemplate->printf ( ".balign\t%u", ( unsigned ) align ); | 2883 insnTemplate << ".balign\t" << align; |
2895 #else | 2884 #else |
2896 insnTemplate->printf ( ".align\t%u", ( unsigned ) align ); | 2885 insnTemplate << ".align\t" << align; |
2897 #endif | 2886 #endif |
2898 } | 2887 } |
2899 else | 2888 else |
2900 { | 2889 { |
2901 stmt->error ( "alignment must be a power of 2, not %u", ( unsigned ) align ); | 2890 stmt->error ( "alignment must be a power of 2, not %u", ( unsigned ) align ); |
2906 | 2895 |
2907 void doEven() | 2896 void doEven() |
2908 { | 2897 { |
2909 // .align for GAS is in bits, others probably use bytes.. | 2898 // .align for GAS is in bits, others probably use bytes.. |
2910 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN | 2899 #ifdef HAVE_GAS_BALIGN_AND_P2ALIGN |
2911 insnTemplate->writestring ( ( char * ) ".align\t2" ); | 2900 insnTemplate << ".align\t2"; |
2912 #else | 2901 #else |
2913 insnTemplate->writestring ( ( char * ) ".align\t2" ); | 2902 insnTemplate << ".align\t2"; |
2914 #endif | 2903 #endif |
2915 setAsmCode(); | 2904 setAsmCode(); |
2916 } | 2905 } |
2917 | 2906 |
2918 void doNaked() | 2907 void doNaked() |