www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.ldc - LDC inline assembler

reply "Mike" <none none.com> writes:
I'm trying to do a write a syscall in x86_64 Linux, but I'm 
having trouble with the LDC inline assembler syntax.  Here's my 
cludgy implementation for DMD and GDC:


extern(C) c_int sys_write(c_int arg1, in void* arg2, c_int arg3) 
nothrow
{
     ssize_t result;

     version(D_LP64)
     {
         version(DigitalMars)
         {
             asm nothrow
             {
                 mov RAX, 1;
                 mov RDI, arg1;
                 mov RSI, arg2;
                 mov RDX, arg3;
                 syscall;
             }
         }
         else version(GNU)
         {
             asm
             {
                 "syscall"       // make the request to the OS
                 : "=a" result   // return result in rax ("a")
                 : "a" 1,        // pass system call number in rax 
("a")
                 "D" arg1,       // pass arg1 in rdi ("D")
                 "S" arg2,       // pass arg2 in rsi ("S")
                 "m" arg2,       // arg2 is a pointer to memory
                 "d" arg3        // pass arg3 in rdx ("d")
                 : "memory", "cc", "rcx", "r11";  // announce to 
the compiler that the memory and condition codes
                                                  // have been 
modified, kernel may clopper rcx and r11
             }
         }
         else
         {
             static assert(false, "sys_write only supports DMD and 
GDC");
         }
     }
     else
     {
         static assert(false, "sys_write only supports 64-bit");
     }


     // TODO: Not sure if this is right
     return result;
}

I've read through 
http://wiki.dlang.org/LDC_inline_assembly_expressions, but I'm 
just not understanding the syntax.  Could you translate the above 
to LDC's syntax?  If I can understand it, I'll document an 
example on the wiki in return.

Thanks,
Mike
May 05 2015
next sibling parent "Kagamin" <spam here.lot> writes:
return 
__asm!long("syscall","=a,a,D,S,*m,d,~{memory},~{cc},~c,~{r11}", 
1,arg1,arg2,arg2,arg3);

Though I have no idea what I'm doing :)
May 06 2015
prev sibling parent reply "Kai Nacke" <kai redstar.de> writes:
Hi Mike!

This should do the trick:

extern(C) ulong dosyscall(ulong a, ulong b, ulong c)
{
     import ldc.llvmasm;

     ulong result = __asm!ulong("syscall", 
"={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11}", 1, a, b, c);
     return result;
}

A named register must be surrounded with { }. If any register is 
ok then you can use simply r. As far as I know there is no way 
that to tell LLVM that a memory range is clobbered.

Regardsm
Kai
May 06 2015
next sibling parent "Mike" <none none.com> writes:
On Wednesday, 6 May 2015 at 10:31:15 UTC, Kai Nacke wrote:
  As far as I know there is no way that to tell LLVM that a 
 memory range is clobbered.
Doesn't ~{memory} do it?
May 06 2015
prev sibling parent reply "Mike" <none none.com> writes:
On Wednesday, 6 May 2015 at 10:31:15 UTC, Kai Nacke wrote:
 Hi Mike!

 This should do the trick:

 extern(C) ulong dosyscall(ulong a, ulong b, ulong c)
 {
     import ldc.llvmasm;

     ulong result = __asm!ulong("syscall", 
 "={rax},{rax},{rdi},{rsi},{rdx},~{rcx},~{r11}", 1, a, b, c);
     return result;
 }

 A named register must be surrounded with { }. If any register 
 is ok then you can use simply r. As far as I know there is no 
 way that to tell LLVM that a memory range is clobbered.

 Regardsm
 Kai
Thank you! It works great. I added it to the Wiki for future reference: http://wiki.dlang.org/LDC_inline_assembly_expressions Mike
May 06 2015
parent "Kai Nacke" <kai redstar.de> writes:
On Wednesday, 6 May 2015 at 13:31:07 UTC, Mike wrote:
 Thank you! It works great. I added it to the Wiki for future 
 reference:
 http://wiki.dlang.org/LDC_inline_assembly_expressions

 Mike
Thanks for the wiki update! Regards, Kai
May 07 2015