0f88e31a8997f7b726ab32c8ab68d45d3bbf398d
[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 7766 2007-04-19 13:24:48Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "md-abi.h"
37
38 #include "vm/jit/s390/codegen.h"
39 #include "vm/jit/s390/emit.h"
40
41 #if defined(ENABLE_THREADS)
42 # include "threads/native/lock.h"
43 #endif
44
45 #include "vm/builtin.h"
46 #include "vm/jit/abi-asm.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/codegen-common.h"
49 #include "vm/jit/emit-common.h"
50 #include "vm/jit/jit.h"
51 #include "vm/jit/replace.h"
52 #include "vm/global.h"
53 #include "mm/memory.h"
54
55 #define __PORTED__
56
57 /* emit_load *******************************************************************
58
59    Emits a possible load of an operand.
60
61 *******************************************************************************/
62
63 __PORTED__ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
64 {
65         codegendata *cd;
66         s4           disp;
67         s4           reg;
68
69         /* get required compiler data */
70
71         cd = jd->cd;
72
73         if (IS_INMEMORY(src->flags)) {
74                 COUNT_SPILLS;
75
76                 disp = src->vv.regoff * 4;
77
78                 if (IS_FLT_DBL_TYPE(src->type)) {
79                         if (IS_2_WORD_TYPE(src->type))
80                                 M_DLD(tempreg, REG_SP, disp);
81                         else
82                                 M_FLD(tempreg, REG_SP, disp);
83                 }
84                 else {
85                         if (IS_2_WORD_TYPE(src->type))
86                                 M_LLD(tempreg, REG_SP, disp);
87                         else
88                                 M_ILD(tempreg, REG_SP, disp);
89                 }
90
91                 reg = tempreg;
92         }
93         else
94                 reg = src->vv.regoff;
95
96         return reg;
97 }
98
99
100 /* emit_store ******************************************************************
101
102    This function generates the code to store the result of an
103    operation back into a spilled pseudo-variable.  If the
104    pseudo-variable has not been spilled in the first place, this
105    function will generate nothing.
106     
107 *******************************************************************************/
108
109 __PORTED__ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
110 {
111         codegendata *cd;
112
113         /* get required compiler data */
114
115         cd = jd->cd;
116
117         if (IS_INMEMORY(dst->flags)) {
118                 COUNT_SPILLS;
119
120                 if (IS_FLT_DBL_TYPE(dst->type)) {
121                         if (IS_2_WORD_TYPE(dst->type))
122                                 M_DST(d, REG_SP, dst->vv.regoff * 4);
123                         else
124                                 M_FST(d, REG_SP, dst->vv.regoff * 4);
125                 }
126                 else {
127                         if (IS_2_WORD_TYPE(dst->type))
128                                 M_LST(d, REG_SP, dst->vv.regoff * 4);
129                         else
130                                 M_IST(d, REG_SP, dst->vv.regoff * 4);
131                 }
132         }
133 }
134
135
136 /* emit_copy *******************************************************************
137
138    Generates a register/memory to register/memory copy.
139
140 *******************************************************************************/
141
142 __PORTED__ void emit_copy(jitdata *jd, instruction *iptr)
143 {
144         codegendata *cd;
145         varinfo     *src;
146         varinfo     *dst;
147         s4           s1, d;
148
149         /* get required compiler data */
150
151         cd = jd->cd;
152
153         /* get source and destination variables */
154
155         src = VAROP(iptr->s1);
156         dst = VAROP(iptr->dst);
157
158         if ((src->vv.regoff != dst->vv.regoff) ||
159                 ((src->flags ^ dst->flags) & INMEMORY)) {
160
161                 if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
162                         /* emit nothing, as the value won't be used anyway */
163                         return;
164                 }
165
166                 /* If one of the variables resides in memory, we can eliminate
167                    the register move from/to the temporary register with the
168                    order of getting the destination register and the load. */
169
170                 if (IS_INMEMORY(src->flags)) {
171                         if (IS_FLT_DBL_TYPE(dst->type))
172                                 d = codegen_reg_of_var(iptr->opc, dst, REG_FTMP1);
173                         else
174                                 d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
175                         s1 = emit_load(jd, iptr, src, d);
176                 }
177                 else {
178                         if (IS_FLT_DBL_TYPE(src->type))
179                                 s1 = emit_load(jd, iptr, src, REG_FTMP1);
180                         else
181                                 s1 = emit_load(jd, iptr, src, REG_ITMP1);
182                         d = codegen_reg_of_var(iptr->opc, dst, s1);
183                 }
184
185                 if (s1 != d) {
186                         if (IS_FLT_DBL_TYPE(src->type))
187                                 M_FMOV(s1, d);
188                         else
189                                 M_MOV(s1, d);
190                 }
191
192                 emit_store(jd, iptr, dst, d);
193         }
194 }
195
196
197 void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d)
198 {
199 #if 0
200         switch (iptr->flags.fields.condition) {
201         case ICMD_IFEQ:
202                 M_CMOVEQ(s, d);
203                 break;
204         case ICMD_IFNE:
205                 M_CMOVNE(s, d);
206                 break;
207         case ICMD_IFLT:
208                 M_CMOVLT(s, d);
209                 break;
210         case ICMD_IFGE:
211                 M_CMOVGE(s, d);
212                 break;
213         case ICMD_IFGT:
214                 M_CMOVGT(s, d);
215                 break;
216         case ICMD_IFLE:
217                 M_CMOVLE(s, d);
218                 break;
219         }
220 #endif
221 }
222
223
224 /* emit_exception_stubs ********************************************************
225
226    Generates the code for the exception stubs.
227
228 *******************************************************************************/
229
230 __PORTED__ void emit_exception_stubs(jitdata *jd)
231 {
232         codegendata  *cd;
233         registerdata *rd;
234         exceptionref *er;
235         s4            branchmpc;
236         s4            targetmpc;
237         s4            targetdisp;
238         s4            disp;
239
240         /* get required compiler data */
241
242         cd = jd->cd;
243         rd = jd->rd;
244
245         /* generate exception stubs */
246
247         targetdisp = 0;
248
249         for (er = cd->exceptionrefs; er != NULL; er = er->next) {
250                 /* back-patch the branch to this exception code */
251
252                 branchmpc = er->branchpos;
253                 targetmpc = cd->mcodeptr - cd->mcodebase;
254
255                 md_codegen_patch_branch(cd, branchmpc, targetmpc);
256
257                 MCODECHECK(512);
258
259                 /* move index register into REG_ITMP1 */
260
261                 /* Check if the exception is an
262                    ArrayIndexOutOfBoundsException.  If so, move index register
263                    into a4. */
264
265                 if (er->reg != -1)
266                         M_MOV(er->reg, rd->argintregs[4]);
267
268                 /* calcuate exception address */
269
270                 if (N_VALID_DISP(er->branchpos - 4)) {
271                         M_LDA(rd->argintregs[3], REG_PV, er->branchpos - 4);
272                 } else {
273                         M_INTMOVE(REG_PV, rd->argintregs[3]);
274                         M_AADD_IMM(er->branchpos - 4, rd->argintregs[3]);
275                 }
276
277                 /* move function to call into REG_ITMP! */
278
279                 disp = dseg_add_functionptr(cd, er->function);
280                 M_ALD(REG_ITMP1, REG_PV, disp);
281
282                 if (targetdisp == 0) {
283                         targetdisp = (cd->mcodeptr) - (cd->mcodebase);
284
285                         M_MOV(REG_PV, rd->argintregs[0]);
286                         M_MOV(REG_SP, rd->argintregs[1]);
287
288                         M_ALD(rd->argintregs[2],
289                                   REG_SP, cd->stackframesize * 4 - SIZEOF_VOID_P);
290
291                         M_ASUB_IMM((2 * 4) + 96, REG_SP);       
292
293                         M_AST(rd->argintregs[3], REG_SP, (0 * 4) + 96); /* store XPC */
294
295                         M_JSR(REG_RA, REG_ITMP1);
296
297                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
298
299                         M_ALD(REG_ITMP2_XPC, REG_SP, (0 * 4) + 96);
300                         M_AADD_IMM((2 * 4) + 96, REG_SP);
301
302                         disp = dseg_add_functionptr(cd, asm_handle_exception);
303                         M_ALD(REG_ITMP3, REG_PV, disp);
304                         M_JMP(RN, REG_ITMP3);
305                 }
306                 else {
307                         disp = ((cd->mcodebase) + targetdisp) -
308                                 (( cd->mcodeptr) );
309
310                         M_BR(disp);
311                 }
312
313         }
314 }
315
316
317 /* emit_patcher_stubs **********************************************************
318
319    Generates the code for the patcher stubs.
320
321 *******************************************************************************/
322
323 __PORTED__ void emit_patcher_stubs(jitdata *jd)
324 {
325         
326         codegendata *cd;
327         patchref    *pref;
328         u4           mcode;
329         u1          *savedmcodeptr;
330         u1          *tmpmcodeptr;
331         s4           targetdisp;
332         s4           disp;
333
334         /* get required compiler data */
335
336         cd = jd->cd;
337
338         /* generate code patching stub call code */
339
340         targetdisp = 0;
341
342         for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
343                 /* check code segment size */
344
345                 MCODECHECK(100);
346
347                 /* Get machine code which is patched back in later. The
348                    call is 1 instruction word long. */
349
350                 tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
351
352                 mcode = *((u4 *) tmpmcodeptr);
353
354                 /* Patch in the call to call the following code (done at
355                    compile time). */
356
357                 savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr              */
358                 cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position     */
359
360                 disp = (savedmcodeptr) - (tmpmcodeptr);
361                 M_BSR(REG_ITMP3, disp);
362
363                 cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr       */
364
365                 /* create stack frame */
366
367                 M_ASUB_IMM(6 * 4, REG_SP);
368
369                 /* move return address onto stack */
370
371                 M_AST(REG_ITMP3, REG_SP, 5 * 4);
372
373                 /* move pointer to java_objectheader onto stack */
374
375 #if defined(ENABLE_THREADS)
376                 /* create a virtual java_objectheader */
377
378                 (void) dseg_add_unique_address(cd, NULL);                  /* flcword */
379                 (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
380                 disp = dseg_add_unique_address(cd, NULL);                  /* vftbl   */
381
382                 M_LDA(REG_ITMP3, REG_PV, disp);
383                 M_AST(REG_ITMP3, REG_SP, 4 * 4);
384 #else
385                 /* nothing to do */
386 #endif
387
388                 /* move machine code onto stack */
389
390                 disp = dseg_add_s4(cd, mcode);
391                 M_ILD(REG_ITMP3, REG_PV, disp);
392                 M_IST(REG_ITMP3, REG_SP, 3 * 4);
393
394                 /* move class/method/field reference onto stack */
395
396                 disp = dseg_add_address(cd, pref->ref);
397                 M_ALD(REG_ITMP3, REG_PV, disp);
398                 M_AST(REG_ITMP3, REG_SP, 2 * 4);
399
400                 /* move data segment displacement onto stack */
401
402                 disp = dseg_add_s4(cd, pref->disp);
403                 M_ILD(REG_ITMP3, REG_PV, disp);
404                 M_IST(REG_ITMP3, REG_SP, 1 * 4);
405
406                 /* move patcher function pointer onto stack */
407
408                 disp = dseg_add_functionptr(cd, pref->patcher);
409                 M_ALD(REG_ITMP3, REG_PV, disp);
410                 M_AST(REG_ITMP3, REG_SP, 0 * 4);
411
412                 if (targetdisp == 0) {
413                         targetdisp = (cd->mcodeptr) - (cd->mcodebase);
414
415                         disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
416                         M_ALD(REG_ITMP3, REG_PV, disp);
417                         M_JMP(RN, REG_ITMP3);
418                 }
419                 else {
420                         disp = ((cd->mcodebase) + targetdisp) -
421                                 (( cd->mcodeptr) );
422
423                         M_BR(disp);
424                 }
425         }
426 }
427
428
429 /* emit_replacement_stubs ******************************************************
430
431    Generates the code for the replacement stubs.
432
433 *******************************************************************************/
434
435 void emit_replacement_stubs(jitdata *jd)
436 {
437 #if 0
438         codegendata *cd;
439         codeinfo    *code;
440         rplpoint    *rplp;
441         s4           disp;
442         s4           i;
443
444         /* get required compiler data */
445
446         cd   = jd->cd;
447         code = jd->code;
448
449         rplp = code->rplpoints;
450
451         for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
452                 /* check code segment size */
453
454                 MCODECHECK(512);
455
456                 /* note start of stub code */
457
458                 rplp->outcode = (u1 *) (ptrint) (cd->mcodeptr - cd->mcodebase);
459
460                 /* make machine code for patching */
461
462                 disp = (ptrint) (rplp->outcode - rplp->pc) - 5;
463
464                 rplp->mcode = 0xe9 | ((u8) disp << 8);
465
466                 /* push address of `rplpoint` struct */
467                         
468                 M_MOV_IMM(rplp, REG_ITMP3);
469                 M_PUSH(REG_ITMP3);
470
471                 /* jump to replacement function */
472
473                 M_MOV_IMM(asm_replacement_out, REG_ITMP3);
474                 M_JMP(REG_ITMP3);
475         }
476 #endif
477 }
478         
479
480 /* emit_verbosecall_enter ******************************************************
481
482    Generates the code for the call trace.
483
484 *******************************************************************************/
485
486 #if !defined(NDEBUG)
487 void emit_verbosecall_enter(jitdata *jd)
488 {
489         
490         methodinfo   *m;
491         codegendata  *cd;
492         registerdata *rd;
493         methoddesc   *md;
494         s4            i, j, k;
495         s4            stackframesize, off, foff, aoff, doff, t, iargctr, fargctr, disp;
496
497         /* get required compiler data */
498
499         m  = jd->m;
500         cd = jd->cd;
501         rd = jd->rd;
502
503         md = m->parseddesc;
504
505         /* mark trace code */
506
507         M_NOP;
508
509         stackframesize = 
510                 (6 * 8) + /* s8 on stack parameters x 6 */
511                 (1 * 4) + /* methodinfo on stack parameter */
512                 (ARG_CNT * 8) +
513                 (TMP_CNT * 8) 
514                 ;
515
516         M_ASUB_IMM(stackframesize, REG_SP); /* allocate stackframe */
517
518         /* save argument registers */
519
520         off = (6 * 8) + (1 * 4);
521
522         for (i = 0; i < INT_ARG_CNT; i++, off += 8)
523                 M_IST(rd->argintregs[i], REG_SP, off);
524
525         for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
526                 M_DST(rd->argfltregs[i], REG_SP, off);
527
528         /* save temporary registers for leaf methods */
529
530         if (jd->isleafmethod) {
531                 for (i = 0; i < INT_TMP_CNT; i++, off += 8)
532                         M_LST(rd->tmpintregs[i], REG_SP, off);
533
534                 for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
535                         M_DST(rd->tmpfltregs[i], REG_SP, off);
536         }
537
538         /* Load arguments to new locations */
539
540         /* First move all arguments to stack
541          *
542          * (s8) a7
543          * (s8) a2
544          *   ...
545          * (s8) a1 \ Auxilliary stack frame
546          * (s8) a0 /
547          * ------- <---- SP
548          */
549
550         M_ASUB_IMM(2 * 8, REG_SP);
551         
552         /* offset to where first integer arg is saved on stack */
553         off = (2 * 8) + (6 * 8) + (1 * 4); 
554         /* offset to where first float arg is saved on stack */
555         foff = off + (INT_ARG_CNT * 8); 
556         /* offset to where first argument is passed on stack */
557         aoff = (2 * 8) + stackframesize + (cd->stackframesize * 4);
558         /* offset to destination on stack */
559         doff = 0; 
560
561         iargctr = fargctr = 0;
562
563         ICONST(REG_ITMP1, 0);
564
565         for (i = 0; i < md->paramcount && i < 8; i++) {
566                 t = md->paramtypes[i].type;
567
568                 M_IST(REG_ITMP1, REG_SP, doff);
569                 M_IST(REG_ITMP1, REG_SP, doff + 4);
570
571                 if (IS_FLT_DBL_TYPE(t)) {
572                         if (fargctr < 2) { /* passed in register */
573                                 N_STD(REG_FA0 + fargctr, doff, RN, REG_SP);
574                                 fargctr += 1;
575                         } else { /* passed on stack */
576                                 if (IS_2_WORD_TYPE(t)) {
577                                         N_MVC(doff, 8, REG_SP, aoff, REG_SP);
578                                         aoff += 8;
579                                 } else {
580                                         N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
581                                         aoff += 4;
582                                 }
583                         }
584                 } else {
585                         if (IS_2_WORD_TYPE(t)) {
586                                 if (iargctr < 4) { /* passed in 2 registers */
587                                         N_STM(REG_A0 + iargctr, REG_A0 + iargctr + 1, doff, REG_SP);
588                                         iargctr += 2;
589                                 } else { /* passed on stack */
590                                         N_MVC(doff, 8, REG_SP, aoff, REG_SP);
591                                         aoff += 8;
592                                 }
593                         } else {
594                                 if (iargctr < 5) { /* passed in register */
595                                         N_ST(REG_A0 + iargctr, doff + 4, RN, REG_SP);
596                                         iargctr += 1;
597                                 } else { /* passed on stack */
598                                         N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
599                                         aoff += 4;
600                                 }
601                         }
602                 }
603
604                 doff += 8;
605         }
606
607         /* Now move a0 and a1 to registers
608          *
609          * (s8) a7
610          *   ...
611          * (s8) a2
612          * ------- <- SP
613          * (s8) a0 ==> a0, a1
614          * (s8) a1 ==> a2, a3
615          */
616
617         N_LM(REG_A0, REG_A1, 0, REG_SP);
618         N_LM(REG_A2, REG_A3, 8, REG_SP);
619
620         M_AADD_IMM(2 * 8, REG_SP);
621
622         /* Finally load methodinfo argument */
623
624         disp = dseg_add_address(cd, m);
625         M_ALD(REG_ITMP2, REG_PV, disp); 
626         M_AST(REG_ITMP2, REG_SP, 6 * 8);
627
628         /* Call builtin_verbosecall_enter */
629
630         disp = dseg_add_address(cd, builtin_verbosecall_enter);
631         M_ALD(REG_ITMP2, REG_PV, disp);
632         M_ASUB_IMM(96, REG_SP);
633         M_CALL(REG_ITMP2);
634         M_AADD_IMM(96, REG_SP);
635
636         /* restore argument registers */
637
638         off = (6 * 8) + (1 * 4);
639
640         for (i = 0; i < INT_ARG_CNT; i++, off += 8)
641                 M_ILD(rd->argintregs[i], REG_SP, off);
642
643         for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
644                 M_DLD(rd->argfltregs[i], REG_SP, off);
645
646         /* restore temporary registers for leaf methods */
647
648         if (jd->isleafmethod) {
649                 for (i = 0; i < INT_TMP_CNT; i++, off += 8)
650                         M_ILD(rd->tmpintregs[i], REG_SP, off);
651
652                 for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
653                         M_DLD(rd->tmpfltregs[i], REG_SP, off);
654         }
655
656         /* remove stackframe */
657
658         M_AADD_IMM(stackframesize, REG_SP);
659
660         /* mark trace code */
661
662         M_NOP;
663 }
664 #endif /* !defined(NDEBUG) */
665
666
667 /* emit_verbosecall_exit *******************************************************
668
669    Generates the code for the call trace.
670
671 *******************************************************************************/
672
673 #if !defined(NDEBUG)
674 void emit_verbosecall_exit(jitdata *jd)
675 {
676         methodinfo   *m;
677         codegendata  *cd;
678         registerdata *rd;
679         s4            disp;
680
681         /* get required compiler data */
682
683         m  = jd->m;
684         cd = jd->cd;
685         rd = jd->rd;
686
687         /* mark trace code */
688
689         M_NOP;
690
691         M_ASUB_IMM(2 * 8, REG_SP);
692
693         N_STM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
694         M_DST(REG_FRESULT, REG_SP, 1 * 8);
695
696         if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) {
697                 /* (REG_A0, REG_A1) == (REG_RESULT, REG_RESULT2), se no need to move */
698         } else {
699                 M_INTMOVE(REG_RESULT, REG_A1);
700                 ICONST(REG_A0, 0);
701         }
702
703         disp = dseg_add_address(cd, m);
704         M_ALD(REG_A2, REG_PV, disp);
705
706         /* REG_FRESULT is REG_FA0, so no need to move */
707         M_FLTMOVE(REG_FRESULT, REG_FA1);
708
709         disp = dseg_add_address(cd, builtin_verbosecall_exit);
710         M_ALD(REG_ITMP1, REG_PV, disp);
711         M_ASUB_IMM(96, REG_SP);
712         M_CALL(REG_ITMP1);
713         M_AADD_IMM(96, REG_SP);
714
715         N_LM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
716         M_DLD(REG_FRESULT, REG_SP, 1 * 8);
717
718         M_AADD_IMM(2 * 8, REG_SP);
719
720         /* mark trace code */
721
722         M_NOP;
723 }
724 #endif /* !defined(NDEBUG) */
725
726
727 /* code generation functions **************************************************/
728
729 static void emit_membase(codegendata *cd, s4 basereg, s4 disp, s4 dreg)
730 {
731         if ((basereg == REG_SP) || (basereg == R12)) {
732                 if (disp == 0) {
733                         emit_address_byte(0, dreg, REG_SP);
734                         emit_address_byte(0, REG_SP, REG_SP);
735
736                 } else if (IS_IMM8(disp)) {
737                         emit_address_byte(1, dreg, REG_SP);
738                         emit_address_byte(0, REG_SP, REG_SP);
739                         emit_imm8(disp);
740
741                 } else {
742                         emit_address_byte(2, dreg, REG_SP);
743                         emit_address_byte(0, REG_SP, REG_SP);
744                         emit_imm32(disp);
745                 }
746
747         } else if ((disp) == 0 && (basereg) != RBP && (basereg) != R13) {
748                 emit_address_byte(0,(dreg),(basereg));
749
750         } else if ((basereg) == RIP) {
751                 emit_address_byte(0, dreg, RBP);
752                 emit_imm32(disp);
753
754         } else {
755                 if (IS_IMM8(disp)) {
756                         emit_address_byte(1, dreg, basereg);
757                         emit_imm8(disp);
758
759                 } else {
760                         emit_address_byte(2, dreg, basereg);
761                         emit_imm32(disp);
762                 }
763         }
764 }
765
766
767 static void emit_membase32(codegendata *cd, s4 basereg, s4 disp, s4 dreg)
768 {
769         if ((basereg == REG_SP) || (basereg == R12)) {
770                 emit_address_byte(2, dreg, REG_SP);
771                 emit_address_byte(0, REG_SP, REG_SP);
772                 emit_imm32(disp);
773         }
774         else {
775                 emit_address_byte(2, dreg, basereg);
776                 emit_imm32(disp);
777         }
778 }
779
780
781 static void emit_memindex(codegendata *cd, s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale)
782 {
783         if (basereg == -1) {
784                 emit_address_byte(0, reg, 4);
785                 emit_address_byte(scale, indexreg, 5);
786                 emit_imm32(disp);
787         }
788         else if ((disp == 0) && (basereg != RBP) && (basereg != R13)) {
789                 emit_address_byte(0, reg, 4);
790                 emit_address_byte(scale, indexreg, basereg);
791         }
792         else if (IS_IMM8(disp)) {
793                 emit_address_byte(1, reg, 4);
794                 emit_address_byte(scale, indexreg, basereg);
795                 emit_imm8(disp);
796         }
797         else {
798                 emit_address_byte(2, reg, 4);
799                 emit_address_byte(scale, indexreg, basereg);
800                 emit_imm32(disp);
801         }
802 }
803
804
805 void emit_ishift(jitdata *jd, s4 shift_op, instruction *iptr)
806 {
807         s4 s1, s2, d, d_old;
808         varinfo *v_s1,*v_s2,*v_dst;
809         codegendata *cd;
810
811         /* get required compiler data */
812
813         cd = jd->cd;
814
815         v_s1  = VAROP(iptr->s1);
816         v_s2  = VAROP(iptr->sx.s23.s2);
817         v_dst = VAROP(iptr->dst);
818
819         s1 = v_s1->vv.regoff;
820         s2 = v_s2->vv.regoff;
821         d  = v_dst->vv.regoff;
822
823         M_INTMOVE(RCX, REG_ITMP1);                                    /* save RCX */
824
825         if (IS_INMEMORY(v_dst->flags)) {
826                 if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
827                         if (s1 == d) {
828                                 M_ILD(RCX, REG_SP, s2 * 8);
829                                 emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
830
831                         } else {
832                                 M_ILD(RCX, REG_SP, s2 * 8);
833                                 M_ILD(REG_ITMP2, REG_SP, s1 * 8);
834                                 emit_shiftl_reg(cd, shift_op, REG_ITMP2);
835                                 M_IST(REG_ITMP2, REG_SP, d * 8);
836                         }
837
838                 } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
839                         /* s1 may be equal to RCX */
840                         if (s1 == RCX) {
841                                 if (s2 == d) {
842                                         M_ILD(REG_ITMP1, REG_SP, s2 * 8);
843                                         M_IST(s1, REG_SP, d * 8);
844                                         M_INTMOVE(REG_ITMP1, RCX);
845
846                                 } else {
847                                         M_IST(s1, REG_SP, d * 8);
848                                         M_ILD(RCX, REG_SP, s2 * 8);
849                                 }
850
851                         } else {
852                                 M_ILD(RCX, REG_SP, s2 * 8);
853                                 M_IST(s1, REG_SP, d * 8);
854                         }
855
856                         emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
857
858                 } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
859                         if (s1 == d) {
860                                 M_INTMOVE(s2, RCX);
861                                 emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
862
863                         } else {
864                                 M_INTMOVE(s2, RCX);
865                                 M_ILD(REG_ITMP2, REG_SP, s1 * 8);
866                                 emit_shiftl_reg(cd, shift_op, REG_ITMP2);
867                                 M_IST(REG_ITMP2, REG_SP, d * 8);
868                         }
869
870                 } else {
871                         /* s1 may be equal to RCX */
872                         M_IST(s1, REG_SP, d * 8);
873                         M_INTMOVE(s2, RCX);
874                         emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
875                 }
876
877                 M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
878
879         } else {
880                 d_old = d;
881                 if (d == RCX) {
882                         d = REG_ITMP3;
883                 }
884                                         
885                 if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
886                         M_ILD(RCX, REG_SP, s2 * 8);
887                         M_ILD(d, REG_SP, s1 * 8);
888                         emit_shiftl_reg(cd, shift_op, d);
889
890                 } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
891                         /* s1 may be equal to RCX */
892                         M_INTMOVE(s1, d);
893                         M_ILD(RCX, REG_SP, s2 * 8);
894                         emit_shiftl_reg(cd, shift_op, d);
895
896                 } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
897                         M_INTMOVE(s2, RCX);
898                         M_ILD(d, REG_SP, s1 * 8);
899                         emit_shiftl_reg(cd, shift_op, d);
900
901                 } else {
902                         /* s1 may be equal to RCX */
903                         if (s1 == RCX) {
904                                 if (s2 == d) {
905                                         /* d cannot be used to backup s1 since this would
906                                            overwrite s2. */
907                                         M_INTMOVE(s1, REG_ITMP3);
908                                         M_INTMOVE(s2, RCX);
909                                         M_INTMOVE(REG_ITMP3, d);
910
911                                 } else {
912                                         M_INTMOVE(s1, d);
913                                         M_INTMOVE(s2, RCX);
914                                 }
915
916                         } else {
917                                 /* d may be equal to s2 */
918                                 M_INTMOVE(s2, RCX);
919                                 M_INTMOVE(s1, d);
920                         }
921                         emit_shiftl_reg(cd, shift_op, d);
922                 }
923
924                 if (d_old == RCX)
925                         M_INTMOVE(REG_ITMP3, RCX);
926                 else
927                         M_INTMOVE(REG_ITMP1, RCX);                         /* restore RCX */
928         }
929 }
930
931
932 void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr)
933 {
934         s4 s1, s2, d, d_old;
935         varinfo *v_s1,*v_s2,*v_dst;
936         codegendata *cd;
937
938         /* get required compiler data */
939
940         cd = jd->cd;
941
942         v_s1  = VAROP(iptr->s1);
943         v_s2  = VAROP(iptr->sx.s23.s2);
944         v_dst = VAROP(iptr->dst);
945
946         s1 = v_s1->vv.regoff;
947         s2 = v_s2->vv.regoff;
948         d  = v_dst->vv.regoff;
949         
950         M_INTMOVE(RCX, REG_ITMP1);                                    /* save RCX */
951
952         if (IS_INMEMORY(v_dst->flags)) {
953                 if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
954                         if (s1 == d) {
955                                 M_ILD(RCX, REG_SP, s2 * 8);
956                                 emit_shift_membase(cd, shift_op, REG_SP, d * 8);
957
958                         } else {
959                                 M_ILD(RCX, REG_SP, s2 * 8);
960                                 M_LLD(REG_ITMP2, REG_SP, s1 * 8);
961                                 emit_shift_reg(cd, shift_op, REG_ITMP2);
962                                 M_LST(REG_ITMP2, REG_SP, d * 8);
963                         }
964
965                 } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
966                         /* s1 may be equal to RCX */
967                         if (s1 == RCX) {
968                                 if (s2 == d) {
969                                         M_ILD(REG_ITMP1, REG_SP, s2 * 8);
970                                         M_LST(s1, REG_SP, d * 8);
971                                         M_INTMOVE(REG_ITMP1, RCX);
972
973                                 } else {
974                                         M_LST(s1, REG_SP, d * 8);
975                                         M_ILD(RCX, REG_SP, s2 * 8);
976                                 }
977
978                         } else {
979                                 M_ILD(RCX, REG_SP, s2 * 8);
980                                 M_LST(s1, REG_SP, d * 8);
981                         }
982
983                         emit_shift_membase(cd, shift_op, REG_SP, d * 8);
984
985                 } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
986                         if (s1 == d) {
987                                 M_INTMOVE(s2, RCX);
988                                 emit_shift_membase(cd, shift_op, REG_SP, d * 8);
989
990                         } else {
991                                 M_INTMOVE(s2, RCX);
992                                 M_LLD(REG_ITMP2, REG_SP, s1 * 8);
993                                 emit_shift_reg(cd, shift_op, REG_ITMP2);
994                                 M_LST(REG_ITMP2, REG_SP, d * 8);
995                         }
996
997                 } else {
998                         /* s1 may be equal to RCX */
999                         M_LST(s1, REG_SP, d * 8);
1000                         M_INTMOVE(s2, RCX);
1001                         emit_shift_membase(cd, shift_op, REG_SP, d * 8);
1002                 }
1003
1004                 M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
1005
1006         } else {
1007                 d_old = d;
1008                 if (d == RCX) {
1009                         d = REG_ITMP3;
1010                 }
1011
1012                 if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
1013                         M_ILD(RCX, REG_SP, s2 * 8);
1014                         M_LLD(d, REG_SP, s1 * 8);
1015                         emit_shift_reg(cd, shift_op, d);
1016
1017                 } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
1018                         /* s1 may be equal to RCX */
1019                         M_INTMOVE(s1, d);
1020                         M_ILD(RCX, REG_SP, s2 * 8);
1021                         emit_shift_reg(cd, shift_op, d);
1022
1023                 } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
1024                         M_INTMOVE(s2, RCX);
1025                         M_LLD(d, REG_SP, s1 * 8);
1026                         emit_shift_reg(cd, shift_op, d);
1027
1028                 } else {
1029                         /* s1 may be equal to RCX */
1030                         if (s1 == RCX) {
1031                                 if (s2 == d) {
1032                                         /* d cannot be used to backup s1 since this would
1033                                            overwrite s2. */
1034                                         M_INTMOVE(s1, REG_ITMP3);
1035                                         M_INTMOVE(s2, RCX);
1036                                         M_INTMOVE(REG_ITMP3, d);
1037
1038                                 } else {
1039                                         M_INTMOVE(s1, d);
1040                                         M_INTMOVE(s2, RCX);
1041                                 }
1042
1043                         } else {
1044                                 /* d may be equal to s2 */
1045                                 M_INTMOVE(s2, RCX);
1046                                 M_INTMOVE(s1, d);
1047                         }
1048                         emit_shift_reg(cd, shift_op, d);
1049                 }
1050
1051                 if (d_old == RCX)
1052                         M_INTMOVE(REG_ITMP3, RCX);
1053                 else
1054                         M_INTMOVE(REG_ITMP1, RCX);                         /* restore RCX */
1055         }
1056 }
1057
1058
1059 /* low-level code emitter functions *******************************************/
1060
1061 void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg)
1062 {
1063         emit_rex(1,(reg),0,(dreg));
1064         *(cd->mcodeptr++) = 0x89;
1065         emit_reg((reg),(dreg));
1066 }
1067
1068
1069 void emit_mov_imm_reg(codegendata *cd, s8 imm, s8 reg)
1070 {
1071         emit_rex(1,0,0,(reg));
1072         *(cd->mcodeptr++) = 0xb8 + ((reg) & 0x07);
1073         emit_imm64((imm));
1074 }
1075
1076
1077 void emit_movl_reg_reg(codegendata *cd, s8 reg, s8 dreg)
1078 {
1079         emit_rex(0,(reg),0,(dreg));
1080         *(cd->mcodeptr++) = 0x89;
1081         emit_reg((reg),(dreg));
1082 }
1083
1084
1085 void emit_movl_imm_reg(codegendata *cd, s8 imm, s8 reg) {
1086         emit_rex(0,0,0,(reg));
1087         *(cd->mcodeptr++) = 0xb8 + ((reg) & 0x07);
1088         emit_imm32((imm));
1089 }
1090
1091
1092 void emit_mov_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
1093         emit_rex(1,(reg),0,(basereg));
1094         *(cd->mcodeptr++) = 0x8b;
1095         emit_membase(cd, (basereg),(disp),(reg));
1096 }
1097
1098
1099 /*
1100  * this one is for INVOKEVIRTUAL/INVOKEINTERFACE to have a
1101  * constant membase immediate length of 32bit
1102  */
1103 void emit_mov_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
1104         emit_rex(1,(reg),0,(basereg));
1105         *(cd->mcodeptr++) = 0x8b;
1106         emit_membase32(cd, (basereg),(disp),(reg));
1107 }
1108
1109
1110 void emit_movl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg)
1111 {
1112         emit_rex(0,(reg),0,(basereg));
1113         *(cd->mcodeptr++) = 0x8b;
1114         emit_membase(cd, (basereg),(disp),(reg));
1115 }
1116
1117
1118 /* ATTENTION: Always emit a REX byte, because the instruction size can
1119    be smaller when all register indexes are smaller than 7. */
1120 void emit_movl_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg)
1121 {
1122         emit_byte_rex((reg),0,(basereg));
1123         *(cd->mcodeptr++) = 0x8b;
1124         emit_membase32(cd, (basereg),(disp),(reg));
1125 }
1126
1127
1128 void emit_mov_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
1129         emit_rex(1,(reg),0,(basereg));
1130         *(cd->mcodeptr++) = 0x89;
1131         emit_membase(cd, (basereg),(disp),(reg));
1132 }
1133
1134
1135 void emit_mov_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
1136         emit_rex(1,(reg),0,(basereg));
1137         *(cd->mcodeptr++) = 0x89;
1138         emit_membase32(cd, (basereg),(disp),(reg));
1139 }
1140
1141
1142 void emit_movl_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
1143         emit_rex(0,(reg),0,(basereg));
1144         *(cd->mcodeptr++) = 0x89;
1145         emit_membase(cd, (basereg),(disp),(reg));
1146 }
1147
1148
1149 /* Always emit a REX byte, because the instruction size can be smaller when   */
1150 /* all register indexes are smaller than 7.                                   */
1151 void emit_movl_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
1152         emit_byte_rex((reg),0,(basereg));
1153         *(cd->mcodeptr++) = 0x89;
1154         emit_membase32(cd, (basereg),(disp),(reg));
1155 }
1156
1157
1158 void emit_mov_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
1159         emit_rex(1,(reg),(indexreg),(basereg));
1160         *(cd->mcodeptr++) = 0x8b;
1161         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1162 }
1163
1164
1165 void emit_movl_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
1166         emit_rex(0,(reg),(indexreg),(basereg));
1167         *(cd->mcodeptr++) = 0x8b;
1168         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1169 }
1170
1171
1172 void emit_mov_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
1173         emit_rex(1,(reg),(indexreg),(basereg));
1174         *(cd->mcodeptr++) = 0x89;
1175         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1176 }
1177
1178
1179 void emit_movl_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
1180         emit_rex(0,(reg),(indexreg),(basereg));
1181         *(cd->mcodeptr++) = 0x89;
1182         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1183 }
1184
1185
1186 void emit_movw_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
1187         *(cd->mcodeptr++) = 0x66;
1188         emit_rex(0,(reg),(indexreg),(basereg));
1189         *(cd->mcodeptr++) = 0x89;
1190         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1191 }
1192
1193
1194 void emit_movb_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
1195         emit_byte_rex((reg),(indexreg),(basereg));
1196         *(cd->mcodeptr++) = 0x88;
1197         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1198 }
1199
1200
1201 void emit_mov_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
1202         emit_rex(1,0,0,(basereg));
1203         *(cd->mcodeptr++) = 0xc7;
1204         emit_membase(cd, (basereg),(disp),0);
1205         emit_imm32((imm));
1206 }
1207
1208
1209 void emit_mov_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
1210         emit_rex(1,0,0,(basereg));
1211         *(cd->mcodeptr++) = 0xc7;
1212         emit_membase32(cd, (basereg),(disp),0);
1213         emit_imm32((imm));
1214 }
1215
1216
1217 void emit_movl_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
1218         emit_rex(0,0,0,(basereg));
1219         *(cd->mcodeptr++) = 0xc7;
1220         emit_membase(cd, (basereg),(disp),0);
1221         emit_imm32((imm));
1222 }
1223
1224
1225 /* Always emit a REX byte, because the instruction size can be smaller when   */
1226 /* all register indexes are smaller than 7.                                   */
1227 void emit_movl_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
1228         emit_byte_rex(0,0,(basereg));
1229         *(cd->mcodeptr++) = 0xc7;
1230         emit_membase32(cd, (basereg),(disp),0);
1231         emit_imm32((imm));
1232 }
1233
1234
1235 void emit_movsbq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
1236 {
1237         emit_rex(1,(dreg),0,(reg));
1238         *(cd->mcodeptr++) = 0x0f;
1239         *(cd->mcodeptr++) = 0xbe;
1240         /* XXX: why do reg and dreg have to be exchanged */
1241         emit_reg((dreg),(reg));
1242 }
1243
1244
1245 void emit_movswq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
1246 {
1247         emit_rex(1,(dreg),0,(reg));
1248         *(cd->mcodeptr++) = 0x0f;
1249         *(cd->mcodeptr++) = 0xbf;
1250         /* XXX: why do reg and dreg have to be exchanged */
1251         emit_reg((dreg),(reg));
1252 }
1253
1254
1255 void emit_movslq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
1256 {
1257         emit_rex(1,(dreg),0,(reg));
1258         *(cd->mcodeptr++) = 0x63;
1259         /* XXX: why do reg and dreg have to be exchanged */
1260         emit_reg((dreg),(reg));
1261 }
1262
1263
1264 void emit_movzwq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
1265 {
1266         emit_rex(1,(dreg),0,(reg));
1267         *(cd->mcodeptr++) = 0x0f;
1268         *(cd->mcodeptr++) = 0xb7;
1269         /* XXX: why do reg and dreg have to be exchanged */
1270         emit_reg((dreg),(reg));
1271 }
1272
1273
1274 void emit_movswq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
1275         emit_rex(1,(reg),(indexreg),(basereg));
1276         *(cd->mcodeptr++) = 0x0f;
1277         *(cd->mcodeptr++) = 0xbf;
1278         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1279 }
1280
1281
1282 void emit_movsbq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
1283         emit_rex(1,(reg),(indexreg),(basereg));
1284         *(cd->mcodeptr++) = 0x0f;
1285         *(cd->mcodeptr++) = 0xbe;
1286         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1287 }
1288
1289
1290 void emit_movzwq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
1291         emit_rex(1,(reg),(indexreg),(basereg));
1292         *(cd->mcodeptr++) = 0x0f;
1293         *(cd->mcodeptr++) = 0xb7;
1294         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
1295 }
1296
1297
1298 void emit_mov_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
1299 {
1300         emit_rex(1,0,(indexreg),(basereg));
1301         *(cd->mcodeptr++) = 0xc7;
1302         emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
1303         emit_imm32((imm));
1304 }
1305
1306
1307 void emit_movl_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
1308 {
1309         emit_rex(0,0,(indexreg),(basereg));
1310         *(cd->mcodeptr++) = 0xc7;
1311         emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
1312         emit_imm32((imm));
1313 }
1314
1315
1316 void emit_movw_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
1317 {
1318         *(cd->mcodeptr++) = 0x66;
1319         emit_rex(0,0,(indexreg),(basereg));
1320         *(cd->mcodeptr++) = 0xc7;
1321         emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
1322         emit_imm16((imm));
1323 }
1324
1325
1326 void emit_movb_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
1327 {
1328         emit_rex(0,0,(indexreg),(basereg));
1329         *(cd->mcodeptr++) = 0xc6;
1330         emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
1331         emit_imm8((imm));
1332 }
1333
1334
1335 /*
1336  * alu operations
1337  */
1338 void emit_alu_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
1339 {
1340         emit_rex(1,(reg),0,(dreg));
1341         *(cd->mcodeptr++) = (((opc)) << 3) + 1;
1342         emit_reg((reg),(dreg));
1343 }
1344
1345
1346 void emit_alul_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
1347 {
1348         emit_rex(0,(reg),0,(dreg));
1349         *(cd->mcodeptr++) = (((opc)) << 3) + 1;
1350         emit_reg((reg),(dreg));
1351 }
1352
1353
1354 void emit_alu_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp)
1355 {
1356         emit_rex(1,(reg),0,(basereg));
1357         *(cd->mcodeptr++) = (((opc)) << 3) + 1;
1358         emit_membase(cd, (basereg),(disp),(reg));
1359 }
1360
1361
1362 void emit_alul_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp)
1363 {
1364         emit_rex(0,(reg),0,(basereg));
1365         *(cd->mcodeptr++) = (((opc)) << 3) + 1;
1366         emit_membase(cd, (basereg),(disp),(reg));
1367 }
1368
1369
1370 void emit_alu_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg)
1371 {
1372         emit_rex(1,(reg),0,(basereg));
1373         *(cd->mcodeptr++) = (((opc)) << 3) + 3;
1374         emit_membase(cd, (basereg),(disp),(reg));
1375 }
1376
1377
1378 void emit_alul_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg)
1379 {
1380         emit_rex(0,(reg),0,(basereg));
1381         *(cd->mcodeptr++) = (((opc)) << 3) + 3;
1382         emit_membase(cd, (basereg),(disp),(reg));
1383 }
1384
1385
1386 void emit_alu_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
1387         if (IS_IMM8(imm)) {
1388                 emit_rex(1,0,0,(dreg));
1389                 *(cd->mcodeptr++) = 0x83;
1390                 emit_reg((opc),(dreg));
1391                 emit_imm8((imm));
1392         } else {
1393                 emit_rex(1,0,0,(dreg));
1394                 *(cd->mcodeptr++) = 0x81;
1395                 emit_reg((opc),(dreg));
1396                 emit_imm32((imm));
1397         }
1398 }
1399
1400
1401 void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
1402         emit_rex(1,0,0,(dreg));
1403         *(cd->mcodeptr++) = 0x81;
1404         emit_reg((opc),(dreg));
1405         emit_imm32((imm));
1406 }
1407
1408
1409 void emit_alul_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
1410         if (IS_IMM8(imm)) {
1411                 emit_rex(0,0,0,(dreg));
1412                 *(cd->mcodeptr++) = 0x83;
1413                 emit_reg((opc),(dreg));
1414                 emit_imm8((imm));
1415         } else {
1416                 emit_rex(0,0,0,(dreg));
1417                 *(cd->mcodeptr++) = 0x81;
1418                 emit_reg((opc),(dreg));
1419                 emit_imm32((imm));
1420         }
1421 }
1422
1423
1424 void emit_alu_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
1425         if (IS_IMM8(imm)) {
1426                 emit_rex(1,(basereg),0,0);
1427                 *(cd->mcodeptr++) = 0x83;
1428                 emit_membase(cd, (basereg),(disp),(opc));
1429                 emit_imm8((imm));
1430         } else {
1431                 emit_rex(1,(basereg),0,0);
1432                 *(cd->mcodeptr++) = 0x81;
1433                 emit_membase(cd, (basereg),(disp),(opc));
1434                 emit_imm32((imm));
1435         }
1436 }
1437
1438
1439 void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
1440         if (IS_IMM8(imm)) {
1441                 emit_rex(0,(basereg),0,0);
1442                 *(cd->mcodeptr++) = 0x83;
1443                 emit_membase(cd, (basereg),(disp),(opc));
1444                 emit_imm8((imm));
1445         } else {
1446                 emit_rex(0,(basereg),0,0);
1447                 *(cd->mcodeptr++) = 0x81;
1448                 emit_membase(cd, (basereg),(disp),(opc));
1449                 emit_imm32((imm));
1450         }
1451 }
1452
1453
1454 void emit_test_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1455         emit_rex(1,(reg),0,(dreg));
1456         *(cd->mcodeptr++) = 0x85;
1457         emit_reg((reg),(dreg));
1458 }
1459
1460
1461 void emit_testl_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1462         emit_rex(0,(reg),0,(dreg));
1463         *(cd->mcodeptr++) = 0x85;
1464         emit_reg((reg),(dreg));
1465 }
1466
1467
1468 void emit_test_imm_reg(codegendata *cd, s8 imm, s8 reg) {
1469         *(cd->mcodeptr++) = 0xf7;
1470         emit_reg(0,(reg));
1471         emit_imm32((imm));
1472 }
1473
1474
1475 void emit_testw_imm_reg(codegendata *cd, s8 imm, s8 reg) {
1476         *(cd->mcodeptr++) = 0x66;
1477         *(cd->mcodeptr++) = 0xf7;
1478         emit_reg(0,(reg));
1479         emit_imm16((imm));
1480 }
1481
1482
1483 void emit_testb_imm_reg(codegendata *cd, s8 imm, s8 reg) {
1484         *(cd->mcodeptr++) = 0xf6;
1485         emit_reg(0,(reg));
1486         emit_imm8((imm));
1487 }
1488
1489
1490 void emit_lea_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
1491         emit_rex(1,(reg),0,(basereg));
1492         *(cd->mcodeptr++) = 0x8d;
1493         emit_membase(cd, (basereg),(disp),(reg));
1494 }
1495
1496
1497 void emit_leal_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
1498         emit_rex(0,(reg),0,(basereg));
1499         *(cd->mcodeptr++) = 0x8d;
1500         emit_membase(cd, (basereg),(disp),(reg));
1501 }
1502
1503
1504
1505 void emit_incl_membase(codegendata *cd, s8 basereg, s8 disp)
1506 {
1507         emit_rex(0,0,0,(basereg));
1508         *(cd->mcodeptr++) = 0xff;
1509         emit_membase(cd, (basereg),(disp),0);
1510 }
1511
1512
1513
1514 void emit_cltd(codegendata *cd) {
1515     *(cd->mcodeptr++) = 0x99;
1516 }
1517
1518
1519 void emit_cqto(codegendata *cd) {
1520         emit_rex(1,0,0,0);
1521         *(cd->mcodeptr++) = 0x99;
1522 }
1523
1524
1525
1526 void emit_imul_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1527         emit_rex(1,(dreg),0,(reg));
1528         *(cd->mcodeptr++) = 0x0f;
1529         *(cd->mcodeptr++) = 0xaf;
1530         emit_reg((dreg),(reg));
1531 }
1532
1533
1534 void emit_imull_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1535         emit_rex(0,(dreg),0,(reg));
1536         *(cd->mcodeptr++) = 0x0f;
1537         *(cd->mcodeptr++) = 0xaf;
1538         emit_reg((dreg),(reg));
1539 }
1540
1541
1542 void emit_imul_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
1543         emit_rex(1,(dreg),0,(basereg));
1544         *(cd->mcodeptr++) = 0x0f;
1545         *(cd->mcodeptr++) = 0xaf;
1546         emit_membase(cd, (basereg),(disp),(dreg));
1547 }
1548
1549
1550 void emit_imull_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
1551         emit_rex(0,(dreg),0,(basereg));
1552         *(cd->mcodeptr++) = 0x0f;
1553         *(cd->mcodeptr++) = 0xaf;
1554         emit_membase(cd, (basereg),(disp),(dreg));
1555 }
1556
1557
1558 void emit_imul_imm_reg(codegendata *cd, s8 imm, s8 dreg) {
1559         if (IS_IMM8((imm))) {
1560                 emit_rex(1,0,0,(dreg));
1561                 *(cd->mcodeptr++) = 0x6b;
1562                 emit_reg(0,(dreg));
1563                 emit_imm8((imm));
1564         } else {
1565                 emit_rex(1,0,0,(dreg));
1566                 *(cd->mcodeptr++) = 0x69;
1567                 emit_reg(0,(dreg));
1568                 emit_imm32((imm));
1569         }
1570 }
1571
1572
1573 void emit_imul_imm_reg_reg(codegendata *cd, s8 imm, s8 reg, s8 dreg) {
1574         if (IS_IMM8((imm))) {
1575                 emit_rex(1,(dreg),0,(reg));
1576                 *(cd->mcodeptr++) = 0x6b;
1577                 emit_reg((dreg),(reg));
1578                 emit_imm8((imm));
1579         } else {
1580                 emit_rex(1,(dreg),0,(reg));
1581                 *(cd->mcodeptr++) = 0x69;
1582                 emit_reg((dreg),(reg));
1583                 emit_imm32((imm));
1584         }
1585 }
1586
1587
1588 void emit_imull_imm_reg_reg(codegendata *cd, s8 imm, s8 reg, s8 dreg) {
1589         if (IS_IMM8((imm))) {
1590                 emit_rex(0,(dreg),0,(reg));
1591                 *(cd->mcodeptr++) = 0x6b;
1592                 emit_reg((dreg),(reg));
1593                 emit_imm8((imm));
1594         } else {
1595                 emit_rex(0,(dreg),0,(reg));
1596                 *(cd->mcodeptr++) = 0x69;
1597                 emit_reg((dreg),(reg));
1598                 emit_imm32((imm));
1599         }
1600 }
1601
1602
1603 void emit_imul_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg) {
1604         if (IS_IMM8((imm))) {
1605                 emit_rex(1,(dreg),0,(basereg));
1606                 *(cd->mcodeptr++) = 0x6b;
1607                 emit_membase(cd, (basereg),(disp),(dreg));
1608                 emit_imm8((imm));
1609         } else {
1610                 emit_rex(1,(dreg),0,(basereg));
1611                 *(cd->mcodeptr++) = 0x69;
1612                 emit_membase(cd, (basereg),(disp),(dreg));
1613                 emit_imm32((imm));
1614         }
1615 }
1616
1617
1618 void emit_imull_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg) {
1619         if (IS_IMM8((imm))) {
1620                 emit_rex(0,(dreg),0,(basereg));
1621                 *(cd->mcodeptr++) = 0x6b;
1622                 emit_membase(cd, (basereg),(disp),(dreg));
1623                 emit_imm8((imm));
1624         } else {
1625                 emit_rex(0,(dreg),0,(basereg));
1626                 *(cd->mcodeptr++) = 0x69;
1627                 emit_membase(cd, (basereg),(disp),(dreg));
1628                 emit_imm32((imm));
1629         }
1630 }
1631
1632
1633 void emit_idiv_reg(codegendata *cd, s8 reg) {
1634         emit_rex(1,0,0,(reg));
1635         *(cd->mcodeptr++) = 0xf7;
1636         emit_reg(7,(reg));
1637 }
1638
1639
1640 void emit_idivl_reg(codegendata *cd, s8 reg) {
1641         emit_rex(0,0,0,(reg));
1642         *(cd->mcodeptr++) = 0xf7;
1643         emit_reg(7,(reg));
1644 }
1645
1646
1647
1648 void emit_ret(codegendata *cd) {
1649     *(cd->mcodeptr++) = 0xc3;
1650 }
1651
1652
1653
1654 /*
1655  * shift ops
1656  */
1657 void emit_shift_reg(codegendata *cd, s8 opc, s8 reg) {
1658         emit_rex(1,0,0,(reg));
1659         *(cd->mcodeptr++) = 0xd3;
1660         emit_reg((opc),(reg));
1661 }
1662
1663
1664 void emit_shiftl_reg(codegendata *cd, s8 opc, s8 reg) {
1665         emit_rex(0,0,0,(reg));
1666         *(cd->mcodeptr++) = 0xd3;
1667         emit_reg((opc),(reg));
1668 }
1669
1670
1671 void emit_shift_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
1672         emit_rex(1,0,0,(basereg));
1673         *(cd->mcodeptr++) = 0xd3;
1674         emit_membase(cd, (basereg),(disp),(opc));
1675 }
1676
1677
1678 void emit_shiftl_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
1679         emit_rex(0,0,0,(basereg));
1680         *(cd->mcodeptr++) = 0xd3;
1681         emit_membase(cd, (basereg),(disp),(opc));
1682 }
1683
1684
1685 void emit_shift_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
1686         if ((imm) == 1) {
1687                 emit_rex(1,0,0,(dreg));
1688                 *(cd->mcodeptr++) = 0xd1;
1689                 emit_reg((opc),(dreg));
1690         } else {
1691                 emit_rex(1,0,0,(dreg));
1692                 *(cd->mcodeptr++) = 0xc1;
1693                 emit_reg((opc),(dreg));
1694                 emit_imm8((imm));
1695         }
1696 }
1697
1698
1699 void emit_shiftl_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
1700         if ((imm) == 1) {
1701                 emit_rex(0,0,0,(dreg));
1702                 *(cd->mcodeptr++) = 0xd1;
1703                 emit_reg((opc),(dreg));
1704         } else {
1705                 emit_rex(0,0,0,(dreg));
1706                 *(cd->mcodeptr++) = 0xc1;
1707                 emit_reg((opc),(dreg));
1708                 emit_imm8((imm));
1709         }
1710 }
1711
1712
1713 void emit_shift_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
1714         if ((imm) == 1) {
1715                 emit_rex(1,0,0,(basereg));
1716                 *(cd->mcodeptr++) = 0xd1;
1717                 emit_membase(cd, (basereg),(disp),(opc));
1718         } else {
1719                 emit_rex(1,0,0,(basereg));
1720                 *(cd->mcodeptr++) = 0xc1;
1721                 emit_membase(cd, (basereg),(disp),(opc));
1722                 emit_imm8((imm));
1723         }
1724 }
1725
1726
1727 void emit_shiftl_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
1728         if ((imm) == 1) {
1729                 emit_rex(0,0,0,(basereg));
1730                 *(cd->mcodeptr++) = 0xd1;
1731                 emit_membase(cd, (basereg),(disp),(opc));
1732         } else {
1733                 emit_rex(0,0,0,(basereg));
1734                 *(cd->mcodeptr++) = 0xc1;
1735                 emit_membase(cd, (basereg),(disp),(opc));
1736                 emit_imm8((imm));
1737         }
1738 }
1739
1740
1741
1742 /*
1743  * jump operations
1744  */
1745 void emit_jmp_imm(codegendata *cd, s8 imm) {
1746         *(cd->mcodeptr++) = 0xe9;
1747         emit_imm32((imm));
1748 }
1749
1750
1751 void emit_jmp_reg(codegendata *cd, s8 reg) {
1752         emit_rex(0,0,0,(reg));
1753         *(cd->mcodeptr++) = 0xff;
1754         emit_reg(4,(reg));
1755 }
1756
1757
1758 void emit_jcc(codegendata *cd, s8 opc, s8 imm) {
1759         *(cd->mcodeptr++) = 0x0f;
1760         *(cd->mcodeptr++) = (0x80 + (opc));
1761         emit_imm32((imm));
1762 }
1763
1764
1765
1766 /*
1767  * conditional set and move operations
1768  */
1769
1770 /* we need the rex byte to get all low bytes */
1771 void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg) {
1772         *(cd->mcodeptr++) = (0x40 | (((reg) >> 3) & 0x01));
1773         *(cd->mcodeptr++) = 0x0f;
1774         *(cd->mcodeptr++) = (0x90 + (opc));
1775         emit_reg(0,(reg));
1776 }
1777
1778
1779 /* we need the rex byte to get all low bytes */
1780 void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
1781         *(cd->mcodeptr++) = (0x40 | (((basereg) >> 3) & 0x01));
1782         *(cd->mcodeptr++) = 0x0f;
1783         *(cd->mcodeptr++) = (0x90 + (opc));
1784         emit_membase(cd, (basereg),(disp),0);
1785 }
1786
1787
1788 void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
1789 {
1790         emit_rex(1,(dreg),0,(reg));
1791         *(cd->mcodeptr++) = 0x0f;
1792         *(cd->mcodeptr++) = (0x40 + (opc));
1793         emit_reg((dreg),(reg));
1794 }
1795
1796
1797 void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
1798 {
1799         emit_rex(0,(dreg),0,(reg));
1800         *(cd->mcodeptr++) = 0x0f;
1801         *(cd->mcodeptr++) = (0x40 + (opc));
1802         emit_reg((dreg),(reg));
1803 }
1804
1805
1806
1807 void emit_neg_reg(codegendata *cd, s8 reg)
1808 {
1809         emit_rex(1,0,0,(reg));
1810         *(cd->mcodeptr++) = 0xf7;
1811         emit_reg(3,(reg));
1812 }
1813
1814
1815 void emit_negl_reg(codegendata *cd, s8 reg)
1816 {
1817         emit_rex(0,0,0,(reg));
1818         *(cd->mcodeptr++) = 0xf7;
1819         emit_reg(3,(reg));
1820 }
1821
1822
1823 void emit_push_reg(codegendata *cd, s8 reg) {
1824         emit_rex(0,0,0,(reg));
1825         *(cd->mcodeptr++) = 0x50 + (0x07 & (reg));
1826 }
1827
1828
1829 void emit_push_imm(codegendata *cd, s8 imm) {
1830         *(cd->mcodeptr++) = 0x68;
1831         emit_imm32((imm));
1832 }
1833
1834
1835 void emit_pop_reg(codegendata *cd, s8 reg) {
1836         emit_rex(0,0,0,(reg));
1837         *(cd->mcodeptr++) = 0x58 + (0x07 & (reg));
1838 }
1839
1840
1841 void emit_xchg_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1842         emit_rex(1,(reg),0,(dreg));
1843         *(cd->mcodeptr++) = 0x87;
1844         emit_reg((reg),(dreg));
1845 }
1846
1847
1848 void emit_nop(codegendata *cd) {
1849     *(cd->mcodeptr++) = 0x90;
1850 }
1851
1852
1853
1854 /*
1855  * call instructions
1856  */
1857 void emit_call_reg(codegendata *cd, s8 reg) {
1858         emit_rex(1,0,0,(reg));
1859         *(cd->mcodeptr++) = 0xff;
1860         emit_reg(2,(reg));
1861 }
1862
1863
1864 void emit_call_imm(codegendata *cd, s8 imm) {
1865         *(cd->mcodeptr++) = 0xe8;
1866         emit_imm32((imm));
1867 }
1868
1869
1870 void emit_call_mem(codegendata *cd, ptrint mem)
1871 {
1872         *(cd->mcodeptr++) = 0xff;
1873         emit_mem(2,(mem));
1874 }
1875
1876
1877
1878 /*
1879  * floating point instructions (SSE2)
1880  */
1881 void emit_addsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1882         *(cd->mcodeptr++) = 0xf2;
1883         emit_rex(0,(dreg),0,(reg));
1884         *(cd->mcodeptr++) = 0x0f;
1885         *(cd->mcodeptr++) = 0x58;
1886         emit_reg((dreg),(reg));
1887 }
1888
1889
1890 void emit_addss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1891         *(cd->mcodeptr++) = 0xf3;
1892         emit_rex(0,(dreg),0,(reg));
1893         *(cd->mcodeptr++) = 0x0f;
1894         *(cd->mcodeptr++) = 0x58;
1895         emit_reg((dreg),(reg));
1896 }
1897
1898
1899 void emit_cvtsi2ssq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1900         *(cd->mcodeptr++) = 0xf3;
1901         emit_rex(1,(dreg),0,(reg));
1902         *(cd->mcodeptr++) = 0x0f;
1903         *(cd->mcodeptr++) = 0x2a;
1904         emit_reg((dreg),(reg));
1905 }
1906
1907
1908 void emit_cvtsi2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1909         *(cd->mcodeptr++) = 0xf3;
1910         emit_rex(0,(dreg),0,(reg));
1911         *(cd->mcodeptr++) = 0x0f;
1912         *(cd->mcodeptr++) = 0x2a;
1913         emit_reg((dreg),(reg));
1914 }
1915
1916
1917 void emit_cvtsi2sdq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1918         *(cd->mcodeptr++) = 0xf2;
1919         emit_rex(1,(dreg),0,(reg));
1920         *(cd->mcodeptr++) = 0x0f;
1921         *(cd->mcodeptr++) = 0x2a;
1922         emit_reg((dreg),(reg));
1923 }
1924
1925
1926 void emit_cvtsi2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1927         *(cd->mcodeptr++) = 0xf2;
1928         emit_rex(0,(dreg),0,(reg));
1929         *(cd->mcodeptr++) = 0x0f;
1930         *(cd->mcodeptr++) = 0x2a;
1931         emit_reg((dreg),(reg));
1932 }
1933
1934
1935 void emit_cvtss2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1936         *(cd->mcodeptr++) = 0xf3;
1937         emit_rex(0,(dreg),0,(reg));
1938         *(cd->mcodeptr++) = 0x0f;
1939         *(cd->mcodeptr++) = 0x5a;
1940         emit_reg((dreg),(reg));
1941 }
1942
1943
1944 void emit_cvtsd2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1945         *(cd->mcodeptr++) = 0xf2;
1946         emit_rex(0,(dreg),0,(reg));
1947         *(cd->mcodeptr++) = 0x0f;
1948         *(cd->mcodeptr++) = 0x5a;
1949         emit_reg((dreg),(reg));
1950 }
1951
1952
1953 void emit_cvttss2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1954         *(cd->mcodeptr++) = 0xf3;
1955         emit_rex(1,(dreg),0,(reg));
1956         *(cd->mcodeptr++) = 0x0f;
1957         *(cd->mcodeptr++) = 0x2c;
1958         emit_reg((dreg),(reg));
1959 }
1960
1961
1962 void emit_cvttss2si_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1963         *(cd->mcodeptr++) = 0xf3;
1964         emit_rex(0,(dreg),0,(reg));
1965         *(cd->mcodeptr++) = 0x0f;
1966         *(cd->mcodeptr++) = 0x2c;
1967         emit_reg((dreg),(reg));
1968 }
1969
1970
1971 void emit_cvttsd2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1972         *(cd->mcodeptr++) = 0xf2;
1973         emit_rex(1,(dreg),0,(reg));
1974         *(cd->mcodeptr++) = 0x0f;
1975         *(cd->mcodeptr++) = 0x2c;
1976         emit_reg((dreg),(reg));
1977 }
1978
1979
1980 void emit_cvttsd2si_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1981         *(cd->mcodeptr++) = 0xf2;
1982         emit_rex(0,(dreg),0,(reg));
1983         *(cd->mcodeptr++) = 0x0f;
1984         *(cd->mcodeptr++) = 0x2c;
1985         emit_reg((dreg),(reg));
1986 }
1987
1988
1989 void emit_divss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1990         *(cd->mcodeptr++) = 0xf3;
1991         emit_rex(0,(dreg),0,(reg));
1992         *(cd->mcodeptr++) = 0x0f;
1993         *(cd->mcodeptr++) = 0x5e;
1994         emit_reg((dreg),(reg));
1995 }
1996
1997
1998 void emit_divsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
1999         *(cd->mcodeptr++) = 0xf2;
2000         emit_rex(0,(dreg),0,(reg));
2001         *(cd->mcodeptr++) = 0x0f;
2002         *(cd->mcodeptr++) = 0x5e;
2003         emit_reg((dreg),(reg));
2004 }
2005
2006
2007 void emit_movd_reg_freg(codegendata *cd, s8 reg, s8 freg) {
2008         *(cd->mcodeptr++) = 0x66;
2009         emit_rex(1,(freg),0,(reg));
2010         *(cd->mcodeptr++) = 0x0f;
2011         *(cd->mcodeptr++) = 0x6e;
2012         emit_reg((freg),(reg));
2013 }
2014
2015
2016 void emit_movd_freg_reg(codegendata *cd, s8 freg, s8 reg) {
2017         *(cd->mcodeptr++) = 0x66;
2018         emit_rex(1,(freg),0,(reg));
2019         *(cd->mcodeptr++) = 0x0f;
2020         *(cd->mcodeptr++) = 0x7e;
2021         emit_reg((freg),(reg));
2022 }
2023
2024
2025 void emit_movd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
2026         *(cd->mcodeptr++) = 0x66;
2027         emit_rex(0,(reg),0,(basereg));
2028         *(cd->mcodeptr++) = 0x0f;
2029         *(cd->mcodeptr++) = 0x7e;
2030         emit_membase(cd, (basereg),(disp),(reg));
2031 }
2032
2033
2034 void emit_movd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
2035         *(cd->mcodeptr++) = 0x66;
2036         emit_rex(0,(reg),(indexreg),(basereg));
2037         *(cd->mcodeptr++) = 0x0f;
2038         *(cd->mcodeptr++) = 0x7e;
2039         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
2040 }
2041
2042
2043 void emit_movd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2044         *(cd->mcodeptr++) = 0x66;
2045         emit_rex(1,(dreg),0,(basereg));
2046         *(cd->mcodeptr++) = 0x0f;
2047         *(cd->mcodeptr++) = 0x6e;
2048         emit_membase(cd, (basereg),(disp),(dreg));
2049 }
2050
2051
2052 void emit_movdl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2053         *(cd->mcodeptr++) = 0x66;
2054         emit_rex(0,(dreg),0,(basereg));
2055         *(cd->mcodeptr++) = 0x0f;
2056         *(cd->mcodeptr++) = 0x6e;
2057         emit_membase(cd, (basereg),(disp),(dreg));
2058 }
2059
2060
2061 void emit_movd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
2062         *(cd->mcodeptr++) = 0x66;
2063         emit_rex(0,(dreg),(indexreg),(basereg));
2064         *(cd->mcodeptr++) = 0x0f;
2065         *(cd->mcodeptr++) = 0x6e;
2066         emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
2067 }
2068
2069
2070 void emit_movq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2071         *(cd->mcodeptr++) = 0xf3;
2072         emit_rex(0,(dreg),0,(reg));
2073         *(cd->mcodeptr++) = 0x0f;
2074         *(cd->mcodeptr++) = 0x7e;
2075         emit_reg((dreg),(reg));
2076 }
2077
2078
2079 void emit_movq_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
2080         *(cd->mcodeptr++) = 0x66;
2081         emit_rex(0,(reg),0,(basereg));
2082         *(cd->mcodeptr++) = 0x0f;
2083         *(cd->mcodeptr++) = 0xd6;
2084         emit_membase(cd, (basereg),(disp),(reg));
2085 }
2086
2087
2088 void emit_movq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2089         *(cd->mcodeptr++) = 0xf3;
2090         emit_rex(0,(dreg),0,(basereg));
2091         *(cd->mcodeptr++) = 0x0f;
2092         *(cd->mcodeptr++) = 0x7e;
2093         emit_membase(cd, (basereg),(disp),(dreg));
2094 }
2095
2096
2097 void emit_movss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2098         *(cd->mcodeptr++) = 0xf3;
2099         emit_rex(0,(reg),0,(dreg));
2100         *(cd->mcodeptr++) = 0x0f;
2101         *(cd->mcodeptr++) = 0x10;
2102         emit_reg((reg),(dreg));
2103 }
2104
2105
2106 void emit_movsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2107         *(cd->mcodeptr++) = 0xf2;
2108         emit_rex(0,(reg),0,(dreg));
2109         *(cd->mcodeptr++) = 0x0f;
2110         *(cd->mcodeptr++) = 0x10;
2111         emit_reg((reg),(dreg));
2112 }
2113
2114
2115 void emit_movss_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
2116         *(cd->mcodeptr++) = 0xf3;
2117         emit_rex(0,(reg),0,(basereg));
2118         *(cd->mcodeptr++) = 0x0f;
2119         *(cd->mcodeptr++) = 0x11;
2120         emit_membase(cd, (basereg),(disp),(reg));
2121 }
2122
2123
2124 /* Always emit a REX byte, because the instruction size can be smaller when   */
2125 /* all register indexes are smaller than 7.                                   */
2126 void emit_movss_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
2127         *(cd->mcodeptr++) = 0xf3;
2128         emit_byte_rex((reg),0,(basereg));
2129         *(cd->mcodeptr++) = 0x0f;
2130         *(cd->mcodeptr++) = 0x11;
2131         emit_membase32(cd, (basereg),(disp),(reg));
2132 }
2133
2134
2135 void emit_movsd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
2136         *(cd->mcodeptr++) = 0xf2;
2137         emit_rex(0,(reg),0,(basereg));
2138         *(cd->mcodeptr++) = 0x0f;
2139         *(cd->mcodeptr++) = 0x11;
2140         emit_membase(cd, (basereg),(disp),(reg));
2141 }
2142
2143
2144 /* Always emit a REX byte, because the instruction size can be smaller when   */
2145 /* all register indexes are smaller than 7.                                   */
2146 void emit_movsd_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
2147         *(cd->mcodeptr++) = 0xf2;
2148         emit_byte_rex((reg),0,(basereg));
2149         *(cd->mcodeptr++) = 0x0f;
2150         *(cd->mcodeptr++) = 0x11;
2151         emit_membase32(cd, (basereg),(disp),(reg));
2152 }
2153
2154
2155 void emit_movss_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2156         *(cd->mcodeptr++) = 0xf3;
2157         emit_rex(0,(dreg),0,(basereg));
2158         *(cd->mcodeptr++) = 0x0f;
2159         *(cd->mcodeptr++) = 0x10;
2160         emit_membase(cd, (basereg),(disp),(dreg));
2161 }
2162
2163
2164 /* Always emit a REX byte, because the instruction size can be smaller when   */
2165 /* all register indexes are smaller than 7.                                   */
2166 void emit_movss_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2167         *(cd->mcodeptr++) = 0xf3;
2168         emit_byte_rex((dreg),0,(basereg));
2169         *(cd->mcodeptr++) = 0x0f;
2170         *(cd->mcodeptr++) = 0x10;
2171         emit_membase32(cd, (basereg),(disp),(dreg));
2172 }
2173
2174
2175 void emit_movlps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg)
2176 {
2177         emit_rex(0,(dreg),0,(basereg));
2178         *(cd->mcodeptr++) = 0x0f;
2179         *(cd->mcodeptr++) = 0x12;
2180         emit_membase(cd, (basereg),(disp),(dreg));
2181 }
2182
2183
2184 void emit_movlps_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp)
2185 {
2186         emit_rex(0,(reg),0,(basereg));
2187         *(cd->mcodeptr++) = 0x0f;
2188         *(cd->mcodeptr++) = 0x13;
2189         emit_membase(cd, (basereg),(disp),(reg));
2190 }
2191
2192
2193 void emit_movsd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2194         *(cd->mcodeptr++) = 0xf2;
2195         emit_rex(0,(dreg),0,(basereg));
2196         *(cd->mcodeptr++) = 0x0f;
2197         *(cd->mcodeptr++) = 0x10;
2198         emit_membase(cd, (basereg),(disp),(dreg));
2199 }
2200
2201
2202 /* Always emit a REX byte, because the instruction size can be smaller when   */
2203 /* all register indexes are smaller than 7.                                   */
2204 void emit_movsd_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2205         *(cd->mcodeptr++) = 0xf2;
2206         emit_byte_rex((dreg),0,(basereg));
2207         *(cd->mcodeptr++) = 0x0f;
2208         *(cd->mcodeptr++) = 0x10;
2209         emit_membase32(cd, (basereg),(disp),(dreg));
2210 }
2211
2212
2213 void emit_movlpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg)
2214 {
2215         *(cd->mcodeptr++) = 0x66;
2216         emit_rex(0,(dreg),0,(basereg));
2217         *(cd->mcodeptr++) = 0x0f;
2218         *(cd->mcodeptr++) = 0x12;
2219         emit_membase(cd, (basereg),(disp),(dreg));
2220 }
2221
2222
2223 void emit_movlpd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp)
2224 {
2225         *(cd->mcodeptr++) = 0x66;
2226         emit_rex(0,(reg),0,(basereg));
2227         *(cd->mcodeptr++) = 0x0f;
2228         *(cd->mcodeptr++) = 0x13;
2229         emit_membase(cd, (basereg),(disp),(reg));
2230 }
2231
2232
2233 void emit_movss_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
2234         *(cd->mcodeptr++) = 0xf3;
2235         emit_rex(0,(reg),(indexreg),(basereg));
2236         *(cd->mcodeptr++) = 0x0f;
2237         *(cd->mcodeptr++) = 0x11;
2238         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
2239 }
2240
2241
2242 void emit_movsd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
2243         *(cd->mcodeptr++) = 0xf2;
2244         emit_rex(0,(reg),(indexreg),(basereg));
2245         *(cd->mcodeptr++) = 0x0f;
2246         *(cd->mcodeptr++) = 0x11;
2247         emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
2248 }
2249
2250
2251 void emit_movss_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
2252         *(cd->mcodeptr++) = 0xf3;
2253         emit_rex(0,(dreg),(indexreg),(basereg));
2254         *(cd->mcodeptr++) = 0x0f;
2255         *(cd->mcodeptr++) = 0x10;
2256         emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
2257 }
2258
2259
2260 void emit_movsd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
2261         *(cd->mcodeptr++) = 0xf2;
2262         emit_rex(0,(dreg),(indexreg),(basereg));
2263         *(cd->mcodeptr++) = 0x0f;
2264         *(cd->mcodeptr++) = 0x10;
2265         emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
2266 }
2267
2268
2269 void emit_mulss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2270         *(cd->mcodeptr++) = 0xf3;
2271         emit_rex(0,(dreg),0,(reg));
2272         *(cd->mcodeptr++) = 0x0f;
2273         *(cd->mcodeptr++) = 0x59;
2274         emit_reg((dreg),(reg));
2275 }
2276
2277
2278 void emit_mulsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2279         *(cd->mcodeptr++) = 0xf2;
2280         emit_rex(0,(dreg),0,(reg));
2281         *(cd->mcodeptr++) = 0x0f;
2282         *(cd->mcodeptr++) = 0x59;
2283         emit_reg((dreg),(reg));
2284 }
2285
2286
2287 void emit_subss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2288         *(cd->mcodeptr++) = 0xf3;
2289         emit_rex(0,(dreg),0,(reg));
2290         *(cd->mcodeptr++) = 0x0f;
2291         *(cd->mcodeptr++) = 0x5c;
2292         emit_reg((dreg),(reg));
2293 }
2294
2295
2296 void emit_subsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2297         *(cd->mcodeptr++) = 0xf2;
2298         emit_rex(0,(dreg),0,(reg));
2299         *(cd->mcodeptr++) = 0x0f;
2300         *(cd->mcodeptr++) = 0x5c;
2301         emit_reg((dreg),(reg));
2302 }
2303
2304
2305 void emit_ucomiss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2306         emit_rex(0,(dreg),0,(reg));
2307         *(cd->mcodeptr++) = 0x0f;
2308         *(cd->mcodeptr++) = 0x2e;
2309         emit_reg((dreg),(reg));
2310 }
2311
2312
2313 void emit_ucomisd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2314         *(cd->mcodeptr++) = 0x66;
2315         emit_rex(0,(dreg),0,(reg));
2316         *(cd->mcodeptr++) = 0x0f;
2317         *(cd->mcodeptr++) = 0x2e;
2318         emit_reg((dreg),(reg));
2319 }
2320
2321
2322 void emit_xorps_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2323         emit_rex(0,(dreg),0,(reg));
2324         *(cd->mcodeptr++) = 0x0f;
2325         *(cd->mcodeptr++) = 0x57;
2326         emit_reg((dreg),(reg));
2327 }
2328
2329
2330 void emit_xorps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2331         emit_rex(0,(dreg),0,(basereg));
2332         *(cd->mcodeptr++) = 0x0f;
2333         *(cd->mcodeptr++) = 0x57;
2334         emit_membase(cd, (basereg),(disp),(dreg));
2335 }
2336
2337
2338 void emit_xorpd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
2339         *(cd->mcodeptr++) = 0x66;
2340         emit_rex(0,(dreg),0,(reg));
2341         *(cd->mcodeptr++) = 0x0f;
2342         *(cd->mcodeptr++) = 0x57;
2343         emit_reg((dreg),(reg));
2344 }
2345
2346
2347 void emit_xorpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
2348         *(cd->mcodeptr++) = 0x66;
2349         emit_rex(0,(dreg),0,(basereg));
2350         *(cd->mcodeptr++) = 0x0f;
2351         *(cd->mcodeptr++) = 0x57;
2352         emit_membase(cd, (basereg),(disp),(dreg));
2353 }
2354
2355
2356 /* system instructions ********************************************************/
2357
2358 void emit_rdtsc(codegendata *cd)
2359 {
2360         *(cd->mcodeptr++) = 0x0f;
2361         *(cd->mcodeptr++) = 0x31;
2362 }
2363
2364 /* emit_load_high **************************************************************
2365
2366    Emits a possible load of the high 32-bits of an operand.
2367
2368 *******************************************************************************/
2369
2370 __PORTED__ s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
2371 {
2372         codegendata  *cd;
2373         s4            disp;
2374         s4            reg;
2375
2376         assert(src->type == TYPE_LNG);
2377
2378         /* get required compiler data */
2379
2380         cd = jd->cd;
2381
2382         if (IS_INMEMORY(src->flags)) {
2383                 COUNT_SPILLS;
2384
2385                 disp = src->vv.regoff * 4;
2386
2387                 M_ILD(tempreg, REG_SP, disp);
2388
2389                 reg = tempreg;
2390         }
2391         else
2392                 reg = GET_HIGH_REG(src->vv.regoff);
2393
2394         return reg;
2395 }
2396
2397 /* emit_load_low ***************************************************************
2398
2399    Emits a possible load of the low 32-bits of an operand.
2400
2401 *******************************************************************************/
2402
2403 __PORTED__ s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
2404 {
2405         codegendata  *cd;
2406         s4            disp;
2407         s4            reg;
2408
2409         assert(src->type == TYPE_LNG);
2410
2411         /* get required compiler data */
2412
2413         cd = jd->cd;
2414
2415         if (IS_INMEMORY(src->flags)) {
2416                 COUNT_SPILLS;
2417
2418                 disp = src->vv.regoff * 4;
2419
2420                 M_ILD(tempreg, REG_SP, disp + 4);
2421
2422                 reg = tempreg;
2423         }
2424         else
2425                 reg = GET_LOW_REG(src->vv.regoff);
2426
2427         return reg;
2428 }
2429
2430 /* emit_nullpointer_check ******************************************************
2431
2432    Emit a NullPointerException check.
2433
2434 *******************************************************************************/
2435
2436 __PORTED__ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
2437 {
2438         if (INSTRUCTION_MUST_CHECK(iptr)) {
2439                 M_TEST(reg);
2440                 M_BEQ(0);
2441                 codegen_add_nullpointerexception_ref(cd);
2442         }
2443 }
2444
2445 /* emit_arrayindexoutofbounds_check ********************************************
2446
2447    Emit a ArrayIndexOutOfBoundsException check.
2448
2449 *******************************************************************************/
2450
2451 __PORTED__ void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
2452 {
2453         if (INSTRUCTION_MUST_CHECK(iptr)) {
2454                 /* Size is s4, >= 0
2455                  * Do unsigned comparison to catch negative indexes.
2456                  */
2457                 N_CL(s2, OFFSET(java_arrayheader, size), RN, s1);
2458         M_BGE(0);
2459         codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
2460         }
2461 }
2462
2463 s4 emit_load_s1_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
2464         codegendata *cd = jd->cd;
2465         s4 reg = emit_load_s1(jd, iptr, tempreg);
2466         if (reg == 0) {
2467                 M_MOV(reg, tempreg);
2468                 return tempreg;
2469         } else {
2470                 return reg;
2471         }
2472 }
2473
2474 s4 emit_load_s2_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
2475         codegendata *cd = jd->cd;
2476         s4 reg = emit_load_s2(jd, iptr, tempreg);
2477         if (reg == 0) {
2478                 M_MOV(reg, tempreg);
2479                 return tempreg;
2480         } else {
2481                 return reg;
2482         }
2483 }
2484
2485 s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
2486         codegendata *cd = jd->cd;
2487         s4 reg = emit_load_s1(jd, iptr, tempreg);
2488         if (reg == notreg) {
2489                 M_MOV(reg, tempreg);
2490                 return tempreg;
2491         } else {
2492                 return reg;
2493         }
2494 }
2495
2496 s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
2497         codegendata *cd = jd->cd;
2498         s4 reg = emit_load_s2(jd, iptr, tempreg);
2499         if (reg == notreg) {
2500                 M_MOV(reg, tempreg);
2501                 return tempreg;
2502         } else {
2503                 return reg;
2504         }
2505 }
2506
2507 s4 emit_alloc_dst_even_odd(jitdata *jd, instruction *iptr, s4 htmpreg, s4 ltmpreg, s4 breg) {
2508         codegendata *cd;
2509         s4           hr, lr;
2510         varinfo     *dst;
2511
2512         /* (r0, r1)    
2513          * (r2, r3)
2514          * (r4, r5)
2515          * (r6, r7)
2516          * (r8, r9)
2517          * (r10, r11)
2518          * (r12, r13) Illegal, because r13 is PV
2519          * (r14, r15) Illegal, because r15 is SP
2520          */
2521
2522         cd = jd->cd;
2523         dst = VAROP(iptr->dst);
2524
2525         if (IS_INMEMORY(dst->flags)) {
2526                 if (! IS_REG_ITMP(ltmpreg)) {
2527                         M_INTMOVE(ltmpreg, breg);
2528                 }
2529                 if (! IS_REG_ITMP(htmpreg)) {
2530                         M_INTMOVE(htmpreg, breg);
2531                 }
2532                 return PACK_REGS(ltmpreg, htmpreg);
2533         } else {
2534                 hr = GET_HIGH_REG(dst->vv.regoff);
2535                 lr = GET_LOW_REG(dst->vv.regoff);
2536                 if (((hr % 2) == 0) && lr == (hr + 1)) {
2537                         /* the result is already in a even-odd pair */
2538                         return dst->vv.regoff;                  
2539                 } else if (((hr % 2) == 0) && (hr < R12)) {
2540                         /* the high register is at a even position */
2541                         M_INTMOVE(hr + 1, breg);
2542                         return PACK_REGS(hr + 1, hr);
2543                 } else if (((lr % 2) == 1) && (lr < R12)) {
2544                         /* the low register is at a odd position */
2545                         M_INTMOVE(lr - 1, breg);
2546                         return PACK_REGS(lr, lr - 1);
2547                 } else {
2548                         /* no way to create an even-odd pair by 1 copy operation,
2549                          * Use the temporary register pair.
2550                          */
2551                         if (! IS_REG_ITMP(ltmpreg)) {
2552                                 M_INTMOVE(ltmpreg, breg);
2553                         }
2554                         if (! IS_REG_ITMP(htmpreg)) {
2555                                 M_INTMOVE(htmpreg, breg);
2556                         }
2557                         return PACK_REGS(ltmpreg, htmpreg);
2558                 }
2559         }
2560 }
2561
2562 void emit_restore_dst_even_odd(jitdata *jd, instruction *iptr, s4 htmpreg, s4 ltmpreg, s4 breg) {
2563         codegendata *cd;
2564         s4           hr, lr;
2565         varinfo     *dst;
2566
2567         cd = jd->cd;
2568         dst = VAROP(iptr->dst);
2569
2570         if (IS_INMEMORY(dst->flags)) {
2571                 if (! IS_REG_ITMP(ltmpreg)) {
2572                         M_INTMOVE(breg, ltmpreg);
2573                 }
2574                 if (! IS_REG_ITMP(htmpreg)) {
2575                         M_INTMOVE(breg, htmpreg);
2576                 }
2577         } else {
2578                 hr = GET_HIGH_REG(dst->vv.regoff);
2579                 lr = GET_LOW_REG(dst->vv.regoff);
2580                 if (((hr % 2) == 0) && lr == (hr + 1)) {
2581                         return;
2582                 } else if (((hr % 2) == 0) && (hr < R12)) {
2583                         M_INTMOVE(breg, hr + 1);
2584                 } else if (((lr % 2) == 1) && (lr < R12)) {
2585                         M_INTMOVE(breg, lr - 1);
2586                 } else {
2587                         if (! IS_REG_ITMP(ltmpreg)) {
2588                                 M_INTMOVE(breg, ltmpreg);
2589                         }
2590                         if (! IS_REG_ITMP(htmpreg)) {
2591                                 M_INTMOVE(breg, htmpreg);
2592                         }
2593                 }
2594         }
2595 }
2596
2597 void emit_copy_dst(jitdata *jd, instruction *iptr, s4 dtmpreg) {
2598         codegendata *cd;
2599         varinfo *dst;
2600         cd = jd->cd;
2601         dst = VAROP(iptr->dst);
2602         if (! IS_INMEMORY(dst->flags)) {
2603                 if (dst->vv.regoff != dtmpreg) {
2604                         if (IS_FLT_DBL_TYPE(dst->type)) {
2605                                 M_FLTMOVE(dtmpreg, dst->vv.regoff);
2606                         } else if (IS_2_WORD_TYPE(dst->type)) {
2607                                 M_LNGMOVE(dtmpreg, dst->vv.regoff);
2608                         } else {
2609                                 M_INTMOVE(dtmpreg, dst->vv.regoff);
2610                         }
2611                 }
2612         }
2613 }
2614
2615 /*
2616  * These are local overrides for various environment variables in Emacs.
2617  * Please do not remove this and leave it at the end of the file, where
2618  * Emacs will automagically detect them.
2619  * ---------------------------------------------------------------------
2620  * Local variables:
2621  * mode: c
2622  * indent-tabs-mode: t
2623  * c-basic-offset: 4
2624  * tab-width: 4
2625  * End:
2626  */