Payload structure problem using inline asm
Baz
burg.basile at yahoo.com
Wed Jul 17 11:04:34 PDT 2013
On Wednesday, 17 July 2013 at 17:11:20 UTC, John Colvin wrote:
> On Wednesday, 17 July 2013 at 17:09:30 UTC, John Colvin wrote:
>> On Wednesday, 17 July 2013 at 16:52:40 UTC, Baz wrote:
>>> Hello, I've defined a simple template used in a double linked
>>> list implementation:
>>>
>>> template tDLListItem(T)
>>> {
>>> const cPrevOffs = size_t.sizeof;
>>> const cNextOffs = size_t.sizeof + size_t.sizeof;
>>> void* NewItemCaps(T* aData, void* aPrevious, void* aNext)
>>> {
>>> auto lPt = std.c.stdlib.malloc( 3 * size_t.sizeof );
>>> if (!lPt)
>>> {
>>> throw new OutOfMemoryError();
>>> }
>>> *cast(size_t*) lPt = cast(size_t) aData;
>>> *cast(size_t*) (lPt + cPrevOffs) = cast(size_t) aPrevious;
>>> *cast(size_t*) (lPt + cNextOffs) = cast(size_t) aNext;
>>> return lPt;
>>> }
>>> void DeleteItemCaps(void* aItemCaps)
>>> {
>>> std.c.stdlib.free(aItemCaps);
>>> }
>>> void SetItemCapsPrev(void* aItemCaps, void* aPrevious)
>>> {
>>> *cast(size_t*) (aItemCaps + cPrevOffs) = cast(size_t)
>>> aPrevious;
>>> }
>>> void SetItemCapsNext(void* aItemCaps, void* aNext)
>>> {
>>> *cast(size_t*) (aItemCaps + cNextOffs) = cast(size_t) aNext;
>>> }
>>> void SetItemCapsData(void* aItemCaps, T* aData)
>>> {
>>> *cast(size_t*) aItemCaps = cast(size_t) aData;
>>> }
>>> T* GetItemCapsData(void* aItemCaps)
>>> {
>>> version(X86) asm
>>> {
>>> naked;
>>> mov EAX, [EAX];
>>> ret;
>>> }
>>> else version(none) asm
>>> {
>>> naked;
>>> mov RAX, [RAX];
>>> ret;
>>> }
>>> else
>>> {
>>> return *cast(T**) (aItemCaps);
>>> }
>>> }
>>> void* PreviousItemCaps(void* aItemCaps)
>>> {
>>> version(X86) asm
>>> {
>>> naked;
>>> mov EAX, [EAX + cPrevOffs];
>>> ret;
>>> }
>>> else version(none) asm
>>> {
>>> naked;
>>> mov RAX, [RAX + cPrevOffs];
>>> ret;
>>> }
>>> else
>>> {
>>> return *cast(size_t**) (aItemCaps + cPrevOffs);
>>> }
>>> }
>>> void* NextItemCaps(void* aItemCaps)
>>> {
>>> version(X86) asm
>>> {
>>> naked;
>>> mov EAX, [EAX + cNextOffs];
>>> ret;
>>> }
>>> else version(none) asm
>>> {
>>> naked;
>>> mov RAX, [RAX + cNextOffs];
>>> ret;
>>> }
>>> else
>>> {
>>> return *cast(size_t**) (aItemCaps + cNextOffs);
>>> }
>>> }
>>> }
>>>
>>> It's used as a struct. (BTW I call the "payload" a "capsule",
>>> a "caps"). In x86 (tested on win) I can optimize the access
>>> into the "capsule" to a simple member (I return the data
>>> pointed by the parameter by digging using the param +
>>> memberoffset as an address...
>>>
>>> But it doesn't work in x86_64 (tested on nux). What's wrong
>>> with that ? Does I miss something in the parameters
>>> convention/ABI for x64 (that's why the x64 versions are
>>> surounded by version(none) instead of version (X86_64) )) ?
>>>
>>> Does dmd produce real x86_64 code or is it possible for a 64
>>> bit appli to work with 32 bit pointers ?
>>> (I know this Q coulds look weird but I've already seen some
>>> false x86_64 while doing some static analysis)
>>>
>>> WTF.MEH.
>>
>> AFAIK on windows dmd uses the optlink calling convention, so
>> the 1st argument is in EAX
>>
>> On linux 32bit (cdecl) the first argument will be on the top
>> of the stack.
>>
>> On linux 64bit (system V) the first argument will be in RDX
>>
>> see:
>> http://en.wikipedia.org/wiki/X86_calling_conventions
>> or find a copy of the system V abi docs somewhere.
>
> big woops there, linux x64 arguments are RDI first, not RDX
> The order is RDI RSI RDX RCX R8 R9
Thx. I'll test that. My initial x86_64 implementation was based
on a wrong assumption...(that rax is used as eax for
parameters...).
More information about the Digitalmars-d-learn
mailing list