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