Difference between revisions of "LDC inline assembly expressions"

From D Wiki
Jump to: navigation, search
(Wiki syntax fixes.)
m (Examples: more wiki syntax fixes)
Line 63: Line 63:
 
<source lang="d">// store val into dst
 
<source lang="d">// store val into dst
 
void store(ref int dst, int val) {
 
void store(ref int dst, int val) {
   __asm(&quot;movl $1, $0&quot;, &quot;=*m,r&quot;, &amp;dst, val);
+
   __asm("movl $1, $0", "=*m,r", &dst, val);
 
}</source>
 
}</source>
 
<source lang="d">// load dst into EAX and return it
 
<source lang="d">// load dst into EAX and return it
 
int load(ref int dst) {
 
int load(ref int dst) {
   return __asm!(int)(&quot;movl $1, $0&quot;, &quot;=a,*m&quot;, &amp;dst);
+
   return __asm!int("movl $1, $0", "=a,*m", &dst);
 
}</source>
 
}</source>
 +
 
== PPC 32 ==
 
== PPC 32 ==
  

Revision as of 22:19, 12 December 2012

Inline assembly expressions are useful when the D asm statement is not yet available, or when the limitations or it being a statement are problematic. Being an expression, extended inline expressions are able to return values!

Additionally issues regarding inlining of function containing inline asm are mostly not relevant for extended inline assembly expressions. Effectively, extended inline assembly expression can be used to efficiently implement new intrinsics in the compiler.

Interface

To use them you must import the module containing the magic declarations:

import ldc.llvmasm;

Three different forms exist:

No return value:

void __asm (char[] asmcode, char[] constraints, [ Arguments... ] );

Single return value:

template __asm(T) {
  T __asm (char[] asmcode, char[] constraints, [ Arguments... ] );
}

Multiple return values:

struct __asmtuple_t(T...) {
  T v;
}
template __asmtuple(T...) {
  __asmtuple_t!(T) __asm (char[] asmcode, char[] constraints, [ Arguments... ] );
}

In all cases the constraint list must match the return type and arguments.

Constraints is a comma seperated list of outputs, inputs and clobbers.

Output constraints must come first, then input constraints, then finally clobbers.

Common output constraints:

  • =*m == memory output
  • =r == general purpose register output

Common input constraints:

  • *m == memory input
  • r == general purpose register input
  • i == immediate value input

Common clobbers:

  • ~{memory} == clobbers memory

X86-32

X86-32 specific constraints

  • a or {ax} or {eax} == EAX
  • b or {bx} or {ebx} == EBX
  • c or {cx} or {ecx} == ECX
  • d or {dx} or {edx} == EDX
  • A == EAX:EDX
  • {st} == ST(0)
  • {st(N)} == ST(N)

Examples

// store val into dst
void store(ref int dst, int val) {
  __asm("movl $1, $0", "=*m,r", &dst, val);
}
// load dst into EAX and return it
int load(ref int dst) {
  return __asm!int("movl $1, $0", "=a,*m", &dst);
}

PPC 32

Examples

// store val into dst
void store(ref int dst, int val) {
  __asm(&quot;ldw r4, $1 ; stw r4, $0&quot;, &quot;=*m,r,~{r4}&quot;, &amp;dst, val);
}