fd8ca4a1a8a7426e226b289dd37b042b25cad6d0
[cacao.git] / src / vm / jit / powerpc64 / emit.c
1 /* src/vm/jit/powerpc64/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/emit.h"
45 #include "vm/jit/jit.h"
46 #include "vm/jit/powerpc64/codegen.h"
47 #include "vm/builtin.h"
48
49
50 /* code generation functions **************************************************/
51
52 /* emit_load_s1 ****************************************************************
53
54    Emits a possible load of the first source operand.
55
56 *******************************************************************************/
57
58 s4 emit_load_s1(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
59 {
60         codegendata  *cd;
61         s4            disp;
62         s4            reg;
63
64         /* get required compiler data */
65
66         cd = jd->cd;
67
68         if (src->flags & INMEMORY) {
69                 COUNT_SPILLS;
70
71                 disp = src->regoff * 4;
72
73                 if (IS_FLT_DBL_TYPE(src->type)) {
74                         if (IS_2_WORD_TYPE(src->type))
75                                 M_DLD(tempreg, REG_SP, disp);
76                         else
77                                 M_FLD(tempreg, REG_SP, disp);
78
79                 } else {
80                         if (IS_2_WORD_TYPE(src->type))
81                                 M_LLD(tempreg, REG_SP, disp);
82                         else
83                                 M_ILD(tempreg, REG_SP, disp);
84                 }
85
86                 reg = tempreg;
87         } else
88                 reg = src->regoff;
89
90         return reg;
91 }
92
93
94 /* emit_load_s2 ****************************************************************
95
96    Emits a possible load of the second source operand.
97
98 *******************************************************************************/
99
100 s4 emit_load_s2(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
101 {
102         codegendata  *cd;
103         s4            disp;
104         s4            reg;
105
106         /* get required compiler data */
107
108         cd = jd->cd;
109
110         if (src->flags & INMEMORY) {
111                 COUNT_SPILLS;
112
113                 disp = src->regoff * 4;
114
115                 if (IS_FLT_DBL_TYPE(src->type)) {
116                         if (IS_2_WORD_TYPE(src->type))
117                                 M_DLD(tempreg, REG_SP, disp);
118                         else
119                                 M_FLD(tempreg, REG_SP, disp);
120
121                 } else {
122                         if (IS_2_WORD_TYPE(src->type))
123                                 M_LLD(tempreg, REG_SP, disp);
124                         else
125                                 M_ILD(tempreg, REG_SP, disp);
126                 }
127
128                 reg = tempreg;
129         } else
130                 reg = src->regoff;
131
132         return reg;
133 }
134
135
136 /* emit_load_s3 ****************************************************************
137
138    Emits a possible load of the third source operand.
139
140 *******************************************************************************/
141
142 s4 emit_load_s3(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
143 {
144         codegendata  *cd;
145         s4            disp;
146         s4            reg;
147
148         /* get required compiler data */
149
150         cd = jd->cd;
151
152         if (src->flags & INMEMORY) {
153                 COUNT_SPILLS;
154
155                 disp = src->regoff * 4;
156
157                 if (IS_FLT_DBL_TYPE(src->type)) {
158                         if (IS_2_WORD_TYPE(src->type))
159                                 M_DLD(tempreg, REG_SP, disp);
160                         else
161                                 M_FLD(tempreg, REG_SP, disp);
162
163                 } else {
164                         if (IS_2_WORD_TYPE(src->type))
165                                 M_LLD(tempreg, REG_SP, disp);
166                         else
167                                 M_ILD(tempreg, REG_SP, disp);
168                 }
169
170                 reg = tempreg;
171         } else
172                 reg = src->regoff;
173
174         return reg;
175 }
176
177
178 /* emit_load_s1_low ************************************************************
179
180    Emits a possible load of the low 32-bits of the first long source
181    operand.
182
183 *******************************************************************************/
184
185 s4 emit_load_s1_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
186 {
187         codegendata  *cd;
188         s4            disp;
189         s4            reg;
190
191         assert(src->type == TYPE_LNG);
192
193         /* get required compiler data */
194
195         cd = jd->cd;
196
197         if (src->flags & INMEMORY) {
198                 COUNT_SPILLS;
199
200                 disp = src->regoff * 4;
201
202                 M_ILD(tempreg, REG_SP, disp + 4);
203
204                 reg = tempreg;
205         } else
206                 reg = GET_LOW_REG(src->regoff);
207
208         return reg;
209 }
210
211
212 /* emit_load_s2_low ************************************************************
213
214    Emits a possible load of the low 32-bits of the second long source
215    operand.
216
217 *******************************************************************************/
218
219 s4 emit_load_s2_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
220 {
221         codegendata  *cd;
222         s4            disp;
223         s4            reg;
224
225         assert(src->type == TYPE_LNG);
226
227         /* get required compiler data */
228
229         cd = jd->cd;
230
231         if (src->flags & INMEMORY) {
232                 COUNT_SPILLS;
233
234                 disp = src->regoff * 4;
235
236                 M_ILD(tempreg, REG_SP, disp + 4);
237
238                 reg = tempreg;
239         } else
240                 reg = GET_LOW_REG(src->regoff);
241
242         return reg;
243 }
244
245
246 /* emit_load_s3_low ************************************************************
247
248    Emits a possible load of the low 32-bits of the third long source
249    operand.
250
251 *******************************************************************************/
252
253 s4 emit_load_s3_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
254 {
255         codegendata  *cd;
256         s4            disp;
257         s4            reg;
258
259         assert(src->type == TYPE_LNG);
260
261         /* get required compiler data */
262
263         cd = jd->cd;
264
265         if (src->flags & INMEMORY) {
266                 COUNT_SPILLS;
267
268                 disp = src->regoff * 4;
269
270                 M_ILD(tempreg, REG_SP, disp + 4);
271
272                 reg = tempreg;
273         } else
274                 reg = GET_LOW_REG(src->regoff);
275
276         return reg;
277 }
278
279
280 /* emit_load_s1_high ***********************************************************
281
282    Emits a possible load of the high 32-bits of the first long source
283    operand.
284
285 *******************************************************************************/
286
287 s4 emit_load_s1_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
288 {
289         codegendata  *cd;
290         s4            disp;
291         s4            reg;
292
293         assert(src->type == TYPE_LNG);
294
295         /* get required compiler data */
296
297         cd = jd->cd;
298
299         if (src->flags & INMEMORY) {
300                 COUNT_SPILLS;
301
302                 disp = src->regoff * 4;
303
304                 M_ILD(tempreg, REG_SP, disp);
305
306                 reg = tempreg;
307         } else
308                 reg = GET_HIGH_REG(src->regoff);
309
310         return reg;
311 }
312
313
314 /* emit_load_s2_high ***********************************************************
315
316    Emits a possible load of the high 32-bits of the second long source
317    operand.
318
319 *******************************************************************************/
320
321 s4 emit_load_s2_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
322 {
323         codegendata  *cd;
324         s4            disp;
325         s4            reg;
326
327         assert(src->type == TYPE_LNG);
328
329         /* get required compiler data */
330
331         cd = jd->cd;
332
333         if (src->flags & INMEMORY) {
334                 COUNT_SPILLS;
335
336                 disp = src->regoff * 4;
337
338                 M_ILD(tempreg, REG_SP, disp);
339
340                 reg = tempreg;
341         } else
342                 reg = GET_HIGH_REG(src->regoff);
343
344         return reg;
345 }
346
347
348 /* emit_load_s3_high ***********************************************************
349
350    Emits a possible load of the high 32-bits of the third long source
351    operand.
352
353 *******************************************************************************/
354
355 s4 emit_load_s3_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
356 {
357         codegendata  *cd;
358         s4            disp;
359         s4            reg;
360
361         assert(src->type == TYPE_LNG);
362
363         /* get required compiler data */
364
365         cd = jd->cd;
366
367         if (src->flags & INMEMORY) {
368                 COUNT_SPILLS;
369
370                 disp = src->regoff * 4;
371
372                 M_ILD(tempreg, REG_SP, disp);
373
374                 reg = tempreg;
375         } else
376                 reg = GET_HIGH_REG(src->regoff);
377
378         return reg;
379 }
380
381
382 /* emit_store ******************************************************************
383
384    XXX
385
386 *******************************************************************************/
387
388 void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
389 {
390         codegendata  *cd;
391
392         /* get required compiler data */
393
394         cd = jd->cd;
395
396         if (dst->flags & INMEMORY) {
397                 COUNT_SPILLS;
398
399                 if (IS_FLT_DBL_TYPE(dst->type)) {
400                         if (IS_2_WORD_TYPE(dst->type))
401                                 M_DST(d, REG_SP, dst->regoff * 4);
402                         else
403                                 M_FST(d, REG_SP, dst->regoff * 4);
404
405                 } else {
406                         if (IS_2_WORD_TYPE(dst->type))
407                                 M_LST(d, REG_SP, dst->regoff * 4);
408                         else
409                                 M_IST(d, REG_SP, dst->regoff * 4);
410                 }
411         }
412 }
413
414
415 /* emit_copy *******************************************************************
416
417    XXX
418
419 *******************************************************************************/
420
421 void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
422 {
423         codegendata  *cd;
424         registerdata *rd;
425         s4            s1, d;
426
427         /* get required compiler data */
428
429         cd = jd->cd;
430         rd = jd->rd;
431
432         if (src->type == TYPE_LNG)
433                 d = codegen_reg_of_var(rd, iptr->opc, dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
434         else
435                 d = codegen_reg_of_var(rd, iptr->opc, dst, REG_IFTMP);
436
437         if ((src->regoff != dst->regoff) ||
438                 ((src->flags ^ dst->flags) & INMEMORY)) {
439                 s1 = emit_load_s1(jd, iptr, src, d);
440
441                 if (s1 != d) {
442                         if (IS_FLT_DBL_TYPE(src->type))
443                                 M_FMOV(s1, d);
444                         else {
445                                 if (IS_2_WORD_TYPE(src->type)) {
446                                         M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
447                                         M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d));
448                 } else
449                     M_MOV(s1, d);
450                         }
451                 }
452
453                 emit_store(jd, iptr, dst, d);
454         }
455 }
456
457
458 /* emit_iconst *****************************************************************
459
460    XXX
461
462 *******************************************************************************/
463
464 void emit_iconst(codegendata *cd, s4 d, s4 value)
465 {
466         s4 disp;
467
468         if ((value >= -32768) && (value <= 32767))
469                 M_LDA_INTERN(d, REG_ZERO, value);
470         else {
471                 disp = dseg_adds4(cd, value);
472                 M_ILD(d, REG_PV, disp);
473         }
474 }
475
476 /* emit_verbosecall_enter ******************************************************
477  *
478  *    Generates the code for the call trace.
479  *
480  ********************************************************************************/
481 void emit_verbosecall_enter (jitdata *jd)
482 {
483         methodinfo   *m;
484         codegendata  *cd;
485         registerdata *rd;
486         s4 s1, p, t, d;
487 /*      int stack_off; */
488         int stack_size;
489         methoddesc *md;
490
491         /* get required compiler data */
492
493         m  = jd->m;
494         cd = jd->cd;
495         rd = jd->rd;
496
497         md = m->parseddesc;
498         
499         /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
500         /* For Darwin:                                                        */
501         /* TODO                                                               */
502         /* For Linux:                                                         */
503         /* setup stack for TRACE_ARGS_NUM registers                           */
504         /* == LA_SIZE + PA_SIZE + 8 (methodinfo argument) + TRACE_ARGS_NUM*8 + 8 (itmp1)              */
505         
506         /* in nativestubs no Place to save the LR (Link Register) would be needed */
507         /* but since the stack frame has to be aligned the 4 Bytes would have to  */
508         /* be padded again */
509
510 #if defined(__DARWIN__)
511         stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
512 #else
513         stack_size = LA_SIZE + PA_SIZE + 8 + TRACE_ARGS_NUM * 8 + 8;
514 #endif
515
516         /* mark trace code */
517         M_NOP;
518
519         /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
520 #if 0
521 #if defined(__DARWIN__)
522         /* Copy Params starting from first to Stack                          */
523         /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs    */ 
524         /* are saved                                                         */
525         p = 0;
526 #else
527         /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in   */
528         /* integer argument regs                                             */
529         /* all integer argument registers have to be saved                   */
530         for (p = 0; p < 8; p++) {
531                 d = rd->argintregs[p];
532                 /* save integer argument registers */
533                 M_LST(d, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + 8 + p * 8);
534         }
535         p = 4;
536 #endif
537 #endif
538         M_MFLR(REG_ZERO);
539         M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
540         M_STDU(REG_SP, REG_SP, -stack_size);
541
542         for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
543                 t = md->paramtypes[p].type;
544                 if (IS_INT_LNG_TYPE(t)) {
545                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
546                                 M_LST(rd->argintregs[md->params[p].regoff], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
547                         } else { /* Param on Stack */
548                                 s1 = (md->params[p].regoff + cd->stackframesize) * 8 + stack_size;
549                                 M_LLD(REG_ITMP2, REG_SP, s1);
550                                 M_LST(REG_ITMP2, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
551                         }
552                 } else { /* IS_FLT_DBL_TYPE(t) */
553                         if (!md->params[p].inmemory) { /* in Arg Reg */
554                                 s1 = rd->argfltregs[md->params[p].regoff];
555                                 M_DST(s1, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
556                         } else { /* on Stack */
557                                 /* this should not happen */
558                                 assert(0);
559                         }
560                 }
561         }
562
563         /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
564 #if defined(__DARWIN__)
565         for (p = 0; p < 8; p++) {
566                 d = rd->argintregs[p];
567                 M_ILD(d, REG_SP, LA_SIZE + p * 4);
568         }
569 #else
570         /* LINUX */
571         /* Set integer and float argument registers for trace_args call */
572         /* offset to saved integer argument registers                   */
573         for (p = 0; (p < TRACE_ARGS_NUM) && (p < md->paramcount); p++) {
574                 t = md->paramtypes[p].type;
575                 if (IS_INT_LNG_TYPE(t)) {
576                         M_LLD(rd->argintregs[p], REG_SP,LA_SIZE + PA_SIZE + 8 + p * 8);
577                 } else { /* Float/Dbl */
578                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
579                                 /* use reserved Place on Stack (sp + 5 * 16) to copy  */
580                                 /* float/double arg reg to int reg                    */
581                                 s1 = rd->argfltregs[md->params[p].regoff];
582                                 M_MOV(s1, rd->argintregs[p]);
583                         } else  {
584                                 assert(0);
585                         }
586                 }
587         }
588 #endif
589
590         /* put methodinfo pointer on Stackframe */
591         p = dseg_addaddress(cd, m);
592         M_ALD(REG_ITMP1, REG_PV, p);
593 #if defined(__DARWIN__)
594         M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8); 
595 #else
596         if (TRACE_ARGS_NUM == 8)        {
597                 /* need to pass via stack */
598                 M_AST(REG_ITMP1, REG_SP, LA_SIZE + PA_SIZE);
599         } else {
600                 /* pass via register, reg 3 is the first  */
601                 M_MOV(REG_ITMP1, 3 + TRACE_ARGS_NUM);
602         }
603 #endif
604         /* call via function descriptor */
605         /* XXX: what about TOC? */
606         p = dseg_addaddress(cd, builtin_trace_args);
607         M_ALD(REG_ITMP2, REG_PV, p);
608         M_ALD(REG_ITMP1, REG_ITMP2, 0);
609         M_MTCTR(REG_ITMP1);
610         M_JSR;
611
612 #if defined(__DARWIN__)
613         /* restore integer argument registers from the reserved stack space */
614
615         stack_off = LA_SIZE;
616         for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
617                 t = md->paramtypes[p].type;
618
619                 if (IS_INT_LNG_TYPE(t)) {
620                         if (!md->params[p].inmemory) {
621                                 M_LLD(rd->argintregs[md->params[p].regoff], REG_SP, stack_off);
622                         } else  {
623                                 assert(0);
624                         }
625                 }
626         }
627 #else
628         /* LINUX */
629         for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
630                 d = rd->argintregs[p];
631                 /* restore integer argument registers */
632                 M_LLD(d, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
633         }
634 #endif
635         M_ALD(REG_ZERO, REG_SP, stack_size + LA_LR_OFFSET);
636         M_MTLR(REG_ZERO);
637         M_LDA(REG_SP, REG_SP, stack_size);
638 }
639
640 /* emit_verbosecall_exit ******************************************************
641  *
642  *    Generates the code for the call trace.
643  *
644  ********************************************************************************/
645 void emit_verbosecall_exit(jitdata *jd)
646 {
647         codegendata *cd = jd->cd;
648         s4 disp;
649
650         M_MFLR(REG_ZERO);
651         M_LDA(REG_SP, REG_SP, -(LA_SIZE+PA_SIZE+10*8));
652         M_DST(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
653         M_LST(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
654         M_AST(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
655
656 #if defined(__DARWIN__)
657         M_MOV(REG_RESULT, jd->rd->argintregs[1]);
658 #else
659         M_MOV(REG_RESULT, jd->rd->argintregs[1]);
660 #endif
661
662         disp = dseg_addaddress(cd, jd->m);
663         M_ALD(jd->rd->argintregs[0], REG_PV, disp);
664
665         M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[0]);
666         M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[1]);
667         disp = dseg_addaddress(cd, builtin_displaymethodstop);
668         /* call via function descriptor, XXX: what about TOC ? */
669         M_ALD(REG_ITMP2, REG_PV, disp);
670         M_ALD(REG_ITMP2, REG_ITMP2, 0);
671         M_MTCTR(REG_ITMP2);
672         M_JSR;
673
674         M_DLD(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
675         M_LLD(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
676         M_ALD(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
677         M_LDA(REG_SP, REG_SP, LA_SIZE+PA_SIZE+10*8);
678         M_MTLR(REG_ZERO);
679 }
680
681
682
683 /*
684  * These are local overrides for various environment variables in Emacs.
685  * Please do not remove this and leave it at the end of the file, where
686  * Emacs will automagically detect them.
687  * ---------------------------------------------------------------------
688  * Local variables:
689  * mode: c
690  * indent-tabs-mode: t
691  * c-basic-offset: 4
692  * tab-width: 4
693  * End:
694  * vim:noexpandtab:sw=4:ts=4:
695  */