7836913ca2e1cbafb6c38938fc2f658c65242fdc
[cacao.git] / src / vm / jit / mips / md.c
1 /* src/vm/jit/mips/md.c - machine dependent MIPS functions
2
3    Copyright (C) 1996-2005, 2006 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    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes: 
30
31    $Id: md.c 4640 2006-03-16 17:24:18Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <unistd.h>
40 #include <sys/cachectl.h>
41 #include <sys/mman.h>
42
43 #include "vm/types.h"
44
45 #include "toolbox/logging.h"
46 #include "vm/global.h"
47 #include "vm/jit/stacktrace.h"
48
49
50 void docacheflush(u1 *p, long bytelen)
51 {
52         u1 *e = p + bytelen;
53         long psize = sysconf(_SC_PAGESIZE);
54         p -= (long) p & (psize - 1);
55         e += psize - ((((long) e - 1) & (psize - 1)) + 1);
56         bytelen = e-p;
57         mprotect(p, bytelen, PROT_READ | PROT_WRITE | PROT_EXEC);
58 }
59
60
61 /* md_stacktrace_get_returnaddress *********************************************
62
63    Returns the return address of the current stackframe, specified by
64    the passed stack pointer and the stack frame size.
65
66 *******************************************************************************/
67
68 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
69 {
70         u1 *ra;
71
72         /* on MIPS the return address is located on the top of the stackframe */
73
74         /* XXX change this if we ever want to use 4-byte stackslots */
75         /* ra = *((u1 **) (sp + framesize - SIZEOF_VOID_P)); */
76         ra = *((u1 **) (sp + framesize - 8));
77
78         return ra;
79 }
80
81
82 /* md_assembler_get_patch_address **********************************************
83
84    Gets the patch address of the currently compiled method. The offset
85    is extracted from the load instruction(s) before the jump and added
86    to the right base address (PV or REG_METHODPTR).
87
88 *******************************************************************************/
89
90 u1 *md_assembler_get_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
91 {
92         u4  mcode;
93         s4  offset;
94         u1 *pa;
95
96         /* go back to the actual load instruction (3 instructions on MIPS) */
97
98         ra -= 3 * 4;
99
100         /* get first instruction word on current PC */
101
102         mcode = *((u4 *) ra);
103
104         /* check if we have 2 instructions (lui) */
105
106         if ((mcode >> 16) == 0x3c19) {
107                 /* XXX write a regression for this */
108                 assert(0);
109
110                 /* get displacement of first instruction (lui) */
111
112                 offset = (s4) (mcode << 16);
113
114                 /* get displacement of second instruction (daddiu) */
115
116                 mcode = *((u4 *) (ra + 1 * 4));
117
118                 assert((mcode >> 16) != 0x6739);
119
120                 offset += (s2) (mcode & 0x0000ffff);
121
122         } else {
123                 /* get first instruction (ld) */
124
125                 mcode = *((u4 *) ra);
126
127                 /* get the offset from the instruction */
128
129                 offset = (s2) (mcode & 0x0000ffff);
130
131                 /* check for call with REG_METHODPTR: ld s8,x(t9) */
132
133 #if SIZEOF_VOID_P == 8
134                 if ((mcode >> 16) == 0xdf3e) {
135 #else
136                 if ((mcode >> 16) == 0x8f3e) {
137 #endif
138                         /* in this case we use the passed method pointer */
139
140                         pa = mptr + offset;
141
142                 } else {
143                         /* in the normal case we check for a `ld s8,x(s8)' instruction */
144
145 #if SIZEOF_VOID_P == 8
146                         assert((mcode >> 16) == 0xdfde);
147 #else
148                         assert((mcode >> 16) == 0x8fde);
149 #endif
150
151                         /* and get the final data segment address */
152
153                         pa = sfi->pv + offset;
154                 }
155         }
156
157         return pa;
158 }
159
160
161 /* md_codegen_findmethod *******************************************************
162
163    Machine code:
164
165    03c0f809    jalr     s8
166    00000000    nop
167    27feff9c    addiu    s8,ra,-100
168
169 *******************************************************************************/
170
171 u1 *md_codegen_findmethod(u1 *ra)
172 {
173         u1 *pv;
174         u4  mcode;
175         s4  offset;
176
177         /* get the offset of the instructions */
178
179         /* get first instruction word after jump */
180
181         mcode = *((u4 *) ra);
182
183         /* check if we have 2 instructions (lui, daddiu) */
184
185         if ((mcode >> 16) == 0x3c19) {
186                 /* get displacement of first instruction (lui) */
187
188                 offset = (s4) (mcode << 16);
189
190                 /* get displacement of second instruction (daddiu) */
191
192                 mcode = *((u4 *) (ra + 1 * 4));
193
194 #if SIZEOF_VOID_P == 8
195                 assert((mcode >> 16) == 0x6739);
196 #else   
197                 assert((mcode >> 16) == 0x2739);
198 #endif
199
200                 offset += (s2) (mcode & 0x0000ffff);
201
202         } else {
203                 /* get offset of first instruction (daddiu) */
204
205                 mcode = *((u4 *) ra);
206
207 #if SIZEOF_VOID_P == 8
208                 assert((mcode >> 16) == 0x67fe);
209 #else
210                 assert((mcode >> 16) == 0x27fe);
211 #endif
212
213                 offset = (s2) (mcode & 0x0000ffff);
214         }
215
216         /* calculate PV via RA + offset */
217
218         pv = ra + offset;
219
220         return pv;
221 }
222
223
224 /* md_cacheflush ***************************************************************
225
226    Calls the system's function to flush the instruction and data
227    cache.
228
229 *******************************************************************************/
230
231 void md_cacheflush(u1 *addr, s4 nbytes)
232 {
233         cacheflush(addr, nbytes, BCACHE);
234 }
235
236
237 /* md_icacheflush **************************************************************
238
239    Calls the system's function to flush the instruction cache.
240
241 *******************************************************************************/
242
243 void md_icacheflush(u1 *addr, s4 nbytes)
244 {
245         cacheflush(addr, nbytes, ICACHE);
246 }
247
248
249 /* md_dcacheflush **************************************************************
250
251    Calls the system's function to flush the data cache.
252
253 *******************************************************************************/
254
255 void md_dcacheflush(u1 *addr, s4 nbytes)
256 {
257         cacheflush(addr, nbytes, DCACHE);
258 }
259
260
261 /*
262  * These are local overrides for various environment variables in Emacs.
263  * Please do not remove this and leave it at the end of the file, where
264  * Emacs will automagically detect them.
265  * ---------------------------------------------------------------------
266  * Local variables:
267  * mode: c
268  * indent-tabs-mode: t
269  * c-basic-offset: 4
270  * tab-width: 4
271  * End:
272  */