5f8fd45e4e97faa79079709a0793f8f7350b9f17
[cacao.git] / src / vm / jit / powerpc / emit.c
1 /* src/vm/jit/powerpc/emit.c - PowerPC code emitter functions
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    $Id: emit.c 7816 2007-04-25 19:38:46Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "md-abi.h"
37
38 #include "vm/jit/powerpc/codegen.h"
39
40 #include "mm/memory.h"
41
42 #include "threads/lock-common.h"
43
44 #include "vm/builtin.h"
45 #include "vm/exceptions.h"
46
47 #include "vm/jit/abi.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/codegen-common.h"
50 #include "vm/jit/dseg.h"
51 #include "vm/jit/emit-common.h"
52 #include "vm/jit/jit.h"
53 #include "vm/jit/replace.h"
54
55 #include "vmcore/options.h"
56
57
58 /* emit_load *******************************************************************
59
60    Emits a possible load of an operand.
61
62 *******************************************************************************/
63
64 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
65 {
66         codegendata *cd;
67         s4           disp;
68         s4           reg;
69
70         /* get required compiler data */
71
72         cd = jd->cd;
73
74         if (IS_INMEMORY(src->flags)) {
75                 COUNT_SPILLS;
76
77                 disp = src->vv.regoff * 4;
78
79                 switch (src->type) {
80                 case TYPE_INT:
81                 case TYPE_ADR:
82                         M_ILD(tempreg, REG_SP, disp);
83                         break;
84                 case TYPE_LNG:
85                         M_LLD(tempreg, REG_SP, disp);
86                         break;
87                 case TYPE_FLT:
88                         M_FLD(tempreg, REG_SP, disp);
89                         break;
90                 case TYPE_DBL:
91                         M_DLD(tempreg, REG_SP, disp);
92                         break;
93                 default:
94                         vm_abort("emit_load: unknown type %d", src->type);
95                 }
96
97                 reg = tempreg;
98         }
99         else
100                 reg = src->vv.regoff;
101
102         return reg;
103 }
104
105
106 /* emit_load_low ***************************************************************
107
108    Emits a possible load of the low 32-bits of an operand.
109
110 *******************************************************************************/
111
112 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
113 {
114         codegendata  *cd;
115         s4            disp;
116         s4            reg;
117
118         assert(src->type == TYPE_LNG);
119
120         /* get required compiler data */
121
122         cd = jd->cd;
123
124         if (IS_INMEMORY(src->flags)) {
125                 COUNT_SPILLS;
126
127                 disp = src->vv.regoff * 4;
128
129                 M_ILD(tempreg, REG_SP, disp + 4);
130
131                 reg = tempreg;
132         }
133         else
134                 reg = GET_LOW_REG(src->vv.regoff);
135
136         return reg;
137 }
138
139
140 /* emit_load_high **************************************************************
141
142    Emits a possible load of the high 32-bits of an operand.
143
144 *******************************************************************************/
145
146 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
147 {
148         codegendata  *cd;
149         s4            disp;
150         s4            reg;
151
152         assert(src->type == TYPE_LNG);
153
154         /* get required compiler data */
155
156         cd = jd->cd;
157
158         if (IS_INMEMORY(src->flags)) {
159                 COUNT_SPILLS;
160
161                 disp = src->vv.regoff * 4;
162
163                 M_ILD(tempreg, REG_SP, disp);
164
165                 reg = tempreg;
166         }
167         else
168                 reg = GET_HIGH_REG(src->vv.regoff);
169
170         return reg;
171 }
172
173
174 /* emit_store ******************************************************************
175
176    Emit a possible store for the given variable.
177
178 *******************************************************************************/
179
180 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
181 {
182         codegendata *cd;
183         s4           disp;
184
185         /* get required compiler data */
186
187         cd = jd->cd;
188
189         if (IS_INMEMORY(dst->flags)) {
190                 COUNT_SPILLS;
191
192                 disp = dst->vv.regoff * 4;
193
194                 switch (dst->type) {
195                 case TYPE_INT:
196                 case TYPE_ADR:
197                         M_IST(d, REG_SP, disp);
198                         break;
199                 case TYPE_LNG:
200                         M_LST(d, REG_SP, disp);
201                         break;
202                 case TYPE_FLT:
203                         M_FST(d, REG_SP, disp);
204                         break;
205                 case TYPE_DBL:
206                         M_DST(d, REG_SP, disp);
207                         break;
208                 default:
209                         vm_abort("emit_store: unknown type %d", dst->type);
210                 }
211         }
212 }
213
214
215 /* emit_copy *******************************************************************
216
217    Generates a register/memory to register/memory copy.
218
219 *******************************************************************************/
220
221 void emit_copy(jitdata *jd, instruction *iptr)
222 {
223         codegendata *cd;
224         varinfo     *src;
225         varinfo     *dst;
226         s4           s1, d;
227
228         /* get required compiler data */
229
230         cd = jd->cd;
231
232         /* get source and destination variables */
233
234         src = VAROP(iptr->s1);
235         dst = VAROP(iptr->dst);
236
237         if ((src->vv.regoff != dst->vv.regoff) ||
238                 (IS_INMEMORY(src->flags ^ dst->flags))) {
239
240                 if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
241                         /* emit nothing, as the value won't be used anyway */
242                         return;
243                 }
244
245                 /* If one of the variables resides in memory, we can eliminate
246                    the register move from/to the temporary register with the
247                    order of getting the destination register and the load. */
248
249                 if (IS_INMEMORY(src->flags)) {
250                         if (IS_LNG_TYPE(src->type))
251                                 d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
252                         else
253                                 d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
254
255                         s1 = emit_load(jd, iptr, src, d);
256                 }
257                 else {
258                         if (IS_LNG_TYPE(src->type))
259                                 s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
260                         else
261                                 s1 = emit_load(jd, iptr, src, REG_IFTMP);
262
263                         d = codegen_reg_of_var(iptr->opc, dst, s1);
264                 }
265
266                 if (s1 != d) {
267                         switch (src->type) {
268                         case TYPE_INT:
269                         case TYPE_ADR:
270                                 M_MOV(s1, d);
271                                 break;
272                         case TYPE_LNG:
273                                 M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
274                                 M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d));
275                                 break;
276                         case TYPE_FLT:
277                         case TYPE_DBL:
278                                 M_FMOV(s1, d);
279                                 break;
280                         default:
281                                 vm_abort("emit_copy: unknown type %d", src->type);
282                         }
283                 }
284
285                 emit_store(jd, iptr, dst, d);
286         }
287 }
288
289
290 /* emit_iconst *****************************************************************
291
292    XXX
293
294 *******************************************************************************/
295
296 void emit_iconst(codegendata *cd, s4 d, s4 value)
297 {
298         s4 disp;
299
300         if ((value >= -32768) && (value <= 32767))
301                 M_LDA_INTERN(d, REG_ZERO, value);
302         else {
303                 disp = dseg_add_s4(cd, value);
304                 M_ILD(d, REG_PV, disp);
305         }
306 }
307
308
309 /* emit_branch *****************************************************************
310
311    Emits the code for conditional and unconditional branchs.
312
313 *******************************************************************************/
314
315 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt)
316 {
317         s4 checkdisp;
318         s4 branchdisp;
319
320         /* calculate the different displacements */
321
322         checkdisp  =  disp + 4;
323         branchdisp = (disp - 4) >> 2;
324
325         /* check which branch to generate */
326
327         if (condition == BRANCH_UNCONDITIONAL) {
328                 /* check displacement for overflow */
329
330                 if ((checkdisp < (s4) 0xfe000000) || (checkdisp > (s4) 0x01fffffc)) {
331                         /* if the long-branches flag isn't set yet, do it */
332
333                         if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
334                                 cd->flags |= (CODEGENDATA_FLAG_ERROR |
335                                                           CODEGENDATA_FLAG_LONGBRANCHES);
336                         }
337
338                         vm_abort("emit_branch: emit unconditional long-branch code");
339                 }
340                 else {
341                         M_BR(branchdisp);
342                 }
343         }
344         else {
345                 /* and displacement for overflow */
346
347                 if ((checkdisp < (s4) 0xffff8000) || (checkdisp > (s4) 0x00007fff)) {
348                         /* if the long-branches flag isn't set yet, do it */
349
350                         if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
351                                 cd->flags |= (CODEGENDATA_FLAG_ERROR |
352                                                           CODEGENDATA_FLAG_LONGBRANCHES);
353                         }
354
355                         switch (condition) {
356                         case BRANCH_EQ:
357                                 M_BNE(1);
358                                 M_BR(branchdisp);
359                                 break;
360                         case BRANCH_NE:
361                                 M_BEQ(1);
362                                 M_BR(branchdisp);
363                                 break;
364                         case BRANCH_LT:
365                                 M_BGE(1);
366                                 M_BR(branchdisp);
367                                 break;
368                         case BRANCH_GE:
369                                 M_BLT(1);
370                                 M_BR(branchdisp);
371                                 break;
372                         case BRANCH_GT:
373                                 M_BLE(1);
374                                 M_BR(branchdisp);
375                                 break;
376                         case BRANCH_LE:
377                                 M_BGT(1);
378                                 M_BR(branchdisp);
379                                 break;
380                         case BRANCH_NAN:
381                                 vm_abort("emit_branch: long BRANCH_NAN");
382                                 break;
383                         default:
384                                 vm_abort("emit_branch: unknown condition %d", condition);
385                         }
386                 }
387                 else {
388                         switch (condition) {
389                         case BRANCH_EQ:
390                                 M_BEQ(branchdisp);
391                                 break;
392                         case BRANCH_NE:
393                                 M_BNE(branchdisp);
394                                 break;
395                         case BRANCH_LT:
396                                 M_BLT(branchdisp);
397                                 break;
398                         case BRANCH_GE:
399                                 M_BGE(branchdisp);
400                                 break;
401                         case BRANCH_GT:
402                                 M_BGT(branchdisp);
403                                 break;
404                         case BRANCH_LE:
405                                 M_BLE(branchdisp);
406                                 break;
407                         case BRANCH_NAN:
408                                 M_BNAN(branchdisp);
409                                 break;
410                         default:
411                                 vm_abort("emit_branch: unknown condition %d", condition);
412                         }
413                 }
414         }
415 }
416
417
418 /* emit_arithmetic_check *******************************************************
419
420    Emit an ArithmeticException check.
421
422 *******************************************************************************/
423
424 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
425 {
426         if (INSTRUCTION_MUST_CHECK(iptr)) {
427                 M_TST(reg);
428                 M_BNE(1);
429                 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
430         }
431 }
432
433
434 /* emit_arrayindexoutofbounds_check ********************************************
435
436    Emit a ArrayIndexOutOfBoundsException check.
437
438 *******************************************************************************/
439
440 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
441 {
442         if (INSTRUCTION_MUST_CHECK(iptr)) {
443                 M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
444                 M_TRAPGEU(s2, REG_ITMP3);
445         }
446 }
447
448
449 /* emit_classcast_check ********************************************************
450
451    Emit a ClassCastException check.
452
453 *******************************************************************************/
454
455 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
456 {
457         if (INSTRUCTION_MUST_CHECK(iptr)) {
458                 switch (condition) {
459                 case BRANCH_LE:
460                         M_BGT(1);
461                         break;
462                 case BRANCH_EQ:
463                         M_BNE(1);
464                         break;
465                 case BRANCH_GT:
466                         M_BLE(1);
467                         break;
468                 default:
469                         vm_abort("emit_classcast_check: unknown condition %d", condition);
470                 }
471                 M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
472         }
473 }
474
475
476 /* emit_nullpointer_check ******************************************************
477
478    Emit a NullPointerException check.
479
480 *******************************************************************************/
481
482 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
483 {
484         if (INSTRUCTION_MUST_CHECK(iptr)) {
485                 M_TST(reg);
486                 M_BNE(1);
487                 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
488         }
489 }
490
491
492 /* emit_exception_check ********************************************************
493
494    Emit an Exception check.
495
496 *******************************************************************************/
497
498 void emit_exception_check(codegendata *cd, instruction *iptr)
499 {
500         if (INSTRUCTION_MUST_CHECK(iptr)) {
501                 M_TST(REG_RESULT);
502                 M_BNE(1);
503                 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
504         }
505 }
506
507
508 /* emit_patcher_stubs **********************************************************
509
510    Generates the code for the patcher stubs.
511
512 *******************************************************************************/
513
514 void emit_patcher_stubs(jitdata *jd)
515 {
516         codegendata *cd;
517         patchref    *pref;
518         u4           mcode;
519         u1          *savedmcodeptr;
520         u1          *tmpmcodeptr;
521         s4           targetdisp;
522         s4           disp;
523
524         /* get required compiler data */
525
526         cd = jd->cd;
527
528         /* generate code patching stub call code */
529
530         targetdisp = 0;
531
532         for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
533                 /* check code segment size */
534
535                 MCODECHECK(100);
536
537                 /* Get machine code which is patched back in later. The
538                    call is 1 instruction word long. */
539
540                 tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
541
542                 mcode = *((u4 *) tmpmcodeptr);
543
544                 /* Patch in the call to call the following code (done at
545                    compile time). */
546
547                 savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
548                 cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
549
550                 disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
551                 M_BR(disp);
552
553                 cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
554
555                 /* create stack frame - keep stack 16-byte aligned */
556
557                 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
558
559                 /* calculate return address and move it onto the stack */
560
561                 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
562                 M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 4);
563
564                 /* move pointer to java_objectheader onto stack */
565
566 #if defined(ENABLE_THREADS)
567                 /* order reversed because of data segment layout */
568
569                 (void) dseg_add_unique_address(cd, NULL);                  /* flcword */
570                 (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
571                 disp = dseg_add_unique_address(cd, NULL);                  /* vftbl   */
572
573                 M_LDA(REG_ITMP3, REG_PV, disp);
574                 M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 4);
575 #else
576                 /* do nothing */
577 #endif
578
579                 /* move machine code onto stack */
580
581                 disp = dseg_add_s4(cd, mcode);
582                 M_ILD(REG_ITMP3, REG_PV, disp);
583                 M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 4);
584
585                 /* move class/method/field reference onto stack */
586
587                 disp = dseg_add_address(cd, pref->ref);
588                 M_ALD(REG_ITMP3, REG_PV, disp);
589                 M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 4);
590
591                 /* move data segment displacement onto stack */
592
593                 disp = dseg_add_s4(cd, pref->disp);
594                 M_ILD(REG_ITMP3, REG_PV, disp);
595                 M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 4);
596
597                 /* move patcher function pointer onto stack */
598
599                 disp = dseg_add_functionptr(cd, pref->patcher);
600                 M_ALD(REG_ITMP3, REG_PV, disp);
601                 M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
602
603                 if (targetdisp == 0) {
604                         targetdisp = ((u4 *) cd->mcodeptr) - ((u4 *) cd->mcodebase);
605
606                         disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
607                         M_ALD(REG_ITMP3, REG_PV, disp);
608                         M_MTCTR(REG_ITMP3);
609                         M_RTS;
610                 }
611                 else {
612                         disp = (((u4 *) cd->mcodebase) + targetdisp) -
613                                 (((u4 *) cd->mcodeptr) + 1);
614                         M_BR(disp);
615                 }
616         }
617 }
618
619
620 /* emit_replacement_stubs ******************************************************
621
622    Generates the code for the replacement stubs.
623
624 *******************************************************************************/
625
626 #if defined(ENABLE_REPLACEMENT)
627 void emit_replacement_stubs(jitdata *jd)
628 {
629         codegendata *cd;
630         codeinfo    *code;
631         rplpoint    *rplp;
632         s4           disp;
633         s4           i;
634 #if !defined(NDEBUG)
635         u1          *savedmcodeptr;
636 #endif
637
638         /* get required compiler data */
639
640         cd   = jd->cd;
641         code = jd->code;
642
643         rplp = code->rplpoints;
644
645         /* store beginning of replacement stubs */
646
647         code->replacementstubs = (u1*) (cd->mcodeptr - cd->mcodebase);
648
649         for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
650                 /* do not generate stubs for non-trappable points */
651
652                 if (rplp->flags & RPLPOINT_FLAG_NOTRAP)
653                         continue;
654
655                 /* check code segment size */
656
657                 MCODECHECK(100);
658
659 #if !defined(NDEBUG)
660                 savedmcodeptr = cd->mcodeptr;
661 #endif
662
663                 /* create stack frame - keep 16-byte aligned */
664
665                 M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
666
667                 /* push address of `rplpoint` struct */
668
669                 disp = dseg_add_address(cd, rplp);
670                 M_ALD(REG_ITMP3, REG_PV, disp);
671                 M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
672
673                 /* jump to replacement function */
674
675                 disp = dseg_add_functionptr(cd, asm_replacement_out);
676                 M_ALD(REG_ITMP3, REG_PV, disp);
677                 M_MTCTR(REG_ITMP3);
678                 M_RTS;
679
680                 assert((cd->mcodeptr - savedmcodeptr) == 4*REPLACEMENT_STUB_SIZE);
681         }
682 }
683 #endif /* defined(ENABLE_REPLACEMENT) */
684
685
686 /* emit_verbosecall_enter ******************************************************
687
688    Generates the code for the call trace.
689
690 *******************************************************************************/
691
692 void emit_verbosecall_enter(jitdata *jd)
693 {
694 #if !defined(NDEBUG)
695         methodinfo   *m;
696         codegendata  *cd;
697         registerdata *rd;
698         s4 s1, p, t, d;
699         int stack_off;
700         int stack_size;
701         methoddesc *md;
702
703         if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
704                 return;
705
706         /* get required compiler data */
707
708         m  = jd->m;
709         cd = jd->cd;
710         rd = jd->rd;
711
712         md = m->parseddesc;
713         
714         /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
715         /* For Darwin:                                                        */
716         /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR                      */
717         /* LA_SIZE(=6*4) + 8*8         + 4          + 4  + 0(Padding)         */
718         /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16                            */
719         /* For Linux:                                                         */
720         /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo         */
721         /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
722         /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8                          */
723         /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16                */
724         
725         /* in nativestubs no Place to save the LR (Link Register) would be needed */
726         /* but since the stack frame has to be aligned the 4 Bytes would have to  */
727         /* be padded again */
728
729 #if defined(__DARWIN__)
730         stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
731 #else
732         stack_size = 6 * 16;
733 #endif
734
735         /* mark trace code */
736
737         M_NOP;
738
739         M_MFLR(REG_ZERO);
740         M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
741         M_STWU(REG_SP, REG_SP, -stack_size);
742
743         M_CLR(REG_ITMP1);    /* clear help register */
744
745         /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
746 #if defined(__DARWIN__)
747         /* Copy Params starting from first to Stack                          */
748         /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs    */ 
749         /* are saved                                                         */
750         p = 0;
751 #else
752         /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in   */
753         /* integer argument regs                                             */
754         /* all integer argument registers have to be saved                   */
755         for (p = 0; p < 8; p++) {
756                 d = abi_registers_integer_argument[p];
757                 /* save integer argument registers */
758                 M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
759         }
760         p = 4;
761 #endif
762         stack_off = LA_SIZE;
763
764         for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
765                 t = md->paramtypes[p].type;
766
767                 if (IS_INT_LNG_TYPE(t)) {
768                         if (!md->params[p].inmemory) {
769                                 s1 = md->params[p].regoff;
770
771                                 if (IS_2_WORD_TYPE(t)) {
772                                         M_IST(GET_HIGH_REG(s1), REG_SP, stack_off);
773                                         M_IST(GET_LOW_REG(s1), REG_SP, stack_off + 4);
774                                 }
775                                 else {
776                                         M_IST(REG_ITMP1, REG_SP, stack_off);
777                                         M_IST(s1, REG_SP, stack_off + 4);
778                                 }
779                         }
780                         else {
781                                 s1 = (md->params[p].regoff + cd->stackframesize) * 4 
782                                         + stack_size;
783                                 if (IS_2_WORD_TYPE(t)) {
784                                         M_ILD(REG_ITMP2, REG_SP, s1);
785                                         M_IST(REG_ITMP2, REG_SP, stack_off);
786                                         M_ILD(REG_ITMP2, REG_SP, s1 + 4);
787                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
788                                 }
789                                 else {
790                                         M_IST(REG_ITMP1, REG_SP, stack_off);
791                                         M_ILD(REG_ITMP2, REG_SP, s1);
792                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
793                                 }
794                         }
795                 }
796                 else {
797                         if (!md->params[p].inmemory) {
798                                 s1 = md->params[p].regoff;
799
800                                 if (!IS_2_WORD_TYPE(t)) {
801                                         M_IST(REG_ITMP1, REG_SP, stack_off);
802                                         M_FST(s1, REG_SP, stack_off + 4);
803                                 }
804                                 else
805                                         M_DST(s1, REG_SP, stack_off);
806                         }
807                         else {
808                                 /* this should not happen */
809                         }
810                 }
811         }
812
813         /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
814 #if defined(__DARWIN__)
815         for (p = 0; p < 8; p++) {
816                 d = abi_registers_integer_argument[p];
817                 M_ILD(d, REG_SP, LA_SIZE + p * 4);
818         }
819 #else
820         /* LINUX */
821         /* Set integer and float argument registers vor trace_args call */
822         /* offset to saved integer argument registers                   */
823
824         stack_off = LA_SIZE + 4 * 8 + 4;
825
826         for (p = 0; (p < 4) && (p < md->paramcount); p++) {
827                 t = md->paramtypes[p].type;
828
829                 if (IS_INT_LNG_TYPE(t)) {
830                         /* "stretch" int types */
831                         if (!IS_2_WORD_TYPE(t)) {
832                                 M_CLR(abi_registers_integer_argument[2 * p]);
833                                 M_ILD(abi_registers_integer_argument[2 * p + 1], REG_SP,stack_off);
834                                 stack_off += 4;
835                         }
836                         else {
837                                 M_ILD(abi_registers_integer_argument[2 * p + 1], REG_SP,stack_off + 4);
838                                 M_ILD(abi_registers_integer_argument[2 * p], REG_SP,stack_off);
839                                 stack_off += 8;
840                         }
841                 }
842                 else {
843                         if (!md->params[p].inmemory) {
844                                 /* use reserved Place on Stack (sp + 5 * 16) to copy  */
845                                 /* float/double arg reg to int reg                    */
846
847                                 s1 = md->params[p].regoff;
848
849                                 if (!IS_2_WORD_TYPE(t)) {
850                                         M_FST(s1, REG_SP, 5 * 16);
851                                         M_ILD(abi_registers_integer_argument[2 * p + 1], REG_SP, 5 * 16);
852                                         M_CLR(abi_registers_integer_argument[2 * p]);
853                                 }
854                                 else {
855                                         M_DST(s1, REG_SP, 5 * 16);
856                                         M_ILD(abi_registers_integer_argument[2 * p + 1], REG_SP,  5 * 16 + 4);
857                                         M_ILD(abi_registers_integer_argument[2 * p], REG_SP, 5 * 16);
858                                 }
859                         }
860                 }
861         }
862 #endif
863
864         /* put methodinfo pointer on Stackframe */
865         p = dseg_add_address(cd, m);
866         M_ALD(REG_ITMP1, REG_PV, p);
867 #if defined(__DARWIN__)
868         M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8); 
869 #else
870         M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
871 #endif
872         p = dseg_add_functionptr(cd, builtin_verbosecall_enter);
873         M_ALD(REG_ITMP2, REG_PV, p);
874         M_MTCTR(REG_ITMP2);
875         M_JSR;
876
877 #if defined(__DARWIN__)
878         /* restore integer argument registers from the reserved stack space */
879
880         stack_off = LA_SIZE;
881
882         for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
883                 t = md->paramtypes[p].type;
884
885                 if (IS_INT_LNG_TYPE(t)) {
886                         if (!md->params[p].inmemory) {
887                                 s1 = md->params[p].regoff;
888
889                                 if (IS_2_WORD_TYPE(t)) {
890                                         M_ILD(GET_HIGH_REG(s1), REG_SP, stack_off);
891                                         M_ILD(GET_LOW_REG(s1), REG_SP, stack_off + 4);
892                                 }
893                                 else
894                                         M_ILD(s1, REG_SP, stack_off + 4);
895                         }
896                 }
897         }
898 #else
899         /* LINUX */
900         for (p = 0; p < 8; p++) {
901                 d = abi_registers_integer_argument[p];
902                 /* save integer argument registers */
903                 M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
904         }
905 #endif
906
907         M_ALD(REG_ZERO, REG_SP, stack_size + LA_LR_OFFSET);
908         M_MTLR(REG_ZERO);
909         M_LDA(REG_SP, REG_SP, stack_size);
910
911         /* mark trace code */
912
913         M_NOP;
914 #endif /* !defined(NDEBUG) */
915 }
916
917
918 /* emit_verbosecall_exit *******************************************************
919
920    Generates the code for the call trace.
921
922    void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
923
924 *******************************************************************************/
925
926 void emit_verbosecall_exit(jitdata *jd)
927 {
928 #if !defined(NDEBUG)
929         methodinfo   *m;
930         codegendata  *cd;
931         registerdata *rd;
932         methoddesc   *md;
933         s4            disp;
934
935         if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
936                 return;
937
938         /* get required compiler data */
939
940         m  = jd->m;
941         cd = jd->cd;
942         rd = jd->rd;
943
944         md = m->parseddesc;
945         
946         /* mark trace code */
947
948         M_NOP;
949
950         M_MFLR(REG_ZERO);
951         M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
952         M_STWU(REG_SP, REG_SP, -(LA_SIZE + (1 + 2 + 2 + 1 + 4) * 4));
953
954         /* save return registers */
955
956         M_LST(REG_RESULT_PACKED, REG_SP, LA_SIZE + (1 + 2 + 2 + 1 + 0) * 4);
957         M_DST(REG_FRESULT, REG_SP, LA_SIZE + (1 + 2 + 2 + 1 + 2) * 4);
958
959         /* keep this order */
960         switch (md->returntype.type) {
961         case TYPE_INT:
962         case TYPE_ADR:
963                 M_INTMOVE(REG_RESULT, REG_A1);
964                 M_CLR(REG_A0);
965                 break;
966
967         case TYPE_LNG:
968                 M_LNGMOVE(REG_RESULT_PACKED, REG_A0_A1_PACKED);
969                 break;
970         }
971
972         M_FLTMOVE(REG_FRESULT, REG_FA0);
973         M_FLTMOVE(REG_FRESULT, REG_FA1);
974
975         disp = dseg_add_address(cd, m);
976         M_ALD(REG_A2, REG_PV, disp);
977
978         disp = dseg_add_functionptr(cd, builtin_verbosecall_exit);
979         M_ALD(REG_ITMP2, REG_PV, disp);
980         M_MTCTR(REG_ITMP2);
981         M_JSR;
982
983         /* restore return registers */
984
985         M_LLD(REG_RESULT_PACKED, REG_SP, LA_SIZE + (1 + 2 + 2 + 1 + 0) * 4);
986         M_DLD(REG_FRESULT, REG_SP, LA_SIZE + (1 + 2 + 2 + 1 + 2) * 4);
987
988         M_ALD(REG_ZERO, REG_SP, LA_SIZE + (1 + 2 + 2 + 1 + 4) * 4 + LA_LR_OFFSET);
989         M_MTLR(REG_ZERO);
990         M_LDA(REG_SP, REG_SP, LA_SIZE + (1 + 2 + 2 + 1 + 4) * 4);
991
992         /* mark trace code */
993
994         M_NOP;
995 #endif /* !defined(NDEBUG) */
996 }
997
998
999 /*
1000  * These are local overrides for various environment variables in Emacs.
1001  * Please do not remove this and leave it at the end of the file, where
1002  * Emacs will automagically detect them.
1003  * ---------------------------------------------------------------------
1004  * Local variables:
1005  * mode: c
1006  * indent-tabs-mode: t
1007  * c-basic-offset: 4
1008  * tab-width: 4
1009  * End:
1010  * vim:noexpandtab:sw=4:ts=4:
1011  */