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