diff --git a/gen/asm-x86-64.h b/gen/asm-x86-64.h index 16f999b2..074715c9 100644 --- a/gen/asm-x86-64.h +++ b/gen/asm-x86-64.h @@ -630,8 +630,7 @@ namespace AsmParserx8664 static AsmOpEnt opData[] = { { "adc", Op_UpdSrcF }, - - { "add", Op_DstSrcNT }, //Op_UpdSrcF }, + { "add", Op_UpdSrcF }, { "addpd", Op_DstSrcSSE }, { "addps", Op_DstSrcSSE }, { "addq", Op_DstSrcSSE }, diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 95e6b5b0..44a4cac1 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -396,8 +396,9 @@ assert(0); // Add input operand with same value, with original as "matching output". std::ostringstream ss; ss << '*' << (n + asmblock->outputcount); - input_constraints.push_front(ss.str()); - input_values.push_front(output_values[n]); + // Must be at the back; unused operands before used ones screw up numbering. + input_constraints.push_back(ss.str()); + input_values.push_back(output_values[n]); } llvmOutConstraints += *i; llvmOutConstraints += ","; @@ -440,7 +441,7 @@ AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s) } // rewrite argument indices to the block scope indices -static void remap_outargs(std::string& insnt, size_t nargs, size_t& idx) +static void remap_outargs(std::string& insnt, size_t nargs, size_t idx) { static const std::string digits[10] = { @@ -465,7 +466,7 @@ static void remap_outargs(std::string& insnt, size_t nargs, size_t& idx) } // rewrite argument indices to the block scope indices -static void remap_inargs(std::string& insnt, size_t nargs, size_t& idx) +static void remap_inargs(std::string& insnt, size_t nargs, size_t idx) { static const std::string digits[10] = { @@ -644,6 +645,7 @@ void AsmBlockStatement::toIR(IRState* p) out_c += a->out_c; } remap_outargs(a->code, onn+a->in.size(), asmIdx); + asmIdx += onn; } Logger::println("do inputs"); @@ -662,6 +664,7 @@ void AsmBlockStatement::toIR(IRState* p) in_c += a->in_c; } remap_inargs(a->code, inn+a->out.size(), asmIdx); + asmIdx += inn; if (!code.empty()) code += "\n\t"; code += a->code; @@ -707,8 +710,12 @@ void AsmBlockStatement::toIR(IRState* p) if (Logger::enabled()) { Logger::cout() << "Arguments:" << '\n'; Logger::indent(); - for (std::vector::iterator b = args.begin(), i = b, e = args.end(); i != e; ++i) - Logger::cout() << '$' << (i - b) << " ==> " << **i; + for (std::vector::iterator b = args.begin(), i = b, e = args.end(); i != e; ++i) { + std::ostream& cout = Logger::cout(); + cout << '$' << (i - b) << " ==> " << **i; + if (llvm::isa(*i)) + cout << '\n'; + } Logger::undent(); } diff --git a/tests/mini/asm9.d b/tests/mini/asm9.d new file mode 100644 index 00000000..bd4a459b --- /dev/null +++ b/tests/mini/asm9.d @@ -0,0 +1,28 @@ +module asm9; + +version(X86) version = DoSome; +else version(X86_64) version = DoSome; + +T add(T, T t)(T a) { + asm { + add a, t; + } + return a; +} + +void main() { + version (DoSome) { + assert(add!(ubyte, 20)(10) == 30); + assert(add!(ushort, 20_000)(10_000) == 30_000); + assert(add!(uint, 2_000_000)(1_000_000) == 3_000_000); + } + version(X86_64) { + // 64-bit immediates aren't allowed on "ADD", nor are + // unsigned 32-bit ones, so make the template parameter + // fit in a 32-bit signed int. + // These values were chosen so that the lower 32-bits overflow + // and we can see the upper half of the 64-bit input increment. + auto result = add!(long, 2_000_000_000)(21_000_000_000); + assert(result == 23_000_000_000); + } +}