1 /* src/vm/jit/executionstate.c - execution-state handling
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
35 #include "vm/descriptor.hpp"
38 #include "vm/jit/abi.h"
39 #include "vm/jit/executionstate.h"
43 * Restore callee-saved registers (including the RA register),
44 * set the stack pointer to the next stackframe,
45 * set the PC to the return address of the popped frame.
47 * *** This function imitates the effects of the method epilog ***
48 * *** and returning from the method call. ***
50 * @param es Execution state to be modified.
51 * NOTE: es->code and es->pv are NOT updated.
53 void executionstate_pop_stackframe(executionstate_t *es)
59 assert(es->code != NULL);
61 // Calculate the size of the stackframe.
62 int32_t framesize = md_stacktrace_get_framesize(es->code);
64 // Read the return address.
66 #if STACKFRAME_LEAFMETHODS_RA_REGISTER
67 if (code_is_leafmethod(es->code))
71 ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
73 // Calculate the base of the stack frame.
74 uintptr_t sp = (uintptr_t) es->sp;
75 uintptr_t basesp = sp + es->code->stackframesize * SIZE_OF_STACKSLOT;
77 // Restore return address, if part of frame.
78 #if STACKFRAME_RA_TOP_OF_FRAME
79 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
80 if (!code_is_leafmethod(es->code)) {
82 basesp -= 1 * SIZE_OF_STACKSLOT;
83 es->ra = *((uint8_t**) basesp);
84 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
87 #endif /* STACKFRAME_RA_TOP_OF_FRAME */
89 // Restore return address, if inside linkage area.
90 #if STACKFRAME_RA_LINKAGE_AREA
91 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
92 if (!code_is_leafmethod(es->code))
94 es->ra = *((uint8_t**) (basesp + LA_LR_OFFSET));
95 #endif /* STACKFRAME_RA_LINKAGE_AREA */
97 // Restore saved int registers.
99 for (i=0; i<es->code->savedintcount; ++i) {
100 while (nregdescint[--reg] != REG_SAV)
102 basesp -= 1 * SIZE_OF_STACKSLOT;
103 es->intregs[reg] = *((uintptr_t*) basesp);
106 // Restore saved flt registers.
109 for (i=0; i<es->code->savedfltcount; ++i) {
110 while (nregdescfloat[--reg] != REG_SAV)
112 basesp -= STACK_SLOTS_PER_FLOAT * SIZE_OF_STACKSLOT;
113 es->fltregs[reg] = *((double*) basesp);
116 #if defined(HAS_ADDRESS_REGISTER_FILE)
117 // Restore saved adr registers.
119 for (i=0; i<es->code->savedadrcount; ++i) {
120 while (nregdescadr[--reg] != REG_SAV)
122 basesp -= 1 * SIZE_OF_STACKSLOT;
123 es->adrregs[reg] = *((uintptr_t*) basesp);
127 // Adjust the stackpointer.
129 #if STACKFRMAE_RA_BETWEEN_FRAMES
130 es->sp += SIZEOF_VOID_P; /* skip return address */
133 // Set the program counter to the return address.
136 // In debugging mode clobber non-saved registers.
138 for (i=0; i<INT_REG_CNT; ++i)
139 if (nregdescint[i] != REG_SAV)
140 es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
141 for (i=0; i<FLT_REG_CNT; ++i)
142 if (nregdescfloat[i] != REG_SAV)
143 *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
144 # if defined(HAS_ADDRESS_REGISTER_FILE)
145 for (i=0; i<ADR_REG_CNT; ++i)
146 if (nregdescadr[i] != REG_SAV)
147 es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
149 #endif /* !defined(NDEBUG) */
153 /* executionstate_sanity_check *************************************************
155 Perform some sanity checks for the md_executionstate_read and
156 md_executionstate_write functions.
158 *******************************************************************************/
161 void executionstate_sanity_check(void *context)
163 /* estimate a minimum for the context size */
165 #if defined(HAS_ADDRESS_REGISTER_FILE)
166 #define MINIMUM_CONTEXT_SIZE (SIZEOF_VOID_P * ADR_REG_CNT \
167 + sizeof(double) * FLT_REG_CNT \
168 + sizeof(int) * INT_REG_CNT)
170 #define MINIMUM_CONTEXT_SIZE (SIZEOF_VOID_P * INT_REG_CNT \
171 + sizeof(double) * FLT_REG_CNT)
174 executionstate_t es1;
175 executionstate_t es2;
176 executionstate_t es3;
178 unsigned char reference[MINIMUM_CONTEXT_SIZE];
180 /* keep a copy of (a prefix of) the context for reference */
182 os_memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
184 /* different poisons */
186 os_memset(&es1, 0xc9, sizeof(executionstate_t));
187 os_memset(&es2, 0xb5, sizeof(executionstate_t));
188 os_memset(&es3, 0x6f, sizeof(executionstate_t));
190 md_executionstate_read(&es1, context);
192 /* verify that item-by-item copying preserves the state */
199 for (i = 0; i < INT_REG_CNT; ++i)
200 es2.intregs[i] = es1.intregs[i];
201 for (i = 0; i < FLT_REG_CNT; ++i)
202 es2.fltregs[i] = es1.fltregs[i];
203 #if defined(HAS_ADDRESS_REGISTER_FILE)
204 for (i = 0; i < ADR_REG_CNT; ++i)
205 es2.adrregs[i] = es1.adrregs[i];
208 /* write it back - this should not change the context */
209 /* We cannot check that completely, unfortunately, as we don't know */
210 /* the size of the (OS-dependent) context. */
212 md_executionstate_write(&es2, context);
214 /* Read it again, Sam! */
216 md_executionstate_read(&es3, context);
218 /* Compare. Note: Because of the NAN madness, we cannot compare
219 * doubles using '=='. */
221 assert(es3.pc == es1.pc);
222 assert(es3.sp == es1.sp);
223 assert(es3.pv == es1.pv);
224 for (i = 0; i < INT_REG_CNT; ++i)
225 assert(es3.intregs[i] == es1.intregs[i]);
226 for (i = 0; i < FLT_REG_CNT; ++i)
227 assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
228 #if defined(HAS_ADDRESS_REGISTER_FILE)
229 for (i = 0; i < ADR_REG_CNT; ++i)
230 assert(es3.adrregs[i] == es1.adrregs[i]);
233 /* i386 and x86_64 do not have an RA register */
235 #if defined(__I386__) || defined(__X86_64__)
236 assert(es3.ra != es1.ra);
238 assert(es3.ra == es1.ra);
241 /* "code" is not set by the md_* functions */
243 assert(es3.code != es1.code);
245 /* assert that we have not messed up the context */
247 assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
252 /* executionstate_println ******************************************************
254 Print execution state
257 es...............the execution state to print
259 *******************************************************************************/
262 void executionstate_println(executionstate_t *es)
270 printf("(executionstate_t *)NULL\n");
274 printf("executionstate_t:\n");
275 printf("\tpc = %p", es->pc);
276 printf(" sp = %p", es->sp);
277 printf(" pv = %p", es->pv);
278 printf(" ra = %p\n", es->ra);
280 #if defined(ENABLE_DISASSEMBLER)
281 for (i=0; i<INT_REG_CNT; ++i) {
286 # if SIZEOF_VOID_P == 8
287 printf("%-3s = %016lx", abi_registers_integer_name[i], es->intregs[i]);
289 printf("%-3s = %08x", abi_registers_integer_name[i], (unsigned) es->intregs[i]);
295 for (i=0; i<FLT_REG_CNT; ++i) {
300 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
305 # if defined(HAS_ADDRESS_REGISTER_FILE)
306 for (i=0; i<ADR_REG_CNT; ++i) {
311 printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
318 sp = (uint64_t *) es->sp;
323 methoddesc *md = es->code->m->parseddesc;
324 slots = es->code->stackframesize;
325 extraslots = 1 + md->memuse;
332 printf("\tstack slots(+%d) at sp:", extraslots);
333 for (i=0; i<slots+extraslots; ++i) {
336 printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
337 printf("%016llx",(unsigned long long)*sp++);
338 printf("%c", (i >= slots) ? ')' : ' ');
343 printf("\tcode: %p", (void*)es->code);
344 if (es->code != NULL) {
345 printf(" stackframesize=%d ", es->code->stackframesize);
346 method_print(es->code->m);
356 * These are local overrides for various environment variables in Emacs.
357 * Please do not remove this and leave it at the end of the file, where
358 * Emacs will automagically detect them.
359 * ---------------------------------------------------------------------
362 * indent-tabs-mode: t
366 * vim:noexpandtab:sw=4:ts=4: