383 reg_class int_rdi_reg(RDI);
384
385 // Singleton class for instruction pointer
386 // reg_class ip_reg(RIP);
387
388 %}
389
390 //----------SOURCE BLOCK-------------------------------------------------------
391 // This is a block of C++ code which provides values, functions, and
392 // definitions necessary in the rest of the architecture description
393 source %{
394 #define RELOC_IMM64 Assembler::imm_operand
395 #define RELOC_DISP32 Assembler::disp32_operand
396
397 #define __ _masm.
398
399 static int preserve_SP_size() {
400 return 3; // rex.w, op, rm(reg/reg)
401 }
402 static int clear_avx_size() {
403 return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper
404 }
405
406 // !!!!! Special hack to get all types of calls to specify the byte offset
407 // from the start of the call to the point where the return address
408 // will point.
409 int MachCallStaticJavaNode::ret_addr_offset()
410 {
411 int offset = 5; // 5 bytes from start of call to where return address points
412 offset += clear_avx_size();
413 if (_method_handle_invoke)
414 offset += preserve_SP_size();
415 return offset;
416 }
417
418 int MachCallDynamicJavaNode::ret_addr_offset()
419 {
420 int offset = 15; // 15 bytes from start of call to where return address points
421 offset += clear_avx_size();
422 return offset;
423 }
921 __ movq(Address(rsp, -8), rax);
922 __ movl(rax, Address(rsp, src_offset));
923 __ movl(Address(rsp, dst_offset), rax);
924 __ movq(rax, Address(rsp, -8));
925 break;
926 case Op_VecD:
927 __ pushq(Address(rsp, src_offset));
928 __ popq (Address(rsp, dst_offset));
929 break;
930 case Op_VecX:
931 __ pushq(Address(rsp, src_offset));
932 __ popq (Address(rsp, dst_offset));
933 __ pushq(Address(rsp, src_offset+8));
934 __ popq (Address(rsp, dst_offset+8));
935 break;
936 case Op_VecY:
937 __ vmovdqu(Address(rsp, -32), xmm0);
938 __ vmovdqu(xmm0, Address(rsp, src_offset));
939 __ vmovdqu(Address(rsp, dst_offset), xmm0);
940 __ vmovdqu(xmm0, Address(rsp, -32));
941 break;
942 default:
943 ShouldNotReachHere();
944 }
945 #ifndef PRODUCT
946 } else {
947 switch (ireg) {
948 case Op_VecS:
949 st->print("movq [rsp - #8], rax\t# 32-bit mem-mem spill\n\t"
950 "movl rax, [rsp + #%d]\n\t"
951 "movl [rsp + #%d], rax\n\t"
952 "movq rax, [rsp - #8]",
953 src_offset, dst_offset);
954 break;
955 case Op_VecD:
956 st->print("pushq [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
957 "popq [rsp + #%d]",
958 src_offset, dst_offset);
959 break;
960 case Op_VecX:
961 st->print("pushq [rsp + #%d]\t# 128-bit mem-mem spill\n\t"
962 "popq [rsp + #%d]\n\t"
963 "pushq [rsp + #%d]\n\t"
964 "popq [rsp + #%d]",
965 src_offset, dst_offset, src_offset+8, dst_offset+8);
966 break;
967 case Op_VecY:
968 st->print("vmovdqu [rsp - #32], xmm0\t# 256-bit mem-mem spill\n\t"
969 "vmovdqu xmm0, [rsp + #%d]\n\t"
970 "vmovdqu [rsp + #%d], xmm0\n\t"
971 "vmovdqu xmm0, [rsp - #32]",
972 src_offset, dst_offset);
973 break;
974 default:
975 ShouldNotReachHere();
976 }
977 #endif
978 }
979 }
980
981 uint MachSpillCopyNode::implementation(CodeBuffer* cbuf,
982 PhaseRegAlloc* ra_,
983 bool do_size,
984 outputStream* st) const {
985 assert(cbuf != NULL || st != NULL, "sanity");
986 // Get registers to move
987 OptoReg::Name src_second = ra_->get_reg_second(in(1));
988 OptoReg::Name src_first = ra_->get_reg_first(in(1));
989 OptoReg::Name dst_second = ra_->get_reg_second(this);
990 OptoReg::Name dst_first = ra_->get_reg_first(this);
991
992 enum RC src_second_rc = rc_class(src_second);
993 enum RC src_first_rc = rc_class(src_first);
994 enum RC dst_second_rc = rc_class(dst_second);
995 enum RC dst_first_rc = rc_class(dst_first);
996
997 assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first),
998 "must move at least 1 register" );
999
1000 if (src_first == dst_first && src_second == dst_second) {
1001 // Self copy, no move
1002 return 0;
1003 }
1004 if (bottom_type()->isa_vect() != NULL) {
1005 uint ireg = ideal_reg();
1006 assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
1007 assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY), "sanity");
1008 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
1009 // mem -> mem
1010 int src_offset = ra_->reg2offset(src_first);
1011 int dst_offset = ra_->reg2offset(dst_first);
1012 vec_stack_to_stack_helper(cbuf, src_offset, dst_offset, ireg, st);
1013 } else if (src_first_rc == rc_float && dst_first_rc == rc_float ) {
1014 vec_mov_helper(cbuf, false, src_first, dst_first, src_second, dst_second, ireg, st);
1015 } else if (src_first_rc == rc_float && dst_first_rc == rc_stack ) {
1016 int stack_offset = ra_->reg2offset(dst_first);
1017 vec_spill_helper(cbuf, false, false, stack_offset, src_first, ireg, st);
1018 } else if (src_first_rc == rc_stack && dst_first_rc == rc_float ) {
1019 int stack_offset = ra_->reg2offset(src_first);
1020 vec_spill_helper(cbuf, false, true, stack_offset, dst_first, ireg, st);
1021 } else {
1022 ShouldNotReachHere();
1023 }
1024 return 0;
1025 }
1026 if (src_first_rc == rc_stack) {
1027 // mem ->
2682 0,
2683 0,
2684 RAX_num, // Op_RegN
2685 RAX_num, // Op_RegI
2686 RAX_num, // Op_RegP
2687 XMM0_num, // Op_RegF
2688 XMM0_num, // Op_RegD
2689 RAX_num // Op_RegL
2690 };
2691 static const int hi[Op_RegL + 1] = {
2692 0,
2693 0,
2694 OptoReg::Bad, // Op_RegN
2695 OptoReg::Bad, // Op_RegI
2696 RAX_H_num, // Op_RegP
2697 OptoReg::Bad, // Op_RegF
2698 XMM0b_num, // Op_RegD
2699 RAX_H_num // Op_RegL
2700 };
2701 // Excluded flags and vector registers.
2702 assert(ARRAY_SIZE(hi) == _last_machine_leaf - 5, "missing type");
2703 return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
2704 %}
2705 %}
2706
2707 //----------ATTRIBUTES---------------------------------------------------------
2708 //----------Operand Attributes-------------------------------------------------
2709 op_attrib op_cost(0); // Required cost attribute
2710
2711 //----------Instruction Attributes---------------------------------------------
2712 ins_attrib ins_cost(100); // Required cost attribute
2713 ins_attrib ins_size(8); // Required size attribute (in bits)
2714 ins_attrib ins_short_branch(0); // Required flag: is this instruction
2715 // a non-matching short branch variant
2716 // of some long branch?
2717 ins_attrib ins_alignment(1); // Required alignment attribute (must
2718 // be a power of 2) specifies the
2719 // alignment that some part of the
2720 // instruction (not necessarily the
2721 // start) requires. If > 1, a
2722 // compute_padding() function must be
3443
3444 // Flags register, used as output of FLOATING POINT compare instructions
3445 operand rFlagsRegU()
3446 %{
3447 constraint(ALLOC_IN_RC(int_flags));
3448 match(RegFlags);
3449
3450 format %{ "RFLAGS_U" %}
3451 interface(REG_INTER);
3452 %}
3453
3454 operand rFlagsRegUCF() %{
3455 constraint(ALLOC_IN_RC(int_flags));
3456 match(RegFlags);
3457 predicate(false);
3458
3459 format %{ "RFLAGS_U_CF" %}
3460 interface(REG_INTER);
3461 %}
3462
3463 // Float register operands
3464 operand regF()
3465 %{
3466 constraint(ALLOC_IN_RC(float_reg));
3467 match(RegF);
3468
3469 format %{ %}
3470 interface(REG_INTER);
3471 %}
3472
3473 // Double register operands
3474 operand regD()
3475 %{
3476 constraint(ALLOC_IN_RC(double_reg));
3477 match(RegD);
3478
3479 format %{ %}
3480 interface(REG_INTER);
3481 %}
3482
3483 //----------Memory Operands----------------------------------------------------
3484 // Direct Memory Operand
3485 // operand direct(immP addr)
3486 // %{
3487 // match(addr);
3488
3489 // format %{ "[$addr]" %}
3490 // interface(MEMORY_INTER) %{
3491 // base(0xFFFFFFFF);
3492 // index(0x4);
3493 // scale(0x0);
3494 // disp($addr);
3495 // %}
3496 // %}
3497
3498 // Indirect Memory Operand
3499 operand indirect(any_RegP reg)
3500 %{
3501 constraint(ALLOC_IN_RC(ptr_reg));
3502 match(reg);
|
383 reg_class int_rdi_reg(RDI);
384
385 // Singleton class for instruction pointer
386 // reg_class ip_reg(RIP);
387
388 %}
389
390 //----------SOURCE BLOCK-------------------------------------------------------
391 // This is a block of C++ code which provides values, functions, and
392 // definitions necessary in the rest of the architecture description
393 source %{
394 #define RELOC_IMM64 Assembler::imm_operand
395 #define RELOC_DISP32 Assembler::disp32_operand
396
397 #define __ _masm.
398
399 static int preserve_SP_size() {
400 return 3; // rex.w, op, rm(reg/reg)
401 }
402 static int clear_avx_size() {
403 if(UseAVX > 2) {
404 return 0; // vzeroupper is ignored
405 } else {
406 return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper
407 }
408 }
409
410 // !!!!! Special hack to get all types of calls to specify the byte offset
411 // from the start of the call to the point where the return address
412 // will point.
413 int MachCallStaticJavaNode::ret_addr_offset()
414 {
415 int offset = 5; // 5 bytes from start of call to where return address points
416 offset += clear_avx_size();
417 if (_method_handle_invoke)
418 offset += preserve_SP_size();
419 return offset;
420 }
421
422 int MachCallDynamicJavaNode::ret_addr_offset()
423 {
424 int offset = 15; // 15 bytes from start of call to where return address points
425 offset += clear_avx_size();
426 return offset;
427 }
925 __ movq(Address(rsp, -8), rax);
926 __ movl(rax, Address(rsp, src_offset));
927 __ movl(Address(rsp, dst_offset), rax);
928 __ movq(rax, Address(rsp, -8));
929 break;
930 case Op_VecD:
931 __ pushq(Address(rsp, src_offset));
932 __ popq (Address(rsp, dst_offset));
933 break;
934 case Op_VecX:
935 __ pushq(Address(rsp, src_offset));
936 __ popq (Address(rsp, dst_offset));
937 __ pushq(Address(rsp, src_offset+8));
938 __ popq (Address(rsp, dst_offset+8));
939 break;
940 case Op_VecY:
941 __ vmovdqu(Address(rsp, -32), xmm0);
942 __ vmovdqu(xmm0, Address(rsp, src_offset));
943 __ vmovdqu(Address(rsp, dst_offset), xmm0);
944 __ vmovdqu(xmm0, Address(rsp, -32));
945 case Op_VecZ:
946 __ evmovdqu(Address(rsp, -64), xmm0, 2);
947 __ evmovdqu(xmm0, Address(rsp, src_offset), 2);
948 __ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
949 __ evmovdqu(xmm0, Address(rsp, -64), 2);
950 break;
951 default:
952 ShouldNotReachHere();
953 }
954 #ifndef PRODUCT
955 } else {
956 switch (ireg) {
957 case Op_VecS:
958 st->print("movq [rsp - #8], rax\t# 32-bit mem-mem spill\n\t"
959 "movl rax, [rsp + #%d]\n\t"
960 "movl [rsp + #%d], rax\n\t"
961 "movq rax, [rsp - #8]",
962 src_offset, dst_offset);
963 break;
964 case Op_VecD:
965 st->print("pushq [rsp + #%d]\t# 64-bit mem-mem spill\n\t"
966 "popq [rsp + #%d]",
967 src_offset, dst_offset);
968 break;
969 case Op_VecX:
970 st->print("pushq [rsp + #%d]\t# 128-bit mem-mem spill\n\t"
971 "popq [rsp + #%d]\n\t"
972 "pushq [rsp + #%d]\n\t"
973 "popq [rsp + #%d]",
974 src_offset, dst_offset, src_offset+8, dst_offset+8);
975 break;
976 case Op_VecY:
977 st->print("vmovdqu [rsp - #32], xmm0\t# 256-bit mem-mem spill\n\t"
978 "vmovdqu xmm0, [rsp + #%d]\n\t"
979 "vmovdqu [rsp + #%d], xmm0\n\t"
980 "vmovdqu xmm0, [rsp - #32]",
981 src_offset, dst_offset);
982 break;
983 case Op_VecZ:
984 st->print("vmovdqu [rsp - #64], xmm0\t# 512-bit mem-mem spill\n\t"
985 "vmovdqu xmm0, [rsp + #%d]\n\t"
986 "vmovdqu [rsp + #%d], xmm0\n\t"
987 "vmovdqu xmm0, [rsp - #64]",
988 src_offset, dst_offset);
989 break;
990 default:
991 ShouldNotReachHere();
992 }
993 #endif
994 }
995 }
996
997 uint MachSpillCopyNode::implementation(CodeBuffer* cbuf,
998 PhaseRegAlloc* ra_,
999 bool do_size,
1000 outputStream* st) const {
1001 assert(cbuf != NULL || st != NULL, "sanity");
1002 // Get registers to move
1003 OptoReg::Name src_second = ra_->get_reg_second(in(1));
1004 OptoReg::Name src_first = ra_->get_reg_first(in(1));
1005 OptoReg::Name dst_second = ra_->get_reg_second(this);
1006 OptoReg::Name dst_first = ra_->get_reg_first(this);
1007
1008 enum RC src_second_rc = rc_class(src_second);
1009 enum RC src_first_rc = rc_class(src_first);
1010 enum RC dst_second_rc = rc_class(dst_second);
1011 enum RC dst_first_rc = rc_class(dst_first);
1012
1013 assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first),
1014 "must move at least 1 register" );
1015
1016 if (src_first == dst_first && src_second == dst_second) {
1017 // Self copy, no move
1018 return 0;
1019 }
1020 if (bottom_type()->isa_vect() != NULL) {
1021 uint ireg = ideal_reg();
1022 assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
1023 assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ), "sanity");
1024 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
1025 // mem -> mem
1026 int src_offset = ra_->reg2offset(src_first);
1027 int dst_offset = ra_->reg2offset(dst_first);
1028 vec_stack_to_stack_helper(cbuf, src_offset, dst_offset, ireg, st);
1029 } else if (src_first_rc == rc_float && dst_first_rc == rc_float ) {
1030 vec_mov_helper(cbuf, false, src_first, dst_first, src_second, dst_second, ireg, st);
1031 } else if (src_first_rc == rc_float && dst_first_rc == rc_stack ) {
1032 int stack_offset = ra_->reg2offset(dst_first);
1033 vec_spill_helper(cbuf, false, false, stack_offset, src_first, ireg, st);
1034 } else if (src_first_rc == rc_stack && dst_first_rc == rc_float ) {
1035 int stack_offset = ra_->reg2offset(src_first);
1036 vec_spill_helper(cbuf, false, true, stack_offset, dst_first, ireg, st);
1037 } else {
1038 ShouldNotReachHere();
1039 }
1040 return 0;
1041 }
1042 if (src_first_rc == rc_stack) {
1043 // mem ->
2698 0,
2699 0,
2700 RAX_num, // Op_RegN
2701 RAX_num, // Op_RegI
2702 RAX_num, // Op_RegP
2703 XMM0_num, // Op_RegF
2704 XMM0_num, // Op_RegD
2705 RAX_num // Op_RegL
2706 };
2707 static const int hi[Op_RegL + 1] = {
2708 0,
2709 0,
2710 OptoReg::Bad, // Op_RegN
2711 OptoReg::Bad, // Op_RegI
2712 RAX_H_num, // Op_RegP
2713 OptoReg::Bad, // Op_RegF
2714 XMM0b_num, // Op_RegD
2715 RAX_H_num // Op_RegL
2716 };
2717 // Excluded flags and vector registers.
2718 assert(ARRAY_SIZE(hi) == _last_machine_leaf - 6, "missing type");
2719 return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
2720 %}
2721 %}
2722
2723 //----------ATTRIBUTES---------------------------------------------------------
2724 //----------Operand Attributes-------------------------------------------------
2725 op_attrib op_cost(0); // Required cost attribute
2726
2727 //----------Instruction Attributes---------------------------------------------
2728 ins_attrib ins_cost(100); // Required cost attribute
2729 ins_attrib ins_size(8); // Required size attribute (in bits)
2730 ins_attrib ins_short_branch(0); // Required flag: is this instruction
2731 // a non-matching short branch variant
2732 // of some long branch?
2733 ins_attrib ins_alignment(1); // Required alignment attribute (must
2734 // be a power of 2) specifies the
2735 // alignment that some part of the
2736 // instruction (not necessarily the
2737 // start) requires. If > 1, a
2738 // compute_padding() function must be
3459
3460 // Flags register, used as output of FLOATING POINT compare instructions
3461 operand rFlagsRegU()
3462 %{
3463 constraint(ALLOC_IN_RC(int_flags));
3464 match(RegFlags);
3465
3466 format %{ "RFLAGS_U" %}
3467 interface(REG_INTER);
3468 %}
3469
3470 operand rFlagsRegUCF() %{
3471 constraint(ALLOC_IN_RC(int_flags));
3472 match(RegFlags);
3473 predicate(false);
3474
3475 format %{ "RFLAGS_U_CF" %}
3476 interface(REG_INTER);
3477 %}
3478
3479 operand regF() %{
3480 constraint(ALLOC_IN_RC(float_reg));
3481 match(RegF);
3482
3483 format %{ %}
3484 interface(REG_INTER);
3485 %}
3486
3487 operand regD() %{
3488 constraint(ALLOC_IN_RC(double_reg));
3489 match(RegD);
3490
3491 format %{ %}
3492 interface(REG_INTER);
3493 %}
3494
3495 // Vectors
3496 operand vecS() %{
3497 constraint(ALLOC_IN_RC(vectors_reg));
3498 match(VecS);
3499
3500 format %{ %}
3501 interface(REG_INTER);
3502 %}
3503
3504 operand vecD() %{
3505 constraint(ALLOC_IN_RC(vectord_reg));
3506 match(VecD);
3507
3508 format %{ %}
3509 interface(REG_INTER);
3510 %}
3511
3512 operand vecX() %{
3513 constraint(ALLOC_IN_RC(vectorx_reg));
3514 match(VecX);
3515
3516 format %{ %}
3517 interface(REG_INTER);
3518 %}
3519
3520 operand vecY() %{
3521 constraint(ALLOC_IN_RC(vectory_reg));
3522 match(VecY);
3523
3524 format %{ %}
3525 interface(REG_INTER);
3526 %}
3527
3528 //----------Memory Operands----------------------------------------------------
3529 // Direct Memory Operand
3530 // operand direct(immP addr)
3531 // %{
3532 // match(addr);
3533
3534 // format %{ "[$addr]" %}
3535 // interface(MEMORY_INTER) %{
3536 // base(0xFFFFFFFF);
3537 // index(0x4);
3538 // scale(0x0);
3539 // disp($addr);
3540 // %}
3541 // %}
3542
3543 // Indirect Memory Operand
3544 operand indirect(any_RegP reg)
3545 %{
3546 constraint(ALLOC_IN_RC(ptr_reg));
3547 match(reg);
|