1496 address base = 1497 __ start_a_stub(size_deopt_handler()); 1498 if (base == NULL) return 0; // CodeBuffer::expand failed 1499 int offset = __ offset(); 1500 address the_pc = (address) __ pc(); 1501 Label next; 1502 // push a "the_pc" on the stack without destroying any registers 1503 // as they all may be live. 1504 1505 // push address of "next" 1506 __ call(next, relocInfo::none); // reloc none is fine since it is a disp32 1507 __ bind(next); 1508 // adjust it so it matches "the_pc" 1509 __ subptr(Address(rsp, 0), __ offset() - offset); 1510 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); 1511 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); 1512 __ end_a_stub(); 1513 return offset; 1514 } 1515 1516 1517 const bool Matcher::match_rule_supported(int opcode) { 1518 if (!has_match_rule(opcode)) 1519 return false; 1520 1521 switch (opcode) { 1522 case Op_PopCountI: 1523 case Op_PopCountL: 1524 if (!UsePopCountInstruction) 1525 return false; 1526 break; 1527 } 1528 1529 return true; // Per default match rules are supported. 1530 } 1531 1532 int Matcher::regnum_to_fpu_offset(int regnum) 1533 { 1534 return regnum - 32; // The FP registers are in the second chunk 1535 } 1536 1537 // This is UltraSparc specific, true just means we have fast l2f conversion 1538 const bool Matcher::convL2FSupported(void) { 1539 return true; 1540 } 1541 1542 // Is this branch offset short enough that a short branch can be used? 1543 // 1544 // NOTE: If the platform does not provide any short branch variants, then 1545 // this method should return false for offset 0. 1546 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { 1547 // The passed offset is relative to address of the branch. 1548 // On 86 a branch displacement is calculated relative to address 1549 // of a next instruction. 1550 offset -= br_size; 1551 10032 effect(DEF dst, USE src); 10033 ins_cost(85); 10034 format %{ "movd $dst,$src\t# MoveF2I" %} 10035 ins_encode %{ 10036 __ movdl($dst$$Register, $src$$XMMRegister); 10037 %} 10038 ins_pipe( pipe_slow ); 10039 %} 10040 10041 instruct MoveD2L_reg_reg(rRegL dst, regD src) %{ 10042 match(Set dst (MoveD2L src)); 10043 effect(DEF dst, USE src); 10044 ins_cost(85); 10045 format %{ "movd $dst,$src\t# MoveD2L" %} 10046 ins_encode %{ 10047 __ movdq($dst$$Register, $src$$XMMRegister); 10048 %} 10049 ins_pipe( pipe_slow ); 10050 %} 10051 10052 // The next instructions have long latency and use Int unit. Set high cost. 10053 instruct MoveI2F_reg_reg(regF dst, rRegI src) %{ 10054 match(Set dst (MoveI2F src)); 10055 effect(DEF dst, USE src); 10056 ins_cost(300); 10057 format %{ "movd $dst,$src\t# MoveI2F" %} 10058 ins_encode %{ 10059 __ movdl($dst$$XMMRegister, $src$$Register); 10060 %} 10061 ins_pipe( pipe_slow ); 10062 %} 10063 10064 instruct MoveL2D_reg_reg(regD dst, rRegL src) %{ 10065 match(Set dst (MoveL2D src)); 10066 effect(DEF dst, USE src); 10067 ins_cost(300); 10068 format %{ "movd $dst,$src\t# MoveL2D" %} 10069 ins_encode %{ 10070 __ movdq($dst$$XMMRegister, $src$$Register); 10071 %} 10072 ins_pipe( pipe_slow ); 10073 %} 10074 10075 10076 // ======================================================================= 10077 // fast clearing of an array 10078 instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, 10079 rFlagsReg cr) 10080 %{ 10081 match(Set dummy (ClearArray cnt base)); 10082 effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); 10083 10084 format %{ "xorl rax, rax\t# ClearArray:\n\t" 10085 "rep stosq\t# Store rax to *rdi++ while rcx--" %} 10086 ins_encode(opc_reg_reg(0x33, RAX, RAX), // xorl %eax, %eax 10087 Opcode(0xF3), Opcode(0x48), Opcode(0xAB)); // rep REX_W stos | 1496 address base = 1497 __ start_a_stub(size_deopt_handler()); 1498 if (base == NULL) return 0; // CodeBuffer::expand failed 1499 int offset = __ offset(); 1500 address the_pc = (address) __ pc(); 1501 Label next; 1502 // push a "the_pc" on the stack without destroying any registers 1503 // as they all may be live. 1504 1505 // push address of "next" 1506 __ call(next, relocInfo::none); // reloc none is fine since it is a disp32 1507 __ bind(next); 1508 // adjust it so it matches "the_pc" 1509 __ subptr(Address(rsp, 0), __ offset() - offset); 1510 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); 1511 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); 1512 __ end_a_stub(); 1513 return offset; 1514 } 1515 1516 int Matcher::regnum_to_fpu_offset(int regnum) 1517 { 1518 return regnum - 32; // The FP registers are in the second chunk 1519 } 1520 1521 // This is UltraSparc specific, true just means we have fast l2f conversion 1522 const bool Matcher::convL2FSupported(void) { 1523 return true; 1524 } 1525 1526 // Is this branch offset short enough that a short branch can be used? 1527 // 1528 // NOTE: If the platform does not provide any short branch variants, then 1529 // this method should return false for offset 0. 1530 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { 1531 // The passed offset is relative to address of the branch. 1532 // On 86 a branch displacement is calculated relative to address 1533 // of a next instruction. 1534 offset -= br_size; 1535 10016 effect(DEF dst, USE src); 10017 ins_cost(85); 10018 format %{ "movd $dst,$src\t# MoveF2I" %} 10019 ins_encode %{ 10020 __ movdl($dst$$Register, $src$$XMMRegister); 10021 %} 10022 ins_pipe( pipe_slow ); 10023 %} 10024 10025 instruct MoveD2L_reg_reg(rRegL dst, regD src) %{ 10026 match(Set dst (MoveD2L src)); 10027 effect(DEF dst, USE src); 10028 ins_cost(85); 10029 format %{ "movd $dst,$src\t# MoveD2L" %} 10030 ins_encode %{ 10031 __ movdq($dst$$Register, $src$$XMMRegister); 10032 %} 10033 ins_pipe( pipe_slow ); 10034 %} 10035 10036 instruct MoveI2F_reg_reg(regF dst, rRegI src) %{ 10037 match(Set dst (MoveI2F src)); 10038 effect(DEF dst, USE src); 10039 ins_cost(100); 10040 format %{ "movd $dst,$src\t# MoveI2F" %} 10041 ins_encode %{ 10042 __ movdl($dst$$XMMRegister, $src$$Register); 10043 %} 10044 ins_pipe( pipe_slow ); 10045 %} 10046 10047 instruct MoveL2D_reg_reg(regD dst, rRegL src) %{ 10048 match(Set dst (MoveL2D src)); 10049 effect(DEF dst, USE src); 10050 ins_cost(100); 10051 format %{ "movd $dst,$src\t# MoveL2D" %} 10052 ins_encode %{ 10053 __ movdq($dst$$XMMRegister, $src$$Register); 10054 %} 10055 ins_pipe( pipe_slow ); 10056 %} 10057 10058 10059 // ======================================================================= 10060 // fast clearing of an array 10061 instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, 10062 rFlagsReg cr) 10063 %{ 10064 match(Set dummy (ClearArray cnt base)); 10065 effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); 10066 10067 format %{ "xorl rax, rax\t# ClearArray:\n\t" 10068 "rep stosq\t# Store rax to *rdi++ while rcx--" %} 10069 ins_encode(opc_reg_reg(0x33, RAX, RAX), // xorl %eax, %eax 10070 Opcode(0xF3), Opcode(0x48), Opcode(0xAB)); // rep REX_W stos |