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 
589 void TrapInst::emit(CodeMemory* CM) const {
590  // TODO Understand, clean up, and unify with CondTrapInst::emit if possible.
591 
592  CodeFragment code = CM->get_CodeFragment(8);
593  // XXX make more readable
595  // move
596  code[0] = 0x48; // rex
597  code[1] = 0x8b; // move
598  code[2] = (0x7 & src_reg->get_index()) << 3 | 0x4;
599  // ModRM: mod=0x00, reg=src_reg, rm=0b100 (SIB)
600  code[3] = 0x25; // SIB scale=0b00, index=0b100, base=0b101 (illegal -> trap)
601  // trap
602  code[4] = u1( 0xff & (trap >> (8 * 0)));
603  code[5] = u1( 0xff & (trap >> (8 * 1)));
604  code[6] = u1( 0xff & (trap >> (8 * 2)));
605  code[7] = u1( 0xff & (trap >> (8 * 3)));
606 }
607 
609  CodeFragment code = CM->get_CodeFragment(8);
610  // XXX make more readable
612  // move
613  code[0] = 0x48; // rex
614  code[1] = 0x8b; // move
615  code[2] = (0x7 & src_reg->get_index()) << 3 | 0x4;
616  // ModRM: mod=0x00, reg=src_reg, rm=0b100 (SIB)
617  code[3] = 0x25; // SIB scale=0b00, index=0b100, base=0b101 (illegal -> trap)
618  // trap
619  code[4] = u1( 0xff & (trap >> (8 * 0)));
620  code[5] = u1( 0xff & (trap >> (8 * 1)));
621  code[6] = u1( 0xff & (trap >> (8 * 2)));
622  code[7] = u1( 0xff & (trap >> (8 * 3)));
623  // skip jump
624  s4 offset = 8;
625  InstructionEncoding::imm_op<u2>(CM, 0x0f80 + cond.code, offset);
626 
627 }
628 
629 void CMovInst::emit(CodeMemory* CM) const {
632 
633  CodeSegmentBuilder code;
634  u1 rex = get_rex(dst,src,get_op_size() == GPInstruction::OS_64);
635  if (rex != 0x40)
636  code += rex;
637  code += 0x0f;
638  code += 0x40 | cond.code;
639  code += get_modrm_reg2reg(dst,src);
640  add_CodeSegmentBuilder(CM,code);
641 }
642 
644  // update jump target (might have changed)
646  // emit else jump (if needed)
647  jump.emit(CM);
648  // emit then jump
650  CodeSegment &CS = CM->get_CodeSegment();
651  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
652  if (CodeSegment::is_invalid(idx)) {
653  LOG2("X86_64CondJumpInst: target not yet known (" << this << " to "
654  << *MBB << ")" << nl);
655  // reserve memory and add to resolve later
656  // worst case -> 32bit offset
657  CodeFragment CF = CM->get_CodeFragment(6);
658  // FIXME pass this the resolve me
659  CM->require_linking(this,CF);
660  return;
661  }
662  s4 offset = CM->get_offset(idx);
663  if (offset == 0) {
664  // XXX fix me! remove empty blocks?
665  ABORT_MSG("x86_64 ERROR","CondJump offset 0 oO!");
666  //return;
667  }
668  LOG2("found offset of " << *MBB << ": " << offset << nl);
669 
670  // only 32bit offset for the time being
671  InstructionEncoding::imm_op<u2>(CM, 0x0f80 + cond.code, offset);
672 }
673 
676  CodeSegment &CS = CF.get_Segment();
677  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
678  s4 offset = CS.get_CodeMemory().get_offset(idx,CF);
679  assert(offset != 0);
680 
681  InstructionEncoding::imm_op<u2>(CF, 0x0f80 + cond.code, offset);
682  jump.link(CF);
683 }
684 
685 void IMulInst::emit(CodeMemory* CM) const {
688 
689  InstructionEncoding::reg2reg<u2>(CM, 0x0faf, dst_reg, src_reg);
690  // imm Byte = 6B, sonst 69
691  // dst = reg, src = reg or mem
692 
693  // 0F AF dst = reg or mem, src = reg
694 }
695 
696 void IMulImmInst::emit(CodeMemory* CM) const {
699  Immediate *imm = cast_to<Immediate>(operands[1].op);
700 
701  s4 immval = imm->get_value<s4>();
702  if (fits_into<s1>(immval)){
703  InstructionEncoding::reg2imm_modrm<u1,s1>(CM, 0x6b, dst_reg, src_reg, immval);
704  } else {
705  InstructionEncoding::reg2imm_modrm<u1,s4>(CM, 0x69, dst_reg, src_reg, immval);
706  }
707 
708 }
709 
710 void IDivInst::emit(CodeMemory *CM) const {
711  CodeFragment code = CM->get_CodeFragment(2);
713  code[0] = 0xf7;
714  code[1] = get_modrm_1reg(7, divisor);
715 }
716 
717 void CDQInst::emit(CodeMemory *CM) const {
718  CodeFragment code = CM->get_CodeFragment(1);
719  code[0] = 0x99;
720 }
721 
722 namespace {
723 
724 void emit_jump(CodeFragment &code, s4 offset) {
725  LOG2("emit_jump codefragment offset: " << hex << offset << nl);
726  code[0] = 0xe9;
727  code[1] = u1( 0xff & (offset >> (8 * 0)));
728  code[2] = u1( 0xff & (offset >> (8 * 1)));
729  code[3] = u1( 0xff & (offset >> (8 * 2)));
730  code[4] = u1( 0xff & (offset >> (8 * 3)));
731 }
732 
733 } // end anonymous namespace
734 void JumpInst::emit(CodeMemory* CM) const {
736  CodeSegment &CS = CM->get_CodeSegment();
737  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
738  if (CodeSegment::is_invalid(idx)) {
739  LOG2("emit_Jump: target not yet known (" << this << " to "
740  << *MBB << ")" << nl);
741  // reserve memory and add to resolve later
742  // worst case -> 32bit offset
743  CodeFragment CF = CM->get_CodeFragment(5);
744  // FIXME pass this the resolve me
745  CM->require_linking(this,CF);
746  return;
747  }
748  s4 offset = CM->get_offset(idx);
749  if (offset == 0) {
750  LOG2("emit_Jump: jump to the next instruction -> can be omitted ("
751  << this << " to " << *MBB << ")" << nl);
752  return;
753  }
754  CodeFragment CF = CM->get_CodeFragment(5);
755  emit_jump(CF,offset);
756 }
757 
758 void JumpInst::link(CodeFragment &CF) const {
760  CodeSegment &CS = CF.get_Segment();
761  CodeSegment::IdxTy idx = CS.get_index(CSLabel(MBB));
762  LOG2("JumpInst:link BI: " << *MBB << " idx: " << idx.idx << " CF begin: "
763  << CF.get_begin().idx << " CF end: " << CF.get_end().idx << nl);
764  s4 offset = CS.get_CodeMemory().get_offset(idx,CF);
765  assert(offset != 0);
766 
767  emit_jump(CF,offset);
768 }
769 
772  CodeFragment code = CM->get_CodeFragment(2);
773  code[0] = 0xff;
774  WARNING_MSG("Not yet implemented","No support for indirect jump yet.");
775  code[1] = get_modrm_1reg(0,src_reg);
776  return;
777 }
778 
779 void UCOMISInst::emit(CodeMemory* CM) const {
782 
783  CodeSegmentBuilder code;
785  code += 0x66;
786  }
787  code += 0x0f;
788  code += 0x2e;
789  code += get_modrm_reg2reg(src1,src2);
790  add_CodeSegmentBuilder(CM,code);
791 }
792 
793 void XORPInst::emit(CodeMemory* CM) const {
796 
797  CodeSegmentBuilder code;
799  code += 0x66;
800  }
801  code += 0x0f;
802  code += 0x57;
803  code += get_modrm_reg2reg(dstsrc1,src2);
804  add_CodeSegmentBuilder(CM,code);
805 }
806 
807 void SSEAluInst::emit(CodeMemory* CM) const {
808  MachineOperand *src = operands[1].op;
809  MachineOperand *dst = result.op;
810 
811  switch (get_OpEncoding(dst,src,get_op_size())) {
813  {
814  X86_64Register *src_reg = cast_to<X86_64Register>(src);
815  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
816 
817  CodeFragment code = CM->get_CodeFragment(4);
818  code[0] = 0xf2;
819  code[1] = 0x0f;
820  code[2] = opcode;
821  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
822  return;
823  }
825  {
826  X86_64Register *src_reg = cast_to<X86_64Register>(src);
827  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
828 
829  CodeFragment code = CM->get_CodeFragment(4);
830  code[0] = 0xf3;
831  code[1] = 0x0f;
832  code[2] = opcode;
833  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
834  return;
835  }
836  default: break;
837  }
838  ABORT_MSG(this << ": Operand(s) not supported",
839  "dst: " << dst << " src: " << src << " op_size: "
840  << get_op_size() * 8 << "bit");
841 }
842 
843 void MovSDInst::emit(CodeMemory* CM) const {
844  MachineOperand *src = operands[0].op;
845  MachineOperand *dst = result.op;
846  if (src->aquivalent(*dst)) return;
847 
848  u1 opcode = 0x06; //invalid
849  switch (get_OpEncoding(dst,src,get_op_size())) {
852  {
853  opcode = 0x10;
854  break;
855  }
857  {
858  opcode = 0x11;
859  break;
860  }
861  default:
862  ABORT_MSG(this << ": Operand(s) not supported",
863  "dst: " << dst << " src: " << src << " op_size: "
864  << get_op_size() * 8 << "bit");
865  break;
866  }
867 
868  InstructionEncoding::emit (CM, opcode, get_op_size(), src, dst, 0, 0, 0xf2, true);
869 }
870 
871 void MovSSInst::emit(CodeMemory* CM) const {
872  MachineOperand *src = operands[0].op;
873  MachineOperand *dst = result.op;
874  if (src->aquivalent(*dst)) return;
875 
876  u1 opcode = 0x06; //invalid
877  switch (get_OpEncoding(dst,src,get_op_size())) {
880  {
881  opcode = 0x10;
882  break;
883  }
885  {
886  opcode = 0x11;
887  break;
888  }
889  default:
890  ABORT_MSG(this << ": Operand(s) not supported",
891  "dst: " << dst << " src: " << src << " op_size: "
892  << get_op_size() * 8 << "bit");
893  break;
894  }
895 
896  InstructionEncoding::emit (CM, opcode, get_op_size(), src, dst, 0, 0, 0xf3, true);
897 }
898 
899 void FPRemInst::emit(CodeMemory* CM) const {
900 
901  CodeFragment code = CM->get_CodeFragment(2);
902  code[0] = 0xd9;
903  code[1] = 0xf8;
904 }
905 
906 void MovImmSInst::emit(CodeMemory* CM) const {
907  Immediate *imm = cast_to<Immediate>(operands[0].op);
909 
910  CodeFragment code = CM->get_CodeFragment(dst->extented ? 9 : 8);
911  if (dst->extented) {
912  code[0] = get_rex(dst,NULL,get_op_size() == OS_64);
913  code[1] = (get_op_size() == OS_64 ? 0xf2 : 0xf3);
914  code[2] = 0x0f;
915  code[3] = 0x10;
916  // RIP-Relateive addressing mod=00b, rm=101b, + disp32
917  code[4] = get_modrm_u1(0x0,dst->get_index(),0x5);
918  #if 1
919  code[5] = 0xaa;
920  code[6] = 0xaa;
921  code[7] = 0xaa;
922  code[8] = 0xaa;
923  #endif
924  } else {
925  code[0] = (get_op_size() == OS_64 ? 0xf2 : 0xf3);
926  code[1] = 0x0f;
927  code[2] = 0x10;
928  // RIP-Relateive addressing mod=00b, rm=101b, + disp32
929  code[3] = get_modrm_u1(0x0,dst->get_index(),0x5);
930  #if 1
931  code[4] = 0xaa;
932  code[5] = 0xaa;
933  code[6] = 0xaa;
934  code[7] = 0xaa;
935  #endif
936  }
937  switch (get_op_size()) {
938  case OS_64:
939  switch (imm->get_type()) {
940  case Type::DoubleTypeID:
941  {
942  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(double));
943  InstructionEncoding::imm<double>(DF,imm->get_Double());
945  break;
946  }
947  case Type::LongTypeID:
948  {
949  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(int64_t));
950  InstructionEncoding::imm<int64_t>(DF,imm->get_Long());
952  break;
953  }
954  default: assert(0);
955  break;
956  }
957  break;
958  case OS_32:
959  switch (imm->get_type()) {
960  case Type::FloatTypeID:
961  {
962  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(float));
963  InstructionEncoding::imm<float>(DF,imm->get_Float());
965  break;
966  }
967  case Type::IntTypeID:
968  {
969  DataFragment DF = CM->get_DataSegment().get_Ref(sizeof(int32_t));
970  InstructionEncoding::imm<int32_t>(DF,imm->get_Int());
971  data_index = CM->get_DataSegment().insert_tag(DSInt(imm->get_Int()),DF);
972  break;
973  }
974  default: assert(0);
975  break;
976  }
977  break;
978  default: assert(0);
979  break;
980  }
981  CM->require_linking(this,code);
982 }
983 
985  CodeMemory &CM = CF.get_Segment().get_CodeMemory();
986  s4 offset = CM.get_offset(data_index,CF);
987  LOG2(this << " offset: " << offset << " data index: " << data_index.idx << " CF end index "
988  << CF.get_end().idx << nl);
989  LOG2("dseg->size " << CM.get_DataSegment().size()
990  << " cseg->size " << CM.get_CodeSegment().size() << nl );
991 
992  assert(offset != 0);
993  int i = 4;
995  i = 5;
996  CF[i++] = u1(0xff & (offset >> 0));
997  CF[i++] = u1(0xff & (offset >> 8));
998  CF[i++] = u1(0xff & (offset >> 16));
999  CF[i ] = u1(0xff & (offset >> 24));
1000 }
1001 
1002 
1003 
1004 
1005 // TODO: refactor
1007  MachineOperand *src = operands[0].op;
1008  MachineOperand *dst = result.op;
1009 
1010  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1011  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1012 
1013  switch (from) {
1014  case GPInstruction::OS_32:
1015  {
1016  CodeFragment code = CM->get_CodeFragment(4);
1017  code[0] = 0xf2;
1018  code[1] = 0x0f;
1019  code[2] = 0x2a;
1020  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1021  return;
1022  }
1023  case GPInstruction::OS_64:
1024  {
1025  CodeFragment code = CM->get_CodeFragment(5);
1026  code[0] = 0xf2;
1027  code[1] = get_rex(dst_reg,src_reg);
1028  code[2] = 0x0f;
1029  code[3] = 0x2a;
1030  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1031  return;
1032  }
1033  default: break;
1034  }
1035  ABORT_MSG(this << ": Operand(s) not supported",
1036  "dst: " << dst << " src: " << src << " op_size: "
1037  << get_op_size() * 8 << "bit");
1038 }
1039 
1040 // TODO: refactor
1042  MachineOperand *src = operands[0].op;
1043  MachineOperand *dst = result.op;
1044 
1045  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1046  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1047 
1048  switch (from) {
1049  case GPInstruction::OS_32:
1050  {
1051  CodeFragment code = CM->get_CodeFragment(4);
1052  code[0] = 0xf3;
1053  code[1] = 0x0f;
1054  code[2] = 0x2a;
1055  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1056  return;
1057  }
1058  case GPInstruction::OS_64:
1059  {
1060  CodeFragment code = CM->get_CodeFragment(5);
1061  code[0] = 0xf3;
1062  code[1] = get_rex(dst_reg,src_reg);
1063  code[2] = 0x0f;
1064  code[3] = 0x2a;
1065  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1066  return;
1067  }
1068  default: break;
1069  }
1070  ABORT_MSG(this << ": Operand(s) not supported",
1071  "dst: " << dst << " src: " << src << " op_size: "
1072  << get_op_size() * 8 << "bit");
1073 }
1074 
1075 
1077  MachineOperand *src = operands[0].op;
1078  MachineOperand *dst = result.op;
1079 
1080  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1081  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1082 
1083  switch (to) {
1084  case GPInstruction::OS_32:
1085  {
1086  CodeFragment code = CM->get_CodeFragment(4);
1087  code[0] = 0xf3;
1088  code[1] = 0x0f;
1089  code[2] = 0x2c;
1090  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1091  return;
1092  }
1093  case GPInstruction::OS_64:
1094  {
1095  CodeFragment code = CM->get_CodeFragment(5);
1096  code[0] = 0xf3;
1097  code[1] = get_rex(dst_reg,src_reg);
1098  code[2] = 0x0f;
1099  code[3] = 0x2c;
1100  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1101  return;
1102  }
1103  default: break;
1104  }
1105  ABORT_MSG(this << ": Operand(s) not supported",
1106  "dst: " << dst << " src: " << src << " op_size: "
1107  << get_op_size() * 8 << "bit");
1108 
1109 }
1110 
1112  MachineOperand *src = operands[0].op;
1113  MachineOperand *dst = result.op;
1114 
1115  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1116  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1117 
1118  switch (to) {
1119  case GPInstruction::OS_32:
1120  {
1121  CodeFragment code = CM->get_CodeFragment(4);
1122  code[0] = 0xf2;
1123  code[1] = 0x0f;
1124  code[2] = 0x2c;
1125  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1126  return;
1127  }
1128  case GPInstruction::OS_64:
1129  {
1130  CodeFragment code = CM->get_CodeFragment(5);
1131  code[0] = 0xf2;
1132  code[1] = get_rex(dst_reg,src_reg);
1133  code[2] = 0x0f;
1134  code[3] = 0x2c;
1135  code[4] = get_modrm_reg2reg(dst_reg,src_reg);
1136  return;
1137  }
1138  default: break;
1139  }
1140  ABORT_MSG(this << ": Operand(s) not supported",
1141  "dst: " << dst << " src: " << src << " op_size: "
1142  << get_op_size() * 8 << "bit");
1143 
1144 }
1145 
1147  MachineOperand *src = operands[0].op;
1148  MachineOperand *dst = result.op;
1149 
1150  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1151  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1152 
1153  CodeFragment code = CM->get_CodeFragment(4);
1154  code[0] = 0xf3;
1155  code[1] = 0x0f;
1156  code[2] = 0x5a;
1157  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1158 
1159 }
1160 
1162  MachineOperand *src = operands[0].op;
1163  MachineOperand *dst = result.op;
1164 
1165  X86_64Register *src_reg = cast_to<X86_64Register>(src);
1166  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
1167 
1168  CodeFragment code = CM->get_CodeFragment(4);
1169  code[0] = 0xf2;
1170  code[1] = 0x0f;
1171  code[2] = 0x5a;
1172  code[3] = get_modrm_reg2reg(dst_reg,src_reg);
1173 
1174 }
1175 
1176 // TODO: refactor
1177 void FLDInst::emit(CodeMemory *CM) const {
1178  CodeSegmentBuilder code;
1179  REX rex;
1181 
1182  switch (op_size) {
1183 
1184  case GPInstruction::OS_32:
1185  code += 0xd9;
1186  break;
1187  case GPInstruction::OS_64:
1188  rex + REX::W;
1189  code += rex;
1190  code += 0xdd;
1191  break;
1192  default:
1193  ABORT_MSG(this << ": Operand size for FLD not supported",
1194  "size: " << get_op_size() * 8 << "bit");
1195  }
1196 
1197  // modmr + imm
1199  if (fits_into<s1>(index)) {
1200  code += get_modrm_u1(0x1,0,RBP.get_index());
1201  code += (u1) 0xff & (index >> 0x00);
1202  } else {
1203  code += get_modrm_u1(0x2,0,RBP.get_index());
1204  code += (u1) 0xff & (index >> 0x00);
1205  code += (u1) 0xff & (index >> 0x08);
1206  code += (u1) 0xff & (index >> 0x10);
1207  code += (u1) 0xff & (index >> 0x18);
1208  }
1209  add_CodeSegmentBuilder(CM,code);
1210 }
1211 
1212 // TODO: refactor
1213 void FSTPInst::emit(CodeMemory *CM) const {
1214  CodeSegmentBuilder code;
1215  REX rex;
1217 
1218  switch (op_size) {
1219 
1220  case GPInstruction::OS_32:
1221  code += 0xd9;
1222  break;
1223  case GPInstruction::OS_64:
1224  rex + REX::W;
1225  code += rex;
1226  code += 0xdd;
1227  break;
1228  default:
1229  ABORT_MSG(this << ": Operand size for FSTP not supported",
1230  "size: " << get_op_size() * 8 << "bit");
1231  }
1232 
1233  // modmr + imm
1235  if (fits_into<s1>(index)) {
1236  code += get_modrm_u1(0x1,3,RBP.get_index());
1237  code += (u1) 0xff & (index >> 0x00);
1238  } else {
1239  code += get_modrm_u1(0x2,3,RBP.get_index());
1240  code += (u1) 0xff & (index >> 0x00);
1241  code += (u1) 0xff & (index >> 0x08);
1242  code += (u1) 0xff & (index >> 0x10);
1243  code += (u1) 0xff & (index >> 0x18);
1244  }
1245  add_CodeSegmentBuilder(CM,code);
1246 }
1247 
1248 void FFREEInst::emit(CodeMemory* CM) const {
1249 
1250  CodeFragment code = CM->get_CodeFragment(2);
1251  code[0] = 0xdd;
1252  code[1] = 0xc0 + fpureg->index;
1253 }
1254 
1256 
1257  CodeFragment code = CM->get_CodeFragment(2);
1258  code[0] = 0xd9;
1259  code[1] = 0xf7;
1260 }
1261 
1262 void TestInst::emit(CodeMemory* CM) const {
1263  CodeSegmentBuilder code;
1264  MachineOperand *src1 = operands[0].op;
1265  MachineOperand *src2 = operands[1].op;
1266 
1267  X86_64Register *src1_reg = cast_to<X86_64Register>(src1);
1268  X86_64Register *src2_reg = cast_to<X86_64Register>(src2);
1269 
1270  // rex
1271  u1 rex = get_rex(src1_reg, src2_reg, get_op_size() == OS_64);
1272  if (rex != 0x40) {
1273  code += rex;
1274  }
1275 
1276  code += 0x85;
1277  code += get_modrm_reg2reg(src1_reg, src2_reg);
1278 
1279  add_CodeSegmentBuilder(CM,code);
1280 }
1281 
1282 } // end namespace x86_64
1283 } // end namespace compiler2
1284 } // end namespace jit
1285 } // end namespace cacao
1286 
1287 
1288 /*
1289  * These are local overrides for various environment variables in Emacs.
1290  * Please do not remove this and leave it at the end of the file, where
1291  * Emacs will automagically detect them.
1292  * ---------------------------------------------------------------------
1293  * Local variables:
1294  * mode: c++
1295  * indent-tabs-mode: t
1296  * c-basic-offset: 4
1297  * tab-width: 4
1298  * End:
1299  * vim:noexpandtab:sw=4:ts=4:
1300  */
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
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
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
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
s4 trap
A trap number as defined in x86_64/md-trap.hpp.
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
int get_stack_position(MachineOperand *op)
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
virtual void emit(CodeMemory *CM) const
emit machine code
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