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