On Sunday, 12 November 2017 at 11:55:23 UTC, Eugene Wissner wrote:
On Sunday, 12 November 2017 at 11:01:39 UTC, Dibyendu Majumdar
wrote:
I have recently started work on building a VM for Lua
(actually a derivative of Lua) in X86-64 assembly. I am using
the dynasm tool that is part of LuaJIT. I was wondering
whether I could also write this in D's inline assembly
perhaps, but there is one aspect that I am not sure how to do.
The assembly code uses static allocation of registers, but
because of the differences in how registers are used in Win64
versus Unix X64 - different registers are assigned depending
on the architecture. dynasm makes this easy to do using
macros; e.g. below.
|.if X64WIN
|.define CARG1, rcx // x64/WIN64 C call arguments.
|.define CARG2, rdx
|.define CARG3, r8
|.define CARG4, r9
|.else
|.define CARG1, rdi // x64/POSIX C call arguments.
|.define CARG2, rsi
|.define CARG3, rdx
|.define CARG4, rcx
|.endif
With above in place, the code can use the mnemonics to refer
to the registers rather than the registers themselves. This
allows the assembly code to be coded once for both
architectures.
How would one do this in D inline assembly?
Thanks and Regards
Dibyendu
Here is an example with mixins:
version (Windows)
{
enum Reg : string
{
CARG1 = "RCX",
CARG2 = "RDX",
}
}
else
{
enum Reg : string
{
CARG1 = "RDI",
CARG2 = "RSI",
}
}
template Instruction(string I, Reg target, Reg source)
{
enum string Instruction = "asm { mov " ~ target ~ ", " ~
source ~ "; }";
}
void func()
{
mixin(Instruction!("mov", Reg.CARG1, Reg.CARG2));
}
Thank you - I probably could use something like this. It is
uglier than the simpler approach in dynasm of course.
How about when I need to combine this with some struct/union
access? In dynasm I can write:
| mov BASE, CI->u.l.base // BASE =
ci->u.l.base (volatile)
| mov PC, CI->u.l.savedpc // PC =
CI->u.l.savedpc
How can I mix the mixin above and combine with struct offsets?
Thanks and Regards
Dibyendu