344dcad6ceb7392d30e33666f349dac078fb2fae
[cacao.git] / src / vm / jit / codegen-common.c
1 /* src/vm/jit/codegen-common.c - architecture independent code generator stuff
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    All functions assume the following code area / data area layout:
26
27    +-----------+
28    |           |
29    | code area | code area grows to higher addresses
30    |           |
31    +-----------+ <-- start of procedure
32    |           |
33    | data area | data area grows to lower addresses
34    |           |
35    +-----------+
36
37    The functions first write into a temporary code/data area allocated by
38    "codegen_init". "codegen_finish" copies the code and data area into permanent
39    memory. All functions writing values into the data area return the offset
40    relative the begin of the code area (start of procedure).    
41
42    $Id: codegen-common.c 7940 2007-05-23 09:42:08Z michi $
43
44 */
45
46
47 #include "config.h"
48
49 #include <assert.h>
50 #include <string.h>
51
52 #include "vm/types.h"
53
54 #if defined(ENABLE_JIT)
55 /* this is required PATCHER_CALL_SIZE */
56 # include "codegen.h"
57 #endif
58
59 #if defined(__ARM__)
60 /* this is required for REG_SPLIT */
61 # include "md-abi.h"
62 #endif
63
64 #include "mm/memory.h"
65
66 #include "toolbox/avl.h"
67 #include "toolbox/list.h"
68 #include "toolbox/logging.h"
69
70 #include "native/jni.h"
71 #include "native/native.h"
72
73 #include "threads/threads-common.h"
74
75 #include "vm/builtin.h"
76 #include "vm/exceptions.h"
77 #include "vm/stringlocal.h"
78
79 #include "vm/jit/abi.h"
80 #include "vm/jit/asmpart.h"
81 #include "vm/jit/codegen-common.h"
82
83 #if defined(ENABLE_DISASSEMBLER)
84 # include "vm/jit/disass.h"
85 #endif
86
87 #include "vm/jit/dseg.h"
88 #include "vm/jit/emit-common.h"
89 #include "vm/jit/jit.h"
90 #include "vm/jit/md.h"
91 #include "vm/jit/replace.h"
92 #if defined(ENABLE_SSA)
93 # include "vm/jit/optimizing/lsra.h"
94 # include "vm/jit/optimizing/ssa.h"
95 #endif
96 #include "vm/jit/stacktrace.h"
97
98 #if defined(ENABLE_INTRP)
99 #include "vm/jit/intrp/intrp.h"
100 #endif
101
102 #include "vmcore/method.h"
103 #include "vmcore/options.h"
104
105 # include "vmcore/statistics.h"
106
107 #if defined(ENABLE_VMLOG)
108 #include <vmlog_cacao.h>
109 #endif
110
111
112 /* in this tree we store all method addresses *********************************/
113
114 static avl_tree_t *methodtree = NULL;
115 static s4 methodtree_comparator(const void *treenode, const void *node);
116
117
118 /* codegen_init ****************************************************************
119
120    TODO
121
122 *******************************************************************************/
123
124 void codegen_init(void)
125 {
126         /* this tree is global, not method specific */
127
128         if (!methodtree) {
129 #if defined(ENABLE_JIT)
130                 methodtree_element *mte;
131 #endif
132
133                 methodtree = avl_create(&methodtree_comparator);
134
135 #if defined(ENABLE_JIT)
136                 /* insert asm_vm_call_method */
137
138                 mte = NEW(methodtree_element);
139
140                 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
141                 mte->endpc   = (u1 *) (ptrint) asm_vm_call_method_end;
142
143                 avl_insert(methodtree, mte);
144 #endif /* defined(ENABLE_JIT) */
145         }
146 }
147
148
149 /* codegen_setup ***************************************************************
150
151    Allocates and initialises code area, data area and references.
152
153 *******************************************************************************/
154
155 void codegen_setup(jitdata *jd)
156 {
157         methodinfo  *m;
158         codegendata *cd;
159
160         /* get required compiler data */
161
162         m  = jd->m;
163         cd = jd->cd;
164
165         /* initialize members */
166
167         cd->flags        = 0;
168
169         cd->mcodebase    = DMNEW(u1, MCODEINITSIZE);
170         cd->mcodeend     = cd->mcodebase + MCODEINITSIZE;
171         cd->mcodesize    = MCODEINITSIZE;
172
173         /* initialize mcode variables */
174
175         cd->mcodeptr     = cd->mcodebase;
176         cd->lastmcodeptr = cd->mcodebase;
177
178 #if defined(ENABLE_INTRP)
179         /* native dynamic superinstructions variables */
180
181         if (opt_intrp) {
182                 cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
183                 cd->ncodesize = NCODEINITSIZE;
184
185                 /* initialize ncode variables */
186         
187                 cd->ncodeptr = cd->ncodebase;
188
189                 cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
190                 cd->superstarts = NULL;
191         }
192 #endif
193
194         cd->dseg           = NULL;
195         cd->dseglen        = 0;
196
197         cd->jumpreferences = NULL;
198
199 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
200         cd->datareferences = NULL;
201 #endif
202
203 /*      cd->patchrefs      = list_create_dump(OFFSET(patchref, linkage)); */
204         cd->patchrefs      = NULL;
205         cd->brancheslabel  = list_create_dump(OFFSET(branch_label_ref_t, linkage));
206         cd->listcritical   = list_create_dump(OFFSET(critical_section_ref_t, linkage));
207
208         cd->linenumberreferences = NULL;
209         cd->linenumbertablesizepos = 0;
210         cd->linenumbertablestartpos = 0;
211         cd->linenumbertab = 0;
212 }
213
214
215 /* codegen_reset ***************************************************************
216
217    Resets the codegen data structure so we can recompile the method.
218
219 *******************************************************************************/
220
221 static void codegen_reset(jitdata *jd)
222 {
223         codeinfo    *code;
224         codegendata *cd;
225         basicblock  *bptr;
226
227         /* get required compiler data */
228
229         code = jd->code;
230         cd   = jd->cd;
231
232         /* reset error flag */
233
234         cd->flags          &= ~CODEGENDATA_FLAG_ERROR;
235
236         /* reset some members, we reuse the code memory already allocated
237            as this should have almost the correct size */
238
239         cd->mcodeptr        = cd->mcodebase;
240         cd->lastmcodeptr    = cd->mcodebase;
241
242         cd->dseg            = NULL;
243         cd->dseglen         = 0;
244
245         cd->jumpreferences  = NULL;
246
247 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
248         cd->datareferences  = NULL;
249 #endif
250
251 /*      cd->patchrefs       = list_create_dump(OFFSET(patchref, linkage)); */
252         cd->patchrefs       = NULL;
253         cd->brancheslabel   = list_create_dump(OFFSET(branch_label_ref_t, linkage));
254         cd->listcritical    = list_create_dump(OFFSET(critical_section_ref_t, linkage));
255
256         cd->linenumberreferences    = NULL;
257         cd->linenumbertablesizepos  = 0;
258         cd->linenumbertablestartpos = 0;
259         cd->linenumbertab           = 0;
260         
261         /* We need to clear the mpc and the branch references from all
262            basic blocks as they will definitely change. */
263
264         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
265                 bptr->mpc        = -1;
266                 bptr->branchrefs = NULL;
267         }
268
269 #if defined(ENABLE_REPLACEMENT)
270         code->rplpoints     = NULL;
271         code->rplpointcount = 0;
272         code->regalloc      = NULL;
273         code->regalloccount = 0;
274         code->globalcount   = 0;
275 #endif
276 }
277
278
279 /* codegen_generate ************************************************************
280
281    Generates the code for the currently compiled method.
282
283 *******************************************************************************/
284
285 bool codegen_generate(jitdata *jd)
286 {
287         codegendata *cd;
288
289         /* get required compiler data */
290
291         cd = jd->cd;
292
293         /* call the machine-dependent code generation function */
294
295         if (!codegen_emit(jd))
296                 return false;
297
298         /* check for an error */
299
300         if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
301                 /* check for long-branches flag, if it is set we recompile the
302                    method */
303
304 #if !defined(NDEBUG)
305         if (compileverbose)
306             log_message_method("Re-generating code: ", jd->m);
307 #endif
308
309                 /* XXX maybe we should tag long-branches-methods for recompilation */
310
311                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
312                         /* we have to reset the codegendata structure first */
313
314                         codegen_reset(jd);
315
316                         /* and restart the compiler run */
317
318                         if (!codegen_emit(jd))
319                                 return false;
320                 }
321                 else {
322                         vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
323                 }
324
325 #if !defined(NDEBUG)
326         if (compileverbose)
327             log_message_method("Re-generating code done: ", jd->m);
328 #endif
329         }
330
331         /* reallocate the memory and finish the code generation */
332
333         codegen_finish(jd);
334
335         /* everything's ok */
336
337         return true;
338 }
339
340
341 /* codegen_close ***************************************************************
342
343    TODO
344
345 *******************************************************************************/
346
347 void codegen_close(void)
348 {
349         /* TODO: release avl tree on i386 and x86_64 */
350 }
351
352
353 /* codegen_increase ************************************************************
354
355    Doubles code area.
356
357 *******************************************************************************/
358
359 void codegen_increase(codegendata *cd)
360 {
361         u1 *oldmcodebase;
362
363         /* save old mcodebase pointer */
364
365         oldmcodebase = cd->mcodebase;
366
367         /* reallocate to new, doubled memory */
368
369         cd->mcodebase = DMREALLOC(cd->mcodebase,
370                                                           u1,
371                                                           cd->mcodesize,
372                                                           cd->mcodesize * 2);
373         cd->mcodesize *= 2;
374         cd->mcodeend   = cd->mcodebase + cd->mcodesize;
375
376         /* set new mcodeptr */
377
378         cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
379
380 #if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP)
381         /* adjust the pointer to the last patcher position */
382
383         if (cd->lastmcodeptr != NULL)
384                 cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
385 #endif
386 }
387
388
389 /* codegen_ncode_increase ******************************************************
390
391    Doubles code area.
392
393 *******************************************************************************/
394
395 #if defined(ENABLE_INTRP)
396 u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
397 {
398         u1 *oldncodebase;
399
400         /* save old ncodebase pointer */
401
402         oldncodebase = cd->ncodebase;
403
404         /* reallocate to new, doubled memory */
405
406         cd->ncodebase = DMREALLOC(cd->ncodebase,
407                                                           u1,
408                                                           cd->ncodesize,
409                                                           cd->ncodesize * 2);
410         cd->ncodesize *= 2;
411
412         /* return the new ncodeptr */
413
414         return (cd->ncodebase + (ncodeptr - oldncodebase));
415 }
416 #endif
417
418
419 /* codegen_add_branch_ref ******************************************************
420
421    Prepends an branch to the list.
422
423 *******************************************************************************/
424
425 void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
426 {
427         branchref *br;
428         s4         branchmpc;
429
430         STATISTICS(count_branches_unresolved++);
431
432         /* calculate the mpc of the branch instruction */
433
434         branchmpc = cd->mcodeptr - cd->mcodebase;
435
436         br = DNEW(branchref);
437
438         br->branchmpc = branchmpc;
439         br->condition = condition;
440         br->reg       = reg;
441         br->options   = options;
442         br->next      = target->branchrefs;
443
444         target->branchrefs = br;
445 }
446
447
448 /* codegen_resolve_branchrefs **************************************************
449
450    Resolves and patches the branch references of a given basic block.
451
452 *******************************************************************************/
453
454 void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
455 {
456         branchref *br;
457         u1        *mcodeptr;
458
459         /* Save the mcodeptr because in the branch emitting functions
460            we generate code somewhere inside already generated code,
461            but we're still in the actual code generation phase. */
462
463         mcodeptr = cd->mcodeptr;
464
465         /* just to make sure */
466
467         assert(bptr->mpc >= 0);
468
469         for (br = bptr->branchrefs; br != NULL; br = br->next) {
470                 /* temporary set the mcodeptr */
471
472                 cd->mcodeptr = cd->mcodebase + br->branchmpc;
473
474                 /* emit_bccz and emit_branch emit the correct code, even if we
475                    pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
476
477                 emit_bccz(cd, bptr, br->condition, br->reg, br->options);
478         }
479
480         /* restore mcodeptr */
481
482         cd->mcodeptr = mcodeptr;
483 }
484
485
486 /* codegen_branch_label_add ****************************************************
487
488    Append an branch to the label-branch list.
489
490 *******************************************************************************/
491
492 void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
493 {
494         list_t             *list;
495         branch_label_ref_t *br;
496         s4                  mpc;
497
498         /* get the label list */
499
500         list = cd->brancheslabel;
501         
502         /* calculate the current mpc */
503
504         mpc = cd->mcodeptr - cd->mcodebase;
505
506         br = DNEW(branch_label_ref_t);
507
508         br->mpc       = mpc;
509         br->label     = label;
510         br->condition = condition;
511         br->reg       = reg;
512         br->options   = options;
513
514         /* add the branch to the list */
515
516         list_add_last_unsynced(list, br);
517 }
518
519
520 /* codegen_add_patch_ref *******************************************************
521
522    Appends a new patcher reference to the list of patching positions.
523
524 *******************************************************************************/
525
526 void codegen_add_patch_ref(codegendata *cd, functionptr patcher, voidptr ref,
527                                                    s4 disp)
528 {
529         patchref *pr;
530         s4        branchmpc;
531
532         branchmpc = cd->mcodeptr - cd->mcodebase;
533
534         pr = DNEW(patchref);
535
536         pr->branchpos = branchmpc;
537         pr->disp      = disp;
538         pr->patcher   = patcher;
539         pr->ref       = ref;
540
541 /*      list_add_first(cd->patchrefs, pr); */
542         pr->next      = cd->patchrefs;
543         cd->patchrefs = pr;
544
545         /* Generate NOPs for opt_shownops. */
546
547         if (opt_shownops)
548                 PATCHER_NOPS;
549
550 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__))
551         /* On some architectures the patcher stub call instruction might
552            be longer than the actual instruction generated.  On this
553            architectures we store the last patcher call position and after
554            the basic block code generation is completed, we check the
555            range and maybe generate some nop's. */
556         /* The nops are generated in codegen_emit in each codegen */
557
558         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
559 #endif
560 }
561
562
563 /* codegen_critical_section_new ************************************************
564
565    Allocates a new critical-section reference and adds it to the
566    critical-section list.
567
568 *******************************************************************************/
569
570 #if defined(ENABLE_THREADS)
571 void codegen_critical_section_new(codegendata *cd)
572 {
573         list_t                 *list;
574         critical_section_ref_t *csr;
575         s4                      mpc;
576
577         /* get the critical section list */
578
579         list = cd->listcritical;
580         
581         /* calculate the current mpc */
582
583         mpc = cd->mcodeptr - cd->mcodebase;
584
585         csr = DNEW(critical_section_ref_t);
586
587         /* We only can set restart right now, as start and end are set by
588            the following, corresponding functions. */
589
590         csr->start   = -1;
591         csr->end     = -1;
592         csr->restart = mpc;
593
594         /* add the branch to the list */
595
596         list_add_last_unsynced(list, csr);
597 }
598 #endif
599
600
601 /* codegen_critical_section_start **********************************************
602
603    Set the start-point of the current critical section (which is the
604    last element of the list).
605
606 *******************************************************************************/
607
608 #if defined(ENABLE_THREADS)
609 void codegen_critical_section_start(codegendata *cd)
610 {
611         list_t                 *list;
612         critical_section_ref_t *csr;
613         s4                      mpc;
614
615         /* get the critical section list */
616
617         list = cd->listcritical;
618         
619         /* calculate the current mpc */
620
621         mpc = cd->mcodeptr - cd->mcodebase;
622
623         /* get the current critical section */
624
625         csr = list_last_unsynced(list);
626
627         /* set the start point */
628
629         assert(csr->start == -1);
630
631         csr->start = mpc;
632 }
633 #endif
634
635
636 /* codegen_critical_section_end ************************************************
637
638    Set the end-point of the current critical section (which is the
639    last element of the list).
640
641 *******************************************************************************/
642
643 #if defined(ENABLE_THREADS)
644 void codegen_critical_section_end(codegendata *cd)
645 {
646         list_t                 *list;
647         critical_section_ref_t *csr;
648         s4                      mpc;
649
650         /* get the critical section list */
651
652         list = cd->listcritical;
653         
654         /* calculate the current mpc */
655
656         mpc = cd->mcodeptr - cd->mcodebase;
657
658         /* get the current critical section */
659
660         csr = list_last_unsynced(list);
661
662         /* set the end point */
663
664         assert(csr->end == -1);
665
666         csr->end = mpc;
667 }
668 #endif
669
670
671 /* codegen_critical_section_finish *********************************************
672
673    Finish the critical sections, create the critical section nodes for
674    the AVL tree and insert them into the tree.
675
676 *******************************************************************************/
677
678 #if defined(ENABLE_THREADS)
679 static void codegen_critical_section_finish(jitdata *jd)
680 {
681         codeinfo    *code;
682         codegendata *cd;
683         list_t                  *list;
684         critical_section_ref_t  *csr;
685         critical_section_node_t *csn;
686
687         /* get required compiler data */
688
689         code = jd->code;
690         cd   = jd->cd;
691
692         /* get the critical section list */
693
694         list = cd->listcritical;
695
696         /* iterate over all critical sections */
697
698         for (csr = list_first_unsynced(list); csr != NULL;
699                  csr = list_next_unsynced(list, csr)) {
700                 /* check if all points are set */
701
702                 assert(csr->start   != -1);
703                 assert(csr->end     != -1);
704                 assert(csr->restart != -1);
705
706                 /* allocate tree node */
707
708                 csn = NEW(critical_section_node_t);
709
710                 csn->start   = code->entrypoint + csr->start;
711                 csn->end     = code->entrypoint + csr->end;
712                 csn->restart = code->entrypoint + csr->restart;
713
714                 /* insert into the tree */
715
716                 critical_section_register(csn);
717         }
718 }
719 #endif
720
721
722 /* methodtree_comparator *******************************************************
723
724    Comparator function used for the AVL tree of methods.
725
726    ARGUMENTS:
727       treenode....the node from the tree
728       node........the node to compare to the tree-node
729
730 *******************************************************************************/
731
732 static s4 methodtree_comparator(const void *treenode, const void *node)
733 {
734         methodtree_element *mte;
735         methodtree_element *mtepc;
736
737         mte   = (methodtree_element *) treenode;
738         mtepc = (methodtree_element *) node;
739
740         /* compare both startpc and endpc of pc, even if they have the same value,
741            otherwise the avl_probe sometimes thinks the element is already in the
742            tree */
743
744 #ifdef __S390__
745         /* On S390 addresses are 31 bit. Compare only 31 bits of value.
746          */
747 #       define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
748 #else
749 #       define ADDR_MASK(a) (a)
750 #endif
751
752         if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
753                 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
754                 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
755                 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
756                 return 0;
757
758         } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
759                 return -1;
760
761         } else {
762                 return 1;
763         }
764
765 #       undef ADDR_MASK
766 }
767
768
769 /* codegen_insertmethod ********************************************************
770
771    Insert the machine code range of a method into the AVL tree of methods.
772
773 *******************************************************************************/
774
775 void codegen_insertmethod(u1 *startpc, u1 *endpc)
776 {
777         methodtree_element *mte;
778
779         /* allocate new method entry */
780
781         mte = NEW(methodtree_element);
782
783         mte->startpc = startpc;
784         mte->endpc   = endpc;
785
786         /* this function does not return an error, but asserts for
787            duplicate entries */
788
789         avl_insert(methodtree, mte);
790 }
791
792
793 /* codegen_get_pv_from_pc ******************************************************
794
795    Find the PV for the given PC by searching in the AVL tree of
796    methods.
797
798 *******************************************************************************/
799
800 u1 *codegen_get_pv_from_pc(u1 *pc)
801 {
802         methodtree_element  mtepc;
803         methodtree_element *mte;
804
805         /* allocation of the search structure on the stack is much faster */
806
807         mtepc.startpc = pc;
808         mtepc.endpc   = pc;
809
810         mte = avl_find(methodtree, &mtepc);
811
812         if (mte == NULL) {
813                 /* No method was found.  Let's dump a stacktrace. */
814
815 #if defined(ENABLE_VMLOG)
816                 vmlog_cacao_signl("SIGSEGV");
817 #endif
818
819                 log_println("We received a SIGSEGV and tried to handle it, but we were");
820                 log_println("unable to find a Java method at:");
821                 log_println("");
822 #if SIZEOF_VOID_P == 8
823                 log_println("PC=0x%016lx", pc);
824 #else
825                 log_println("PC=0x%08x", pc);
826 #endif
827                 log_println("");
828                 log_println("Dumping the current stacktrace:");
829
830 #if defined(ENABLE_THREADS)
831                 /* XXX michi: This should be available even without threads! */
832                 threads_print_stacktrace();
833 #endif
834
835                 vm_abort("Exiting...");
836         }
837
838         return mte->startpc;
839 }
840
841
842 /* codegen_get_pv_from_pc_nocheck **********************************************
843
844    Find the PV for the given PC by searching in the AVL tree of
845    methods.  This method does not check the return value and is used
846    by the profiler.
847
848 *******************************************************************************/
849
850 u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
851 {
852         methodtree_element  mtepc;
853         methodtree_element *mte;
854
855         /* allocation of the search structure on the stack is much faster */
856
857         mtepc.startpc = pc;
858         mtepc.endpc   = pc;
859
860         mte = avl_find(methodtree, &mtepc);
861
862         if (mte == NULL)
863                 return NULL;
864         else
865                 return mte->startpc;
866 }
867
868
869 /* codegen_set_replacement_point_notrap ****************************************
870
871    Record the position of a non-trappable replacement point.
872
873 *******************************************************************************/
874
875 #if defined(ENABLE_REPLACEMENT)
876 #if !defined(NDEBUG)
877 void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
878 #else
879 void codegen_set_replacement_point_notrap(codegendata *cd)
880 #endif
881 {
882         assert(cd->replacementpoint);
883         assert(cd->replacementpoint->type == type);
884         assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
885
886         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
887
888         cd->replacementpoint++;
889 }
890 #endif /* defined(ENABLE_REPLACEMENT) */
891
892
893 /* codegen_set_replacement_point ***********************************************
894
895    Record the position of a trappable replacement point.
896
897 *******************************************************************************/
898
899 #if defined(ENABLE_REPLACEMENT)
900 #if !defined(NDEBUG)
901 void codegen_set_replacement_point(codegendata *cd, s4 type)
902 #else
903 void codegen_set_replacement_point(codegendata *cd)
904 #endif
905 {
906         assert(cd->replacementpoint);
907         assert(cd->replacementpoint->type == type);
908         assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
909
910         cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
911
912         cd->replacementpoint++;
913
914         /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
915
916         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
917 }
918 #endif /* defined(ENABLE_REPLACEMENT) */
919
920
921 /* codegen_finish **************************************************************
922
923    Finishes the code generation. A new memory, large enough for both
924    data and code, is allocated and data and code are copied together
925    to their final layout, unresolved jumps are resolved, ...
926
927 *******************************************************************************/
928
929 void codegen_finish(jitdata *jd)
930 {
931         codeinfo    *code;
932         codegendata *cd;
933         s4           mcodelen;
934 #if defined(ENABLE_INTRP)
935         s4           ncodelen;
936 #endif
937         s4           alignedmcodelen;
938         jumpref     *jr;
939         u1          *epoint;
940         s4           alignedlen;
941
942         /* get required compiler data */
943
944         code = jd->code;
945         cd   = jd->cd;
946
947         /* prevent compiler warning */
948
949 #if defined(ENABLE_INTRP)
950         ncodelen = 0;
951 #endif
952
953         /* calculate the code length */
954
955         mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
956
957 #if defined(ENABLE_STATISTICS)
958         if (opt_stat) {
959                 count_code_len += mcodelen;
960                 count_data_len += cd->dseglen;
961         }
962 #endif
963
964         alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
965
966 #if defined(ENABLE_INTRP)
967         if (opt_intrp)
968                 ncodelen = cd->ncodeptr - cd->ncodebase;
969         else {
970                 ncodelen = 0; /* avoid compiler warning */
971         }
972 #endif
973
974         cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
975         alignedlen = alignedmcodelen + cd->dseglen;
976
977 #if defined(ENABLE_INTRP)
978         if (opt_intrp) {
979                 alignedlen += ncodelen;
980         }
981 #endif
982
983         /* allocate new memory */
984
985         code->mcodelength = mcodelen + cd->dseglen;
986         code->mcode       = CNEW(u1, alignedlen);
987
988         /* set the entrypoint of the method */
989         
990         assert(code->entrypoint == NULL);
991         code->entrypoint = epoint = (code->mcode + cd->dseglen);
992
993         /* fill the data segment (code->entrypoint must already be set!) */
994
995         dseg_finish(jd);
996
997         /* copy code to the new location */
998
999         MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
1000
1001 #if defined(ENABLE_INTRP)
1002         /* relocate native dynamic superinstruction code (if any) */
1003
1004         if (opt_intrp) {
1005                 cd->mcodebase = code->entrypoint;
1006
1007                 if (ncodelen > 0) {
1008                         u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
1009
1010                         MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
1011
1012                         /* flush the instruction and data caches */
1013
1014                         md_cacheflush(ncodebase, ncodelen);
1015
1016                         /* set some cd variables for dynamic_super_rerwite */
1017
1018                         cd->ncodebase = ncodebase;
1019
1020                 } else {
1021                         cd->ncodebase = NULL;
1022                 }
1023
1024                 dynamic_super_rewrite(cd);
1025         }
1026 #endif
1027
1028         /* jump table resolving */
1029
1030         for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
1031                 *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
1032                         (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
1033
1034         /* line number table resolving */
1035         {
1036                 linenumberref *lr;
1037                 ptrint lrtlen = 0;
1038                 ptrint target;
1039
1040                 for (lr = cd->linenumberreferences; lr != NULL; lr = lr->next) {
1041                         lrtlen++;
1042                         target = lr->targetmpc;
1043                         /* if the entry contains an mcode pointer (normal case), resolve it */
1044                         /* (see doc/inlining_stacktrace.txt for details)                    */
1045                         if (lr->linenumber >= -2) {
1046                             target += (ptrint) epoint;
1047                         }
1048                         *((functionptr *) ((ptrint) epoint + (ptrint) lr->tablepos)) = 
1049                                 (functionptr) target;
1050                 }
1051                 
1052                 *((functionptr *) ((ptrint) epoint + cd->linenumbertablestartpos)) =
1053                         (functionptr) ((ptrint) epoint + cd->linenumbertab);
1054
1055                 *((ptrint *) ((ptrint) epoint + cd->linenumbertablesizepos)) = lrtlen;
1056         }
1057
1058 #if defined(ENABLE_REPLACEMENT)
1059         /* replacement point resolving */
1060         {
1061                 int i;
1062                 rplpoint *rp;
1063
1064                 code->replacementstubs += (ptrint) epoint;
1065
1066                 rp = code->rplpoints;
1067                 for (i=0; i<code->rplpointcount; ++i, ++rp) {
1068                         rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
1069                 }
1070         }
1071 #endif /* defined(ENABLE_REPLACEMENT) */
1072
1073         /* add method into methodtree to find the entrypoint */
1074
1075         codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
1076
1077 #if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
1078         /* resolve data segment references */
1079
1080         dseg_resolve_datareferences(jd);
1081 #endif
1082
1083 #if defined(ENABLE_THREADS)
1084         /* create cirtical sections */
1085
1086         codegen_critical_section_finish(jd);
1087 #endif
1088
1089         /* flush the instruction and data caches */
1090
1091         md_cacheflush(code->mcode, code->mcodelength);
1092 }
1093
1094
1095 /* codegen_generate_stub_compiler **********************************************
1096
1097    Wrapper for codegen_emit_stub_compiler.
1098
1099    Returns:
1100        pointer to the compiler stub code.
1101
1102 *******************************************************************************/
1103
1104 u1 *codegen_generate_stub_compiler(methodinfo *m)
1105 {
1106         jitdata     *jd;
1107         codegendata *cd;
1108         ptrint      *d;                     /* pointer to data memory             */
1109         u1          *c;                     /* pointer to code memory             */
1110         s4           dumpsize;
1111
1112         /* mark dump memory */
1113
1114         dumpsize = dump_size();
1115
1116         /* allocate required data structures */
1117
1118         jd = DNEW(jitdata);
1119
1120         jd->m     = m;
1121         jd->cd    = DNEW(codegendata);
1122         jd->flags = 0;
1123
1124         /* get required compiler data */
1125
1126         cd = jd->cd;
1127
1128         /* allocate code memory */
1129
1130         c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1131
1132         /* set pointers correctly */
1133
1134         d = (ptrint *) c;
1135
1136         cd->mcodebase = c;
1137
1138         c = c + 3 * SIZEOF_VOID_P;
1139         cd->mcodeptr = c;
1140
1141         /* NOTE: The codeinfo pointer is actually a pointer to the
1142            methodinfo (this fakes a codeinfo structure). */
1143
1144         d[0] = (ptrint) asm_call_jit_compiler;
1145         d[1] = (ptrint) m;
1146         d[2] = (ptrint) &d[1];                                    /* fake code->m */
1147
1148         /* call the emit function */
1149
1150         codegen_emit_stub_compiler(jd);
1151
1152 #if defined(ENABLE_STATISTICS)
1153         if (opt_stat)
1154                 count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
1155 #endif
1156
1157         /* flush caches */
1158
1159         md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
1160
1161         /* release dump memory */
1162
1163         dump_release(dumpsize);
1164
1165         /* return native stub code */
1166
1167         return c;
1168 }
1169
1170
1171 /* codegen_generate_stub_builtin ***********************************************
1172
1173    Wrapper for codegen_emit_stub_builtin.
1174
1175    Returns:
1176        Pointer to the entrypoint of the stub.
1177
1178 *******************************************************************************/
1179
1180 void codegen_generate_stub_builtin(builtintable_entry *bte)
1181 {
1182         jitdata  *jd;
1183         codeinfo *code;
1184         s4        dumpsize;
1185
1186         /* mark dump memory */
1187
1188         dumpsize = dump_size();
1189
1190         jd = DNEW(jitdata);
1191
1192         jd->m     = NULL;
1193         jd->cd    = DNEW(codegendata);
1194         jd->rd    = NULL;
1195         jd->flags = 0;
1196
1197         /* Allocate codeinfo memory from the heap as we need to keep them. */
1198
1199         jd->code  = code_codeinfo_new(NULL);
1200
1201         /* get required compiler data */
1202
1203         code = jd->code;
1204
1205         /* setup code generation stuff */
1206
1207         codegen_setup(jd);
1208
1209         /* generate the code */
1210
1211 #if defined(ENABLE_JIT)
1212 # if defined(ENABLE_INTRP)
1213         if (!opt_intrp)
1214 # endif
1215                 codegen_emit_stub_builtin(jd, bte);
1216 #endif
1217
1218         /* reallocate the memory and finish the code generation */
1219
1220         codegen_finish(jd);
1221
1222         /* set the stub entry point in the builtin table */
1223
1224         bte->stub = code->entrypoint;
1225
1226 #if defined(ENABLE_STATISTICS)
1227         if (opt_stat)
1228                 size_stub_native += code->mcodelength;
1229 #endif
1230
1231         /* release memory */
1232
1233         dump_release(dumpsize);
1234 }
1235
1236
1237 /* codegen_generate_stub_native ************************************************
1238
1239    Wrapper for codegen_emit_stub_native.
1240
1241    Returns:
1242        the codeinfo representing the stub code.
1243
1244 *******************************************************************************/
1245
1246 codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
1247 {
1248         jitdata     *jd;
1249         codeinfo    *code;
1250         s4           dumpsize;
1251         methoddesc  *md;
1252         methoddesc  *nmd;       
1253         s4           nativeparams;
1254
1255         /* mark dump memory */
1256
1257         dumpsize = dump_size();
1258
1259         jd = DNEW(jitdata);
1260
1261         jd->m     = m;
1262         jd->cd    = DNEW(codegendata);
1263         jd->rd    = DNEW(registerdata);
1264         jd->flags = 0;
1265
1266         /* Allocate codeinfo memory from the heap as we need to keep them. */
1267
1268         jd->code  = code_codeinfo_new(m); /* XXX check allocation */
1269
1270         /* get required compiler data */
1271
1272         code = jd->code;
1273
1274         /* set the flags for the current JIT run */
1275
1276 #if defined(ENABLE_PROFILING)
1277         if (opt_prof)
1278                 jd->flags |= JITDATA_FLAG_INSTRUMENT;
1279 #endif
1280
1281         if (opt_verbosecall)
1282                 jd->flags |= JITDATA_FLAG_VERBOSECALL;
1283
1284         /* setup code generation stuff */
1285
1286 #if defined(ENABLE_JIT)
1287 # if defined(ENABLE_INTRP)
1288         if (!opt_intrp)
1289 # endif
1290                 reg_setup(jd);
1291 #endif
1292
1293         codegen_setup(jd);
1294
1295         /* create new method descriptor with additional native parameters */
1296
1297         md = m->parseddesc;
1298         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
1299         
1300         nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
1301                                                            md->paramcount * sizeof(typedesc) +
1302                                                            nativeparams * sizeof(typedesc));
1303
1304         nmd->paramcount = md->paramcount + nativeparams;
1305
1306         nmd->params = DMNEW(paramdesc, nmd->paramcount);
1307
1308         nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer            */
1309
1310         if (m->flags & ACC_STATIC)
1311                 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer              */
1312
1313         MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
1314                   md->paramcount);
1315
1316 #if defined(ENABLE_JIT)
1317 # if defined(ENABLE_INTRP)
1318         if (!opt_intrp)
1319 # endif
1320                 /* pre-allocate the arguments for the native ABI */
1321
1322                 md_param_alloc_native(nmd);
1323 #endif
1324
1325         /* generate the code */
1326
1327 #if defined(ENABLE_JIT)
1328 # if defined(ENABLE_INTRP)
1329         if (opt_intrp)
1330                 intrp_createnativestub(f, jd, nmd);
1331         else
1332 # endif
1333                 codegen_emit_stub_native(jd, nmd, f);
1334 #else
1335         intrp_createnativestub(f, jd, nmd);
1336 #endif
1337
1338         /* reallocate the memory and finish the code generation */
1339
1340         codegen_finish(jd);
1341
1342 #if defined(ENABLE_STATISTICS)
1343         /* must be done after codegen_finish() */
1344
1345         if (opt_stat)
1346                 size_stub_native += code->mcodelength;
1347 #endif
1348
1349 #if !defined(NDEBUG)
1350         /* disassemble native stub */
1351
1352         if (opt_shownativestub) {
1353 #if defined(ENABLE_DISASSEMBLER)
1354                 codegen_disassemble_nativestub(m,
1355                                                                            (u1 *) (ptrint) code->entrypoint,
1356                                                                            (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
1357 #endif
1358
1359                 /* show data segment */
1360
1361                 if (opt_showddatasegment)
1362                         dseg_display(jd);
1363         }
1364 #endif /* !defined(NDEBUG) */
1365
1366         /* release memory */
1367
1368         dump_release(dumpsize);
1369
1370         /* return native stub code */
1371
1372         return code;
1373 }
1374
1375
1376 /* codegen_disassemble_nativestub **********************************************
1377
1378    Disassembles the generated native stub.
1379
1380 *******************************************************************************/
1381
1382 #if defined(ENABLE_DISASSEMBLER)
1383 void codegen_disassemble_nativestub(methodinfo *m, u1 *start, u1 *end)
1384 {
1385         printf("Native stub: ");
1386         utf_fprint_printable_ascii_classname(stdout, m->class->name);
1387         printf(".");
1388         utf_fprint_printable_ascii(stdout, m->name);
1389         utf_fprint_printable_ascii(stdout, m->descriptor);
1390         printf("\n\nLength: %d\n\n", (s4) (end - start));
1391
1392         DISASSEMBLE(start, end);
1393 }
1394 #endif
1395
1396
1397 /* codegen_stub_builtin_enter **************************************************
1398
1399    Prepares the stuff required for a builtin function call:
1400
1401    - adds a stackframe info structure to the chain, for stacktraces
1402
1403    The layout of the builtin stub stackframe should look like this:
1404
1405    +---------------------------+ <- SP (of parent Java function)
1406    | return address            |
1407    +---------------------------+
1408    |                           |
1409    | stackframe info structure |
1410    |                           |
1411    +---------------------------+
1412    |                           |
1413    | arguments (if any)        |
1414    |                           |
1415    +---------------------------+ <- SP (native stub)
1416
1417 *******************************************************************************/
1418
1419 void codegen_stub_builtin_enter(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1420 {
1421         stackframeinfo *sfi;
1422
1423         /* get data structures from stack */
1424
1425         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1426
1427         /* add a stackframeinfo to the chain */
1428
1429         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1430
1431 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1432         /* set the native world flag */
1433
1434         THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1435 #endif
1436 }
1437
1438
1439 /* codegen_stub_builtin_exit ***************************************************
1440
1441    Removes the stuff required for a builtin function call.
1442
1443 *******************************************************************************/
1444
1445 void codegen_stub_builtin_exit(u1 *datasp)
1446 {
1447         stackframeinfo     *sfi;
1448         stackframeinfo    **psfi;
1449
1450         /* get data structures from stack */
1451
1452         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1453
1454         /* remove current stackframeinfo from chain */
1455
1456         psfi = &STACKFRAMEINFO;
1457
1458         *psfi = sfi->prev;
1459
1460 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1461         /* clear the native world flag */
1462
1463         THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1464 #endif
1465 }
1466
1467
1468 /* codegen_start_native_call ***************************************************
1469
1470    Prepares the stuff required for a native (JNI) function call:
1471
1472    - adds a stackframe info structure to the chain, for stacktraces
1473    - prepares the local references table on the stack
1474
1475    The layout of the native stub stackframe should look like this:
1476
1477    +---------------------------+ <- SP (of parent Java function)
1478    | return address            |
1479    +---------------------------+
1480    |                           |
1481    | stackframe info structure |
1482    |                           |
1483    +---------------------------+
1484    |                           |
1485    | local references table    |
1486    |                           |
1487    +---------------------------+
1488    |                           |
1489    | arguments (if any)        |
1490    |                           |
1491    +---------------------------+ <- SP (native stub)
1492
1493 *******************************************************************************/
1494
1495 void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra)
1496 {
1497         stackframeinfo *sfi;
1498         localref_table *lrt;
1499
1500         /* get data structures from stack */
1501
1502         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1503         lrt = (localref_table *) (datasp - sizeof(stackframeinfo) - 
1504                                                           sizeof(localref_table));
1505
1506         /* add a stackframeinfo to the chain */
1507
1508         stacktrace_create_native_stackframeinfo(sfi, pv, sp, ra);
1509
1510 #if defined(ENABLE_JNI)
1511         /* add current JNI local references table to this thread */
1512
1513         lrt->capacity    = LOCALREFTABLE_CAPACITY;
1514         lrt->used        = 0;
1515         lrt->localframes = 1;
1516         lrt->prev        = LOCALREFTABLE;
1517
1518         /* clear the references array (memset is faster the a for-loop) */
1519
1520         MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY);
1521
1522         LOCALREFTABLE = lrt;
1523 #endif
1524
1525 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1526         /* set the native world flag */
1527
1528         THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE;
1529 #endif
1530 }
1531
1532
1533 /* codegen_finish_native_call **************************************************
1534
1535    Removes the stuff required for a native (JNI) function call.
1536    Additionally it checks for an exceptions and in case, get the
1537    exception object and clear the pointer.
1538
1539 *******************************************************************************/
1540
1541 java_objectheader *codegen_finish_native_call(u1 *datasp)
1542 {
1543         stackframeinfo     *sfi;
1544         stackframeinfo    **psfi;
1545 #if defined(ENABLE_JNI)
1546         localref_table     *lrt;
1547         localref_table     *plrt;
1548         s4                  localframes;
1549 #endif
1550         java_objectheader  *e;
1551
1552         /* get data structures from stack */
1553
1554         sfi = (stackframeinfo *) (datasp - sizeof(stackframeinfo));
1555
1556 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
1557         /* clear the native world flag */
1558
1559         THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE;
1560 #endif
1561
1562         /* remove current stackframeinfo from chain */
1563
1564         psfi = &STACKFRAMEINFO;
1565
1566         *psfi = sfi->prev;
1567
1568 #if defined(ENABLE_JNI)
1569         /* release JNI local references tables for this thread */
1570
1571         lrt = LOCALREFTABLE;
1572
1573         /* release all current local frames */
1574
1575         for (localframes = lrt->localframes; localframes >= 1; localframes--) {
1576                 /* get previous frame */
1577
1578                 plrt = lrt->prev;
1579
1580                 /* Clear all reference entries (only for tables allocated on
1581                    the Java heap). */
1582
1583                 if (localframes > 1)
1584                         MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
1585
1586                 lrt->prev = NULL;
1587
1588                 /* set new local references table */
1589
1590                 lrt = plrt;
1591         }
1592
1593         /* now store the previous local frames in the thread structure */
1594
1595         LOCALREFTABLE = lrt;
1596 #endif
1597
1598         /* get the exception and return it */
1599
1600         e = exceptions_get_and_clear_exception();
1601
1602         return e;
1603 }
1604
1605
1606 /* removecompilerstub **********************************************************
1607
1608    Deletes a compilerstub from memory (simply by freeing it).
1609
1610 *******************************************************************************/
1611
1612 void removecompilerstub(u1 *stub)
1613 {
1614         /* pass size 1 to keep the intern function happy */
1615
1616         CFREE((void *) stub, 1);
1617 }
1618
1619
1620 /* removenativestub ************************************************************
1621
1622    Removes a previously created native-stub from memory.
1623     
1624 *******************************************************************************/
1625
1626 void removenativestub(u1 *stub)
1627 {
1628         /* pass size 1 to keep the intern function happy */
1629
1630         CFREE((void *) stub, 1);
1631 }
1632
1633
1634 /* codegen_reg_of_var **********************************************************
1635
1636    This function determines a register, to which the result of an
1637    operation should go, when it is ultimatively intended to store the
1638    result in pseudoregister v.  If v is assigned to an actual
1639    register, this register will be returned.  Otherwise (when v is
1640    spilled) this function returns tempregnum.  If not already done,
1641    regoff and flags are set in the stack location.
1642        
1643    On ARM we have to check if a long/double variable is splitted
1644    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1645    register of v for LOW_REG and the tempregnum for HIGH_REG in such
1646    cases.  (michi 2005/07/24)
1647
1648 *******************************************************************************/
1649
1650 s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
1651 {
1652
1653 #if 0
1654         /* Do we have to generate a conditional move?  Yes, then always
1655            return the temporary register.  The real register is identified
1656            during the store. */
1657
1658         if (opcode & ICMD_CONDITION_MASK)
1659                 return tempregnum;
1660 #endif
1661
1662         if (!(v->flags & INMEMORY)) {
1663 #if defined(__ARM__) && defined(__ARMEL__)
1664                 if (IS_2_WORD_TYPE(v->type) && (GET_HIGH_REG(v->vv.regoff) == REG_SPLIT))
1665                         return PACK_REGS(GET_LOW_REG(v->vv.regoff),
1666                                                          GET_HIGH_REG(tempregnum));
1667 #endif
1668 #if defined(__ARM__) && defined(__ARMEB__)
1669                 if (IS_2_WORD_TYPE(v->type) && (GET_LOW_REG(v->vv.regoff) == REG_SPLIT))
1670                         return PACK_REGS(GET_LOW_REG(tempregnum),
1671                                                          GET_HIGH_REG(v->vv.regoff));
1672 #endif
1673                 return v->vv.regoff;
1674         }
1675
1676 #if defined(ENABLE_STATISTICS)
1677         if (opt_stat)
1678                 count_spills_read++;
1679 #endif
1680
1681         return tempregnum;
1682 }
1683
1684 /* codegen_reg_of_dst **********************************************************
1685
1686    This function determines a register, to which the result of an
1687    operation should go, when it is ultimatively intended to store the
1688    result in iptr->dst.var.  If dst.var is assigned to an actual
1689    register, this register will be returned.  Otherwise (when it is
1690    spilled) this function returns tempregnum.  If not already done,
1691    regoff and flags are set in the stack location.
1692        
1693    On ARM we have to check if a long/double variable is splitted
1694    across reg/stack (HIGH_REG == REG_SPLIT). We return the actual
1695    register of dst.var for LOW_REG and the tempregnum for HIGH_REG in such
1696    cases.  (michi 2005/07/24)
1697
1698 *******************************************************************************/
1699
1700 s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
1701 {
1702         return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
1703 }
1704
1705
1706 /* codegen_emit_phi_moves ****************************************************
1707
1708    Emits phi moves at the end of the basicblock.
1709
1710 *******************************************************************************/
1711
1712 #if defined(ENABLE_SSA)
1713 void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
1714 {
1715         int lt_d,lt_s,i;
1716         lsradata *ls;
1717         codegendata *cd;
1718         varinfo *s, *d;
1719         instruction tmp_i;
1720
1721         cd = jd->cd;
1722         ls = jd->ls;
1723
1724         MCODECHECK(512);
1725
1726         /* Moves from phi functions with highest indices have to be */
1727         /* inserted first, since this is the order as is used for   */
1728         /* conflict resolution */
1729
1730         for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
1731                 lt_d = ls->phi_moves[bptr->nr][i][0];
1732                 lt_s = ls->phi_moves[bptr->nr][i][1];
1733 #if defined(SSA_DEBUG_VERBOSE)
1734                 if (compileverbose)
1735                         printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
1736 #endif
1737                 if (lt_s == UNUSED) {
1738 #if defined(SSA_DEBUG_VERBOSE)
1739                 if (compileverbose)
1740                         printf(" ... not processed \n");
1741 #endif
1742                         continue;
1743                 }
1744                         
1745                 d = VAR(ls->lifetime[lt_d].v_index);
1746                 s = VAR(ls->lifetime[lt_s].v_index);
1747                 
1748
1749                 if (d->type == -1) {
1750 #if defined(SSA_DEBUG_VERBOSE)
1751                         if (compileverbose)
1752                                 printf("...returning - phi lifetimes where joined\n");
1753 #endif
1754                         return;
1755                 }
1756
1757                 if (s->type == -1) {
1758 #if defined(SSA_DEBUG_VERBOSE)
1759                         if (compileverbose)
1760                                 printf("...returning - phi lifetimes where joined\n");
1761 #endif
1762                         return;
1763                 }
1764
1765                 tmp_i.opc = 0;
1766                 tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
1767                 tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
1768                 emit_copy(jd, &tmp_i);
1769
1770 #if defined(SSA_DEBUG_VERBOSE)
1771                 if (compileverbose) {
1772                         if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
1773                                 /* mem -> mem */
1774                                 printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1775                         }
1776                         else if (IS_INMEMORY(s->flags)) {
1777                                 /* mem -> reg */
1778                                 printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
1779                         }
1780                         else if (IS_INMEMORY(d->flags)) {
1781                                 /* reg -> mem */
1782                                 printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1783                         }
1784                         else {
1785                                 /* reg -> reg */
1786                                 printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
1787                         }
1788                         printf("\n");
1789                 }
1790 #endif /* defined(SSA_DEBUG_VERBOSE) */
1791         }
1792 }
1793 #endif /* defined(ENABLE_SSA) */
1794
1795
1796
1797 /*
1798  * These are local overrides for various environment variables in Emacs.
1799  * Please do not remove this and leave it at the end of the file, where
1800  * Emacs will automagically detect them.
1801  * ---------------------------------------------------------------------
1802  * Local variables:
1803  * mode: c
1804  * indent-tabs-mode: t
1805  * c-basic-offset: 4
1806  * tab-width: 4
1807  * End:
1808  * vim:noexpandtab:sw=4:ts=4:
1809  */