* src/vmcore/linker.c (build_display): Removed superfluous recursion; return
[cacao.git] / src / vm / jit / x86_64 / md.c
1 /* src/vm/jit/x86_64/md.c - machine dependent x86_64 functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33
34 #include "vm/jit/x86_64/md-abi.h"
35
36 #include "vm/vm.h"
37
38 #include "vm/jit/codegen-common.h"
39 #include "vm/jit/jit.h"
40
41
42 /* md_init *********************************************************************
43
44    Do some machine dependent initialization.
45
46 *******************************************************************************/
47
48 void md_init(void)
49 {
50         /* nothing to do */
51 }
52
53
54 /* md_jit_method_patch_address *************************************************
55
56    Gets the patch address of the currently compiled method. The offset
57    is extracted from the load instruction(s) before the jump and added
58    to the right base address (PV or REG_METHODPTR).
59
60    INVOKESTATIC/SPECIAL:
61
62    4d 8b 15 e2 fe ff ff             mov    -286(%rip),%r10
63    49 ff d2                         rex64Z callq  *%r10
64
65    INVOKEVIRTUAL:
66
67    4c 8b 17                         mov    (%rdi),%r10
68    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
69    48 ff d3                         rex64 callq  *%rax
70
71    INVOKEINTERFACE:
72
73    4c 8b 17                         mov    (%rdi),%r10
74    4d 8b 92 00 00 00 00             mov    0x0(%r10),%r10
75    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
76    48 ff d3                         rex64 callq  *%r11
77
78 *******************************************************************************/
79
80 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
81 {
82         uint8_t *pc;
83         uint8_t  mcode;
84         int32_t  offset;
85         void    *pa;                        /* patch address                      */
86
87         /* go back to the actual call instruction (3-bytes) */
88
89         pc = ((uint8_t *) ra) - 3;
90
91         /* get the last byte of the call */
92
93         mcode = pc[2];
94
95         /* check for the different calls */
96
97         if (mcode == 0xd2) {
98                 /* INVOKESTATIC/SPECIAL */
99
100                 /* Get the offset from the instruction (the offset address is
101                    4-bytes before the call instruction). */
102
103                 offset = *((int32_t *) (pc - 4));
104
105                 /* add the offset to the return address (IP-relative addressing) */
106
107                 pa = pc + offset;
108         }
109         else if (mcode == 0xd3) {
110                 /* INVOKEVIRTUAL/INTERFACE */
111
112                 /* return NULL if no mptr was specified (used for replacement) */
113
114                 if (mptr == NULL)
115                         return NULL;
116
117                 /* Get the offset from the instruction (the offset address is
118                    4-bytes before the call instruction). */
119
120                 offset = *((int32_t *) (pc - 4));
121
122                 /* add the offset to the method pointer */
123
124                 pa = ((uint8_t *) mptr) + offset;
125         }
126         else {
127                 /* catch any problems */
128
129                 vm_abort("md_jit_method_patch_address: unknown instruction %x", mcode);
130
131                 /* keep compiler happy */
132
133                 pa = NULL;
134         }
135
136         return pa;
137 }
138
139
140 /* md_patch_replacement_point **************************************************
141
142    Patch the given replacement point.
143
144 *******************************************************************************/
145
146 #if defined(ENABLE_REPLACEMENT)
147 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
148 {
149         u2 mcode;
150
151         if (revert) {
152                 /* write saved machine code */
153                 *(u2*)(pc) = *(u2*)(savedmcode);
154         }
155         else {
156                 /* save the current machine code */
157                 *(u2*)(savedmcode) = *(u2*)(pc);
158
159                 /* build the machine code for the patch */
160                 mcode = 0x0b0f;
161
162                 /* write new machine code */
163                 *(u2*)(pc) = (u2) mcode;
164         }
165
166     /* XXX if required asm_cacheflush(pc,8); */
167 }
168 #endif /* defined(ENABLE_REPLACEMENT) */
169
170
171 /*
172  * These are local overrides for various environment variables in Emacs.
173  * Please do not remove this and leave it at the end of the file, where
174  * Emacs will automagically detect them.
175  * ---------------------------------------------------------------------
176  * Local variables:
177  * mode: c
178  * indent-tabs-mode: t
179  * c-basic-offset: 4
180  * tab-width: 4
181  * End:
182  * vim:noexpandtab:sw=4:ts=4:
183  */