1 /* src/vm/jit/dseg.c - data segment handling stuff
3 Copyright (C) 1996-2005, 2006, 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
32 #include "mm/memory.hpp"
34 #include "vm/options.h"
36 #include "vm/jit/codegen-common.hpp"
37 #include "vm/jit/methodheader.h"
40 /* dseg_finish *****************************************************************
42 Fills the data segment with the values stored.
44 *******************************************************************************/
46 void dseg_finish(jitdata *jd)
52 /* get required compiler data */
57 /* process all data segment entries */
59 for (de = cd->dseg; de != NULL; de = de->next) {
62 *((s4 *) (code->entrypoint + de->disp)) = de->val.i;
66 *((s8 *) (code->entrypoint + de->disp)) = de->val.l;
70 *((float *) (code->entrypoint + de->disp)) = de->val.f;
74 *((double *) (code->entrypoint + de->disp)) = de->val.d;
78 *((void **) (code->entrypoint + de->disp)) = de->val.a;
85 static s4 dseg_find_s4(codegendata *cd, s4 value)
89 /* search all data segment entries for a matching entry */
91 for (de = cd->dseg; de != NULL; de = de->next) {
92 if (IS_INT_TYPE(de->type))
93 if (de->flags & DSEG_FLAG_READONLY)
94 if (de->val.i == value)
98 /* no matching entry was found */
104 static s4 dseg_find_s8(codegendata *cd, s8 value)
108 /* search all data segment entries for a matching entry */
110 for (de = cd->dseg; de != NULL; de = de->next) {
111 if (IS_LNG_TYPE(de->type))
112 if (de->flags & DSEG_FLAG_READONLY)
113 if (de->val.l == value)
117 /* no matching entry was found */
123 static s4 dseg_find_float(codegendata *cd, float value)
128 /* we compare the hex value of the float as 0.0 == -0.0 */
132 /* search all data segment entries for a matching entry */
134 for (de = cd->dseg; de != NULL; de = de->next) {
135 if (IS_FLT_TYPE(de->type))
136 if (de->flags & DSEG_FLAG_READONLY)
137 if (de->val.i == val.i)
141 /* no matching entry was found */
147 static s4 dseg_find_double(codegendata *cd, double value)
152 /* we compare the hex value of the double as 0.0 == -0.0 */
156 /* search all data segment entries for a matching entry */
158 for (de = cd->dseg; de != NULL; de = de->next) {
159 if (IS_DBL_TYPE(de->type))
160 if (de->flags & DSEG_FLAG_READONLY)
161 if (de->val.l == val.l)
165 /* no matching entry was found */
171 static s4 dseg_find_address(codegendata *cd, void *value)
175 /* search all data segment entries for a matching entry */
177 for (de = cd->dseg; de != NULL; de = de->next) {
178 if (IS_ADR_TYPE(de->type))
179 if (de->flags & DSEG_FLAG_READONLY)
180 if (de->val.a == value)
184 /* no matching entry was found */
190 /* dseg_add_s4_intern **********************************************************
192 Internal function to add an s4 value to the data segment.
194 *******************************************************************************/
196 static s4 dseg_add_s4_intern(codegendata *cd, s4 value, u4 flags)
200 /* Increase data segment size, which is also the displacement into
205 /* allocate new entry */
207 de = DNEW(dsegentry);
211 de->disp = -(cd->dseglen);
215 /* insert into the chain */
223 /* dseg_add_unique_s4 **********************************************************
225 Adds uniquely an s4 value to the data segment.
227 *******************************************************************************/
229 s4 dseg_add_unique_s4(codegendata *cd, s4 value)
233 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_UNIQUE);
239 /* dseg_add_s4 *****************************************************************
241 Adds an s4 value to the data segment. It tries to reuse previously
244 *******************************************************************************/
246 s4 dseg_add_s4(codegendata *cd, s4 value)
250 /* search the data segment if the value is already stored */
252 disp = dseg_find_s4(cd, value);
257 disp = dseg_add_s4_intern(cd, value, DSEG_FLAG_READONLY);
263 /* dseg_add_s8_intern **********************************************************
265 Internal function to add an s8 value to the data segment.
267 *******************************************************************************/
269 static s4 dseg_add_s8_intern(codegendata *cd, s8 value, u4 flags)
273 /* Increase data segment size, which is also the displacement into
276 cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
278 /* allocate new entry */
280 de = DNEW(dsegentry);
284 de->disp = -(cd->dseglen);
288 /* insert into the chain */
296 /* dseg_add_unique_s8 **********************************************************
298 Adds uniquely an s8 value to the data segment.
300 *******************************************************************************/
302 s4 dseg_add_unique_s8(codegendata *cd, s8 value)
306 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_UNIQUE);
312 /* dseg_add_s8 *****************************************************************
314 Adds an s8 value to the data segment. It tries to reuse previously
317 *******************************************************************************/
319 s4 dseg_add_s8(codegendata *cd, s8 value)
323 /* search the data segment if the value is already stored */
325 disp = dseg_find_s8(cd, value);
330 disp = dseg_add_s8_intern(cd, value, DSEG_FLAG_READONLY);
336 /* dseg_add_float_intern *******************************************************
338 Internal function to add a float value to the data segment.
340 *******************************************************************************/
342 static s4 dseg_add_float_intern(codegendata *cd, float value, u4 flags)
346 /* Increase data segment size, which is also the displacement into
351 /* allocate new entry */
353 de = DNEW(dsegentry);
357 de->disp = -(cd->dseglen);
361 /* insert into the chain */
369 /* dseg_add_unique_float *******************************************************
371 Adds uniquely an float value to the data segment.
373 *******************************************************************************/
375 s4 dseg_add_unique_float(codegendata *cd, float value)
379 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_UNIQUE);
385 /* dseg_add_float **************************************************************
387 Adds an float value to the data segment. It tries to reuse
388 previously added values.
390 *******************************************************************************/
392 s4 dseg_add_float(codegendata *cd, float value)
396 /* search the data segment if the value is already stored */
398 disp = dseg_find_float(cd, value);
403 disp = dseg_add_float_intern(cd, value, DSEG_FLAG_READONLY);
409 /* dseg_add_double_intern ******************************************************
411 Internal function to add a double value to the data segment.
413 *******************************************************************************/
415 static s4 dseg_add_double_intern(codegendata *cd, double value, u4 flags)
419 /* Increase data segment size, which is also the displacement into
422 cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
424 /* allocate new entry */
426 de = DNEW(dsegentry);
430 de->disp = -(cd->dseglen);
434 /* insert into the chain */
442 /* dseg_add_unique_double ******************************************************
444 Adds uniquely a double value to the data segment.
446 *******************************************************************************/
448 s4 dseg_add_unique_double(codegendata *cd, double value)
452 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_UNIQUE);
458 /* dseg_add_double *************************************************************
460 Adds a double value to the data segment. It tries to reuse
461 previously added values.
463 *******************************************************************************/
465 s4 dseg_add_double(codegendata *cd, double value)
469 /* search the data segment if the value is already stored */
471 disp = dseg_find_double(cd, value);
476 disp = dseg_add_double_intern(cd, value, DSEG_FLAG_READONLY);
482 /* dseg_add_address_intern *****************************************************
484 Internal function to add an address pointer to the data segment.
486 *******************************************************************************/
488 static s4 dseg_add_address_intern(codegendata *cd, void *value, u4 flags)
492 /* Increase data segment size, which is also the displacement into
495 #if SIZEOF_VOID_P == 8
496 cd->dseglen = MEMORY_ALIGN(cd->dseglen + 8, 8);
501 /* allocate new entry */
503 de = DNEW(dsegentry);
507 de->disp = -(cd->dseglen);
511 /* insert into the chain */
519 /* dseg_add_unique_address *****************************************************
521 Adds uniquely an address value to the data segment.
523 *******************************************************************************/
525 s4 dseg_add_unique_address(codegendata *cd, void *value)
529 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_UNIQUE);
535 /* dseg_add_address ************************************************************
537 Adds an address value to the data segment. It tries to reuse
538 previously added values.
540 *******************************************************************************/
542 s4 dseg_add_address(codegendata *cd, void *value)
546 /* search the data segment if the value is already stored */
548 disp = dseg_find_address(cd, value);
553 disp = dseg_add_address_intern(cd, value, DSEG_FLAG_READONLY);
559 /* dseg_add_target *************************************************************
563 *******************************************************************************/
565 void dseg_add_target(codegendata *cd, basicblock *target)
571 jr->tablepos = dseg_add_unique_address(cd, NULL);
573 jr->next = cd->jumpreferences;
575 cd->jumpreferences = jr;
579 /* dseg_adddata ****************************************************************
581 Adds a data segment reference to the codegendata.
583 *******************************************************************************/
585 #if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
586 void dseg_adddata(codegendata *cd)
592 dr->datapos = cd->mcodeptr - cd->mcodebase;
593 dr->next = cd->datareferences;
595 cd->datareferences = dr;
600 /* dseg_resolve_datareferences *************************************************
602 Resolve data segment references.
604 *******************************************************************************/
606 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
607 void dseg_resolve_datareferences(jitdata *jd)
613 /* get required compiler data */
618 /* data segment references resolving */
620 for (dr = cd->datareferences; dr != NULL; dr = dr->next)
621 *((u1 **) (code->entrypoint + dr->datapos - SIZEOF_VOID_P)) = code->entrypoint;
626 /* dseg_display ****************************************************************
628 Displays the content of the methods' data segment.
630 *******************************************************************************/
633 void dseg_display(jitdata *jd)
640 /* get required compiler data */
646 printf("\033[34m"); /* blue */
648 printf(" --- dump of datasegment\n");
650 /* process all data segment entries */
652 for (de = cd->dseg; de != NULL; de = de->next) {
653 #if SIZEOF_VOID_P == 8
654 printf("0x%016lx:", (ptrint) (code->entrypoint + de->disp));
656 printf("0x%08x:", (ptrint) (code->entrypoint + de->disp));
659 printf(" %6x (%6d): ", de->disp, de->disp);
661 /* We read the values from the data segment as some values,
662 like the line number table, have been written directly to
667 val.i = *((s4 *) (code->entrypoint + de->disp));
668 printf("(INT) %d (0x%08x)", val.i, val.i);
672 val.l = *((s8 *) (code->entrypoint + de->disp));
673 #if SIZEOF_VOID_P == 8
674 printf("(LNG) %ld (0x%016lx)", val.l, val.l);
676 printf("(LNG) %lld (0x%016llx)", val.l, val.l);
681 val.f = *((float *) (code->entrypoint + de->disp));
682 printf("(FLT) %g (0x%08x)", val.f, val.i);
686 val.d = *((double *) (code->entrypoint + de->disp));
687 #if SIZEOF_VOID_P == 8
688 printf("(DBL) %g (0x%016lx)", val.d, val.l);
690 printf("(DBL) %g (0x%016llx)", val.d, val.l);
695 val.a = *((void **) (code->entrypoint + de->disp));
696 #if SIZEOF_VOID_P == 8
697 printf("(ADR) %016lx", (ptrint) val.a);
699 printf("(ADR) %08x", (ptrint) val.a);
707 printf(" --- begin of data segment: ");
708 #if SIZEOF_VOID_P == 8
709 printf("0x%016lx\n", (ptrint) code->entrypoint);
711 printf("0x%08x\n", (ptrint) code->entrypoint);
717 #endif /* !defined(NDEBUG) */
721 * These are local overrides for various environment variables in Emacs.
722 * Please do not remove this and leave it at the end of the file, where
723 * Emacs will automagically detect them.
724 * ---------------------------------------------------------------------
727 * indent-tabs-mode: t
731 * vim:noexpandtab:sw=4:ts=4: