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 
721 /// A TrapInst represents a hardware trap.
722 class TrapInst : public X86_64Instruction {
723 private:
724 
725  /// A trap number as defined in x86_64/md-trap.hpp
727 
728 public:
729 
730  /// Construct a TrapInst.
731  ///
732  /// @param trap A trap number as defined in x86_64/md-trap.hpp.
733  /// @param SrcOp TODO
735  : X86_64Instruction("X86_64TrapInst", &NoOperand, 1), trap(trap) {
736  operands[0].op = index.op;
737  }
738 
739  virtual bool is_end() const { return true; }
740  virtual void emit(CodeMemory* CM) const;
741 };
742 
744 private:
747 public:
749  : X86_64Instruction("X86_64CondTrapInst", &NoOperand, 1), cond(cond), trap(trap) {
750  operands[0].op = index.op;
751  }
752  virtual void emit(CodeMemory* CM) const;
753 };
754 
755 class CMovInst : public GPInstruction {
756 private:
758 public:
760  : GPInstruction("X86_64CMovInst", dstsrc1.op, op_size, 2), cond(cond) {
761  operands[0].op = dstsrc1.op;
762  operands[1].op = src2.op;
763  }
764  virtual void emit(CodeMemory* CM) const;
765 };
766 
767 
769 public:
771  : X86_64Instruction("X86_64IndirectJumpInst", &NoOperand, 1) {
772  operands[0].op = src.op;
773  }
774  virtual bool is_jump() const {
775  return true;
776  }
777  virtual void emit(CodeMemory* CM) const;
779  successors.push_back(MBB);
780  }
781 };
782 // Double & Float operations
783 /**
784  * Convert Dword Integer to Scalar Double-Precision FP Value
785  */
786 class CVTSI2SDInst : public MoveInst {
788 public:
789  CVTSI2SDInst(const SrcOp &src, const DstOp &dst,
791  : MoveInst("X86_64CVTSI2SDInst", src.op, dst.op, to),
792  from(from) {}
793  virtual void emit(CodeMemory* CM) const;
794 };
795 
796 /**
797  * Convert Dword Integer to Scalar Single-Precision FP Value
798  */
799 class CVTSI2SSInst: public MoveInst {
801 public:
802  CVTSI2SSInst(const SrcOp &src, const DstOp &dst,
804  MoveInst("X86_64CVTSI2SSInst", src.op, dst.op, to), from(from) {
805  }
806  virtual void emit(CodeMemory* CM) const;
807 };
808 
809 /**
810  * Convert with truncation Scalar Single-FP Value to DW Integer
811  */
812 class CVTTSS2SIInst: public MoveInst {
814 
815 public:
816  CVTTSS2SIInst(const SrcOp &src, const DstOp &dst,
818  MoveInst("X86_64CVTTSS2SIInst", src.op, dst.op, to), to(to) {
819  }
820  virtual void emit(CodeMemory* CM) const;
821 };
822 
823 class CVTTSD2SIInst: public MoveInst {
825 
826 public:
827  CVTTSD2SIInst(const SrcOp &src, const DstOp &dst,
829  MoveInst("X86_64CVTTSD2SIInst", src.op, dst.op, to), to(to) {
830  }
831  virtual void emit(CodeMemory* CM) const;
832 };
833 
834 
835 class CVTSS2SDInst: public MoveInst {
836 
837 public:
838  CVTSS2SDInst(const SrcOp &src, const DstOp &dst,
840  MoveInst("X86_64CVTSS2SDInst", src.op, dst.op, to){
841  }
842  virtual void emit(CodeMemory* CM) const;
843 };
844 
845 class CVTSD2SSInst: public MoveInst {
846 
847 public:
848  CVTSD2SSInst(const SrcOp &src, const DstOp &dst,
850  MoveInst("X86_64CVTSD2SSInst", src.op, dst.op, to){
851  }
852  virtual void emit(CodeMemory* CM) const;
853 };
854 
855 class FLDInst: public GPInstruction {
856 
857 public:
859  GPInstruction("X86_64FLDInst", src.op, op_size, 1) {
860  operands[0].op = src.op;
861 
862  }
863  virtual void emit(CodeMemory* CM) const;
864 };
865 
866 class FSTPInst: public GPInstruction {
867 
868 public:
870  GPInstruction("X86_64FSTPInst", dst.op, op_size, 1) {
871  operands[0].op = dst.op;
872  }
873  virtual void emit(CodeMemory* CM) const;
874 };
875 
877 private:
879 public:
881  X86_64Instruction("X86_64FFREEInst", &NoOperand, 0), fpureg(fpureg) {}
882  virtual void emit(CodeMemory* CM) const;
883 };
884 
886 public:
888  X86_64Instruction("X86_64FINCSTPInst", &NoOperand, 0) {}
889  virtual void emit(CodeMemory* CM) const;
890 };
891 
892 // compare
893 class UCOMISInst : public GPInstruction {
894 protected:
895  UCOMISInst(const char* name, const Src2Op &src2, const Src1Op &src1,
897  : GPInstruction(name, &NoOperand, op_size, 2) {
898  operands[0].op = src1.op;
899  operands[1].op = src2.op;
900  }
901 public:
902  virtual void emit(CodeMemory* CM) const;
903 };
904 
905 class UCOMISSInst : public UCOMISInst{
906 public:
907  UCOMISSInst(const Src2Op &src2, const Src1Op &src1)
908  : UCOMISInst("X86_64UCOMISSInst",src2,src1,GPInstruction::OS_32) {}
909 };
910 class UCOMISDInst : public UCOMISInst{
911 public:
912  UCOMISDInst(const Src2Op &src2, const Src1Op &src1)
913  : UCOMISInst("X86_64UCOMISDInst",src2,src1,GPInstruction::OS_64) {}
914 };
915 
916 // XORP
917 class XORPInst : public GPInstruction {
918 protected:
919  XORPInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
921  : GPInstruction(name, dstsrc1.op, op_size, 2) {
922  operands[0].op = dstsrc1.op;
923  operands[1].op = src2.op;
924  }
925 public:
926  virtual void emit(CodeMemory* CM) const;
927 };
928 
929 class XORPSInst : public XORPInst{
930 public:
931  XORPSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
932  : XORPInst("X86_64XORPSInst",src2,dstsrc1,GPInstruction::OS_32) {}
933 };
934 class XORPDInst : public XORPInst{
935 public:
936  XORPDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
937  : XORPInst("X86_64XORPDInst",src2,dstsrc1,GPInstruction::OS_64) {}
938 };
939 
940 
941 /// SSE Alu Instruction
942 class SSEAluInst : public GPInstruction {
943 private:
945 protected:
946  SSEAluInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
948  : GPInstruction(name, dstsrc1.op, op_size, 2), opcode(opcode) {
949  operands[0].op = dstsrc1.op;
950  operands[1].op = src2.op;
951  }
952 public:
953  virtual void emit(CodeMemory* CM) const;
954 };
955 /// SSE Alu Instruction (Double-Precision)
956 class SSEAluSDInst : public SSEAluInst {
957 protected:
958  SSEAluSDInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
959  u1 opcode)
960  : SSEAluInst(name, src2, dstsrc1, opcode, GPInstruction::OS_64) {}
961 };
962 /// SSE Alu Instruction (Single-Precision)
963 class SSEAluSSInst : public SSEAluInst {
964 protected:
965  SSEAluSSInst(const char* name, const Src2Op &src2, const DstSrc1Op &dstsrc1,
966  u1 opcode)
967  : SSEAluInst(name, src2, dstsrc1, opcode, GPInstruction::OS_32) {}
968 };
969 
970 // Double-Precision
971 
972 /// Add Scalar Double-Precision Floating-Point Values
973 class AddSDInst : public SSEAluSDInst {
974 public:
975  AddSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
976  : SSEAluSDInst("X86_64AddSDInst", src2, dstsrc1, 0x58) {}
977 };
978 /// Multiply Scalar Double-Precision Floating-Point Values
979 class MulSDInst : public SSEAluSDInst {
980 public:
981  MulSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
982  : SSEAluSDInst("X86_64MulSDInst", src2, dstsrc1, 0x59) {}
983 };
984 /// Subtract Scalar Double-Precision Floating-Point Values
985 class SubSDInst : public SSEAluSDInst {
986 public:
987  SubSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
988  : SSEAluSDInst("X86_64SubSDInst", src2, dstsrc1, 0x5c) {}
989 };
990 /// Divide Scalar Double-Precision Floating-Point Values
991 class DivSDInst : public SSEAluSDInst {
992 public:
993  DivSDInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
994  : SSEAluSDInst("X86_64DivSDInst", src2, dstsrc1, 0x5e) {}
995 };
996 
997 class FPRemInst: public GPInstruction {
998 private:
999 public:
1000 
1002  GPInstruction("X86_64FPRemInst", &NoOperand, op_size, 0) {
1003  }
1004 
1005  virtual void emit(CodeMemory* CM) const;
1006 };
1007 
1008 // SQRTSD Compute Square Root of Scalar Double-Precision Floating-Point Value 0x51
1009 // MINSD Return Minimum Scalar Double-Precision Floating-Point Value 0x5d
1010 // MAXSD Return Maximum Scalar Double-Precision Floating-Point Value 0x5f
1011 
1012 
1013 // Single-Precision
1014 
1015 /// Add Scalar Single-Precision Floating-Point Values
1016 class AddSSInst : public SSEAluSSInst {
1017 public:
1018  AddSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
1019  : SSEAluSSInst("X86_64AddSSInst", src2, dstsrc1, 0x58) {}
1020 };
1021 /// Multiply Scalar Single-Precision Floating-Point Values
1022 class MulSSInst : public SSEAluSSInst {
1023 public:
1024  MulSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
1025  : SSEAluSSInst("X86_64MulSSInst", src2, dstsrc1, 0x59) {}
1026 };
1027 /// Subtract Scalar Single-Precision Floating-Point Values
1028 class SubSSInst : public SSEAluSSInst {
1029 public:
1030  SubSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
1031  : SSEAluSSInst("X86_64SubSSInst", src2, dstsrc1, 0x5c) {}
1032 };
1033 /// Divide Scalar Single-Precision Floating-Point Values
1034 class DivSSInst : public SSEAluSSInst {
1035 public:
1036  DivSSInst(const Src2Op &src2, const DstSrc1Op &dstsrc1)
1037  : SSEAluSSInst("X86_64DivSSInst", src2, dstsrc1, 0x5e) {}
1038 };
1039 // SQRTSS Compute Square Root of Scalar Single-Precision Floating-Point Value 0x51
1040 // MINSS Return Minimum Scalar Single-Precision Floating-Point Value 0x5d
1041 // MAXSS Return Maximum Scalar Single-Precision Floating-Point Value 0x5f
1042 
1043 
1044 class MovSDInst : public MoveInst {
1045 public:
1046  MovSDInst(const SrcOp &src, const DstOp &dst)
1047  : MoveInst("X86_64MovSDInst", src.op, dst.op, OS_64) {}
1048  virtual void emit(CodeMemory* CM) const;
1049 };
1050 
1051 
1052 class MovImmSInst : public MoveInst {
1053 private:
1054  // mutable because changed in emit (which is const)
1055  mutable DataSegment::IdxTy data_index;
1056 protected:
1057  MovImmSInst(const char *name, const SrcOp &src, const DstOp &dst, GPInstruction::OperandSize op_size)
1058  : MoveInst(name, src.op, dst.op, op_size),
1059  data_index(0) {}
1060 public:
1061  virtual void emit(CodeMemory* CM) const;
1062  virtual void link(CodeFragment &CF) const;
1063 };
1064 
1065 class MovImmSDInst : public MovImmSInst {
1066 public:
1067  MovImmSDInst(const SrcOp &src, const DstOp &dst)
1068  : MovImmSInst("X86_64MovImmSDInst", src, dst, OS_64) {}
1069 };
1070 class MovImmSSInst : public MovImmSInst {
1071 public:
1072  MovImmSSInst(const SrcOp &src, const DstOp &dst)
1073  : MovImmSInst("X86_64MovImmSSInst", src, dst, OS_32) {}
1074 };
1075 
1076 class MovSSInst : public MoveInst {
1077 public:
1078  MovSSInst(const SrcOp &src, const DstOp &dst)
1079  : MoveInst("X86_64MovSSInst", src.op, dst.op, OS_32) {}
1080  virtual void emit(CodeMemory* CM) const;
1081 };
1082 
1083 class TestInst : public GPInstruction {
1084 public:
1085  TestInst(const SrcOp &src1, SrcOp &src2, OperandSize op_size)
1086  : GPInstruction("X86_64TestInst", &NoOperand, op_size, 2) {
1087  operands[0].op = src1.op;
1088  operands[1].op = src2.op;
1089  }
1090  virtual void emit(CodeMemory* CM) const;
1091 };
1092 
1093 } // end namespace x86_64
1094 } // end namespace compiler2
1095 } // end namespace jit
1096 } // end namespace cacao
1097 
1098 #endif /* _JIT_COMPILER2_X86_64INSTRUCTIONS */
1099 
1100 
1101 /*
1102  * These are local overrides for various environment variables in Emacs.
1103  * Please do not remove this and leave it at the end of the file, where
1104  * Emacs will automagically detect them.
1105  * ---------------------------------------------------------------------
1106  * Local variables:
1107  * mode: c++
1108  * indent-tabs-mode: t
1109  * c-basic-offset: 4
1110  * tab-width: 4
1111  * End:
1112  * vim:noexpandtab:sw=4:ts=4:
1113  */
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
A TrapInst represents a hardware trap.
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)
virtual void emit(CodeMemory *CM) const
emit machine code
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)
TrapInst(s4 trap, const SrcOp &index)
Construct a TrapInst.
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...
TestInst(const SrcOp &src1, SrcOp &src2, OperandSize op_size)
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)
A &quot;virtual&quot; slot that will eventually be mapped to a machine-level slot.
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
s4 trap
A trap number as defined in x86_64/md-trap.hpp.
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 void emit(CodeMemory *CM) const
emit machine code
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