diff options
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm new file mode 100644 index 000000000000..09f1177b9a9e --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm @@ -0,0 +1,328 @@ +; -*- Mode: text; tab-width: 8; indent-tabs-mode: nil comment-column: 32; comment-start: "; " comment-start-skip: "; *" -*- + +;************************************************************************* +;* +;* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +;* +;* Copyright 2000, 2011 Oracle and/or its affiliates. +;* +;* OpenOffice.org - a multi-platform office productivity suite +;* +;* This file is part of OpenOffice.org. +;* +;* OpenOffice.org is free software: you can redistribute it and/or modify +;* it under the terms of the GNU Lesser General Public License version 3 +;* only, as published by the Free Software Foundation. +;* +;* OpenOffice.org is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;* GNU Lesser General Public License version 3 for more details +;* (a copy is included in the LICENSE file that accompanied this code). +;* +;* You should have received a copy of the GNU Lesser General Public License +;* version 3 along with OpenOffice.org. If not, see +;* <http://www.openoffice.org/license.html> +;* for a copy of the LGPLv3 License. +;* +;************************************************************************ + +; Emacs asm-mode is not really ideal for the convention in this +; file. So I use text-mode with custom comment syntax... not really +; ideal either. Maybe I should just re-format this to match asm-mode's +; conventions? + +; NOTE: EXTREMELY UNFINISHED, I KNOW. WORK IN PROGRESS. + +; I really don't have a good high-level understanding of the big +; picture and what the actual task of the C++/UNO bridge is yet... I +; should debug the x86 version and see what is actually going on to +; get an understanding. + +; This is in a separate file for x86-64 as MSVC doesn't have in-line +; assembly for x64. The code here is still partly just a crude copy of +; the in-line x86 code from ../msvc_win32_intel that is totally +; pointless on x64. But parts have been properly changed into x64 +; calling convention and might even work. + +; Random web links and other documentation about low-level +; implementation details for the C++/UNO bridge on x64 Windows kept +; here: + +; Caolan's "Lazy Hackers Guide To Porting" is useful: +; http://wiki.services.openoffice.org/wiki/Lazy_Hackers_Guide_To_Porting + +; As for details about the x64 Windows calling convention, register +; usage, stack usage, exception handling etc, the official +; documentation (?) on MSDN is a bit fragmented and split up into a +; needlessly large number of short pages. But still: +; http://msdn.microsoft.com/en-us/library/7kcdt6fy%28v=VS.90%29.aspx + +; Also see Raymond Chen's blog post: +; http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx + +; This one is actually more readable: "Improving Automated Analysis of +; Windows x64 Binaries": +; http://www.uninformed.org/?v=4&a=1 + +; The bridge uses dynamic code generation. For exception handling and +; unwinding to work across that (as I assume we want?), one apparently +; needs to use either RtlAddFunctionTable() or +; RtlInstallFunctionTableCallback(). See Windows SDK documentation. + +; Random interesting discussion threads: +; http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/300bd6d3-9381-4d2d-8129-e48b392c05d8 + +; Ken Johnson's blog http://www.nynaeve.net/ has much interesting +; information, for instance: +; http://www.nynaeve.net/?p=11 + +; From <typelib/typeclass.h> +typelib_TypeClass_VOID = 0 +typelib_TypeClass_CHAR = 1 +typelib_TypeClass_BOOLEAN = 2 +typelib_TypeClass_BYTE = 3 +typelib_TypeClass_SHORT = 4 +typelib_TypeClass_UNSIGNED_SHORT = 5 +typelib_TypeClass_LONG = 6 +typelib_TypeClass_UNSIGNED_LONG = 7 +typelib_TypeClass_HYPER = 8 +typelib_TypeClass_UNSIGNED_HYPER = 9 +typelib_TypeClass_FLOAT = 10 +typelib_TypeClass_DOUBLE = 11 +typelib_TypeClass_ENUM = 15 + +extrn __copyConstruct : proc +extrn __destruct : proc +extrn cpp_mediate: proc + +.code + +; First we have three code snippets that aren't real functions, but +; "naked" (in x86 calling convention parlance) functions jumped to +; from code generated in C++. + +; I think that for x64 Windows we shouldn't be jumping so wildly from +; generated code snippets into fixed code snippets here. "Procedures" +; should be continuous in memory, or the unwinding information will be +; broken. (For dynamically generated code, that is dynamically +; registered unwind information, obviously.) + +; So instead of generating jumps into here, we should just make the +; C++ code copy the machine code that these three "naked" functions +; compile to after the snippet it is generating. Of course, that means +; the code here needs to be position independent, or (eek) that we +; would need to come up with some home-brewed minimal relocation +; mechanism. + +; Jumped to from code generated in except.cxx: ObjectFunction::ObjectFunction() + +copyConstruct proc + ; ObjectFunction this already on stack + push [rsp+8] ; source exc object this + push rcx ; exc object + call __copyConstruct + add rsp, 12 ; + ObjectFunction this + ret 4 +copyConstruct endp + +; Ditto + +destruct proc + ; ObjectFunction this already on stack + push rcx ; exc object + call __destruct + add rsp, 8 ; + ObjectFunction this + ret +destruct endp + +; Jumped to from code generated in cpp2uno.cxx:codeSnippet() + +cpp_vtable_call proc + sub rsp, 8 ; space for immediate return type + push rsp + push rdx ; vtable offset + push rax ; function index + mov rax, rsp + add rax, 20 + push rax ; original stack ptr + + call cpp_mediate + add rsp, 16 + + cmp rax, typelib_TypeClass_FLOAT + je Lfloat + cmp rax, typelib_TypeClass_DOUBLE + je Ldouble + cmp rax, typelib_TypeClass_HYPER + je Lhyper + cmp eax, typelib_TypeClass_UNSIGNED_HYPER + je Lhyper + ; rest is eax + pop rax + add rsp, 4 + ret +Lhyper: + pop rax + pop rdx + ret +Lfloat: + fld dword ptr [rsp] + add rsp, 8 + ret +Ldouble: + fld qword ptr [rsp] + add rsp, 8 + ret +cpp_vtable_call endp + +; Called from uno2cpp.cxx + +; This one is now hopefully proper x64 Windows code following the +; appropriate conventions and might actually work. + +; void callVirtualMethod( ; location on entry +; void * pAdjustedThisPtr, ; rcx +; sal_Int32 nVtableIndex, ; rdx +; void * pReturn, ; r8 +; typelib_TypeClass eReturnTypeClass, ; r9 +; sal_Int64 * pStack, ; ((4+1)*8)[rsp] +; sal_Int32 nStack ; ((5+1)*8)[rsp] +; sal_uInt64 *pGPR, ; ((6+1)*8)[rsp] +; double *pFPR) ; ((7+1)*8)[rsp] + +callVirtualMethod proc frame + ; Prologue + mov ((3+1)*8)[rsp], r9 + mov ((2+1)*8)[rsp], r8 + mov ((0+1)*8)[rsp], rcx + push rsi + .pushreg rsi + push rdi + .pushreg rdi + + ; Our stack frame size is 24 qwords (space for 20 parameters + ; to pass, plus the two pushed registers rsi and rdi, plus + ; return address, rounded up to 16 bytes) + + sub rsp, (20+1)*8 + .allocstack (20+1)*8 + .endprolog + + ; Stack parameters first + + ; nStack is number of qwords of stack space (including spilled + ; registers). If four or less, 4 is passed in anyway to make + ; code here simpler. + + mov rcx, ((24+5)*8)[rsp] ; nStack + sub rcx, 4 + jle Lxmmregs + + mov rsi, ((24+4)*8)[rsp] ; pStack + add rsi, 32 + lea rdi, 32[rsp] + rep movsq + +Lxmmregs: + ; Parameters passed in XMM registers + + ; We don't bother checking which actually needed, if any. + mov rax, ((24+7)*8)[rsp] ; pFPR + movsd xmm0, qword ptr [rax] + movsd xmm1, qword ptr 8[rax] + movsd xmm2, qword ptr 16[rax] + movsd xmm3, qword ptr 24[rax] + + ; Prepare pointer to function to call + mov rcx, ((24+0)*8)[rsp] + mov r12, [rcx] ; pAdjustedThisPtr->vtable + shl rdx, 3 ; nVtableIndex *= 8 + add r12, rdx + + ; Fill parameters passed in general purpose registers + mov rax, ((24+6)*8)[rsp] ; pGPR + mov rcx, (0*8)[rax] + mov rdx, (1*8)[rax] + mov r8, (2*8)[rax] + mov r9, (3*8)[rax] + + call qword ptr [r12] + + ; Test return type + mov r9, ((24+3)*8)[rsp] + cmp r9, typelib_TypeClass_VOID + je Lepilog + + ; int32 + cmp r9, typelib_TypeClass_LONG + je Lint32 + cmp r9, typelib_TypeClass_UNSIGNED_LONG + je Lint32 + cmp r9, typelib_TypeClass_ENUM + je Lint32 + + ; int8 + cmp r9, typelib_TypeClass_BOOLEAN + je Lint8 + cmp r9, typelib_TypeClass_BYTE + je Lint8 + + ; int16 + cmp r9, typelib_TypeClass_CHAR + je Lint16 + cmp r9, typelib_TypeClass_SHORT + je Lint16 + cmp r9, typelib_TypeClass_UNSIGNED_SHORT + je Lint16 + + ; int64 + cmp r9, typelib_TypeClass_HYPER + je Lint64 + cmp r9, typelib_TypeClass_UNSIGNED_HYPER + je Lint64 + + ; float + cmp r9, typelib_TypeClass_FLOAT + je Lfloat + + ; double + cmp r9, typelib_TypeClass_DOUBLE + je Ldouble + + jmp Lepilog ; no simple type + +Lint8: + mov byte ptr [r8], al + jmp Lepilog + +Lint16: + mov word ptr [r8], ax + jmp Lepilog + +Lint32: + mov dword ptr [r8], eax + jmp Lepilog + +Lint64: + mov qword ptr [r8], rax + jmp Lepilog + +Lfloat: + movss dword ptr [r8], xmm0 + jmp Lepilog + +Ldouble: + movsd qword ptr [r8], xmm0 + +Lepilog: + ; Epilogue + add rsp, (20+1)*8 + pop rdi + pop rsi + ret +callVirtualMethod endp + +end + +; vim:set shiftwidth=4 softtabstop=4 expandtab: |