CACAO
X86_64Instructions.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/X86_64Instructions.hpp - X86_64Instructions
2 
3  Copyright (C) 2013
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 
30 #include "vm/jit/PatcherNew.hpp"
31 
33 
34 #include "toolbox/logging.hpp"
35 
36 #define DEBUG_NAME "compiler2/x86_64"
37 
38 namespace cacao {
39 namespace jit {
40 namespace compiler2 {
41 namespace x86_64 {
42 
43 template <class A,A>
44 inline A* cast_to(A* a) {
45  assert(a);
46  return a;
47 }
48 
50  switch (type) {
51  case Type::ByteTypeID:
52  case Type::CharTypeID:
53  return GPInstruction::OS_8;
60  default: break;
61  }
62  ABORT_MSG("Type Not supported!","get_OperandSize_from_Type: " << type);
64 }
65 
66 
69 
70  switch (src1->get_OperandID()) {
72  {
73  //X86_64Register *reg1 = cast_to<X86_64Register>(src1);
74 
75  // switch second operand
76  switch (src2->get_OperandID()) {
78  {
79  switch (op_size) {
84  default: break;
85  }
86  }
88  {
89  Immediate *imm = cast_to<Immediate>(src2);
90  if ( (imm->get_type() == Type::IntTypeID
91  && fits_into<s1>(imm->get_Int())) ||
92  (imm->get_type() == Type::LongTypeID
93  && fits_into<s1>(imm->get_Long())) ) {
94  // 8bit
95  switch (op_size) {
100  default: break;
101  }
102  }
103  switch (op_size) {
104  case GPInstruction::OS_8 : // can this happen?
108  default: break;
109  }
110  }
114  {
115  switch (op_size) {
120  default: break;
121  }
122  }
123  default: break;
124  }
125  break;
126  }
129  {
130  // switch second operand
131  switch (src2->get_OperandID()) {
133  {
134  switch (op_size) {
139  default: break;
140  }
141  }
143  {
144  switch (op_size) {
149  default: break;
150  }
151  }
152  default: break;
153  }
154  break;
155  }
156  default: break;
157  }
159 }
160 
162  switch (type) {
163  case Type::ByteTypeID:
164  return GPInstruction::OS_8;
165  case Type::IntTypeID:
166  case Type::FloatTypeID:
167  return GPInstruction::OS_32;
168  case Type::LongTypeID:
169  case Type::DoubleTypeID:
171  return GPInstruction::OS_64;
172  default: break;
173  }
174  ABORT_MSG("x86_64: get operand size not support",
175  "type: " << type);
176  return GPInstruction::NO_SIZE;
177 }
178 
180  MachineOperand *dst = result.op;
181  MachineOperand *src1 = operands[0].op;
182  MachineOperand *src2 = operands[1].op;
183  MachineOperand *src;
184 
185  if (dst->is_VoidOperand()) {
186  dst = src1;
187  src = src2;
188  }
189  else if (dst == src1) {
190  src = src2;
191  }
192  else {
193  src = src1;
194  }
195 
197  u1 opcode = 0x06; //invalid
198  u1 op_reg = 0;
199  bool imm_sign_extended = false;
200 
201  switch (openc) {
204  opcode = (alu_id * 0x08) + 0x00;
205  break;
209  opcode = (alu_id * 0x08) + 0x03;
210  break;
212  opcode = (alu_id * 0x08) + 0x02;
213  break;
217  opcode = (alu_id * 0x08) + 0x01;
218  break;
222  opcode = (alu_id * 0x08) + 0x03;
223  break;
226  opcode = 0x80;
227  op_reg = alu_id;
228  break;
232  opcode = 0x83;
233  op_reg = alu_id;
234  imm_sign_extended = true;
235  break;
242  opcode = 0x81;
243  op_reg = alu_id;
244  break;
245  default:
246  ABORT_MSG(this << ": Operand(s) not supported",
247  "dst: " << dst << " src: " << src << " op_size: "
248  << get_op_size() * 8 << "bit");
249  break;
250  }
251 
252  InstructionEncoding::emit(CM,opcode,get_op_size(),src,dst,0,op_reg,0,false,true,imm_sign_extended);
253 }
254 
255 void emit_nop(CodeFragment code, int length) {
256  assert(length >= 0 && length <= 9);
257  unsigned mcodeptr = 0;
258  switch (length) {
259  case 0:
260  break;
261  case 1:
262  code[mcodeptr++] = 0x90;
263  break;
264  case 2:
265  code[mcodeptr++] = 0x66;
266  code[mcodeptr++] = 0x90;
267  break;
268  case 3:
269  code[mcodeptr++] = 0x0f;
270  code[mcodeptr++] = 0x1f;
271  code[mcodeptr++] = 0x00;
272  break;
273  case 4:
274  code[mcodeptr++] = 0x0f;
275  code[mcodeptr++] = 0x1f;
276  code[mcodeptr++] = 0x40;
277  code[mcodeptr++] = 0x00;
278  break;
279  case 5:
280  code[mcodeptr++] = 0x0f;
281  code[mcodeptr++] = 0x1f;
282  code[mcodeptr++] = 0x44;
283  code[mcodeptr++] = 0x00;
284  code[mcodeptr++] = 0x00;
285  break;
286  case 6:
287  code[mcodeptr++] = 0x66;
288  code[mcodeptr++] = 0x0f;
289  code[mcodeptr++] = 0x1f;
290  code[mcodeptr++] = 0x44;
291  code[mcodeptr++] = 0x00;
292  code[mcodeptr++] = 0x00;
293  break;
294  case 7:
295  code[mcodeptr++] = 0x0f;
296  code[mcodeptr++] = 0x1f;
297  code[mcodeptr++] = 0x80;
298  code[mcodeptr++] = 0x00;
299  code[mcodeptr++] = 0x00;
300  code[mcodeptr++] = 0x00;
301  code[mcodeptr++] = 0x00;
302  break;
303  case 8:
304  code[mcodeptr++] = 0x0f;
305  code[mcodeptr++] = 0x1f;
306  code[mcodeptr++] = 0x84;
307  code[mcodeptr++] = 0x00;
308  code[mcodeptr++] = 0x00;
309  code[mcodeptr++] = 0x00;
310  code[mcodeptr++] = 0x00;
311  code[mcodeptr++] = 0x00;
312  break;
313  case 9:
314  code[mcodeptr++] = 0x66;
315  code[mcodeptr++] = 0x0f;
316  code[mcodeptr++] = 0x1f;
317  code[mcodeptr++] = 0x84;
318  code[mcodeptr++] = 0x00;
319  code[mcodeptr++] = 0x00;
320  code[mcodeptr++] = 0x00;
321  code[mcodeptr++] = 0x00;
322  code[mcodeptr++] = 0x00;
323  break;
324  }
325 }
326 void PatchInst::emit(CodeMemory* CM) const {
328  code[0] = 0x0f;
329  code[1] = 0x0b;
330  emit_nop(code + 2, code.size() - 2);
331  CM->require_linking(this,code);
332 }
333 void PatchInst::link(CodeFragment &CF) const {
334  CodeMemory &CM = CF.get_Segment().get_CodeMemory();
336  LOG2(this << " link: reposition: " << patcher->get_mpc() << nl);
337 }
338 
339 void EnterInst::emit(CodeMemory* CM) const {
340  CodeFragment code = CM->get_CodeFragment(4);
341  code[0] = 0xc8;
342  code[1] = (0xff & (framesize >> 0));
343  code[2] = (0xff & (framesize >> 8));
344  code[3] = 0x0;
345 }
346 
347 void LeaveInst::emit(CodeMemory* CM) const {
348  CodeFragment code = CM->get_CodeFragment(1);
349  code[0] = 0xc9;
350 }
351 
352 void BreakInst::emit(CodeMemory* CM) const {
353  CodeFragment code = CM->get_CodeFragment(1);
354  // INT3 - drop to debugger
355  code[0] = 0xcc;
356 }
357 
358 void RetInst::emit(CodeMemory* CM) const {
359  CodeFragment code = CM->get_CodeFragment(1);
360  code[0] = 0xc3;
361 }
362 
363 void NegInst::emit(CodeMemory* CM) const {
365  CodeSegmentBuilder code;
366 
367  u1 rex = get_rex(reg,NULL,get_op_size() == OS_64);
368  // rex
369  if (rex != 0x40) {
370  code += rex;
371  }
372  // opcode
373  if (get_op_size() == OS_8)
374  code += 0xf6;
375  else
376  code += 0xf7;
377  code += get_modrm_u1(0x3,0x3,reg->get_index());
378  add_CodeSegmentBuilder(CM,code);
379 }
380 
381 void CallInst::emit(CodeMemory* CM) const {
382  CodeFragment code = CM->get_CodeFragment(2);
384  //code[0] = get_rex(reg_src);
385  code[0] = 0xff;
386  code[1] = get_modrm_1reg(2, reg_src);
387 }
388 
389 void MovInst::emit(CodeMemory* CM) const {
390  MachineOperand *src = operands[0].op;
391  MachineOperand *dst = result.op;
392 
394  u1 opcode = 0x06; //invalid
395  bool encode_dst = true;
396  switch (openc) {
401  {
402  X86_64Register *reg_dst = cast_to<X86_64Register>(dst);
403  X86_64Register *reg_src = cast_to<X86_64Register>(src);
404  if (reg_dst == reg_src && !forceSameRegisters) return;
405  opcode = 0x8b;
406  break;
407  }
412  opcode = 0x89;
413  break;
416  opcode = 0x8b;
417  break;
419  opcode = 0xb0;
420  encode_dst = false;
421  break;
426  opcode = 0xb8;
427  encode_dst = false;
428  break;
430  opcode = 0xc6;
431  break;
435  opcode = 0xc7;
436  break;
437  default:
438  ABORT_MSG(this << ": Operand(s) not supported",
439  "dst: " << dst << " src: " << src << " op_size: "
440  << get_op_size() * 8 << "bit");
441  break;
442  }
443 
444  InstructionEncoding::emit(CM,opcode,get_op_size(),src,dst,0,0,0,false,encode_dst);
445 }
446 
447 inline u1 get_rex(X86_64Register *reg, const ModRMOperandDesc &modrm, bool opsize64) {
448  REX rex;
449  if (opsize64)
450  rex + REX::W;
451  if (reg->extented)
452  rex + REX::R;
453  if (modrm.base.op != &NoOperand && cast_to<X86_64Register>(modrm.base.op)->extented)
454  rex + REX::B;
455  if (modrm.index.op != &NoOperand && cast_to<X86_64Register>(modrm.index.op)->extented)
456  rex + REX::X;
457 
458  return rex;
459 }
460 
461 void LEAInst::emit(CodeMemory* CM) const {
462  u1 opcode = 0x8D;
463  InstructionEncoding::emit(CM,opcode,get_op_size(),get(0).op,get_result().op);
464 }
465 
466 void MovSXInst::emit(CodeMemory* CM) const {
467  MachineOperand *src = operands[0].op;
468  MachineOperand *dst = result.op;
469  X86_64Register *src_reg = cast_to<X86_64Register>(src);
470  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
471 
472  switch (from) {
473  case GPInstruction::OS_8:
474  switch (to) {
476  {
477  CodeFragment code = CM->get_CodeFragment(4);
478 
479  code[0] = get_rex(dst_reg, src_reg);
480  code[1] = 0x0f;
481  code[2] = 0xbe;
482  code[3] = get_modrm_reg2reg(dst_reg, src_reg);
483  return;
484  }
485  default: break;
486  }
487  break;
489  switch (to) {
491  {
492  CodeFragment code = CM->get_CodeFragment(4);
493 
494  code[0] = get_rex(dst_reg, src_reg);
495  code[1] = 0x0f;
496  code[2] = 0xbf;
497  code[3] = get_modrm_reg2reg(dst_reg, src_reg);
498  return;
499  }
500  default: break;
501  }
502  break;
504  switch (to) {
506  {
507  // r32 -> r64
508  CodeFragment code = CM->get_CodeFragment(3);
509  code[0] = get_rex(dst_reg,src_reg);
510  code[1] = 0x63;
511  code[2] = get_modrm_reg2reg(dst_reg,src_reg);
512  return;
513  }
514  default: break;
515  }
516  break;
517  default: break;
518  }
519 
520  ABORT_MSG("x86_64 sext cast not supported","from " << from << "bits to "
521  << to << "bits");
522 }
523 
524 void MovDSEGInst::emit(CodeMemory* CM) const {
526  switch (get_op_size()) {
527  case OS_8:
528  case OS_16:
529  case OS_32:
530  break;
531  case OS_64:
532  {
533  CodeFragment code = CM->get_CodeFragment(7);
534  code[0] = get_rex(dst);
535  code[1] = 0x8b;
536  // RIP-Relateive addressing mod=00b, rm=101b, + disp32
537  code[2] = get_modrm_u1(0x0,dst->get_index(),0x5);
538  #if 1
539  code[3] = 0xaa;
540  code[4] = 0xaa;
541  code[5] = 0xaa;
542  code[6] = 0xaa;
543  #endif
544  CM->require_linking(this,code);
545  }
546  return;
547  default: break;
548  }
549  ABORT_MSG(this << ": Operand(s) not supported",
550  "op_size: " << get_op_size() * 8 << "bit");
551 }
552 
554  CodeMemory &CM = CF.get_Segment().get_CodeMemory();
555  s4 offset = CM.get_offset(data_index,CF);
556  LOG2(this << " offset: " << offset << " data index: " << data_index.idx << " CF end index "
557  << CF.get_end().idx << nl);
558  LOG2("dseg->size " << CM.get_DataSegment().size()
559  << " cseg->size " << CM.get_CodeSegment().size() << nl );
560  assert(offset != 0);
561  switch (get_op_size()) {
562  case OS_8:
563  case OS_16:
564  case OS_32:
565  break;
566  case OS_64:
567  {
568  CF[3] = u1(0xff & (offset >> 0));
569  CF[4] = u1(0xff & (offset >> 8));
570  CF[5] = u1(0xff & (offset >> 16));
571  CF[6] = u1(0xff & (offset >> 24));
572  }
573  return;
574  default: break;
575  }
576  ABORT_MSG(this << ": Operand(s) not supported",
577  "op_size: " << get_op_size() * 8 << "bit");
578 }
579 
581  switch(index){
582  case 0: return OS << "then";
583  case 1: return OS << "else";
584  default: assert(0); break;
585  }
586  return OS << index;
587 }
588 
590  CodeFragment code = CM->get_CodeFragment(8);
591  // XXX make more readable
593  // move
594  code[0] = 0x48; // rex
595  code[1] = 0x8b; // move
596  code[2] = (0x7 & src_reg->get_index()) << 3 | 0x4;
597  // ModRM: mod=0x00, reg=src_reg, rm=0b100 (SIB)
598  code[3] = 0x25; // SIB scale=0b00, index=0b100, base=0b101 (illegal -> trap)
599  // trap
600  code[4] = u1( 0xff & (trap >> (8 * 0)));
601  code[5] = u1( 0xff & (trap >> (8 * 1)));
602  code[6] = u1( 0xff & (trap >> (8 * 2)));
603  code[7] = u1( 0xff & (trap >> (8 * 3)));
604  // skip jump
605  s4 offset = 8;
606  InstructionEncoding::imm_op<u2>(CM, 0x0f80 + cond.code, offset);
607 
608 }
609 
610 void CMovInst::emit(CodeMemory* CM) const {
613 
614  CodeSegmentBuilder code;
615  u1 rex = get_rex(dst,src,get_op_size() == GPInstruction::OS_64);
616  if (rex != 0x40)
617  code += rex;
618  code += 0x0f;
619  code += 0x40 | cond.code;
620  code += get_modrm_reg2reg(dst,src);
621  add_CodeSegmentBuilder(CM,code);
622 }
623 
625  // update jump target (might have changed)
627  // emit else jump (if needed)
628  jump.emit(CM);
629  // emit then jump
631  CodeSegment &CS = CM->get_CodeSegment();
632  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
633  if (CodeSegment::is_invalid(idx)) {
634  LOG2("X86_64CondJumpInst: target not yet known (" << this << " to "
635  << *MBB << ")" << nl);
636  // reserve memory and add to resolve later
637  // worst case -> 32bit offset
638  CodeFragment CF = CM->get_CodeFragment(6);
639  // FIXME pass this the resolve me
640  CM->require_linking(this,CF);
641  return;
642  }
643  s4 offset = CM->get_offset(idx);
644  if (offset == 0) {
645  // XXX fix me! remove empty blocks?
646  ABORT_MSG("x86_64 ERROR","CondJump offset 0 oO!");
647  //return;
648  }
649  LOG2("found offset of " << *MBB << ": " << offset << nl);
650 
651  // only 32bit offset for the time being
652  InstructionEncoding::imm_op<u2>(CM, 0x0f80 + cond.code, offset);
653 }
654 
657  CodeSegment &CS = CF.get_Segment();
658  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
659  s4 offset = CS.get_CodeMemory().get_offset(idx,CF);
660  assert(offset != 0);
661 
662  InstructionEncoding::imm_op<u2>(CF, 0x0f80 + cond.code, offset);
663  jump.link(CF);
664 }
665 
666 void IMulInst::emit(CodeMemory* CM) const {
669 
670  InstructionEncoding::reg2reg<u2>(CM, 0x0faf, dst_reg, src_reg);
671  // imm Byte = 6B, sonst 69
672  // dst = reg, src = reg or mem
673 
674  // 0F AF dst = reg or mem, src = reg
675 }
676 
677 void IMulImmInst::emit(CodeMemory* CM) const {
680  Immediate *imm = cast_to<Immediate>(operands[1].op);
681 
682  s4 immval = imm->get_value<s4>();
683  if (fits_into<s1>(immval)){
684  InstructionEncoding::reg2imm_modrm<u1,s1>(CM, 0x6b, dst_reg, src_reg, immval);
685  } else {
686  InstructionEncoding::reg2imm_modrm<u1,s4>(CM, 0x69, dst_reg, src_reg, immval);
687  }
688 
689 }
690 
691 void IDivInst::emit(CodeMemory *CM) const {
692  CodeFragment code = CM->get_CodeFragment(2);
694  code[0] = 0xf7;
695  code[1] = get_modrm_1reg(7, divisor);
696 }
697 
698 void CDQInst::emit(CodeMemory *CM) const {
699  CodeFragment code = CM->get_CodeFragment(1);
700  code[0] = 0x99;
701 }
702 
703 namespace {
704 
705 void emit_jump(CodeFragment &code, s4 offset) {
706  LOG2("emit_jump codefragment offset: " << hex << offset << nl);
707  code[0] = 0xe9;
708  code[1] = u1( 0xff & (offset >> (8 * 0)));
709  code[2] = u1( 0xff & (offset >> (8 * 1)));
710  code[3] = u1( 0xff & (offset >> (8 * 2)));
711  code[4] = u1( 0xff & (offset >> (8 * 3)));
712 }
713 
714 } // end anonymous namespace
715 void JumpInst::emit(CodeMemory* CM) const {
717  CodeSegment &CS = CM->get_CodeSegment();
718  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
719  if (CodeSegment::is_invalid(idx)) {
720  LOG2("emit_Jump: target not yet known (" << this << " to "
721  << *MBB << ")" << nl);
722  // reserve memory and add to resolve later
723  // worst case -> 32bit offset
724  CodeFragment CF = CM->get_CodeFragment(5);
725  // FIXME pass this the resolve me
726  CM->require_linking(this,CF);
727  return;
728  }
729  s4 offset = CM->get_offset(idx);
730  if (offset == 0) {
731  LOG2("emit_Jump: jump to the next instruction -> can be omitted ("
732  << this << " to " << *MBB << ")" << nl);
733  return;
734  }
735  CodeFragment CF = CM->get_CodeFragment(5);
736  emit_jump(CF,offset);
737 }
738 
739 void JumpInst::link(CodeFragment &CF) const {
741  CodeSegment &CS = CF.get_Segment();
742  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
743  LOG2("JumpInst:link BI: " << *MBB << " idx: " << idx.idx << " CF begin: "
744  << CF.get_begin().idx << " CF end: " << CF.get_end().idx << nl);
745  s4 offset = CS.get_CodeMemory().get_offset(idx,CF);
746  assert(offset != 0);
747 
748  emit_jump(CF,offset);
749 }
750 
753  CodeFragment code = CM->get_CodeFragment(2);
754  code[0] = 0xff;
755  WARNING_MSG("Not yet implemented","No support for indirect jump yet.");
756  code[1] = get_modrm_1reg(0,src_reg);
757  return;
758 }
759 
760 void UCOMISInst::emit(CodeMemory* CM) const {
763 
764  CodeSegmentBuilder code;
766  code += 0x66;
767  }
768  code += 0x0f;
769  code += 0x2e;
770  code += get_modrm_reg2reg(src1,src2);
771  add_CodeSegmentBuilder(CM,code);
772 }
773 
774 void XORPInst::emit(CodeMemory* CM) const {
777 
778  CodeSegmentBuilder code;
780  code += 0x66;
781  }
782  code += 0x0f;
783  code += 0x57;
784  code += get_modrm_reg2reg(dstsrc1,src2);
785  add_CodeSegmentBuilder(CM,code);
786 }
787 
788 void SSEAluInst::emit(CodeMemory* CM) const {
789  MachineOperand *src = operands[1].op;
790  MachineOperand *dst = result.op;
791 
792  switch (get_OpEncoding(dst,src,get_op_size())) {
794  {
795  X86_64Register *src_reg = cast_to<X86_64Register>(src);
796  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
797 
798  CodeFragment code = CM->get_CodeFragment(4);
799  code[0] = 0xf2;
800  code[1] = 0x0f;
801  code[2] = opcode;
802  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
803  return;
804  }
806  {
807  X86_64Register *src_reg = cast_to<X86_64Register>(src);
808  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
809 
810  CodeFragment code = CM->get_CodeFragment(4);
811  code[0] = 0xf3;
812  code[1] = 0x0f;
813  code[2] = opcode;
814  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
815  return;
816  }
817  default: break;
818  }
819  ABORT_MSG(this << ": Operand(s) not supported",
820  "dst: " << dst << " src: " << src << " op_size: "
821  << get_op_size() * 8 << "bit");
822 }
823 
824 void MovSDInst::emit(CodeMemory* CM) const {
825  MachineOperand *src = operands[0].op;
826  MachineOperand *dst = result.op;
827  if (src->aquivalent(*dst)) return;
828 
829  u1 opcode = 0x06; //invalid
830  switch (get_OpEncoding(dst,src,get_op_size())) {
833  {
834  opcode = 0x10;
835  break;
836  }
838  {
839  opcode = 0x11;
840  break;
841  }
842  default:
843  ABORT_MSG(this << ": Operand(s) not supported",
844  "dst: " << dst << " src: " << src << " op_size: "
845  << get_op_size() * 8 << "bit");
846  break;
847  }
848 
849  InstructionEncoding::emit (CM, opcode, get_op_size(), src, dst, 0, 0, 0xf2, true);
850 }
851 
852 void MovSSInst::emit(CodeMemory* CM) const {
853  MachineOperand *src = operands[0].op;
854  MachineOperand *dst = result.op;
855  if (src->aquivalent(*dst)) return;
856 
857  u1 opcode = 0x06; //invalid
858  switch (get_OpEncoding(dst,src,get_op_size())) {
861  {
862  opcode = 0x10;
863  break;
864  }
866  {
867  opcode = 0x11;
868  break;
869  }
870  default:
871  ABORT_MSG(this << ": Operand(s) not supported",
872  "dst: " << dst << " src: " << src << " op_size: "
873  << get_op_size() * 8 << "bit");
874  break;
875  }
876 
877  InstructionEncoding::emit (CM, opcode, get_op_size(), src, dst, 0, 0, 0xf3, true);
878 }
879 
880 void FPRemInst::emit(CodeMemory* CM) const {
881 
882  CodeFragment code = CM->get_CodeFragment(2);
883  code[0] = 0xd9;
884  code[1] = 0xf8;
885 }
886 
887 void MovImmSInst::emit(CodeMemory* CM) const {
888  Immediate *imm = cast_to<Immediate>(operands[0].op);
890 
891  CodeFragment code = CM->get_CodeFragment(dst->extented ? 9 : 8);
892  if (dst->extented) {
893  code[0] = get_rex(dst,NULL,get_op_size() == OS_64);
894  code[1] = (get_op_size() == OS_64 ? 0xf2 : 0xf3);
895  code[2] = 0x0f;
896  code[3] = 0x10;
897  // RIP-Relateive addressing mod=00b, rm=101b, + disp32
898  code[4] = get_modrm_u1(0x0,dst->get_index(),0x5);
899  #if 1
900  code[5] = 0xaa;
901  code[6] = 0xaa;
902  code[7] = 0xaa;
903  code[8] = 0xaa;
904  #endif
905  } else {
906  code[0] = (get_op_size() == OS_64 ? 0xf2 : 0xf3);
907  code[1] = 0x0f;
908  code[2] = 0x10;
909  // RIP-Relateive addressing mod=00b, rm=101b, + disp32
910  code[3] = get_modrm_u1(0x0,dst->get_index(),0x5);
911  #if 1
912  code[4] = 0xaa;
913  code[5] = 0xaa;
914  code[6] = 0xaa;
915  code[7] = 0xaa;
916  #endif
917  }
918  switch (get_op_size()) {
919  case OS_64:
920  switch (imm->get_type()) {
921  case Type::DoubleTypeID:
922  {
923  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(double));
924  InstructionEncoding::imm<double>(DF,imm->get_Double());
926  break;
927  }
928  case Type::LongTypeID:
929  {
930  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(int64_t));
931  InstructionEncoding::imm<int64_t>(DF,imm->get_Long());
933  break;
934  }
935  default: assert(0);
936  break;
937  }
938  break;
939  case OS_32:
940  switch (imm->get_type()) {
941  case Type::FloatTypeID:
942  {
943  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(float));
944  InstructionEncoding::imm<float>(DF,imm->get_Float());
946  break;
947  }
948  case Type::IntTypeID:
949  {
950  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(int32_t));
951  InstructionEncoding::imm<int32_t>(DF,imm->get_Int());
952  data_index = CM->get_DataSegment().insert_tag(DSInt(imm->get_Int()),DF);
953  break;
954  }
955  default: assert(0);
956  break;
957  }
958  break;
959  default: assert(0);
960  break;
961  }
962  CM->require_linking(this,code);
963 }
964 
966  CodeMemory &CM = CF.get_Segment().get_CodeMemory();
967  s4 offset = CM.get_offset(data_index,CF);
968  LOG2(this << " offset: " << offset << " data index: " << data_index.idx << " CF end index "
969  << CF.get_end().idx << nl);
970  LOG2("dseg->size " << CM.get_DataSegment().size()
971  << " cseg->size " << CM.get_CodeSegment().size() << nl );
972 
973  assert(offset != 0);
974  int i = 4;
976  i = 5;
977  CF[i++] = u1(0xff & (offset >> 0));
978  CF[i++] = u1(0xff & (offset >> 8));
979  CF[i++] = u1(0xff & (offset >> 16));
980  CF[i ] = u1(0xff & (offset >> 24));
981 }
982 
983 
984 
985 
986 // TODO: refactor
988  MachineOperand *src = operands[0].op;
989  MachineOperand *dst = result.op;
990 
991  X86_64Register *src_reg = cast_to<X86_64Register>(src);
992  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
993 
994  switch (from) {
996  {
997  CodeFragment code = CM->get_CodeFragment(4);
998  code[0] = 0xf2;
999  code[1] = 0x0f;
1000  code[2] = 0x2a;
1001  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1002  return;
1003  }
1004  case GPInstruction::OS_64:
1005  {
1006  CodeFragment code = CM->get_CodeFragment(5);
1007  code[0] = 0xf2;
1008  code[1] = get_rex(dst_reg,src_reg);
1009  code[2] = 0x0f;
1010  code[3] = 0x2a;
1011  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1012  return;
1013  }
1014  default: break;
1015  }
1016  ABORT_MSG(this << ": Operand(s) not supported",
1017  "dst: " << dst << " src: " << src << " op_size: "
1018  << get_op_size() * 8 << "bit");
1019 }
1020 
1021 // TODO: refactor
1023  MachineOperand *src = operands[0].op;
1024  MachineOperand *dst = result.op;
1025 
1026  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1027  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1028 
1029  switch (from) {
1030  case GPInstruction::OS_32:
1031  {
1032  CodeFragment code = CM->get_CodeFragment(4);
1033  code[0] = 0xf3;
1034  code[1] = 0x0f;
1035  code[2] = 0x2a;
1036  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1037  return;
1038  }
1039  case GPInstruction::OS_64:
1040  {
1041  CodeFragment code = CM->get_CodeFragment(5);
1042  code[0] = 0xf3;
1043  code[1] = get_rex(dst_reg,src_reg);
1044  code[2] = 0x0f;
1045  code[3] = 0x2a;
1046  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1047  return;
1048  }
1049  default: break;
1050  }
1051  ABORT_MSG(this << ": Operand(s) not supported",
1052  "dst: " << dst << " src: " << src << " op_size: "
1053  << get_op_size() * 8 << "bit");
1054 }
1055 
1056 
1058  MachineOperand *src = operands[0].op;
1059  MachineOperand *dst = result.op;
1060 
1061  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1062  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1063 
1064  switch (to) {
1065  case GPInstruction::OS_32:
1066  {
1067  CodeFragment code = CM->get_CodeFragment(4);
1068  code[0] = 0xf3;
1069  code[1] = 0x0f;
1070  code[2] = 0x2c;
1071  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1072  return;
1073  }
1074  case GPInstruction::OS_64:
1075  {
1076  CodeFragment code = CM->get_CodeFragment(5);
1077  code[0] = 0xf3;
1078  code[1] = get_rex(dst_reg,src_reg);
1079  code[2] = 0x0f;
1080  code[3] = 0x2c;
1081  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1082  return;
1083  }
1084  default: break;
1085  }
1086  ABORT_MSG(this << ": Operand(s) not supported",
1087  "dst: " << dst << " src: " << src << " op_size: "
1088  << get_op_size() * 8 << "bit");
1089 
1090 }
1091 
1093  MachineOperand *src = operands[0].op;
1094  MachineOperand *dst = result.op;
1095 
1096  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1097  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1098 
1099  switch (to) {
1100  case GPInstruction::OS_32:
1101  {
1102  CodeFragment code = CM->get_CodeFragment(4);
1103  code[0] = 0xf2;
1104  code[1] = 0x0f;
1105  code[2] = 0x2c;
1106  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1107  return;
1108  }
1109  case GPInstruction::OS_64:
1110  {
1111  CodeFragment code = CM->get_CodeFragment(5);
1112  code[0] = 0xf2;
1113  code[1] = get_rex(dst_reg,src_reg);
1114  code[2] = 0x0f;
1115  code[3] = 0x2c;
1116  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1117  return;
1118  }
1119  default: break;
1120  }
1121  ABORT_MSG(this << ": Operand(s) not supported",
1122  "dst: " << dst << " src: " << src << " op_size: "
1123  << get_op_size() * 8 << "bit");
1124 
1125 }
1126 
1128  MachineOperand *src = operands[0].op;
1129  MachineOperand *dst = result.op;
1130 
1131  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1132  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1133 
1134  CodeFragment code = CM->get_CodeFragment(4);
1135  code[0] = 0xf3;
1136  code[1] = 0x0f;
1137  code[2] = 0x5a;
1138  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1139 
1140 }
1141 
1143  MachineOperand *src = operands[0].op;
1144  MachineOperand *dst = result.op;
1145 
1146  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1147  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1148 
1149  CodeFragment code = CM->get_CodeFragment(4);
1150  code[0] = 0xf2;
1151  code[1] = 0x0f;
1152  code[2] = 0x5a;
1153  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1154 
1155 }
1156 
1157 // TODO: refactor
1158 void FLDInst::emit(CodeMemory *CM) const {
1159  StackSlot *slot;
1160 
1161  slot = cast_to<StackSlot>(result.op);
1162  CodeSegmentBuilder code;
1163  REX rex;
1165 
1166  switch (op_size) {
1167 
1168  case GPInstruction::OS_32:
1169  {
1170  code += 0xd9;
1171  break;
1172  }
1173  case GPInstruction::OS_64:
1174  {
1175  rex + REX::W;
1176  code += rex;
1177  code += 0xdd;
1178  break;
1179  }
1180  default:
1181  {
1182  ABORT_MSG(this << ": Operand size for FLD not supported",
1183  "size: " << get_op_size() * 8 << "bit");
1184  }
1185  }
1186 
1187 
1188  // modmr + imm
1189  s4 index = slot->get_index() * 8;
1190  if (fits_into<s1>(index)) {
1191  code += get_modrm_u1(0x1,0,RBP.get_index());
1192  code += (u1) 0xff & (index >> 0x00);
1193  } else {
1194  code += get_modrm_u1(0x2,0,RBP.get_index());
1195  code += (u1) 0xff & (index >> 0x00);
1196  code += (u1) 0xff & (index >> 0x08);
1197  code += (u1) 0xff & (index >> 0x10);
1198  code += (u1) 0xff & (index >> 0x18);
1199  }
1200  add_CodeSegmentBuilder(CM,code);
1201 
1202 }
1203 
1204 // TODO: refactor
1205 void FSTPInst::emit(CodeMemory *CM) const {
1206  StackSlot *slot;
1207 
1208  slot = cast_to<StackSlot>(result.op);
1209  CodeSegmentBuilder code;
1210  REX rex;
1212 
1213  switch (op_size) {
1214 
1215  case GPInstruction::OS_32:
1216  {
1217  code += 0xd9;
1218  break;
1219  }
1220  case GPInstruction::OS_64:
1221  {
1222  rex + REX::W;
1223  code += rex;
1224  code += 0xdd;
1225  break;
1226  }
1227  default:
1228  {
1229  ABORT_MSG(this << ": Operand size for FSTP not supported",
1230  "size: " << get_op_size() * 8 << "bit");
1231  }
1232  }
1233 
1234 
1235  // modmr + imm
1236  s4 index = slot->get_index() * 8;
1237  if (fits_into<s1>(index)) {
1238  code += get_modrm_u1(0x1,3,RBP.get_index());
1239  code += (u1) 0xff & (index >> 0x00);
1240  } else {
1241  code += get_modrm_u1(0x2,3,RBP.get_index());
1242  code += (u1) 0xff & (index >> 0x00);
1243  code += (u1) 0xff & (index >> 0x08);
1244  code += (u1) 0xff & (index >> 0x10);
1245  code += (u1) 0xff & (index >> 0x18);
1246  }
1247  add_CodeSegmentBuilder(CM,code);
1248 
1249 
1250 }
1251 
1252 void FFREEInst::emit(CodeMemory* CM) const {
1253 
1254  CodeFragment code = CM->get_CodeFragment(2);
1255  code[0] = 0xdd;
1256  code[1] = 0xc0 + fpureg->index;
1257 }
1258 
1260 
1261  CodeFragment code = CM->get_CodeFragment(2);
1262  code[0] = 0xd9;
1263  code[1] = 0xf7;
1264 }
1265 
1266 } // end namespace x86_64
1267 } // end namespace compiler2
1268 } // end namespace jit
1269 } // end namespace cacao
1270 
1271 
1272 /*
1273  * These are local overrides for various environment variables in Emacs.
1274  * Please do not remove this and leave it at the end of the file, where
1275  * Emacs will automagically detect them.
1276  * ---------------------------------------------------------------------
1277  * Local variables:
1278  * mode: c++
1279  * indent-tabs-mode: t
1280  * c-basic-offset: 4
1281  * tab-width: 4
1282  * End:
1283  * vim:noexpandtab:sw=4:ts=4:
1284  */
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
jlong jlong jlong jlong jint jmethodID jint slot
Definition: jvmti.h:497
std::size_t index
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void link(CodeFragment &CF) const
link machine code
X86_64Register * cast_to< X86_64Register >(Register *reg)
CodeFragment get_CodeFragment(std::size_t size)
get a code fragment
Definition: CodeMemory.cpp:79
ConstTag< DataSegmentType, float, FloatID > DSFloat
Definition: DataSegment.hpp:47
virtual void emit(CodeMemory *CM) const
emit machine code
void set_target(MachineBasicBlock *target)
CodeFragment get_aligned_CodeFragment(std::size_t size)
get an aligned code fragment
Definition: CodeMemory.cpp:83
GPInstruction::OperandSize get_OperandSize_from_Type(const Type::TypeID type)
#define WARNING_MSG(EXPR_SHORT, EXPR_LONG)
Definition: logging.hpp:96
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
u1 get_modrm_reg2reg(X86_64Register *reg, X86_64Register *rm)
virtual void emit(CodeMemory *CM) const
emit machine code
u2 op
Definition: disass.cpp:129
A basic block of (scheduled) machine instructions.
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void link(CodeFragment &CF) const
link machine code
u1 get_modrm_1reg(u1 reg, X86_64Register *rm)
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
void add_CodeSegmentBuilder(CodeMemory *CM, const CodeSegmentBuilder &CSB)
virtual void emit(CodeMemory *CM) const
emit machine code
uint8_t u1
Definition: types.hpp:40
virtual void emit(CodeMemory *CM) const
emit machine code
Hex hex
Definition: OStream.cpp:50
virtual void link(CodeFragment &CF) const
link machine code
Extension of the ModR/M reg field.
std::size_t size() const
get size
Definition: Segment.hpp:153
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
u1 get_rex(X86_64Register *reg, X86_64Register *rm=NULL, bool opsiz64=true)
virtual void emit(CodeMemory *CM) const
emit machine code
ConstTag< DataSegmentType, int32_t, IntID > DSInt
Definition: DataSegment.hpp:48
virtual uintptr_t get_mpc() const =0
get the absolute position in code segment
const CodeSegment & get_CodeSegment() const
get CodeSegment
Definition: CodeMemory.hpp:65
virtual OStream & print_successor_label(OStream &OS, std::size_t index) const
print successor label
Extension of the SIB index field.
virtual void emit(CodeMemory *CM) const
emit machine code
GPInstruction::OpEncoding get_OpEncoding(MachineOperand *src1, MachineOperand *src2, GPInstruction::OperandSize op_size)
void require_linking(const MachineInstruction *, CodeFragment CF)
Add a MachineInstruction that require linking.
Definition: CodeMemory.cpp:56
MachineBasicBlock * successor_front() const
virtual void emit(CodeMemory *CM) const
emit machine code
GPInstruction::OperandSize get_operand_size_from_Type(Type::TypeID type)
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
s4 get_offset(CodeSegment::IdxTy to, CodeSegment::IdxTy from) const
Definition: CodeMemory.cpp:43
virtual void emit(CodeMemory *CM) const
emit machine code
GPRegister RBP("RBP", 0x5, false, 0x5 *8, 8)
virtual void emit(CodeMemory *CM) const
emit machine code
Segment< Tag, RefCategory > * get_Segment() const
Get containing segment.
Definition: Segment.hpp:328
virtual void emit(CodeMemory *CM) const
emit machine code
0 = Operand size determined by CS.D 1 = 64 Bit Operand Size
CodeMemory * get_CodeMemory() const
Get containing CodeMemory.
Definition: Segment.hpp:145
void emit_nop(CodeFragment code, int length)
IdxTy get_end() const
Get the index of the first element after the reference.
Definition: Segment.hpp:356
Simple stream class for formatted output.
Definition: OStream.hpp:141
StackSlot * cast_to< StackSlot >(MachineOperand *op)
virtual void reposition(intptr_t base)=0
reposition to another base
std::size_t size() const
size of the reference
Definition: Segment.hpp:392
virtual void link(CodeFragment &CF) const
link machine code
MIIterator i
#define LOG2(STMT)
Definition: logging.hpp:93
PointerTag< CodeSegmentType, const MachineBasicBlock, LabelID > CSLabel
Definition: CodeSegment.hpp:42
int32_t s4
Definition: types.hpp:45
virtual void emit(CodeMemory *CM) const
emit machine code
IdxTy insert_tag(SegmentTag< Tag > *tag, IdxTy o)
insert tag
Definition: Segment.hpp:123
Immediate * cast_to< Immediate >(MachineOperand *op)
virtual void emit(CodeMemory *CM) const
emit machine code
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)
virtual void emit(CodeMemory *CM) const
emit machine code
ConstTag< DataSegmentType, int64_t, LongID > DSLong
Definition: DataSegment.hpp:46
OStream & OS
IdxTy get_index(Tag2 tag) const
get the index of a tag
Definition: Segment.hpp:254
bool aquivalent(const MachineOperand &MO) const
u1 get_modrm_u1(u1 mod, u1 reg, u1 rm)
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
This must be implemented by subclasses.
Operands that can be directly used by the machine (register, memory, stackslot)
virtual void link(CodeFragment &CF) const
link machine code
const MachineOperandDesc & get_result() const
Extension of the ModR/M r/m field, SIB base field, or Opcode reg field.
Segment reference.
Definition: Segment.hpp:44
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
ConstTag< DataSegmentType, double, DoubleID > DSDouble
Definition: DataSegment.hpp:45
IdxTy get_begin() const
Get the index of the first element.
Definition: Segment.hpp:343
virtual void emit(CodeMemory *CM) const
emit machine code
#define ABORT_MSG(EXPR_SHORT, EXPR_LONG)
Definition: logging.hpp:133
virtual void emit(CodeMemory *CM) const
emit machine code
Nl nl
Definition: OStream.cpp:56
const char const void jint length
Definition: jvmti.h:352
Ref get_Ref(std::size_t t)
get a new reference to the segment
Definition: Segment.hpp:208
const DataSegment & get_DataSegment() const
get DataSegment
Definition: CodeMemory.hpp:69
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code