* src/threads/none/threads.h [!defined(NDEBUG)] (_no_threads_tracejavacallindent...
[cacao.git] / src / vm / jit / s390 / emit.c
1 /* src/vm/jit/s390/emit.c - s390 code emitter functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: emit.c 8304 2007-08-14 19:57:20Z pm $
26
27 */
28
29 #include "config.h"
30
31 #include <assert.h>
32 #include <stdint.h>
33
34 #include "mm/memory.h"
35 #if defined(ENABLE_THREADS)
36 # include "threads/native/lock.h"
37 #endif
38 #include "vm/builtin.h"
39 #include "vm/exceptions.h"
40 #include "vm/global.h"
41 #include "vm/jit/abi.h"
42 #include "vm/jit/abi-asm.h"
43 #include "vm/jit/asmpart.h"
44 #include "vm/jit/codegen-common.h"
45 #include "vm/jit/emit-common.h"
46 #include "vm/jit/jit.h"
47 #include "vm/jit/patcher-common.h"
48 #include "vm/jit/replace.h"
49 #include "vm/jit/s390/codegen.h"
50 #include "vm/jit/s390/emit.h"
51 #include "vm/jit/s390/md-abi.h"
52 #include "vm/types.h"
53 #include "vmcore/options.h"
54
55 /* emit_load *******************************************************************
56
57    Emits a possible load of an operand.
58
59 *******************************************************************************/
60
61 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
62 {
63         codegendata *cd;
64         s4           disp;
65         s4           reg;
66
67         /* get required compiler data */
68
69         cd = jd->cd;
70
71         if (IS_INMEMORY(src->flags)) {
72                 COUNT_SPILLS;
73
74                 disp = src->vv.regoff;
75
76                 if (IS_FLT_DBL_TYPE(src->type)) {
77                         if (IS_2_WORD_TYPE(src->type))
78                                 M_DLD(tempreg, REG_SP, disp);
79                         else
80                                 M_FLD(tempreg, REG_SP, disp);
81                 }
82                 else {
83                         if (IS_2_WORD_TYPE(src->type))
84                                 M_LLD(tempreg, REG_SP, disp);
85                         else
86                                 M_ILD(tempreg, REG_SP, disp);
87                 }
88
89                 reg = tempreg;
90         }
91         else
92                 reg = src->vv.regoff;
93
94         return reg;
95 }
96
97
98 /* emit_store ******************************************************************
99
100    This function generates the code to store the result of an
101    operation back into a spilled pseudo-variable.  If the
102    pseudo-variable has not been spilled in the first place, this
103    function will generate nothing.
104     
105 *******************************************************************************/
106
107 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
108 {
109         codegendata *cd;
110
111         /* get required compiler data */
112
113         cd = jd->cd;
114
115         if (IS_INMEMORY(dst->flags)) {
116                 COUNT_SPILLS;
117
118                 if (IS_FLT_DBL_TYPE(dst->type)) {
119                         if (IS_2_WORD_TYPE(dst->type))
120                                 M_DST(d, REG_SP, dst->vv.regoff);
121                         else
122                                 M_FST(d, REG_SP, dst->vv.regoff);
123                 }
124                 else {
125                         if (IS_2_WORD_TYPE(dst->type))
126                                 M_LST(d, REG_SP, dst->vv.regoff);
127                         else
128                                 M_IST(d, REG_SP, dst->vv.regoff);
129                 }
130         }
131 }
132
133
134 /* emit_copy *******************************************************************
135
136    Generates a register/memory to register/memory copy.
137
138 *******************************************************************************/
139
140 void emit_copy(jitdata *jd, instruction *iptr)
141 {
142         codegendata *cd;
143         varinfo     *src;
144         varinfo     *dst;
145         s4           s1, d;
146
147         /* get required compiler data */
148
149         cd = jd->cd;
150
151         /* get source and destination variables */
152
153         src = VAROP(iptr->s1);
154         dst = VAROP(iptr->dst);
155
156         if ((src->vv.regoff != dst->vv.regoff) ||
157                 ((src->flags ^ dst->flags) & INMEMORY)) {
158
159                 if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
160                         /* emit nothing, as the value won't be used anyway */
161                         return;
162                 }
163
164                 /* If one of the variables resides in memory, we can eliminate
165                    the register move from/to the temporary register with the
166                    order of getting the destination register and the load. */
167
168                 if (IS_INMEMORY(src->flags)) {
169                         if (IS_FLT_DBL_TYPE(dst->type)) {
170                                 d = codegen_reg_of_var(iptr->opc, dst, REG_FTMP1);
171                         } else {
172                                 if (IS_2_WORD_TYPE(dst->type)) {
173                                         d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
174                                 } else {
175                                         d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
176                                 }
177                         }
178                         s1 = emit_load(jd, iptr, src, d);
179                 }
180                 else {
181                         if (IS_FLT_DBL_TYPE(src->type)) {
182                                 s1 = emit_load(jd, iptr, src, REG_FTMP1);
183                         } else {
184                                 if (IS_2_WORD_TYPE(src->type)) {
185                                         s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
186                                 } else {
187                                         s1 = emit_load(jd, iptr, src, REG_ITMP1);
188                                 }
189                         }
190                         d = codegen_reg_of_var(iptr->opc, dst, s1);
191                 }
192
193                 if (s1 != d) {
194                         if (IS_FLT_DBL_TYPE(src->type)) {
195                                 M_FMOV(s1, d);
196                         } else {
197                                 if (IS_2_WORD_TYPE(src->type)) {
198                                         M_LNGMOVE(s1, d);
199                                 } else {
200                                         M_MOV(s1, d);
201                                 }
202                         }
203                 }
204
205                 emit_store(jd, iptr, dst, d);
206         }
207 }
208
209 /* emit_trap *******************************************************************
210
211    Emit a trap instruction and return the original machine code.
212
213 *******************************************************************************/
214
215 uint32_t emit_trap(codegendata *cd)
216 {
217         uint32_t mcode;
218
219         /* Get machine code which is patched back in later. The
220            trap is 2 bytes long. */
221
222         mcode = *((u2 *) cd->mcodeptr);
223
224         M_ILL(EXCEPTION_HARDWARE_PATCHER);
225
226         return mcode;
227 }
228
229
230 /* emit_verbosecall_enter ******************************************************
231
232    Generates the code for the call trace.
233
234 *******************************************************************************/
235
236 #if !defined(NDEBUG)
237 #include "vm/jit/trace.h"
238 void emit_verbosecall_enter(jitdata *jd)
239 {
240 #if 1
241         methodinfo   *m;
242         codegendata  *cd;
243         s4            stackframesize;
244         s4            i, off, disp;
245
246         m  = jd->m;
247         cd = jd->cd;
248
249         /* mark trace code */
250
251         M_NOP;
252
253         /* allocate stack frame */
254
255         stackframesize = 96 + (ARG_CNT * 8);
256         M_ASUB_IMM(stackframesize, REG_SP);
257
258         /* store argument registers in array */
259
260         off = 96;
261
262         for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
263                 M_IST(abi_registers_integer_argument[i], REG_SP, off + 4);
264                 /* high bytes are sign extension */
265                 M_SRA_IMM(31, abi_registers_integer_argument[i]);
266                 M_IST(abi_registers_integer_argument[i], REG_SP, off);
267         }
268
269         for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
270                 M_DST(abi_registers_float_argument[i], REG_SP, off);
271         }
272         
273         /* load arguments for trace_java_call_enter */
274
275         /* methodinfo */
276         disp = dseg_add_address(cd, m);
277         M_ALD_DSEG(REG_A0, disp);       
278         /* pointer to argument registers array */
279         M_LDA(REG_A1, REG_SP, 96);
280         /* pointer to on stack arguments */
281         M_LDA(REG_A2, REG_SP, stackframesize + (cd->stackframesize * 8));
282
283         /* call trace_java_call_enter */
284
285         disp = dseg_add_functionptr(cd, trace_java_call_enter);
286         M_ALD_DSEG(REG_ITMP3, disp);
287         M_CALL(REG_ITMP3);
288
289         /* restore argument registers */
290
291         off = 96;
292
293         for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
294                 M_ILD(abi_registers_integer_argument[i], REG_SP, off + 4);
295         }
296
297         for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
298                 M_DLD(abi_registers_float_argument[i], REG_SP, off);
299         }
300
301         /* remove stack frame */
302
303         M_AADD_IMM(stackframesize, REG_SP);
304
305         /* mark trace code */
306
307         M_NOP;
308
309 #else
310         methodinfo   *m;
311         codegendata  *cd;
312         methoddesc   *md;
313         s4            i, j, k;
314         s4            stackframesize, off, foff, aoff, doff, t, iargctr, fargctr, disp;
315
316         /* get required compiler data */
317
318         m  = jd->m;
319         cd = jd->cd;
320
321         md = m->parseddesc;
322
323         /* mark trace code */
324
325         M_NOP;
326
327         stackframesize = 
328                 (6 * 8) + /* s8 on stack parameters x 6 */
329                 (1 * 4) + /* methodinfo on stack parameter */
330                 (ARG_CNT * 8) +
331                 (TMP_CNT * 8) 
332                 ;
333
334         M_ASUB_IMM(stackframesize, REG_SP); /* allocate stackframe */
335
336         /* save argument registers */
337
338         off = (6 * 8) + (1 * 4);
339
340         for (i = 0; i < INT_ARG_CNT; i++, off += 8)
341                 M_IST(abi_registers_integer_argument[i], REG_SP, off);
342
343         for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
344                 M_DST(abi_registers_float_argument[i], REG_SP, off);
345
346         /* save temporary registers for leaf methods */
347
348         if (jd->isleafmethod) {
349                 for (i = 0; i < INT_TMP_CNT; i++, off += 8)
350                         M_LST(abi_registers_integer_temporary[i], REG_SP, off);
351
352                 for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
353                         M_DST(abi_registers_float_temporary[i], REG_SP, off);
354         }
355
356         /* Load arguments to new locations */
357
358         /* First move all arguments to stack
359          *
360          * (s8) a7
361          * (s8) a2
362          *   ...
363          * (s8) a1 \ Auxilliary stack frame
364          * (s8) a0 /
365          * ------- <---- SP
366          */
367
368         M_ASUB_IMM(2 * 8, REG_SP);
369         
370         /* offset to where first integer arg is saved on stack */
371         off = (2 * 8) + (6 * 8) + (1 * 4); 
372         /* offset to where first float arg is saved on stack */
373         foff = off + (INT_ARG_CNT * 8); 
374         /* offset to where first argument is passed on stack */
375         aoff = (2 * 8) + stackframesize + (cd->stackframesize * 8);
376         /* offset to destination on stack */
377         doff = 0; 
378
379         iargctr = fargctr = 0;
380
381         ICONST(REG_ITMP1, 0);
382
383         for (i = 0; i < md->paramcount && i < 8; i++) {
384                 t = md->paramtypes[i].type;
385
386                 M_IST(REG_ITMP1, REG_SP, doff);
387                 M_IST(REG_ITMP1, REG_SP, doff + 4);
388
389                 if (IS_FLT_DBL_TYPE(t)) {
390                         if (fargctr < 2) { /* passed in register */
391                                 N_STD(abi_registers_float_argument[fargctr], doff, RN, REG_SP);
392                                 fargctr += 1;
393                         } else { /* passed on stack */
394                                 /*
395                                 if (IS_2_WORD_TYPE(t)) {
396                                         N_MVC(doff, 8, REG_SP, aoff, REG_SP);
397                                 } else {
398                                         N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
399                                 }
400                                 */
401                                 N_MVC(doff, 8, REG_SP, aoff, REG_SP);
402                                 aoff += 8;
403                         }
404                 } else {
405                         if (IS_2_WORD_TYPE(t)) {
406                                 if (iargctr < 4) { /* passed in 2 registers */
407                                         N_STM(REG_A0 + iargctr, REG_A0 + iargctr + 1, doff, REG_SP);
408                                         iargctr += 2;
409                                 } else { /* passed on stack */
410                                         N_MVC(doff, 8, REG_SP, aoff, REG_SP);
411                                         aoff += 8;
412                                 }
413                         } else {
414                                 if (iargctr < 5) { /* passed in register */
415                                         N_ST(REG_A0 + iargctr, doff + 4, RN, REG_SP);
416                                         iargctr += 1;
417                                 } else { /* passed on stack */
418                                         N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
419                                         aoff += 8;
420                                 }
421                         }
422                 }
423
424                 doff += 8;
425         }
426
427         /* Now move a0 and a1 to registers
428          *
429          * (s8) a7
430          *   ...
431          * (s8) a2
432          * ------- <- SP
433          * (s8) a0 ==> a0, a1
434          * (s8) a1 ==> a2, a3
435          */
436
437         N_LM(REG_A0, REG_A1, 0, REG_SP);
438         N_LM(REG_A2, REG_A3, 8, REG_SP);
439
440         M_AADD_IMM(2 * 8, REG_SP);
441
442         /* Finally load methodinfo argument */
443
444         disp = dseg_add_address(cd, m);
445         M_ALD_DSEG(REG_ITMP2, disp);    
446         M_AST(REG_ITMP2, REG_SP, 6 * 8);
447
448         /* Call builtin_verbosecall_enter */
449
450         disp = dseg_add_address(cd, builtin_verbosecall_enter);
451         M_ALD_DSEG(REG_ITMP2, disp);
452         M_ASUB_IMM(96, REG_SP);
453         M_CALL(REG_ITMP2);
454         M_AADD_IMM(96, REG_SP);
455
456         /* restore argument registers */
457
458         off = (6 * 8) + (1 * 4);
459
460         for (i = 0; i < INT_ARG_CNT; i++, off += 8)
461                 M_ILD(abi_registers_integer_argument[i], REG_SP, off);
462
463         for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
464                 M_DLD(abi_registers_float_argument[i], REG_SP, off);
465
466         /* restore temporary registers for leaf methods */
467
468         if (jd->isleafmethod) {
469                 for (i = 0; i < INT_TMP_CNT; i++, off += 8)
470                         M_ILD(abi_registers_integer_temporary[i], REG_SP, off);
471
472                 for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
473                         M_DLD(abi_registers_float_temporary[i], REG_SP, off);
474         }
475
476         /* remove stackframe */
477
478         M_AADD_IMM(stackframesize, REG_SP);
479
480         /* mark trace code */
481
482         M_NOP;
483 #endif
484 }
485 #endif /* !defined(NDEBUG) */
486
487
488 /* emit_verbosecall_exit *******************************************************
489
490    Generates the code for the call trace.
491
492 *******************************************************************************/
493
494 #if !defined(NDEBUG)
495 void emit_verbosecall_exit(jitdata *jd)
496 {
497 #if 1
498         methodinfo   *m;
499         codegendata  *cd;
500         s4            disp;
501         s4            stackframesize;
502
503         m  = jd->m;
504         cd = jd->cd;
505
506         /* mark trace code */
507
508         M_NOP;
509
510         /* allocate stackframe */
511
512         stackframesize = 96 + (3 * 8);
513         M_ASUB_IMM(stackframesize, REG_SP);
514
515         /* store return values in array and sign extend them */
516
517         M_IST(REG_RESULT, REG_SP, 96 + (0 * 8) + 4);
518         M_SRA_IMM(31, REG_RESULT);
519         M_IST(REG_RESULT, REG_SP, 96 + (0 * 8));
520
521         M_IST(REG_RESULT2, REG_SP, 96 + (1 * 8) + 4);
522         M_SRA_IMM(31, REG_RESULT2);
523         M_IST(REG_RESULT2, REG_SP, 96 + (1 * 8));
524
525         M_DST(REG_FRESULT, REG_SP, 96 + (2 * 8));
526
527         /* call trace_java_call_exit */
528
529         disp = dseg_add_address(cd, m);
530         M_ALD_DSEG(REG_A0, disp);
531         M_LDA(REG_A1, REG_SP, 96);
532         disp = dseg_add_functionptr(cd, trace_java_call_exit);
533         M_ALD_DSEG(REG_ITMP3, disp);
534         M_CALL(REG_ITMP3);
535
536         /* restore return values */
537
538         M_ILD(REG_RESULT, REG_SP, 96 + (0 * 8) + 4);
539         M_ILD(REG_RESULT2, REG_SP, 96 + (1 * 8) + 4);
540         M_DLD(REG_FRESULT, REG_SP, 96 + (2 * 8));
541
542         /* remove stackframe */
543
544         M_AADD_IMM(stackframesize, REG_SP);
545
546         /* mark trace code */
547
548         M_NOP;
549
550 #else
551
552         methodinfo   *m;
553         codegendata  *cd;
554         registerdata *rd;
555         s4            disp;
556
557         /* get required compiler data */
558
559         m  = jd->m;
560         cd = jd->cd;
561         rd = jd->rd;
562
563         /* mark trace code */
564
565         M_NOP;
566
567         M_ASUB_IMM(2 * 8, REG_SP);
568
569         N_STM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
570         M_DST(REG_FRESULT, REG_SP, 1 * 8);
571
572         if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) {
573                 /* (REG_A0, REG_A1) == (REG_RESULT, REG_RESULT2), se no need to move */
574         } else {
575                 M_INTMOVE(REG_RESULT, REG_A1);
576                 ICONST(REG_A0, 0);
577         }
578
579         disp = dseg_add_address(cd, m);
580         M_ALD_DSEG(REG_A2, disp);
581
582         /* REG_FRESULT is REG_FA0, so no need to move */
583         M_FLTMOVE(REG_FRESULT, REG_FA1);
584
585         disp = dseg_add_address(cd, builtin_verbosecall_exit);
586         M_ALD_DSEG(REG_ITMP1, disp);
587         M_ASUB_IMM(96, REG_SP);
588         M_CALL(REG_ITMP1);
589         M_AADD_IMM(96, REG_SP);
590
591         N_LM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
592         M_DLD(REG_FRESULT, REG_SP, 1 * 8);
593
594         M_AADD_IMM(2 * 8, REG_SP);
595
596         /* mark trace code */
597
598         M_NOP;
599 #endif
600 }
601 #endif /* !defined(NDEBUG) */
602
603
604 /* emit_load_high **************************************************************
605
606    Emits a possible load of the high 32-bits of an operand.
607
608 *******************************************************************************/
609
610 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
611 {
612         codegendata  *cd;
613         s4            disp;
614         s4            reg;
615
616         assert(src->type == TYPE_LNG);
617
618         /* get required compiler data */
619
620         cd = jd->cd;
621
622         if (IS_INMEMORY(src->flags)) {
623                 COUNT_SPILLS;
624
625                 disp = src->vv.regoff;
626
627                 M_ILD(tempreg, REG_SP, disp);
628
629                 reg = tempreg;
630         }
631         else
632                 reg = GET_HIGH_REG(src->vv.regoff);
633
634         return reg;
635 }
636
637 /* emit_load_low ***************************************************************
638
639    Emits a possible load of the low 32-bits of an operand.
640
641 *******************************************************************************/
642
643 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
644 {
645         codegendata  *cd;
646         s4            disp;
647         s4            reg;
648
649         assert(src->type == TYPE_LNG);
650
651         /* get required compiler data */
652
653         cd = jd->cd;
654
655         if (IS_INMEMORY(src->flags)) {
656                 COUNT_SPILLS;
657
658                 disp = src->vv.regoff;
659
660                 M_ILD(tempreg, REG_SP, disp + 4);
661
662                 reg = tempreg;
663         }
664         else
665                 reg = GET_LOW_REG(src->vv.regoff);
666
667         return reg;
668 }
669
670 s4 emit_load_s1_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
671         codegendata *cd = jd->cd;
672         s4 reg = emit_load_s1(jd, iptr, tempreg);
673         if (reg == 0) {
674                 M_MOV(reg, tempreg);
675                 return tempreg;
676         } else {
677                 return reg;
678         }
679 }
680
681 s4 emit_load_s2_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
682         codegendata *cd = jd->cd;
683         s4 reg = emit_load_s2(jd, iptr, tempreg);
684         if (reg == 0) {
685                 if (IS_FLT_DBL_TYPE(VAROP(iptr->sx.s23.s2)->type)) {
686                         M_FMOV(reg, tempreg);
687                 } else {
688                         M_MOV(reg, tempreg);
689                 }
690                 return tempreg;
691         } else {
692                 return reg;
693         }
694 }
695
696 s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
697         codegendata *cd = jd->cd;
698         s4 reg = emit_load_s1(jd, iptr, tempreg);
699         if (reg == notreg) {
700                 if (IS_FLT_DBL_TYPE(VAROP(iptr->s1)->type)) {
701                         M_FMOV(reg, tempreg);
702                 } else {
703                         M_MOV(reg, tempreg);
704                 }
705                 return tempreg;
706         } else {
707                 return reg;
708         }
709 }
710
711 s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
712         codegendata *cd = jd->cd;
713         s4 reg = emit_load_s2(jd, iptr, tempreg);
714         if (reg == notreg) {
715                 if (IS_FLT_DBL_TYPE(VAROP(iptr->sx.s23.s2)->type)) {
716                         M_FMOV(reg, tempreg);
717                 } else {
718                         M_MOV(reg, tempreg);
719                 }
720                 return tempreg;
721         } else {
722                 return reg;
723         }
724 }
725
726 s4 emit_alloc_dst_even_odd(jitdata *jd, instruction *iptr, s4 htmpreg, s4 ltmpreg, s4 breg) {
727         codegendata *cd;
728         s4           hr, lr;
729         varinfo     *dst;
730
731         /* (r0, r1)    
732          * (r2, r3)
733          * (r4, r5)
734          * (r6, r7)
735          * (r8, r9)
736          * (r10, r11)
737          * (r12, r13) Illegal, because r13 is PV
738          * (r14, r15) Illegal, because r15 is SP
739          */
740
741         cd = jd->cd;
742         dst = VAROP(iptr->dst);
743
744         if (IS_INMEMORY(dst->flags)) {
745                 if (! IS_REG_ITMP(ltmpreg)) {
746                         M_INTMOVE(ltmpreg, breg);
747                 }
748                 if (! IS_REG_ITMP(htmpreg)) {
749                         M_INTMOVE(htmpreg, breg);
750                 }
751                 return PACK_REGS(ltmpreg, htmpreg);
752         } else {
753                 hr = GET_HIGH_REG(dst->vv.regoff);
754                 lr = GET_LOW_REG(dst->vv.regoff);
755                 if (((hr % 2) == 0) && lr == (hr + 1)) {
756                         /* the result is already in a even-odd pair */
757                         return dst->vv.regoff;                  
758                 } else if (((hr % 2) == 0) && (hr < R12)) {
759                         /* the high register is at a even position */
760                         M_INTMOVE(hr + 1, breg);
761                         return PACK_REGS(hr + 1, hr);
762                 } else if (((lr % 2) == 1) && (lr < R12)) {
763                         /* the low register is at a odd position */
764                         M_INTMOVE(lr - 1, breg);
765                         return PACK_REGS(lr, lr - 1);
766                 } else {
767                         /* no way to create an even-odd pair by 1 copy operation,
768                          * Use the temporary register pair.
769                          */
770                         if (! IS_REG_ITMP(ltmpreg)) {
771                                 M_INTMOVE(ltmpreg, breg);
772                         }
773                         if (! IS_REG_ITMP(htmpreg)) {
774                                 M_INTMOVE(htmpreg, breg);
775                         }
776                         return PACK_REGS(ltmpreg, htmpreg);
777                 }
778         }
779 }
780
781 void emit_restore_dst_even_odd(jitdata *jd, instruction *iptr, s4 htmpreg, s4 ltmpreg, s4 breg) {
782         codegendata *cd;
783         s4           hr, lr;
784         varinfo     *dst;
785
786         cd = jd->cd;
787         dst = VAROP(iptr->dst);
788
789         if (IS_INMEMORY(dst->flags)) {
790                 if (! IS_REG_ITMP(ltmpreg)) {
791                         M_INTMOVE(breg, ltmpreg);
792                 }
793                 if (! IS_REG_ITMP(htmpreg)) {
794                         M_INTMOVE(breg, htmpreg);
795                 }
796         } else {
797                 hr = GET_HIGH_REG(dst->vv.regoff);
798                 lr = GET_LOW_REG(dst->vv.regoff);
799                 if (((hr % 2) == 0) && lr == (hr + 1)) {
800                         return;
801                 } else if (((hr % 2) == 0) && (hr < R12)) {
802                         M_INTMOVE(breg, hr + 1);
803                 } else if (((lr % 2) == 1) && (lr < R12)) {
804                         M_INTMOVE(breg, lr - 1);
805                 } else {
806                         if (! IS_REG_ITMP(ltmpreg)) {
807                                 M_INTMOVE(breg, ltmpreg);
808                         }
809                         if (! IS_REG_ITMP(htmpreg)) {
810                                 M_INTMOVE(breg, htmpreg);
811                         }
812                 }
813         }
814 }
815
816 void emit_copy_dst(jitdata *jd, instruction *iptr, s4 dtmpreg) {
817         codegendata *cd;
818         varinfo *dst;
819         cd = jd->cd;
820         dst = VAROP(iptr->dst);
821         if (! IS_INMEMORY(dst->flags)) {
822                 if (dst->vv.regoff != dtmpreg) {
823                         if (IS_FLT_DBL_TYPE(dst->type)) {
824                                 M_FLTMOVE(dtmpreg, dst->vv.regoff);
825                         } else if (IS_2_WORD_TYPE(dst->type)) {
826                                 M_LNGMOVE(dtmpreg, dst->vv.regoff);
827                         } else {
828                                 M_INTMOVE(dtmpreg, dst->vv.regoff);
829                         }
830                 }
831         }
832 }
833
834 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) {
835
836         s4 branchdisp = disp;
837         s4 branchmpc;
838         u1 *ref;
839
840         if (N_VALID_BRANCH(branchdisp)) {
841
842                 /* valid displacement */
843
844                 switch (condition) {
845                         case BRANCH_EQ:
846                                 M_BEQ(branchdisp);
847                                 break;
848                         case BRANCH_NE:
849                                 M_BNE(branchdisp);
850                                 break;
851                         case BRANCH_LT:
852                                 M_BLT(branchdisp);
853                                 break;
854                         case BRANCH_GE:
855                                 M_BGE(branchdisp);
856                                 break;
857                         case BRANCH_GT:
858                                 M_BGT(branchdisp);
859                                 break;
860                         case BRANCH_LE:
861                                 M_BLE(branchdisp);
862                                 break;
863                         case BRANCH_UNCONDITIONAL:
864                                 M_BR(branchdisp);
865                                 break;
866                         default:
867                                 vm_abort("emit_branch: unknown condition %d", condition);
868                 }
869         } else {
870
871                 /* If LONGBRANCHES is not set, the flag and the error flag */
872
873                 if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
874                         cd->flags |= (CODEGENDATA_FLAG_ERROR |
875                                 CODEGENDATA_FLAG_LONGBRANCHES);
876                 }
877
878                 /* If error flag is set, do nothing. The method has to be recompiled. */
879
880                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) && CODEGENDATA_HAS_FLAG_ERROR(cd)) {
881                         return;
882                 }
883
884                 /* Patch the displacement to branch over the actual branch manually
885                  * to not get yet more nops.
886                  */
887
888                 branchmpc = cd->mcodeptr - cd->mcodebase;
889                 ref = cd->mcodeptr;
890
891                 switch (condition) {
892                         case BRANCH_EQ:
893                                 M_BNE(0);
894                                 break;
895                         case BRANCH_NE:
896                                 M_BEQ(0);
897                                 break;
898                         case BRANCH_LT:
899                                 M_BGE(0);
900                                 break;
901                         case BRANCH_GE:
902                                 M_BLT(0);
903                                 break;
904                         case BRANCH_GT:
905                                 M_BLE(0);
906                                 break;
907                         case BRANCH_LE:
908                                 M_BGT(0);
909                                 break;
910                         case BRANCH_UNCONDITIONAL:
911                                 /* fall through, no displacement to patch */
912                                 ref = NULL;
913                                 break;
914                         default:
915                                 vm_abort("emit_branch: unknown condition %d", condition);
916                 }
917
918                 /* The actual long branch */
919
920                 disp = dseg_add_s4(cd, branchmpc + disp - N_PV_OFFSET);
921                 M_ILD_DSEG(REG_ITMP3, disp);
922                 M_AADD(REG_PV, REG_ITMP3);
923                 M_JMP(RN, REG_ITMP3);
924
925                 /* Patch back the displacement */
926
927                 if (ref != NULL) {
928                         *(u4 *)ref |= (u4)((cd->mcodeptr - ref) / 2);
929                 }
930         }
931 }
932
933 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg) {
934         if (INSTRUCTION_MUST_CHECK(iptr)) {
935                 M_TEST(reg);
936                 M_BNE(SZ_BRC + SZ_ILL);
937                 M_ILL(EXCEPTION_HARDWARE_ARITHMETIC);
938         }
939 }
940
941 /* emit_arrayindexoutofbounds_check ********************************************
942
943    Emit a ArrayIndexOutOfBoundsException check.
944
945 *******************************************************************************/
946
947 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
948 {
949         if (INSTRUCTION_MUST_CHECK(iptr)) {
950                 /* Size is s4, >= 0
951                  * Do unsigned comparison to catch negative indexes.
952                  */
953                 N_CL(s2, OFFSET(java_arrayheader, size), RN, s1);
954         M_BLT(SZ_BRC + SZ_ILL);
955                 M_ILL2(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
956         }
957 }
958
959 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1) {
960         if (INSTRUCTION_MUST_CHECK(iptr)) {
961                 if (reg != RN) {
962                         M_TEST(reg);
963                 }
964                 switch (condition) {
965                         case BRANCH_LE:
966                                 M_BGT(SZ_BRC + SZ_ILL);
967                                 break;
968                         case BRANCH_EQ:
969                                 M_BNE(SZ_BRC + SZ_ILL);
970                                 break;
971                         case BRANCH_GT:
972                                 M_BLE(SZ_BRC + SZ_ILL);
973                                 break;
974                         default:
975                                 vm_abort("emit_classcast_check: unknown condition %d", condition);
976                 }
977                 M_ILL2(s1, EXCEPTION_HARDWARE_CLASSCAST);
978         }
979 }
980
981 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg) {
982         if (INSTRUCTION_MUST_CHECK(iptr)) {
983                 M_TEST(reg);
984                 M_BNE(SZ_BRC + SZ_ILL);
985                 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
986         }
987 }
988
989 void emit_exception_check(codegendata *cd, instruction *iptr) {
990         if (INSTRUCTION_MUST_CHECK(iptr)) {
991                 M_TEST(REG_RESULT);
992                 M_BNE(SZ_BRC + SZ_ILL);
993                 M_ILL(EXCEPTION_HARDWARE_EXCEPTION);
994         }
995 }
996
997 void emit_restore_pv(codegendata *cd) {
998         s4 offset, offset_imm;
999
1000         /*
1001         N_BASR(REG_PV, RN);
1002         disp = (s4) (cd->mcodeptr - cd->mcodebase);
1003         M_ASUB_IMM32(disp, REG_ITMP1, REG_PV);
1004         */
1005
1006         /* If the offset from the method start does not fit into an immediate
1007          * value, we can't put it into the data segment!
1008          */
1009
1010         /* Displacement from start of method to here */
1011
1012         offset = (s4) (cd->mcodeptr - cd->mcodebase);
1013         offset_imm = -offset - SZ_BASR + N_PV_OFFSET;
1014
1015         if (N_VALID_IMM(offset_imm)) {
1016                 /* Get program counter */
1017                 N_BASR(REG_PV, RN);
1018                 /* Substract displacement */
1019                 M_AADD_IMM(offset_imm, REG_PV);
1020         } else {
1021                 /* Save program counter and jump over displacement in instruction flow */
1022                 N_BRAS(REG_PV, SZ_BRAS + SZ_LONG);
1023                 /* Place displacement here */
1024                 /* REG_PV points now exactly to this position */
1025                 N_LONG(-offset - SZ_BRAS + N_PV_OFFSET);
1026                 /* Substract *(REG_PV) from REG_PV */
1027                 N_A(REG_PV, 0, RN, REG_PV);
1028         }
1029 }
1030
1031 /*
1032  * These are local overrides for various environment variables in Emacs.
1033  * Please do not remove this and leave it at the end of the file, where
1034  * Emacs will automagically detect them.
1035  * ---------------------------------------------------------------------
1036  * Local variables:
1037  * mode: c
1038  * indent-tabs-mode: t
1039  * c-basic-offset: 4
1040  * tab-width: 4
1041  * End:
1042  */