* src/vm/jit/codegen-common.cpp, src/vm/jit/x86_64/codegen.c: Generate
[cacao.git] / src / vm / jit / executionstate.c
1 /* src/vm/jit/executionstate.c - execution-state handling
2
3    Copyright (C) 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29 #include <stdio.h>
30
31 #include "md-abi.h"
32
33 #include "vm/descriptor.hpp"
34 #include "vm/os.hpp"
35
36 #include "vm/jit/abi.h"
37 #include "vm/jit/executionstate.h"
38
39
40 /* executionstate_sanity_check *************************************************
41
42    Perform some sanity checks for the md_executionstate_read and
43    md_executionstate_write functions.
44
45 *******************************************************************************/
46
47 #if !defined(NDEBUG)
48 void executionstate_sanity_check(void *context)
49 {
50     /* estimate a minimum for the context size */
51
52 #if defined(HAS_ADDRESS_REGISTER_FILE)
53 #define MINIMUM_CONTEXT_SIZE  (SIZEOF_VOID_P    * ADR_REG_CNT \
54                                        + sizeof(double) * FLT_REG_CNT \
55                                                            + sizeof(int)    * INT_REG_CNT)
56 #else
57 #define MINIMUM_CONTEXT_SIZE  (SIZEOF_VOID_P    * INT_REG_CNT \
58                                        + sizeof(double) * FLT_REG_CNT)
59 #endif
60
61         executionstate_t es1;
62         executionstate_t es2;
63         executionstate_t es3;
64         unsigned int i;
65         unsigned char reference[MINIMUM_CONTEXT_SIZE];
66
67         /* keep a copy of (a prefix of) the context for reference */
68
69         os_memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
70
71         /* different poisons */
72
73         os_memset(&es1, 0xc9, sizeof(executionstate_t));
74         os_memset(&es2, 0xb5, sizeof(executionstate_t));
75         os_memset(&es3, 0x6f, sizeof(executionstate_t));
76
77         md_executionstate_read(&es1, context);
78
79         /* verify that item-by-item copying preserves the state */
80
81         es2.pc = es1.pc;
82         es2.sp = es1.sp;
83         es2.pv = es1.pv;
84         es2.ra = es1.ra;
85         es2.code = es1.code;
86         for (i = 0; i < INT_REG_CNT; ++i)
87                 es2.intregs[i] = es1.intregs[i];
88         for (i = 0; i < FLT_REG_CNT; ++i)
89                 es2.fltregs[i] = es1.fltregs[i];
90 #if defined(HAS_ADDRESS_REGISTER_FILE)
91         for (i = 0; i < ADR_REG_CNT; ++i)
92                 es2.adrregs[i] = es1.adrregs[i];
93 #endif
94
95         /* write it back - this should not change the context */
96         /* We cannot check that completely, unfortunately, as we don't know */
97         /* the size of the (OS-dependent) context. */
98
99         md_executionstate_write(&es2, context);
100
101         /* Read it again, Sam! */
102
103         md_executionstate_read(&es3, context);
104
105         /* Compare. Note: Because of the NAN madness, we cannot compare
106          * doubles using '=='. */
107
108         assert(es3.pc == es1.pc);
109         assert(es3.sp == es1.sp);
110         assert(es3.pv == es1.pv);
111         for (i = 0; i < INT_REG_CNT; ++i)
112                 assert(es3.intregs[i] == es1.intregs[i]);
113         for (i = 0; i < FLT_REG_CNT; ++i)
114                 assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
115 #if defined(HAS_ADDRESS_REGISTER_FILE)
116         for (i = 0; i < ADR_REG_CNT; ++i)
117                 assert(es3.adrregs[i] == es1.adrregs[i]);
118 #endif
119
120         /* i386 and x86_64 do not have an RA register */
121
122 #if defined(__I386__) || defined(__X86_64__)
123         assert(es3.ra != es1.ra);
124 #else
125         assert(es3.ra == es1.ra);
126 #endif
127
128         /* "code" is not set by the md_* functions */
129
130         assert(es3.code != es1.code);
131
132         /* assert that we have not messed up the context */
133
134         assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
135 }
136 #endif
137
138
139 /* executionstate_println ******************************************************
140  
141    Print execution state
142   
143    IN:
144        es...............the execution state to print
145   
146 *******************************************************************************/
147
148 #if !defined(NDEBUG)
149 void executionstate_println(executionstate_t *es)
150 {
151         uint64_t *sp;
152         int       slots;
153         int       extraslots;
154         int       i;
155
156         if (!es) {
157                 printf("(executionstate_t *)NULL\n");
158                 return;
159         }
160
161         printf("executionstate_t:\n");
162         printf("\tpc = %p", es->pc);
163         printf("  sp = %p", es->sp);
164         printf("  pv = %p", es->pv);
165         printf("  ra = %p\n", es->ra);
166
167 #if defined(ENABLE_DISASSEMBLER)
168         for (i=0; i<INT_REG_CNT; ++i) {
169                 if (i%4 == 0)
170                         printf("\t");
171                 else
172                         printf(" ");
173 # if SIZEOF_VOID_P == 8
174                 printf("%-3s = %016lx", abi_registers_integer_name[i], es->intregs[i]);
175 # else
176                 printf("%-3s = %08x", abi_registers_integer_name[i], (unsigned) es->intregs[i]);
177 # endif
178                 if (i%4 == 3)
179                         printf("\n");
180         }
181
182         for (i=0; i<FLT_REG_CNT; ++i) {
183                 if (i%4 == 0)
184                         printf("\t");
185                 else
186                         printf(" ");
187                 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
188                 if (i%4 == 3)
189                         printf("\n");
190         }
191
192 # if defined(HAS_ADDRESS_REGISTER_FILE)
193         for (i=0; i<ADR_REG_CNT; ++i) {
194                 if (i%4 == 0)
195                         printf("\t");
196                 else
197                         printf(" ");
198                 printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
199                 if (i%4 == 3)
200                         printf("\n");
201         }
202 # endif
203 #endif
204
205         sp = (uint64_t *) es->sp;
206
207         extraslots = 2;
208
209         if (es->code) {
210                 methoddesc *md = es->code->m->parseddesc;
211                 slots = es->code->stackframesize;
212                 extraslots = 1 + md->memuse;
213         }
214         else
215                 slots = 0;
216
217
218         if (slots) {
219                 printf("\tstack slots(+%d) at sp:", extraslots);
220                 for (i=0; i<slots+extraslots; ++i) {
221                         if (i%4 == 0)
222                                 printf("\n\t\t");
223                         printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
224                         printf("%016llx",(unsigned long long)*sp++);
225                         printf("%c", (i >= slots) ? ')' : ' ');
226                 }
227                 printf("\n");
228         }
229
230         printf("\tcode: %p", (void*)es->code);
231         if (es->code != NULL) {
232                 printf(" stackframesize=%d ", es->code->stackframesize);
233                 method_print(es->code->m);
234         }
235         printf("\n");
236
237         printf("\n");
238 }
239 #endif
240
241
242 /*
243  * These are local overrides for various environment variables in Emacs.
244  * Please do not remove this and leave it at the end of the file, where
245  * Emacs will automagically detect them.
246  * ---------------------------------------------------------------------
247  * Local variables:
248  * mode: c
249  * indent-tabs-mode: t
250  * c-basic-offset: 4
251  * tab-width: 4
252  * End:
253  * vim:noexpandtab:sw=4:ts=4:
254  */