25 #ifndef _JIT_COMPILER2_X86_64EMITHELPER
26 #define _JIT_COMPILER2_X86_64EMITHELPER
34 #define DEBUG_NAME "compiler2/x86_64 Emit"
96 bool opsiz64 =
true) {
97 const unsigned rex_w = 3;
98 const unsigned rex_r = 2;
100 const unsigned rex_b = 0;
112 if (rm && rm->extented) {
121 const unsigned rex_w = 3;
122 const unsigned rex_r = 2;
123 const unsigned rex_x = 1;
124 const unsigned rex_b = 0;
135 if (reg2 && reg2->extented) {
138 if (reg3 && reg3->extented) {
146 return index || base == &
RSP || base == &
R12;
158 if (disp == 0 || base == 0x05 ) {
162 else if (fits_into<s1>(disp)) {
165 }
else if (fits_into<s4>(disp)) {
170 ABORT_MSG(
"Illegal displacement",
"Displacement: "<<disp);
180 modrm = mod << modrm_mod;
181 modrm |= reg << modrm_reg;
182 modrm |= rm << modrm_rm;
198 sib = scale << sib_scale;
200 sib |=
index->get_index() << sib_index;
213 const unsigned modrm_mod = 6;
214 const unsigned modrm_reg = 3;
215 const unsigned modrm_rm = 0;
217 u1 modrm = (0x3 &
mod) << modrm_mod;
218 modrm |= (0x7 & reg) << modrm_reg;
219 modrm |= (0x7 & rm) << modrm_rm;
268 for (std::size_t
i = 0,
e = CSB.
size();
i <
e; ++
i) {
275 switch (
op->get_OperandID()) {
292 assert(0 &&
"Not a stackslot");
311 for (
int i = 0,
e =
sizeof(T) ;
i <
e ; ++
i) {
312 code[
i + 1] = (
u1) 0xff & (opcode >> (8 * (e -
i - 1)));
324 for (
int i = 0,
e =
sizeof(T) ;
i <
e ; ++
i) {
325 code[
i + 1] = (
u1) 0xff & (opcode >> (8 * (e -
i - 1)));
329 code[2 +
sizeof(T)] =
u1(disp);
338 for (
int i = 0,
e =
sizeof(T) ;
i <
e ; ++
i) {
339 code[
i + 1] = (
u1) 0xff & (opcode >> (8 * (e -
i - 1)));
343 code[2 +
sizeof(T)] =
u1( 0xff & (disp >> (0 * 8)));
344 code[3 +
sizeof(T)] =
u1( 0xff & (disp >> (1 * 8)));
345 code[4 +
sizeof(T)] =
u1( 0xff & (disp >> (2 * 8)));
346 code[5 +
sizeof(T)] =
u1( 0xff & (disp >> (3 * 8)));
348 template <
class O,
class I>
355 for (
int i = 0,
e =
sizeof(O) ;
i <
e ; ++
i) {
356 code[
i + 1] = (
u1) 0xff & (opcode >> (8 * (e -
i - 1)));
358 for (
int i = 0, e =
sizeof(
I) ;
i <
e ; ++
i) {
359 code[
i +
sizeof(O) + 1] = (
u1) 0xff & (imm >> (8 *
i));
363 template <
class O,
class I>
370 for (
int i = 0,
e =
sizeof(O) ;
i <
e ; ++
i) {
371 code[
i + 1] = (
u1) 0xff & (opcode >> (8 * (e -
i - 1)));
374 for (
int i = 0, e =
sizeof(
I) ;
i <
e ; ++
i) {
375 code[
i +
sizeof(O) + 2] = (
u1) 0xff & (imm >> (8 *
i));
379 template <
class O,
class I>
383 for (
int i = 0,
e =
sizeof(O) ;
i <
e ; ++
i) {
384 code[
i] = (
u1) 0xff & (opcode >> (8 * (e -
i - 1)));
386 for (
int i = 0, e =
sizeof(
I) ;
i <
e ; ++
i) {
387 code[
i +
sizeof(O)] = (
u1) 0xff & (imm >> (8 *
i));
391 template <
class O,
class I>
393 assert(code.
size() == (
sizeof(O) +
sizeof(
I)));
395 for (
int i = 0,
e =
sizeof(O) ;
i <
e ; ++
i) {
396 code[
i] = (
u1) 0xff & (opcode >> (8 * (e -
i - 1)));
398 for (
int i = 0, e =
sizeof(
I) ;
i <
e ; ++
i) {
399 code[
i +
sizeof(O)] = (
u1) 0xff & (imm >> (8 *
i));
403 template <
class I,
class Seg>
405 assert(seg.size() ==
sizeof(
I));
407 for (
int i = 0,
e =
sizeof(
I) ;
i <
e ; ++
i) {
408 seg[
i] = (
u1) 0xff & *(reinterpret_cast<u1*>(&imm) +
i);
413 static void emit (
CodeMemory* CM,
u1 primary_opcode,
GPInstruction::OperandSize op_size,
MachineOperand *src,
MachineOperand *dst,
u1 secondary_opcode = 0,
u1 op_reg = 0,
u1 prefix = 0,
bool prefix_0f =
false,
bool encode_dst =
true,
bool imm_sign_extended =
false) {
426 code += primary_opcode;
427 if (secondary_opcode != 0x00) {
428 code += secondary_opcode;
443 code += primary_opcode;
444 if (secondary_opcode != 0x00) {
445 code += secondary_opcode;
450 if (!imm_sign_extended) {
455 code += (
u1) 0xff & (immval >> 0x00);
461 code += (
u1) 0xff & (immval >> 0x00);
462 code += (
u1) 0xff & (immval >> 0x08);
468 code += (
u1) 0xff & (immval >> 0x00);
469 code += (
u1) 0xff & (immval >> 0x08);
470 code += (
u1) 0xff & (immval >> 0x10);
471 code += (
u1) 0xff & (immval >> 0x18);
477 code += (
u1) 0xff & (immval >> 0x00);
478 code += (
u1) 0xff & (immval >> 0x08);
479 code += (
u1) 0xff & (immval >> 0x10);
480 code += (
u1) 0xff & (immval >> 0x18);
481 code += (
u1) 0xff & (immval >> 0x20);
482 code += (
u1) 0xff & (immval >> 0x28);
483 code += (
u1) 0xff & (immval >> 0x30);
484 code += (
u1) 0xff & (immval >> 0x38);
489 "dst: " << dst_reg <<
" src: " << src_imm <<
" op_code: " << primary_opcode);
496 code += (
u1) 0xff & (immval >> 0x00);
498 else if (fits_into<s2>(src_imm->
get_value<
s8>())) {
500 code += (
u1) 0xff & (immval >> 0x00);
501 code += (
u1) 0xff & (immval >> 0x08);
503 else if (fits_into<s4>(src_imm->
get_value<
s8>())) {
505 code += (
u1) 0xff & (immval >> 0x00);
506 code += (
u1) 0xff & (immval >> 0x08);
507 code += (
u1) 0xff & (immval >> 0x10);
508 code += (
u1) 0xff & (immval >> 0x18);
512 code += (
u1) 0xff & (immval >> 0x00);
513 code += (
u1) 0xff & (immval >> 0x08);
514 code += (
u1) 0xff & (immval >> 0x10);
515 code += (
u1) 0xff & (immval >> 0x18);
516 code += (
u1) 0xff & (immval >> 0x20);
517 code += (
u1) 0xff & (immval >> 0x28);
518 code += (
u1) 0xff & (immval >> 0x30);
519 code += (
u1) 0xff & (immval >> 0x38);
533 code += primary_opcode;
534 if (secondary_opcode != 0x00) {
535 code += secondary_opcode;
537 if (fits_into<s1>(index)) {
543 code += (
u1) 0xff & (index >> 0x00);
544 code += (
u1) 0xff & (index >> 0x08);
545 code += (
u1) 0xff & (index >> 0x10);
546 code += (
u1) 0xff & (index >> 0x18);
555 u1 rex =
get_rex(dst_reg, base, op_size, index);
562 code += primary_opcode;
563 if (secondary_opcode != 0x00) {
564 code += secondary_opcode;
566 bool sib =
use_sib(base, index);
567 code +=
get_modrm(dst_reg,base,disp,sib);
569 code +=
get_sib(base,index,scale);
572 if (fits_into<s1>(disp) && base != &
RBP) {
576 code += (
u1) 0xff & (disp >> 0x00);
577 code += (
u1) 0xff & (disp >> 0x08);
578 code += (
u1) 0xff & (disp >> 0x10);
579 code += (
u1) 0xff & (disp >> 0x18);
585 "dst_reg: " << dst_reg <<
" src: " << src <<
" op_code: " << primary_opcode);
600 code += primary_opcode;
601 if (secondary_opcode != 0x00) {
602 code += secondary_opcode;
604 if (fits_into<s1>(index)) {
610 code += (
u1) 0xff & (index >> 0x00);
611 code += (
u1) 0xff & (index >> 0x08);
612 code += (
u1) 0xff & (index >> 0x10);
613 code += (
u1) 0xff & (index >> 0x18);
618 "dst: " << dst_slot <<
" src: " << src <<
" op_code: " << primary_opcode);
629 u1 rex =
get_rex(src_reg, base, op_size, index);
636 code += primary_opcode;
637 if (secondary_opcode != 0x00) {
638 code += secondary_opcode;
640 bool sib =
use_sib(base, index);
641 code +=
get_modrm(src_reg,base,disp,sib);
643 code +=
get_sib(base,index,scale);
646 if (fits_into<s1>(disp) && base != &
RBP) {
650 code += (
u1) 0xff & (disp >> 0x00);
651 code += (
u1) 0xff & (disp >> 0x08);
652 code += (
u1) 0xff & (disp >> 0x10);
653 code += (
u1) 0xff & (disp >> 0x18);
659 u1 rex =
get_rex(NULL, base, op_size, index);
666 code += primary_opcode;
667 if (secondary_opcode != 0x00) {
668 code += secondary_opcode;
670 bool sib =
use_sib(base, index);
671 code +=
get_modrm(op_reg,base->get_index(),disp,sib);
673 code +=
get_sib(base,index,scale);
676 if (fits_into<s1>(disp) && base != &
RBP) {
680 code += (
u1) 0xff & (disp >> 0x00);
681 code += (
u1) 0xff & (disp >> 0x08);
682 code += (
u1) 0xff & (disp >> 0x10);
683 code += (
u1) 0xff & (disp >> 0x18);
690 code += (
u1) 0xff & (immval >> 0x00);
696 code += (
u1) 0xff & (immval >> 0x00);
697 code += (
u1) 0xff & (immval >> 0x08);
703 code += (
u1) 0xff & (immval >> 0x00);
704 code += (
u1) 0xff & (immval >> 0x08);
705 code += (
u1) 0xff & (immval >> 0x10);
706 code += (
u1) 0xff & (immval >> 0x18);
712 ABORT_MSG(
"Invalid Immediate Size (imm64 with disp not allowed)",
713 "dst: " << dst_mod <<
" src: " << src_imm <<
" op_code: " << primary_opcode);
716 code += (
u1) 0xff & (immval >> 0x00);
717 code += (
u1) 0xff & (immval >> 0x08);
718 code += (
u1) 0xff & (immval >> 0x10);
719 code += (
u1) 0xff & (immval >> 0x18);
720 code += (
u1) 0xff & (immval >> 0x20);
721 code += (
u1) 0xff & (immval >> 0x28);
722 code += (
u1) 0xff & (immval >> 0x30);
723 code += (
u1) 0xff & (immval >> 0x38);
728 "dst: " << dst_mod <<
" src: " << src_imm <<
" op_code: " << primary_opcode);
734 "dst: " << dst_mod <<
" src: " << src <<
" op_code: " << primary_opcode);
739 "dst: " << dst <<
" src: " << src <<
" op_code: " << primary_opcode);
749 static void InstructionEncoding::reg2reg<u1>(
jlong jlong jlong jlong jint jmethodID jint slot
X86_64Register * cast_to< X86_64Register >(Register *reg)
CodeFragment get_CodeFragment(std::size_t size)
get a code fragment
bool is_stackslot() const
u1 get_modrm(u1 reg, u1 base, s4 disp, bool use_sib=false)
alloc::deque< u1 >::type Container
static void reg2rbp_disp8(CodeMemory *CM, T opcode, X86_64Register *reg, s1 disp)
virtual StackSlot * to_StackSlot()
FIXME this should be managed.
X86_64Register * getBase()
u1 get_modrm_reg2reg(X86_64Register *reg, X86_64Register *rm)
static void reg2reg(CodeMemory *CM, T opcode, X86_64Register *reg, X86_64Register *rm)
alloc::set< EdgeType >::type mod
u1 get_modrm_1reg(u1 reg, X86_64Register *rm)
Container::const_iterator const_iterator
std::deque< T, Allocator< T > > type
static void imm_op(CodeMemory *CM, O opcode, I imm)
void add_CodeSegmentBuilder(CodeMemory *CM, const CodeSegmentBuilder &CSB)
X86_64Register * operator*() const
u1 get_sib(X86_64Register *base, X86_64Register *index=NULL, u1 scale=1)
Extension of the ModR/M reg field.
bool use_sib(X86_64Register *base, X86_64Register *index)
GPRegister R12("R12", 0x4, true, 0xc *8, 8)
u1 get_rex(X86_64Register *reg, X86_64Register *rm=NULL, bool opsiz64=true)
const_iterator end() const
CodeSegmentBuilder & operator+=(u1 d)
Extension of the SIB index field.
static void reg2imm(CodeMemory *CM, O opcode, X86_64Register *reg, I imm)
u1 operator[](std::size_t i) const
const_iterator begin() const
GPRegister RBP("RBP", 0x5, false, 0x5 *8, 8)
Container::iterator iterator
0 = Operand size determined by CS.D 1 = 64 Bit Operand Size
X86_64ModRMOperand * cast_to< X86_64ModRMOperand >(MachineOperand *op)
StackSlot * cast_to< StackSlot >(MachineOperand *op)
unsigned get_index() const
std::size_t size() const
size of the reference
X86_64Register * operator->() const
Immediate * cast_to< Immediate >(MachineOperand *op)
static void emit(CodeMemory *CM, u1 primary_opcode, GPInstruction::OperandSize op_size, MachineOperand *src, MachineOperand *dst, u1 secondary_opcode=0, u1 op_reg=0, u1 prefix=0, bool prefix_0f=false, bool encode_dst=true, bool imm_sign_extended=false)
X86_64Register * getIndex()
static void reg2imm_modrm(CodeMemory *CM, O opcode, X86_64Register *reg, X86_64Register *rm, I imm)
u1 get_modrm_u1(u1 mod, u1 reg, u1 rm)
Container::value_type value_type
OpReg(X86_64Register *reg)
Operands that can be directly used by the machine (register, memory, stackslot)
u1 & operator[](std::size_t i)
Extension of the ModR/M r/m field, SIB base field, or Opcode reg field.
static void imm(Seg seg, I imm)
static void imm_op(CodeFragment &code, O opcode, I imm)
REX & operator+(OpReg reg)
static void reg2rbp_disp32(CodeMemory *CM, T opcode, X86_64Register *reg, s4 disp)
#define ABORT_MSG(EXPR_SHORT, EXPR_LONG)
GPRegister RSP("RSP", 0x4, false, 0x4 *8, 8)
bool is_Immediate() const