CACAO
X86_64Instructions.hpp
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 
25 #ifndef _JIT_COMPILER2_X86_64INSTRUCTIONS
26 #define _JIT_COMPILER2_X86_64INSTRUCTIONS
27 
34 #include "vm/types.hpp"
35 
36 namespace cacao {
37 // forward declaration
38 class Patcher;
39 
40 namespace jit {
41 namespace compiler2 {
42 
43 namespace x86_64 {
44 
45 /**
46  * @addtogroup x86_64_operand x86_64 Operand Helper
47  *
48  * These wrapper classes are used to enforce the correct
49  * ordering of the parameters.
50  *
51  * See Item 18 in "Efficient C++" @cite Meyers2005.
52  *
53  * @{
54  */
55 
56 /**
57  * Simple wrapper for the operand of an
58  * single operand x86_64 instruction.
59  */
60 struct SrcOp {
62  explicit SrcOp(MachineOperand *op) : op(op) {}
63 };
64 
65 struct SrcMemOp {
67  explicit SrcMemOp(StackSlot *op) : op(op) {
68 
69  }
70  explicit SrcMemOp(ManagedStackSlot *op) : op(op) {
71 
72  }
73 };
74 
75 
76 struct DstMemOp {
78  explicit DstMemOp(StackSlot *op) : op(op) {
79 
80  }
81  explicit DstMemOp(ManagedStackSlot *op) : op(op) {
82 
83  }
84 };
85 
86 
87 /**
88  * Simple wrapper for first operand of an
89  * x86_64 instruction.
90  */
91 struct Src1Op {
93  explicit Src1Op(MachineOperand *op) : op(op) {}
94 };
95 /**
96  * Simple wrapper for second operand of an
97  * x86_64 instruction.
98  */
99 struct Src2Op {
101  explicit Src2Op(MachineOperand *op) : op(op) {}
102 };
103 /**
104  * Simple wrapper for first operand of an
105  * x86_64 instruction which is also used for the result.
106  */
107 struct DstSrc1Op {
109  explicit DstSrc1Op(MachineOperand *op) : op(op) {}
110 };
111 
112 struct DstSrc2Op {
115  op(op) {
116  }
117 };
118 
119 /**
120  * Simple wrapper for first operand of an
121  * x86_64 instruction which is also used for the result.
122  */
123 struct DstSrcOp {
125  explicit DstSrcOp(MachineOperand *op) : op(op) {}
126 };
127 
128 /**
129  * Simple wrapper for destination of an
130  * x86_64 instruction.
131  */
132 struct DstOp {
134  explicit DstOp(MachineOperand *op) : op(op) {}
135 };
136 
138 public:
139  enum ScaleFactor {
140  Scale1 = 0,
141  Scale2 = 1,
142  Scale4 = 2,
143  Scale8 = 3
144  };
148  int32_t disp;
149  /// constructor. base and disp only
150  explicit ModRMOperand(const BaseOp& base, int32_t disp=0)
151  : scale(Scale1), index(&NoOperand), base(base.op), disp(disp) {}
152  /// constructor. Full
154  : scale(scale), index(index.op), base(base.op), disp(disp) {}
155  /// constructor. Full (with Type::TypeID for scale)
156  ModRMOperand(Type::TypeID type, const IndexOp &index, const BaseOp& base, int32_t disp=0)
157  : scale(get_scale(type)), index(index.op), base(base.op), disp(disp) {}
158 
159  /// covert type to scale
161  switch (type) {
162  case Type::ByteTypeID:
163  return Scale1;
164  case Type::ShortTypeID:
165  return Scale2;
166  case Type::IntTypeID:
167  case Type::FloatTypeID:
168  return Scale4;
169  case Type::LongTypeID:
170  case Type::DoubleTypeID:
172  return Scale8;
173  default:
174  break;
175  }
176  ABORT_MSG("type not supported", "x86_64 ModRMOperand::get_scale() type: " << type);
177  return Scale1;
178  }
179 
180  /// covert type to scale
181  static ScaleFactor get_scale(int32_t value) {
182  switch (value) {
183  case 1:
184  return Scale1;
185  case 2:
186  return Scale2;
187  case 4:
188  return Scale4;
189  case 8:
190  return Scale8;
191  default:
192  break;
193  }
194  ABORT_MSG("constant value not supported", "x86_64 ModRMOperand::get_scale() value: " << value);
195  return Scale1;
196  }
197 };
199 public:
203  int32_t disp;
204  /// constructor
206  : scale(scale), index(index), base(base), disp(disp) {}
207 };
208 
210 
211 
212 /// Simple wrapper for a ModRM destination operand
213 struct DstModRM {
215  explicit DstModRM(ModRMOperand &op) : op(op) {}
216 };
217 /// Simple wrapper for a ModRM source operand
218 struct SrcModRM {
220  explicit SrcModRM(ModRMOperand &op) : op(op) {}
221 };
222 /**
223  * @}
224  */
225 
226 /**
227  * Superclass for general purpose register instruction
228  */
230 public:
232  std::size_t num_operands) :
233  MachineInstruction(name, result, num_operands) {}
234 };
235 /**
236  * Superclass for general purpose register instruction
237  */
239 public:
240  enum OperandSize {
241  OS_8 = 1,
242  OS_16 = 2,
243  OS_32 = 4,
244  OS_64 = 8,
246  };
247  enum OperandType {
248  // Reg
253  // Memory
258  //
260  };
261  enum OpEncoding {
262  // Immediate to Register
267  // Immediate to Memory
272  // Immediate 8 to Register
276  // Register to Register
281  // Memory to Register
286  // Register to Memory
291  //
293  };
294 private:
296 public:
298  OperandSize op_size, std::size_t num_operands) :
299  X86_64Instruction(name, result, num_operands),
300  op_size(op_size) {}
301 
302  OperandSize get_op_size() const { return op_size; }
303 };
304 
306 void emit_nop(CodeFragment code, int length);
307 
308 /**
309  * Move super instruction
310  */
311 class MoveInst : public GPInstruction {
312 public:
313  MoveInst( const char* name,
314  MachineOperand *src,
315  MachineOperand *dst,
317  : GPInstruction(name, dst, op_size, 1) {
318  set_operand(0,src);
320  }
321  virtual bool is_move() const { return true; }
322 };
323 
325 
326 /**
327  * This abstract class represents a x86_64 ALU instruction.
328  *
329  *
330  */
332 private:
334 
335 #if 0
336 void emit_impl_I(CodeMemory* CM, Immediate* imm) const;
337 void emit_impl_RI(CodeMemory* CM, NativeRegister* src1,
338  Immediate* imm) const;
339 void emit_impl_MR(CodeMemory* CM, NativeRegister* src1,
340  NativeRegister* src2) const;
341 void emit_impl_RR(CodeMemory* CM, NativeRegister* src1,
342  NativeRegister* src2) const;
343 #endif
344 
345 public:
346  /**
347  * @param alu_id this parameter is used to identify the
348  * instruction. The mapping is as follows:
349  * - 0 ADD
350  * - 1 OR
351  * - 2 ADC
352  * - 3 SBB
353  * - 4 AND
354  * - 5 SUB
355  * - 6 XOR
356  * - 7 CMP
357  */
358  ALUInstruction(const char * name, const DstSrc1Op &dstsrc1,
359  const Src2Op &src2, OperandSize op_size, u1 alu_id)
360  : GPInstruction(name, dstsrc1.op, op_size, 2) , alu_id(alu_id) {
361  assert(alu_id < 8);
362  set_operand(0,dstsrc1.op);
363  set_operand(1,src2.op);
365  }
366  ALUInstruction(const char * name, const Src1Op &src1,
367  const Src2Op &src2, OperandSize op_size, u1 alu_id)
368  : GPInstruction(name, &NoOperand, op_size, 2) , alu_id(alu_id) {
369  assert(alu_id < 8);
370  set_operand(0,src1.op);
371  set_operand(1,src2.op);
373  }
374  /**
375  * This must be implemented by subclasses.
376  */
377  virtual void emit(CodeMemory* CM) const;
378 
379  virtual bool accepts_immediate(std::size_t i, Immediate *imm) const {
380  if (i != 1) return false;
381  switch (imm->get_type()) {
382  case Type::IntTypeID: return true;
383  case Type::LongTypeID: return fits_into<s4>(imm->get_Long());
384  default: break;
385  }
386  return false;
387  }
388 };
389 
390 
391 
392 
393 // ALU instructions
394 class AddInst : public ALUInstruction {
395 public:
396  AddInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
398  : ALUInstruction("X86_64AddInst", dstsrc1, src2, op_size, 0) {
399  }
400 };
401 class OrInst : public ALUInstruction {
402 public:
403  OrInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
405  : ALUInstruction("X86_64OrInst", dstsrc1, src2, op_size, 1) {
406  }
407 };
408 class AdcInst : public ALUInstruction {
409 public:
410  AdcInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
412  : ALUInstruction("X86_64AdcInst", dstsrc1, src2, op_size, 2) {
413  }
414 };
415 class SbbInst : public ALUInstruction {
416 public:
417  SbbInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
419  : ALUInstruction("X86_64SbbInst", dstsrc1, src2, op_size, 3) {
420  }
421 };
422 class AndInst : public ALUInstruction {
423 public:
424  AndInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
426  : ALUInstruction("X86_64AndInst", dstsrc1, src2, op_size, 4) {
427  }
428 };
429 class SubInst : public ALUInstruction {
430 public:
431  SubInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
433  : ALUInstruction("X86_64SubInst", dstsrc1, src2, op_size, 5) {
434  }
435 };
436 class XorInst : public ALUInstruction {
437 public:
438  XorInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
440  : ALUInstruction("X86_64XorInst", dstsrc1, src2, op_size, 6) {
441  }
442 };
443 class CmpInst : public ALUInstruction {
444 public:
445  /**
446  * TODO: return type actually is status-flags
447  */
448  CmpInst(const Src2Op &src2, const Src1Op &src1,
450  : ALUInstruction("X86_64CmpInst", src1, src2, op_size, 7) {
451  }
452 };
453 
454 
455 class PatchInst : public X86_64Instruction {
456 private:
458 public:
460  : X86_64Instruction("X86_64PatchInst", &NoOperand, 0),
461  patcher(patcher) {}
462  virtual void emit(CodeMemory* CM) const;
463  virtual void link(CodeFragment &CF) const;
464 };
465 
466 
467 class EnterInst : public X86_64Instruction {
468 private:
470 public:
472  : X86_64Instruction("X86_64EnterInst", &NoOperand, 0),
473  framesize(framesize) {}
474  virtual void emit(CodeMemory* CM) const;
475 };
476 
477 class LeaveInst : public X86_64Instruction {
478 public:
480  : X86_64Instruction("X86_64LeaveInst", &NoOperand, 0) {}
481  virtual void emit(CodeMemory* CM) const;
482 };
483 
484 class BreakInst : public X86_64Instruction {
485 public:
487  : X86_64Instruction("X86_64BreakInst", &NoOperand, 0) {}
488  virtual void emit(CodeMemory* CM) const;
489 };
490 
491 class IMulInst : public GPInstruction {
492 public:
493  IMulInst(const Src2Op &src2, const DstSrc1Op &dstsrc1,
495  : GPInstruction("X86_64IMulInst", dstsrc1.op, op_size, 2) {
496  set_operand(0,dstsrc1.op);
497  set_operand(1,src2.op);
499  }
500  virtual void emit(CodeMemory* CM) const;
501 };
502 
503 class IMulImmInst : public GPInstruction {
504 public:
505  IMulImmInst(const Src1Op &src1, const Src2Op &src2, const DstOp &dst,
507  : GPInstruction("X86_64IMulImmInst", dst.op, op_size, 3) {
508  operands[0].op = src1.op;
509  operands[1].op = src2.op;
510  operands[2].op = dst.op;
511  }
512  virtual void emit(CodeMemory* CM) const;
513 };
514 
515 class IDivInst: public GPInstruction {
516 public:
517  /**
518  * The destination operands are only used to guide
519  * the register allocator. The user must ensure that the values
520  * are moved to the desired destination registers afterwards (e.g. by inserting a move)
521  */
522  IDivInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, const DstSrc2Op &dst2, OperandSize op_size) :
523  GPInstruction("X86_64IDivInst", dstsrc1.op, op_size, 3) {
524  operands[0].op = dstsrc1.op;
525  operands[1].op = src2.op;
526  operands[2].op = dst2.op;
527 
528  }
529  virtual void emit(CodeMemory* CM) const;
530 };
531 
532 class CDQInst : public GPInstruction {
533 public:
534  CDQInst(const DstSrc1Op &src1, const DstSrc2Op &src2, OperandSize op_size) : GPInstruction("X86_64CDQInst", &NoOperand, NO_SIZE, 2) {
535  operands[0].op = src1.op;
536  operands[1].op = src2.op;
537  }
538 
539  virtual void emit(CodeMemory* CM) const;
540 };
541 
542 class RetInst : public GPInstruction {
543 public:
544  /// void return
545  RetInst() : GPInstruction("X86_64RetInst", &NoOperand, NO_SIZE, 0) {}
546  //RetInst(OperandSize op_size)
547  /**
548  * Non-void return. The source operand is only used to guide
549  * the register allocator. The user must ensure that the value
550  * really is in the correct register (e.g. by inserting a move)
551  */
553  : GPInstruction("X86_64RetInst", &NoOperand, op_size, 1) {
554  operands[0].op = src.op;
555  }
556  virtual bool is_end() const { return true; }
557  virtual void emit(CodeMemory* CM) const;
558 };
559 
560 
561 class NegInst : public GPInstruction {
562 public:
564  : GPInstruction("X86_64NegInst", dstsrc.op, op_size, 1) {
565  operands[0].op = dstsrc.op;
566  }
567  virtual void emit(CodeMemory* CM) const;
568 };
569 
570 class CallInst : public GPInstruction {
571 public:
572  CallInst(const SrcOp &src, const DstOp &dst, std::size_t argc)
573  : GPInstruction("X86_64CallInst", dst.op, OS_64, 1 + argc) {
574  operands[0].op = src.op;
575  }
576  virtual void emit(CodeMemory* CM) const;
577 };
578 
579 class MovInst : public MoveInst {
580 private:
582 public:
583  MovInst(const SrcOp &src, const DstOp &dst,
585  : MoveInst("X86_64MovInst", src.op, dst.op, op_size), forceSameRegisters(forceSameRegisters) {
586  }
587 
588  virtual bool accepts_immediate(std::size_t i, Immediate *imm) const {
589  return true;
590  }
591  virtual void emit(CodeMemory* CM) const;
592 };
593 
594 /**
595  * Load from pointer
596  *
597  * @todo merge with MovInst
598  */
599 class MovModRMInst : public GPInstruction {
600 public:
601  /// constructor. full arguments
603  : GPInstruction("X86_64MovModRMInst", dst.op, op_size, 2),
604  modrm(ModRMOperandDesc(src.op.scale,operands[Index],operands[Base],src.op.disp)),
605  enc(RM), floatingpoint(floatingpoint) {
606  operands[Base].op = src.op.base;
607  operands[Index].op = src.op.index;
608  }
610  : GPInstruction("X86_64MovModRMInst", &NoOperand, op_size, 3),
611  modrm(ModRMOperandDesc(dst.op.scale,operands[Index],operands[Base],dst.op.disp)),
612  enc(MR), floatingpoint(floatingpoint) {
613  operands[Base].op = dst.op.base;
614  operands[Index].op = dst.op.index;
615  operands[Value].op = src.op;
616  }
617  //virtual bool is_move() const { return true; }
618  virtual void emit(CodeMemory* CM) const;
619  virtual OStream& print_operands(OStream &OS) const;
620  virtual OStream& print_result(OStream &OS) const;
621 private:
622  enum OpIndex {
623  Base = 0,
624  Index = 1,
625  Value = 2
626  };
627  enum OpEnc {
628  MR,
630  };
634 };
635 
636 
637 
638 class LEAInst : public GPInstruction {
639 private:
640 public:
641  LEAInst( const DstOp &dst, OperandSize op_size, const SrcOp src )
642  : GPInstruction("X86_64LEAInst", dst.op, op_size, 1) {
643  set_operand(0,src.op);
645 
646  }
647  virtual void emit(CodeMemory* CM) const;
648 };
649 
650 /**
651  * Move with Sign-Extension
652  */
653 class MovSXInst : public MoveInst {
656 public:
657  MovSXInst(const SrcOp &src, const DstOp &dst,
659  : MoveInst("X86_64MovSXInst", src.op, dst.op, to),
660  from(from), to(to) {}
661  virtual void emit(CodeMemory* CM) const;
662 };
663 
664 /**
665  * Move data seg to register
666  */
667 class MovDSEGInst : public GPInstruction {
668 private:
669  // mutable because changed in emit (which is const)
670  DataSegment::IdxTy data_index;
671 public:
672  MovDSEGInst(const DstOp &dst, DataSegment::IdxTy &data_index)
673  : GPInstruction("X86_64MovDSEGInst", dst.op, get_operand_size_from_Type(dst.op->get_type()), 0),
674  data_index(data_index) {}
675  virtual void emit(CodeMemory* CM) const;
676  virtual void link(CodeFragment &CF) const;
677 };
678 
679 class JumpInst : public MachineJumpInst {
680 public:
682  successors.push_back(target);
683  }
684  virtual bool is_jump() const {
685  return true;
686  }
688  successors.front() = target;
689  }
690  virtual void emit(CodeMemory* CM) const;
691  virtual void link(CodeFragment &CF) const;
692 };
693 
695 private:
697  /// jump to the else target
698  /// @todo change this!
699  mutable JumpInst jump;
700 public:
702  : X86_64Instruction("X86_64CondJumpInst", &NoOperand, 0),
703  cond(cond), jump(else_target) {
704  successors.push_back(then_target);
705  successors.push_back(else_target);
706  }
707  virtual bool is_jump() const {
708  return true;
709  }
710  virtual void emit(CodeMemory* CM) const;
711  virtual void link(CodeFragment &CF) const;
712  virtual OStream& print_successor_label(OStream &OS,std::size_t index) const;
714  return successor_front();
715  }
717  return successor_back();
718  }
719 };
720 
722 private:
725 public:
727  : X86_64Instruction("X86_64CondTrapInst", &NoOperand, 1), cond(cond), trap(trap) {
728  operands[0].op = index.op;
729  }
730  virtual void emit(CodeMemory* CM) const;
731 };
732 
733 class CMovInst : public GPInstruction {
734 private:
736 public:
738  : GPInstruction("X86_64CMovInst", dstsrc1.op, op_size, 2), cond(cond) {
739  operands[0].op = dstsrc1.op;
740  operands[1].op = src2.op;
741  }
742  virtual void emit(CodeMemory* CM) const;
743 };
744 
745 
747 public:
749  : X86_64Instruction("X86_64IndirectJumpInst", &NoOperand, 1) {
750  operands[0].op = src.op;
751  }
752  virtual bool is_jump() const {
753  return true;
754  }
755  virtual void emit(CodeMemory* CM) const;
757  successors.push_back(MBB);
758  }
759 };
760 // Double & Float operations
761 /**
762  * Convert Dword Integer to Scalar Double-Precision FP Value
763  */
764 class CVTSI2SDInst : public MoveInst {
766 public:
767  CVTSI2SDInst(const SrcOp &src, const DstOp &dst,
769  : MoveInst("X86_64CVTSI2SDInst", src.op, dst.op, to),
770  from(from) {}
771  virtual void emit(CodeMemory* CM) const;
772 };
773 
774 /**
775  * Convert Dword Integer to Scalar Single-Precision FP Value
776  */
777 class CVTSI2SSInst: public MoveInst {
779 public:
780  CVTSI2SSInst(const SrcOp &src, const DstOp &dst,
782  MoveInst("X86_64CVTSI2SSInst", src.op, dst.op, to), from(from) {
783  }
784  virtual void emit(CodeMemory* CM) const;
785 };
786 
787 /**
788  * Convert with truncation Scalar Single-FP Value to DW Integer
789  */
790 class CVTTSS2SIInst: public MoveInst {
792 
793 public:
794  CVTTSS2SIInst(const SrcOp &src, const DstOp &dst,
796  MoveInst("X86_64CVTTSS2SIInst", src.op, dst.op, to), to(to) {
797  }
798  virtual void emit(CodeMemory* CM) const;
799 };
800 
801 class CVTTSD2SIInst: public MoveInst {
803 
804 public:
805  CVTTSD2SIInst(const SrcOp &src, const DstOp &dst,
807  MoveInst("X86_64CVTTSD2SIInst", src.op, dst.op, to), to(to) {
808  }
809  virtual void emit(CodeMemory* CM) const;
810 };
811 
812 
813 class CVTSS2SDInst: public MoveInst {
814 
815 public:
816  CVTSS2SDInst(const SrcOp &src, const DstOp &dst,
818  MoveInst("X86_64CVTSS2SDInst", src.op, dst.op, to){
819  }
820  virtual void emit(CodeMemory* CM) const;
821 };
822 
823 class CVTSD2SSInst: public MoveInst {
824 
825 public:
826  CVTSD2SSInst(const SrcOp &src, const DstOp &dst,
828  MoveInst("X86_64CVTSD2SSInst", src.op, dst.op, to){
829  }
830  virtual void emit(CodeMemory* CM) const;
831 };
832 
833 class FLDInst: public GPInstruction {
834 
835 public:
837  GPInstruction("X86_64FLDInst", src.op, op_size, 1) {
838  operands[0].op = src.op;
839 
840  }
841  virtual void emit(CodeMemory* CM) const;
842 };
843 
844 class FSTPInst: public GPInstruction {
845 
846 public:
848  GPInstruction("X86_64FSTPInst", dst.op, op_size, 1) {
849  operands[0].op = dst.op;
850  }
851  virtual void emit(CodeMemory* CM) const;
852 };
853 
855 private:
857 public:
859  X86_64Instruction("X86_64FFREEInst", &NoOperand, 0), fpureg(fpureg) {}
860  virtual void emit(CodeMemory* CM) const;
861 };
862 
864 public:
866  X86_64Instruction("X86_64FINCSTPInst", &NoOperand, 0) {}
867  virtual void emit(CodeMemory* CM) const;
868 };
869 
870 // compare
871 class UCOMISInst : public GPInstruction {
872 protected:
873  UCOMISInst(const char* name, const Src2Op &src2, const Src1Op &src1,
875  : GPInstruction(name, &NoOperand, op_size, 2) {
876  operands[0].op = src1.op;
877  operands[1].op = src2.op;
878  }
879 public:
880  virtual void emit(CodeMemory* CM) const;
881 };
882 
883 class UCOMISSInst : public UCOMISInst{
884 public:
885  UCOMISSInst(const Src2Op &src2, const Src1Op &src1)
886  : UCOMISInst("X86_64UCOMISSInst",src2,src1,GPInstruction::OS_32) {}
887 };
888 class UCOMISDInst : public UCOMISInst{
889 public:
890  UCOMISDInst(const Src2Op &src2, const Src1Op &src1)
891  : UCOMISInst("X86_64UCOMISDInst",src2,src1,GPInstruction::OS_64) {}
892 };
893 
894 // XORP
895 class XORPInst : public GPInstruction {
896 protected:
897  XORPInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
899  : GPInstruction(name, dstsrc1.op, op_size, 2) {
900  operands[0].op = dstsrc1.op;
901  operands[1].op = src2.op;
902  }
903 public:
904  virtual void emit(CodeMemory* CM) const;
905 };
906 
907 class XORPSInst : public XORPInst{
908 public:
909  XORPSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
910  : XORPInst("X86_64XORPSInst",src2,dstsrc1,GPInstruction::OS_32) {}
911 };
912 class XORPDInst : public XORPInst{
913 public:
914  XORPDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
915  : XORPInst("X86_64XORPDInst",src2,dstsrc1,GPInstruction::OS_64) {}
916 };
917 
918 
919 /// SSE Alu Instruction
920 class SSEAluInst : public GPInstruction {
921 private:
923 protected:
924  SSEAluInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
926  : GPInstruction(name, dstsrc1.op, op_size, 2), opcode(opcode) {
927  operands[0].op = dstsrc1.op;
928  operands[1].op = src2.op;
929  }
930 public:
931  virtual void emit(CodeMemory* CM) const;
932 };
933 /// SSE Alu Instruction (Double-Precision)
934 class SSEAluSDInst : public SSEAluInst {
935 protected:
936  SSEAluSDInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
937  u1 opcode)
938  : SSEAluInst(name, src2, dstsrc1, opcode, GPInstruction::OS_64) {}
939 };
940 /// SSE Alu Instruction (Single-Precision)
941 class SSEAluSSInst : public SSEAluInst {
942 protected:
943  SSEAluSSInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
944  u1 opcode)
945  : SSEAluInst(name, src2, dstsrc1, opcode, GPInstruction::OS_32) {}
946 };
947 
948 // Double-Precision
949 
950 /// Add Scalar Double-Precision Floating-Point Values
951 class AddSDInst : public SSEAluSDInst {
952 public:
953  AddSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
954  : SSEAluSDInst("X86_64AddSDInst", src2, dstsrc1, 0x58) {}
955 };
956 /// Multiply Scalar Double-Precision Floating-Point Values
957 class MulSDInst : public SSEAluSDInst {
958 public:
959  MulSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
960  : SSEAluSDInst("X86_64MulSDInst", src2, dstsrc1, 0x59) {}
961 };
962 /// Subtract Scalar Double-Precision Floating-Point Values
963 class SubSDInst : public SSEAluSDInst {
964 public:
965  SubSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
966  : SSEAluSDInst("X86_64SubSDInst", src2, dstsrc1, 0x5c) {}
967 };
968 /// Divide Scalar Double-Precision Floating-Point Values
969 class DivSDInst : public SSEAluSDInst {
970 public:
971  DivSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
972  : SSEAluSDInst("X86_64DivSDInst", src2, dstsrc1, 0x5e) {}
973 };
974 
975 class FPRemInst: public GPInstruction {
976 private:
977 public:
978 
980  GPInstruction("X86_64FPRemInst", &NoOperand, op_size, 0) {
981  }
982 
983  virtual void emit(CodeMemory* CM) const;
984 };
985 
986 // SQRTSD Compute Square Root of Scalar Double-Precision Floating-Point Value 0x51
987 // MINSD Return Minimum Scalar Double-Precision Floating-Point Value 0x5d
988 // MAXSD Return Maximum Scalar Double-Precision Floating-Point Value 0x5f
989 
990 
991 // Single-Precision
992 
993 /// Add Scalar Single-Precision Floating-Point Values
994 class AddSSInst : public SSEAluSSInst {
995 public:
996  AddSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
997  : SSEAluSSInst("X86_64AddSSInst", src2, dstsrc1, 0x58) {}
998 };
999 /// Multiply Scalar Single-Precision Floating-Point Values
1000 class MulSSInst : public SSEAluSSInst {
1001 public:
1002  MulSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
1003  : SSEAluSSInst("X86_64MulSSInst", src2, dstsrc1, 0x59) {}
1004 };
1005 /// Subtract Scalar Single-Precision Floating-Point Values
1006 class SubSSInst : public SSEAluSSInst {
1007 public:
1008  SubSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
1009  : SSEAluSSInst("X86_64SubSSInst", src2, dstsrc1, 0x5c) {}
1010 };
1011 /// Divide Scalar Single-Precision Floating-Point Values
1012 class DivSSInst : public SSEAluSSInst {
1013 public:
1014  DivSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
1015  : SSEAluSSInst("X86_64DivSSInst", src2, dstsrc1, 0x5e) {}
1016 };
1017 // SQRTSS Compute Square Root of Scalar Single-Precision Floating-Point Value 0x51
1018 // MINSS Return Minimum Scalar Single-Precision Floating-Point Value 0x5d
1019 // MAXSS Return Maximum Scalar Single-Precision Floating-Point Value 0x5f
1020 
1021 
1022 class MovSDInst : public MoveInst {
1023 public:
1024  MovSDInst(const SrcOp &src, const DstOp &dst)
1025  : MoveInst("X86_64MovSDInst", src.op, dst.op, OS_64) {}
1026  virtual void emit(CodeMemory* CM) const;
1027 };
1028 
1029 
1030 class MovImmSInst : public MoveInst {
1031 private:
1032  // mutable because changed in emit (which is const)
1033  mutable DataSegment::IdxTy data_index;
1034 protected:
1035  MovImmSInst(const char *name, const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize op_size)
1036  : MoveInst(name, src.op, dst.op, op_size),
1037  data_index(0) {}
1038 public:
1039  virtual void emit(CodeMemory* CM) const;
1040  virtual void link(CodeFragment &CF) const;
1041 };
1042 
1043 class MovImmSDInst : public MovImmSInst {
1044 public:
1045  MovImmSDInst(const SrcOp &src, const DstOp &dst)
1046  : MovImmSInst("X86_64MovImmSDInst", src, dst, OS_64) {}
1047 };
1048 class MovImmSSInst : public MovImmSInst {
1049 public:
1050  MovImmSSInst(const SrcOp &src, const DstOp &dst)
1051  : MovImmSInst("X86_64MovImmSSInst", src, dst, OS_32) {}
1052 };
1053 
1054 class MovSSInst : public MoveInst {
1055 public:
1056  MovSSInst(const SrcOp &src, const DstOp &dst)
1057  : MoveInst("X86_64MovSSInst", src.op, dst.op, OS_32) {}
1058  virtual void emit(CodeMemory* CM) const;
1059 };
1060 
1061 } // end namespace x86_64
1062 } // end namespace compiler2
1063 } // end namespace jit
1064 } // end namespace cacao
1065 
1066 #endif /* _JIT_COMPILER2_X86_64INSTRUCTIONS */
1067 
1068 
1069 /*
1070  * These are local overrides for various environment variables in Emacs.
1071  * Please do not remove this and leave it at the end of the file, where
1072  * Emacs will automagically detect them.
1073  * ---------------------------------------------------------------------
1074  * Local variables:
1075  * mode: c++
1076  * indent-tabs-mode: t
1077  * c-basic-offset: 4
1078  * tab-width: 4
1079  * End:
1080  * vim:noexpandtab:sw=4:ts=4:
1081  */
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
DivSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
std::size_t index
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void link(CodeFragment &CF) const
link machine code
Superclass for general purpose register instruction.
Subtract Scalar Double-Precision Floating-Point Values.
MovSDInst(const SrcOp &src, const DstOp &dst)
SubSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
virtual void emit(CodeMemory *CM) const
emit machine code
This represents a machine register usage.
void set_target(MachineBasicBlock *target)
ModRMOperand(ScaleFactor scale, const IndexOp &index, const BaseOp &base, int32_t disp=0)
constructor. Full
Simple wrapper for second operand of an x86_64 instruction.
GPInstruction::OperandSize get_OperandSize_from_Type(const Type::TypeID type)
virtual void emit(CodeMemory *CM) const
emit machine code
Simple wrapper for first operand of an x86_64 instruction.
Superclass for general purpose register instruction.
virtual void emit(CodeMemory *CM) const
emit machine code
Simple wrapper for a ModRM source operand.
argument_type from
MulSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
virtual void emit(CodeMemory *CM) const
emit machine code
UCOMISSInst(const Src2Op &src2, const Src1Op &src1)
static ScaleFactor get_scale(Type::TypeID type)
covert type to scale
MulSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
Multiply Scalar Double-Precision Floating-Point Values.
RetInst(OperandSize op_size, const SrcOp &src)
Non-void return.
u2 op
Definition: disass.cpp:129
A basic block of (scheduled) machine instructions.
LEAInst(const DstOp &dst, OperandSize op_size, const SrcOp src)
virtual void emit(CodeMemory *CM) const
emit machine code
SSEAluSDInst(const char *name, const Src2Op &src2, const DstSrc1Op &dstsrc1, u1 opcode)
This abstract class represents a x86_64 ALU instruction.
virtual void link(CodeFragment &CF) const
link machine code
AdcInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
Simple wrapper for a ModRM destination operand.
MovInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize op_size, bool forceSameRegisters=false)
virtual void emit(CodeMemory *CM) const
emit machine code
XORPDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
AddSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
UCOMISDInst(const Src2Op &src2, const Src1Op &src1)
SSEAluInst(const char *name, const Src2Op &src2, const DstSrc1Op &dstsrc1, u1 opcode, GPInstruction::OperandSize op_size)
virtual void emit(CodeMemory *CM) const
emit machine code
CVTSD2SSInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize from, GPInstruction::OperandSize to)
Convert Dword Integer to Scalar Single-Precision FP Value.
SubInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
Descriptor of a MachineOperand.
SSEAluSSInst(const char *name, const Src2Op &src2, const DstSrc1Op &dstsrc1, u1 opcode)
Add Scalar Single-Precision Floating-Point Values.
SSE Alu Instruction (Double-Precision)
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
virtual void link(CodeFragment &CF) const
link machine code
MovImmSSInst(const SrcOp &src, const DstOp &dst)
void set_operand(std::size_t i, MachineOperand *op)
JNIEnv jclass jobject const char * name
Definition: jvmti.h:312
Divide Scalar Single-Precision Floating-Point Values.
virtual void emit(CodeMemory *CM) const
emit machine code
ModRMOperandDesc(ModRMOperand::ScaleFactor scale, MachineOperandDesc &index, MachineOperandDesc &base, int32_t disp=0)
constructor
virtual void emit(CodeMemory *CM) const
emit machine code
CMovInst(Cond::COND cond, const DstSrc1Op &dstsrc1, const Src2Op &src2, GPInstruction::OperandSize op_size)
MovDSEGInst(const DstOp &dst, DataSegment::IdxTy &data_index)
virtual void emit(CodeMemory *CM) const
emit machine code
Simple wrapper for first operand of an x86_64 instruction which is also used for the result...
CVTTSS2SIInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize from, GPInstruction::OperandSize to)
CondJumpInst(Cond::COND cond, MachineBasicBlock *then_target, MachineBasicBlock *else_target)
virtual OStream & print_successor_label(OStream &OS, std::size_t index) const
print successor label
virtual void emit(CodeMemory *CM) const
emit machine code
CVTSS2SDInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize to)
MachineBasicBlock * successor_front() const
Subtract Scalar Single-Precision Floating-Point Values.
virtual void emit(CodeMemory *CM) const
emit machine code
GPInstruction::OperandSize get_operand_size_from_Type(Type::TypeID type)
MoveInst(const char *name, MachineOperand *src, MachineOperand *dst, OperandSize op_size)
virtual void emit(CodeMemory *CM) const
emit machine code
NegInst(const DstSrcOp &dstsrc, OperandSize op_size)
virtual void emit(CodeMemory *CM) const
emit machine code
CDQInst(const DstSrc1Op &src1, const DstSrc2Op &src2, OperandSize op_size)
GPInstruction(const char *name, MachineOperand *result, OperandSize op_size, std::size_t num_operands)
MovModRMInst(const SrcOp &src, GPInstruction::OperandSize op_size, const DstModRM &dst, bool floatingpoint)
virtual void emit(CodeMemory *CM) const
emit machine code
virtual bool accepts_immediate(std::size_t i, Immediate *imm) const
OStream & operator<<(OStream &OS, const ModRMOperandDesc &modrm)
virtual void emit(CodeMemory *CM) const
emit machine code
MovImmSDInst(const SrcOp &src, const DstOp &dst)
virtual void emit(CodeMemory *CM) const
emit machine code
DivSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
uint16_t u2
Definition: types.hpp:43
Simple wrapper for the operand of an single operand x86_64 instruction.
IMulInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
void emit_nop(CodeFragment code, int length)
AndInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
Multiply Scalar Single-Precision Floating-Point Values.
IDivInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, const DstSrc2Op &dst2, OperandSize op_size)
The destination operands are only used to guide the register allocator.
Convert Dword Integer to Scalar Double-Precision FP Value.
Convert with truncation Scalar Single-FP Value to DW Integer.
Simple stream class for formatted output.
Definition: OStream.hpp:141
MovImmSInst(const char *name, const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize op_size)
virtual void link(CodeFragment &CF) const
link machine code
XorInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
MIIterator i
virtual bool accepts_immediate(std::size_t i, Immediate *imm) const
int32_t s4
Definition: types.hpp:45
virtual void emit(CodeMemory *CM) const
emit machine code
ModRMOperand(Type::TypeID type, const IndexOp &index, const BaseOp &base, int32_t disp=0)
constructor. Full (with Type::TypeID for scale)
virtual void emit(CodeMemory *CM) const
emit machine code
virtual void emit(CodeMemory *CM) const
emit machine code
OStream & OS
Simple wrapper for first operand of an x86_64 instruction which is also used for the result...
XORPSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
ModRMOperand(const BaseOp &base, int32_t disp=0)
constructor. base and disp only
CVTTSD2SIInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize from, GPInstruction::OperandSize to)
Simple wrapper for destination of an x86_64 instruction.
Proxy to encode explicit and implicit successors.
AddSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
virtual void emit(CodeMemory *CM) const
emit machine code
ALUInstruction(const char *name, const Src1Op &src1, const Src2Op &src2, OperandSize op_size, u1 alu_id)
ALUInstruction(const char *name, const DstSrc1Op &dstsrc1, const Src2Op &src2, OperandSize op_size, u1 alu_id)
virtual void emit(CodeMemory *CM) const
emit machine code
CVTSI2SDInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize from, GPInstruction::OperandSize to)
virtual void emit(CodeMemory *CM) const
This must be implemented by subclasses.
CVTSI2SSInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize from, GPInstruction::OperandSize to)
MovSSInst(const SrcOp &src, const DstOp &dst)
MovModRMInst(const DstOp &dst, GPInstruction::OperandSize op_size, const SrcModRM &src, bool floatingpoint)
constructor. full arguments
virtual OStream & print_operands(OStream &OS) const
print operands
CallInst(const SrcOp &src, const DstOp &dst, std::size_t argc)
SubSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
CondTrapInst(Cond::COND cond, s4 trap, const SrcOp &index)
Operands that can be directly used by the machine (register, memory, stackslot)
void finalize_operands()
has to be called after all operands with embedded operands have been added
virtual void link(CodeFragment &CF) const
link machine code
IMulImmInst(const Src1Op &src1, const Src2Op &src2, const DstOp &dst, OperandSize op_size)
virtual OStream & print_result(OStream &OS) const
print result
Segment reference.
Definition: Segment.hpp:44
AddInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
virtual void emit(CodeMemory *CM) const
emit machine code
FLDInst(const SrcMemOp &src, GPInstruction::OperandSize op_size)
virtual void emit(CodeMemory *CM) const
emit machine code
static ScaleFactor get_scale(int32_t value)
covert type to scale
SSE Alu Instruction (Single-Precision)
BeginInst * target
virtual void emit(CodeMemory *CM) const
emit machine code
X86_64Instruction(const char *name, MachineOperand *result, std::size_t num_operands)
CmpInst(const Src2Op &src2, const Src1Op &src1, OperandSize op_size)
TODO: return type actually is status-flags.
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
UCOMISInst(const char *name, const Src2Op &src2, const Src1Op &src1, GPInstruction::OperandSize op_size)
XORPInst(const char *name, const Src2Op &src2, const DstSrc1Op &dstsrc1, GPInstruction::OperandSize op_size)
MovSXInst(const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize from, GPInstruction::OperandSize to)
const char const void jint length
Definition: jvmti.h:352
Add Scalar Double-Precision Floating-Point Values.
Patcher super class.
Definition: PatcherNew.hpp:49
OrInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
SbbInst(const Src2Op &src2, const DstSrc1Op &dstsrc1, OperandSize op_size)
Divide Scalar Double-Precision Floating-Point Values.
virtual void emit(CodeMemory *CM) const
emit machine code
FSTPInst(const DstMemOp &dst, GPInstruction::OperandSize op_size)
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