* src/vm/jit/s390/codegen.c: Fixed build.
[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, 2008, 2010
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25 #include "config.h"
26
27 #include <assert.h>
28 #include <stdint.h>
29
30 #include "vm/jit/s390/codegen.h"
31 #include "vm/jit/s390/emit.h"
32 #include "vm/jit/s390/md-abi.h"
33
34 #include "mm/memory.hpp"
35
36 #include "threads/lock.hpp"
37
38 #include "vm/jit/builtin.hpp"
39 #include "vm/global.h"
40 #include "vm/types.h"
41 #include "vm/options.h"
42
43 #include "vm/jit/abi.h"
44 #include "vm/jit/abi-asm.h"
45 #include "vm/jit/asmpart.h"
46 #include "vm/jit/codegen-common.hpp"
47 #include "vm/jit/emit-common.hpp"
48 #include "vm/jit/jit.hpp"
49 #include "vm/jit/patcher-common.hpp"
50 #include "vm/jit/replace.hpp"
51 #include "vm/jit/trace.hpp"
52 #include "vm/jit/trap.hpp"
53
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 (IS_INMEMORY(src->flags) && IS_INMEMORY(dst->flags)) {
165                         if (IS_2_WORD_TYPE(src->type)) {
166                                 N_MVC(dst->vv.regoff, 8, REG_SP, src->vv.regoff, REG_SP);
167                         } else {
168                                 N_MVC(dst->vv.regoff, 4, REG_SP, src->vv.regoff, REG_SP);
169                         }
170                 } else {
171
172                         /* If one of the variables resides in memory, we can eliminate
173                            the register move from/to the temporary register with the
174                            order of getting the destination register and the load. */
175
176                         if (IS_INMEMORY(src->flags)) {
177                                 if (IS_FLT_DBL_TYPE(dst->type)) {
178                                         d = codegen_reg_of_var(iptr->opc, dst, REG_FTMP1);
179                                 } else {
180                                         if (IS_2_WORD_TYPE(dst->type)) {
181                                                 d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
182                                         } else {
183                                                 d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
184                                         }
185                                 }
186                                 s1 = emit_load(jd, iptr, src, d);
187                         }
188                         else {
189                                 if (IS_FLT_DBL_TYPE(src->type)) {
190                                         s1 = emit_load(jd, iptr, src, REG_FTMP1);
191                                 } else {
192                                         if (IS_2_WORD_TYPE(src->type)) {
193                                                 s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
194                                         } else {
195                                                 s1 = emit_load(jd, iptr, src, REG_ITMP1);
196                                         }
197                                 }
198                                 d = codegen_reg_of_var(iptr->opc, dst, s1);
199                         }
200
201                         if (s1 != d) {
202                                 if (IS_FLT_DBL_TYPE(src->type)) {
203                                         M_FMOV(s1, d);
204                                 } else {
205                                         if (IS_2_WORD_TYPE(src->type)) {
206                                                 M_LNGMOVE(s1, d);
207                                         } else {
208                                                 M_MOV(s1, d);
209                                         }
210                                 }
211                         }
212
213                         emit_store(jd, iptr, dst, d);
214                 }
215         }
216 }
217
218
219 /**
220  * Emits code updating the condition register by comparing one integer
221  * register to an immediate integer value.
222  */
223 void emit_icmp_imm(codegendata* cd, int reg, int32_t value)
224 {
225         int32_t disp;
226
227         if (N_VALID_IMM(value)) {
228                 M_ICMP_IMM(reg, value);
229         } else {
230                 disp = dseg_add_s4(cd, value);
231                 if (N_VALID_DSEG_DISP(disp)) {
232                         N_C(reg, N_DSEG_DISP(disp), RN, REG_PV);
233                 } else {
234                         assert(reg != REG_ITMP2);
235                         ICONST(REG_ITMP2, disp);
236                         N_C(reg, -N_PV_OFFSET, REG_ITMP2, REG_PV);
237                 }
238         }
239 }
240
241
242 /* emit_trap *******************************************************************
243
244    Emit a trap instruction and return the original machine code.
245
246 *******************************************************************************/
247
248 uint32_t emit_trap(codegendata *cd)
249 {
250         uint32_t mcode;
251
252         /* Get machine code which is patched back in later. The
253            trap is 2 bytes long. */
254
255         mcode = *((u2 *) cd->mcodeptr);
256
257         M_ILL(TRAP_PATCHER);
258
259         return mcode;
260 }
261
262
263 /**
264  * Generates synchronization code to enter a monitor.
265  */
266 #if defined(ENABLE_THREADS)
267 void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset)
268 {
269         int32_t p;
270         int32_t disp;
271
272         // Get required compiler data.
273         methodinfo*  m  = jd->m;
274         codegendata* cd = jd->cd;
275
276 #if !defined(NDEBUG)
277         if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
278                 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
279
280                 for (p = 0; p < INT_ARG_CNT; p++)
281                         M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
282
283                 for (p = 0; p < FLT_ARG_CNT; p++)
284                         M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
285
286                 syncslot_offset += (INT_ARG_CNT + FLT_ARG_CNT) * 8;
287         }
288 #endif
289
290         /* decide which monitor enter function to call */
291
292         if (m->flags & ACC_STATIC) {
293                 disp = dseg_add_address(cd, &m->clazz->object.header);
294                 M_ALD_DSEG(REG_A0, disp);
295         }
296         else {
297                 M_TEST(REG_A0);
298                 M_BNE(SZ_BRC + SZ_ILL);
299                 M_ILL(TRAP_NullPointerException);
300         }
301
302         disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
303         M_ALD_DSEG(REG_ITMP2, disp);
304
305         M_AST(REG_A0, REG_SP, syncslot_offset);
306
307         M_ASUB_IMM(96, REG_SP); 
308         M_CALL(REG_ITMP2);
309         M_AADD_IMM(96, REG_SP); 
310
311 #if !defined(NDEBUG)
312         if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
313                 for (p = 0; p < INT_ARG_CNT; p++)
314                         M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
315
316                 for (p = 0; p < FLT_ARG_CNT; p++)
317                         M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
318
319                 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
320         }
321 #endif
322 }
323 #endif
324
325
326 /**
327  * Generates synchronization code to leave a monitor.
328  */
329 #if defined(ENABLE_THREADS)
330 void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset)
331 {
332         int32_t disp;
333
334         // Get required compiler data.
335         methodinfo*  m  = jd->m;
336         codegendata* cd = jd->cd;
337
338         /* we need to save the proper return value */
339
340         methoddesc* md = m->parseddesc;
341
342         switch (md->returntype.type) {
343         case TYPE_LNG:
344                 M_IST(REG_RESULT2, REG_SP, syncslot_offset + 8 + 4);
345                 /* fall through */
346         case TYPE_INT:
347         case TYPE_ADR:
348                 M_IST(REG_RESULT , REG_SP, syncslot_offset + 8);
349                 break;
350         case TYPE_FLT:
351                 M_FST(REG_FRESULT, REG_SP, syncslot_offset + 8);
352                 break;
353         case TYPE_DBL:
354                 M_DST(REG_FRESULT, REG_SP, syncslot_offset + 8);
355                 break;
356         }
357
358         M_ALD(REG_A0, REG_SP, syncslot_offset);
359
360         disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
361         M_ALD_DSEG(REG_ITMP2, disp);
362
363         M_ASUB_IMM(96, REG_SP);
364         M_CALL(REG_ITMP2);
365         M_AADD_IMM(96, REG_SP);
366
367         /* and now restore the proper return value */
368
369         switch (md->returntype.type) {
370         case TYPE_LNG:
371                 M_ILD(REG_RESULT2, REG_SP, syncslot_offset + 8 + 4);
372                 /* fall through */
373         case TYPE_INT:
374         case TYPE_ADR:
375                 M_ILD(REG_RESULT , REG_SP, syncslot_offset + 8);
376                 break;
377         case TYPE_FLT:
378                 M_FLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
379                 break;
380         case TYPE_DBL:
381                 M_DLD(REG_FRESULT, REG_SP, syncslot_offset + 8);
382                 break;
383         }
384 }
385 #endif
386
387
388 /**
389  * Emit profiling code for method frequency counting.
390  */
391 #if defined(ENABLE_PROFILING)
392 void emit_profile_method(codegendata* cd, codeinfo* code)
393 {
394         M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
395         ICONST(REG_ITMP2, 1);
396         N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
397         M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
398 }
399 #endif
400
401
402 /**
403  * Emit profiling code for basicblock frequency counting.
404  */
405 #if defined(ENABLE_PROFILING)
406 void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
407 {
408         M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
409         M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
410         ICONST(REG_ITMP2, 1);
411         N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
412         M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
413 }
414 #endif
415
416
417 /**
418  * Emit profiling code to start CPU cycle counting.
419  */
420 #if defined(ENABLE_PROFILING)
421 void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
422 {
423         // XXX Not implemented yet!
424 }
425 #endif
426
427
428 /**
429  * Emit profiling code to stop CPU cycle counting.
430  */
431 #if defined(ENABLE_PROFILING)
432 void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
433 {
434         // XXX Not implemented yet!
435 }
436 #endif
437
438
439 /* emit_verbosecall_enter ******************************************************
440
441    Generates the code for the call trace.
442
443 *******************************************************************************/
444
445 #if !defined(NDEBUG)
446 void emit_verbosecall_enter(jitdata *jd)
447 {
448         methodinfo   *m;
449         codeinfo     *code;
450         codegendata  *cd;
451         methoddesc   *md;
452         s4            stackframesize;
453         s4            i, off, disp, s;
454
455         m    = jd->m;
456         code = jd->code;
457         cd   = jd->cd;
458
459         md   = m->parseddesc;
460
461         /* mark trace code */
462
463         M_NOP;
464
465         /* allocate stack frame */
466
467         stackframesize = 96 + (md->paramcount * 8);
468
469         /* for leaf methods we need to store unused argument and temporary registers */
470
471         if (code_is_leafmethod(code)) {
472                 stackframesize += (ARG_CNT + TMP_CNT) * 8;
473         }
474
475         /* allocate stack frame */
476
477         M_ASUB_IMM(stackframesize, REG_SP);
478
479         /* store argument registers in array */
480
481         off = 96;
482
483         for (i = 0; i < md->paramcount; i++) {
484                 if (! md->params[i].inmemory) {
485                         s = md->params[i].regoff;
486                         switch (md->paramtypes[i].type) {
487                                 case TYPE_INT:
488                                 case TYPE_ADR:
489                                         M_IST(s, REG_SP, off);
490                                         break;
491                                 case TYPE_LNG:
492                                         M_LST(s, REG_SP, off);
493                                         break;
494                                 case TYPE_FLT:
495                                         M_FST(s, REG_SP, off);
496                                         break;
497                                 case TYPE_DBL:
498                                         M_DST(s, REG_SP, off);
499                                         break;
500                         }
501                 }
502                 off += 8;
503         }
504
505         /* save unused (currently all) argument registers for leaf methods */
506         /* save temporary registers for leaf methods */
507
508         if (code_is_leafmethod(code)) {
509
510                 for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
511                         M_IST(abi_registers_integer_argument[i], REG_SP, off);
512                 }
513
514                 for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
515                         M_DST(abi_registers_float_argument[i], REG_SP, off);
516                 }
517
518                 for (i = 0; i < INT_TMP_CNT; ++i, off += 8) {
519                         M_IST(abi_registers_integer_temporary[i], REG_SP, off);
520                 }
521
522                 for (i = 0; i < FLT_TMP_CNT; ++i, off += 8) {
523                         M_DST(abi_registers_float_temporary[i], REG_SP, off);
524                 }
525         }
526
527         /* load arguments for trace_java_call_enter */
528
529         /* methodinfo */
530
531         disp = dseg_add_address(cd, m);
532         M_ALD_DSEG(REG_A0, disp);       
533         /* pointer to argument registers array */
534         M_LDA(REG_A1, REG_SP, 96);
535         /* pointer to on stack arguments */
536         M_LDA(REG_A2, REG_SP, stackframesize + (cd->stackframesize * 8));
537
538         /* call trace_java_call_enter */
539
540         disp = dseg_add_functionptr(cd, trace_java_call_enter);
541         M_ALD_DSEG(REG_ITMP2, disp);
542         M_CALL(REG_ITMP2);
543
544         /* restore used argument registers */
545         /* for leaf methods restore all argument and temporary registers */
546
547         if (code_is_leafmethod(code)) {
548                 off = 96 + (8 * md->paramcount);
549
550                 for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
551                         M_ILD(abi_registers_integer_argument[i], REG_SP, off);
552                 }
553
554                 for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
555                         M_DLD(abi_registers_float_argument[i], REG_SP, off);
556                 }
557
558                 for (i = 0; i < INT_TMP_CNT; ++i, off += 8) {
559                         M_ILD(abi_registers_integer_temporary[i], REG_SP, off);
560                 }
561
562                 for (i = 0; i < FLT_TMP_CNT; ++i, off += 8) {
563                         M_DLD(abi_registers_float_temporary[i], REG_SP, off);
564                 }
565         } else {
566                 off = 96;
567
568                 for (i = 0; i < md->paramcount; i++) {
569                         if (! md->params[i].inmemory) {
570                                 s = md->params[i].regoff;
571                                 switch (md->paramtypes[i].type) {
572                                         case TYPE_INT:
573                                         case TYPE_ADR:
574                                                 M_ILD(s, REG_SP, off);
575                                                 break;
576                                         case TYPE_LNG:
577                                                 M_LLD(s, REG_SP, off);
578                                                 break;
579                                         case TYPE_FLT:
580                                                 M_FLD(s, REG_SP, off);
581                                                 break;
582                                         case TYPE_DBL:
583                                                 M_DLD(s, REG_SP, off);
584                                                 break;
585                                 }
586                         }
587                         off += 8;
588                 }
589         }
590
591         /* remove stack frame */
592
593         M_AADD_IMM(stackframesize, REG_SP);
594
595         /* mark trace code */
596
597         M_NOP;
598
599 }
600 #endif /* !defined(NDEBUG) */
601
602
603 /* emit_verbosecall_exit *******************************************************
604
605    Generates the code for the call trace.
606
607 *******************************************************************************/
608
609 #if !defined(NDEBUG)
610 void emit_verbosecall_exit(jitdata *jd)
611 {
612         methodinfo   *m;
613         codegendata  *cd;
614         s4            disp;
615         s4            stackframesize;
616         s4            off;
617         s4            t;
618
619         m  = jd->m;
620         cd = jd->cd;
621         t = m->parseddesc->returntype.type;
622
623         /* mark trace code */
624
625         M_NOP;
626
627         /* allocate stackframe */
628
629         stackframesize = 96 + (1 * 8);
630         M_ASUB_IMM(stackframesize, REG_SP);
631
632         off = 96;
633
634         /* store return values in array */
635
636         if (IS_INT_LNG_TYPE(t)) {
637                 if (IS_2_WORD_TYPE(t)) {
638                         M_LST(REG_RESULT_PACKED, REG_SP, off);
639                 } else {
640                         M_IST(REG_RESULT, REG_SP, off);
641                 }
642         } else {
643                 M_DST(REG_FRESULT, REG_SP, off);
644         }
645
646         /* call trace_java_call_exit */
647
648         disp = dseg_add_address(cd, m);
649         M_ALD_DSEG(REG_A0, disp);
650         M_LDA(REG_A1, REG_SP, off);
651         disp = dseg_add_functionptr(cd, trace_java_call_exit);
652         M_ALD_DSEG(REG_ITMP2, disp);
653         M_CALL(REG_ITMP2);
654
655         /* restore return value */
656
657         if (IS_INT_LNG_TYPE(t)) {
658                 if (IS_2_WORD_TYPE(t)) {
659                         M_LLD(REG_RESULT_PACKED, REG_SP, off);
660                 } else {
661                         M_ILD(REG_RESULT, REG_SP, off);
662                 }
663         } else {
664                 M_DLD(REG_FRESULT, REG_SP, off);
665         }
666
667         /* remove stackframe */
668
669         M_AADD_IMM(stackframesize, REG_SP);
670
671         /* mark trace code */
672
673         M_NOP;
674 }
675 #endif /* !defined(NDEBUG) */
676
677
678 /* emit_load_high **************************************************************
679
680    Emits a possible load of the high 32-bits of an operand.
681
682 *******************************************************************************/
683
684 s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
685 {
686         codegendata  *cd;
687         s4            disp;
688         s4            reg;
689
690         assert(src->type == TYPE_LNG);
691
692         /* get required compiler data */
693
694         cd = jd->cd;
695
696         if (IS_INMEMORY(src->flags)) {
697                 COUNT_SPILLS;
698
699                 disp = src->vv.regoff;
700
701                 M_ILD(tempreg, REG_SP, disp);
702
703                 reg = tempreg;
704         }
705         else
706                 reg = GET_HIGH_REG(src->vv.regoff);
707
708         return reg;
709 }
710
711 /* emit_load_low ***************************************************************
712
713    Emits a possible load of the low 32-bits of an operand.
714
715 *******************************************************************************/
716
717 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
718 {
719         codegendata  *cd;
720         s4            disp;
721         s4            reg;
722
723         assert(src->type == TYPE_LNG);
724
725         /* get required compiler data */
726
727         cd = jd->cd;
728
729         if (IS_INMEMORY(src->flags)) {
730                 COUNT_SPILLS;
731
732                 disp = src->vv.regoff;
733
734                 M_ILD(tempreg, REG_SP, disp + 4);
735
736                 reg = tempreg;
737         }
738         else
739                 reg = GET_LOW_REG(src->vv.regoff);
740
741         return reg;
742 }
743
744 s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
745         codegendata *cd = jd->cd;
746         s4 reg = emit_load_s1(jd, iptr, tempreg);
747         if (reg == notreg) {
748                 if (IS_FLT_DBL_TYPE(VAROP(iptr->s1)->type)) {
749                         M_FMOV(reg, tempreg);
750                 } else {
751                         M_MOV(reg, tempreg);
752                 }
753                 return tempreg;
754         } else {
755                 return reg;
756         }
757 }
758
759 s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
760         codegendata *cd = jd->cd;
761         s4 reg = emit_load_s2(jd, iptr, tempreg);
762         if (reg == notreg) {
763                 if (IS_FLT_DBL_TYPE(VAROP(iptr->sx.s23.s2)->type)) {
764                         M_FMOV(reg, tempreg);
765                 } else {
766                         M_MOV(reg, tempreg);
767                 }
768                 return tempreg;
769         } else {
770                 return reg;
771         }
772 }
773
774 void emit_copy_dst(jitdata *jd, instruction *iptr, s4 dtmpreg) {
775         codegendata *cd;
776         varinfo *dst;
777         cd = jd->cd;
778         dst = VAROP(iptr->dst);
779         if (! IS_INMEMORY(dst->flags)) {
780                 if (dst->vv.regoff != dtmpreg) {
781                         if (IS_FLT_DBL_TYPE(dst->type)) {
782                                 M_FLTMOVE(dtmpreg, dst->vv.regoff);
783                         } else if (IS_2_WORD_TYPE(dst->type)) {
784                                 M_LNGMOVE(dtmpreg, dst->vv.regoff);
785                         } else {
786                                 M_INTMOVE(dtmpreg, dst->vv.regoff);
787                         }
788                 }
789         }
790 }
791
792 void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) {
793
794         s4 branchdisp = disp;
795         s4 branchmpc;
796         u1 *ref;
797
798         if (N_VALID_BRANCH(branchdisp)) {
799
800                 /* valid displacement */
801
802                 switch (condition) {
803                         case BRANCH_EQ:
804                                 M_BEQ(branchdisp);
805                                 break;
806                         case BRANCH_NE:
807                                 M_BNE(branchdisp);
808                                 break;
809                         case BRANCH_LT:
810                                 M_BLT(branchdisp);
811                                 break;
812                         case BRANCH_GE:
813                                 M_BGE(branchdisp);
814                                 break;
815                         case BRANCH_GT:
816                                 M_BGT(branchdisp);
817                                 break;
818                         case BRANCH_LE:
819                                 M_BLE(branchdisp);
820                                 break;
821                         case BRANCH_UNCONDITIONAL:
822                                 M_BR(branchdisp);
823                                 break;
824                         default:
825                                 vm_abort("emit_branch: unknown condition %d", condition);
826                 }
827         } else {
828
829                 /* If LONGBRANCHES is not set, the flag and the error flag */
830
831                 if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
832                         cd->flags |= (CODEGENDATA_FLAG_ERROR |
833                                 CODEGENDATA_FLAG_LONGBRANCHES);
834                 }
835
836                 /* If error flag is set, do nothing. The method has to be recompiled. */
837
838                 if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) && CODEGENDATA_HAS_FLAG_ERROR(cd)) {
839                         return;
840                 }
841
842                 /* Patch the displacement to branch over the actual branch manually
843                  * to not get yet more nops.
844                  */
845
846                 branchmpc = cd->mcodeptr - cd->mcodebase;
847                 ref = cd->mcodeptr;
848
849                 switch (condition) {
850                         case BRANCH_EQ:
851                                 M_BNE(0);
852                                 break;
853                         case BRANCH_NE:
854                                 M_BEQ(0);
855                                 break;
856                         case BRANCH_LT:
857                                 M_BGE(0);
858                                 break;
859                         case BRANCH_GE:
860                                 M_BLT(0);
861                                 break;
862                         case BRANCH_GT:
863                                 M_BLE(0);
864                                 break;
865                         case BRANCH_LE:
866                                 M_BGT(0);
867                                 break;
868                         case BRANCH_UNCONDITIONAL:
869                                 /* fall through, no displacement to patch */
870                                 ref = NULL;
871                                 break;
872                         default:
873                                 vm_abort("emit_branch: unknown condition %d", condition);
874                 }
875
876                 /* The actual long branch */
877
878                 disp = dseg_add_s4(cd, branchmpc + disp - N_PV_OFFSET);
879                 M_ILD_DSEG(REG_ITMP2, disp);
880                 M_AADD(REG_PV, REG_ITMP2);
881                 M_JMP(RN, REG_ITMP2);
882
883                 /* Patch back the displacement */
884
885                 N_BRC_BACK_PATCH(ref);
886         }
887 }
888
889 void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
890 {
891         if (INSTRUCTION_MUST_CHECK(iptr)) {
892                 M_TEST(reg);
893                 M_BNE(SZ_BRC + SZ_ILL);
894                 M_ILL(TRAP_ArithmeticException);
895         }
896 }
897
898 /* emit_arrayindexoutofbounds_check ********************************************
899
900    Emit a ArrayIndexOutOfBoundsException check.
901
902 *******************************************************************************/
903
904 void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
905 {
906         if (INSTRUCTION_MUST_CHECK(iptr)) {
907                 /* Size is s4, >= 0
908                  * Do unsigned comparison to catch negative indexes.
909                  */
910                 N_CL(s2, OFFSET(java_array_t, size), RN, s1);
911         M_BLT(SZ_BRC + SZ_ILL);
912                 M_ILL2(s2, TRAP_ArrayIndexOutOfBoundsException);
913         }
914 }
915
916
917 /* emit_arraystore_check *******************************************************
918
919    Emit an ArrayStoreException check.
920
921 *******************************************************************************/
922
923 void emit_arraystore_check(codegendata *cd, instruction *iptr)
924 {
925         if (INSTRUCTION_MUST_CHECK(iptr)) {
926                 M_TEST(REG_RESULT);
927                 M_BNE(SZ_BRC + SZ_ILL);
928                 M_ILL(TRAP_ArrayStoreException);
929         }
930 }
931
932
933 void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1) {
934         if (INSTRUCTION_MUST_CHECK(iptr)) {
935                 if (reg != RN) {
936                         M_TEST(reg);
937                 }
938                 switch (condition) {
939                         case BRANCH_LE:
940                                 M_BGT(SZ_BRC + SZ_ILL);
941                                 break;
942                         case BRANCH_EQ:
943                                 M_BNE(SZ_BRC + SZ_ILL);
944                                 break;
945                         case BRANCH_GT:
946                                 M_BLE(SZ_BRC + SZ_ILL);
947                                 break;
948                         default:
949                                 vm_abort("emit_classcast_check: unknown condition %d", condition);
950                 }
951                 M_ILL2(s1, TRAP_ClassCastException);
952         }
953 }
954
955 void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
956 {
957         if (INSTRUCTION_MUST_CHECK(iptr)) {
958                 M_TEST(reg);
959                 M_BNE(SZ_BRC + SZ_ILL);
960                 M_ILL(TRAP_NullPointerException);
961         }
962 }
963
964 void emit_exception_check(codegendata *cd, instruction *iptr)
965 {
966         if (INSTRUCTION_MUST_CHECK(iptr)) {
967                 M_TEST(REG_RESULT);
968                 M_BNE(SZ_BRC + SZ_ILL);
969                 M_ILL(TRAP_CHECK_EXCEPTION);
970         }
971 }
972
973 void emit_recompute_pv(codegendata *cd) {
974         s4 offset, offset_imm;
975
976         /*
977         N_BASR(REG_PV, RN);
978         disp = (s4) (cd->mcodeptr - cd->mcodebase);
979         M_ASUB_IMM32(disp, REG_ITMP1, REG_PV);
980         */
981
982         /* If the offset from the method start does not fit into an immediate
983          * value, we can't put it into the data segment!
984          */
985
986         /* Displacement from start of method to here */
987
988         offset = (s4) (cd->mcodeptr - cd->mcodebase);
989         offset_imm = -offset - SZ_BASR + N_PV_OFFSET;
990
991         if (N_VALID_IMM(offset_imm)) {
992                 /* Get program counter */
993                 N_BASR(REG_PV, RN);
994                 /* Substract displacement */
995                 M_AADD_IMM(offset_imm, REG_PV);
996         } else {
997                 /* Save program counter and jump over displacement in instruction flow */
998                 N_BRAS(REG_PV, SZ_BRAS + SZ_LONG);
999                 /* Place displacement here */
1000                 /* REG_PV points now exactly to this position */
1001                 N_LONG(-offset - SZ_BRAS + N_PV_OFFSET);
1002                 /* Substract *(REG_PV) from REG_PV */
1003                 N_A(REG_PV, 0, RN, REG_PV);
1004         }
1005 }
1006
1007 /* emit_trap_compiler **********************************************************
1008
1009    Emit a trap instruction which calls the JIT compiler.
1010
1011 *******************************************************************************/
1012
1013 void emit_trap_compiler(codegendata *cd)
1014 {
1015         M_ILL2(REG_METHODPTR, TRAP_COMPILER);
1016 }
1017
1018 /*
1019  * These are local overrides for various environment variables in Emacs.
1020  * Please do not remove this and leave it at the end of the file, where
1021  * Emacs will automagically detect them.
1022  * ---------------------------------------------------------------------
1023  * Local variables:
1024  * mode: c
1025  * indent-tabs-mode: t
1026  * c-basic-offset: 4
1027  * tab-width: 4
1028  * End:
1029  */