Thread overview
LDC inline assembler
May 06, 2015
Mike
May 06, 2015
Kagamin
May 06, 2015
Kai Nacke
May 06, 2015
Mike
May 06, 2015
Mike
May 08, 2015
Kai Nacke
May 06, 2015
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 06, 2015
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
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
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
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 08, 2015
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