summaryrefslogtreecommitdiff
path: root/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm
diff options
context:
space:
mode:
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.asm328
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: