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