1.1 --- a/src/cpu/x86/vm/x86_32.ad Tue Oct 21 11:23:52 2008 -0700 1.2 +++ b/src/cpu/x86/vm/x86_32.ad Tue Oct 28 09:31:30 2008 -0700 1.3 @@ -495,8 +495,8 @@ 1.4 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { 1.5 Compile* C = ra_->C; 1.6 if( C->in_24_bit_fp_mode() ) { 1.7 - tty->print("FLDCW 24 bit fpu control word"); 1.8 - tty->print_cr(""); tty->print("\t"); 1.9 + st->print("FLDCW 24 bit fpu control word"); 1.10 + st->print_cr(""); st->print("\t"); 1.11 } 1.12 1.13 int framesize = C->frame_slots() << LogBytesPerInt; 1.14 @@ -510,22 +510,22 @@ 1.15 // stack. But the stack safety zone should account for that. 1.16 // See bugs 4446381, 4468289, 4497237. 1.17 if (C->need_stack_bang(framesize)) { 1.18 - tty->print_cr("# stack bang"); tty->print("\t"); 1.19 + st->print_cr("# stack bang"); st->print("\t"); 1.20 } 1.21 - tty->print_cr("PUSHL EBP"); tty->print("\t"); 1.22 + st->print_cr("PUSHL EBP"); st->print("\t"); 1.23 1.24 if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth 1.25 - tty->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); 1.26 - tty->print_cr(""); tty->print("\t"); 1.27 + st->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); 1.28 + st->print_cr(""); st->print("\t"); 1.29 framesize -= wordSize; 1.30 } 1.31 1.32 if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { 1.33 if (framesize) { 1.34 - tty->print("SUB ESP,%d\t# Create frame",framesize); 1.35 + st->print("SUB ESP,%d\t# Create frame",framesize); 1.36 } 1.37 } else { 1.38 - tty->print("SUB ESP,%d\t# Create frame",framesize); 1.39 + st->print("SUB ESP,%d\t# Create frame",framesize); 1.40 } 1.41 } 1.42 #endif 1.43 @@ -725,18 +725,19 @@ 1.44 return rc_xmm; 1.45 } 1.46 1.47 -static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size ) { 1.48 +static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset, int reg, 1.49 + int opcode, const char *op_str, int size, outputStream* st ) { 1.50 if( cbuf ) { 1.51 emit_opcode (*cbuf, opcode ); 1.52 encode_RegMem(*cbuf, Matcher::_regEncode[reg], ESP_enc, 0x4, 0, offset, false); 1.53 #ifndef PRODUCT 1.54 } else if( !do_size ) { 1.55 - if( size != 0 ) tty->print("\n\t"); 1.56 + if( size != 0 ) st->print("\n\t"); 1.57 if( opcode == 0x8B || opcode == 0x89 ) { // MOV 1.58 - if( is_load ) tty->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); 1.59 - else tty->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); 1.60 + if( is_load ) st->print("%s %s,[ESP + #%d]",op_str,Matcher::regName[reg],offset); 1.61 + else st->print("%s [ESP + #%d],%s",op_str,offset,Matcher::regName[reg]); 1.62 } else { // FLD, FST, PUSH, POP 1.63 - tty->print("%s [ESP + #%d]",op_str,offset); 1.64 + st->print("%s [ESP + #%d]",op_str,offset); 1.65 } 1.66 #endif 1.67 } 1.68 @@ -746,7 +747,7 @@ 1.69 1.70 // Helper for XMM registers. Extra opcode bits, limited syntax. 1.71 static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load, 1.72 - int offset, int reg_lo, int reg_hi, int size ) { 1.73 + int offset, int reg_lo, int reg_hi, int size, outputStream* st ) { 1.74 if( cbuf ) { 1.75 if( reg_lo+1 == reg_hi ) { // double move? 1.76 if( is_load && !UseXmmLoadAndClearUpper ) 1.77 @@ -764,17 +765,17 @@ 1.78 encode_RegMem(*cbuf, Matcher::_regEncode[reg_lo], ESP_enc, 0x4, 0, offset, false); 1.79 #ifndef PRODUCT 1.80 } else if( !do_size ) { 1.81 - if( size != 0 ) tty->print("\n\t"); 1.82 + if( size != 0 ) st->print("\n\t"); 1.83 if( reg_lo+1 == reg_hi ) { // double move? 1.84 - if( is_load ) tty->print("%s %s,[ESP + #%d]", 1.85 + if( is_load ) st->print("%s %s,[ESP + #%d]", 1.86 UseXmmLoadAndClearUpper ? "MOVSD " : "MOVLPD", 1.87 Matcher::regName[reg_lo], offset); 1.88 - else tty->print("MOVSD [ESP + #%d],%s", 1.89 + else st->print("MOVSD [ESP + #%d],%s", 1.90 offset, Matcher::regName[reg_lo]); 1.91 } else { 1.92 - if( is_load ) tty->print("MOVSS %s,[ESP + #%d]", 1.93 + if( is_load ) st->print("MOVSS %s,[ESP + #%d]", 1.94 Matcher::regName[reg_lo], offset); 1.95 - else tty->print("MOVSS [ESP + #%d],%s", 1.96 + else st->print("MOVSS [ESP + #%d],%s", 1.97 offset, Matcher::regName[reg_lo]); 1.98 } 1.99 #endif 1.100 @@ -785,7 +786,7 @@ 1.101 1.102 1.103 static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, 1.104 - int src_hi, int dst_hi, int size ) { 1.105 + int src_hi, int dst_hi, int size, outputStream* st ) { 1.106 if( UseXmmRegToRegMoveAll ) {//Use movaps,movapd to move between xmm registers 1.107 if( cbuf ) { 1.108 if( (src_lo+1 == src_hi && dst_lo+1 == dst_hi) ) { 1.109 @@ -796,11 +797,11 @@ 1.110 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); 1.111 #ifndef PRODUCT 1.112 } else if( !do_size ) { 1.113 - if( size != 0 ) tty->print("\n\t"); 1.114 + if( size != 0 ) st->print("\n\t"); 1.115 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? 1.116 - tty->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.117 + st->print("MOVAPD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.118 } else { 1.119 - tty->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.120 + st->print("MOVAPS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.121 } 1.122 #endif 1.123 } 1.124 @@ -813,11 +814,11 @@ 1.125 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst_lo], Matcher::_regEncode[src_lo] ); 1.126 #ifndef PRODUCT 1.127 } else if( !do_size ) { 1.128 - if( size != 0 ) tty->print("\n\t"); 1.129 + if( size != 0 ) st->print("\n\t"); 1.130 if( src_lo+1 == src_hi && dst_lo+1 == dst_hi ) { // double move? 1.131 - tty->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.132 + st->print("MOVSD %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.133 } else { 1.134 - tty->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.135 + st->print("MOVSS %s,%s",Matcher::regName[dst_lo],Matcher::regName[src_lo]); 1.136 } 1.137 #endif 1.138 } 1.139 @@ -825,28 +826,29 @@ 1.140 } 1.141 } 1.142 1.143 -static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size ) { 1.144 +static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) { 1.145 if( cbuf ) { 1.146 emit_opcode(*cbuf, 0x8B ); 1.147 emit_rm (*cbuf, 0x3, Matcher::_regEncode[dst], Matcher::_regEncode[src] ); 1.148 #ifndef PRODUCT 1.149 } else if( !do_size ) { 1.150 - if( size != 0 ) tty->print("\n\t"); 1.151 - tty->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); 1.152 + if( size != 0 ) st->print("\n\t"); 1.153 + st->print("MOV %s,%s",Matcher::regName[dst],Matcher::regName[src]); 1.154 #endif 1.155 } 1.156 return size+2; 1.157 } 1.158 1.159 -static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, int offset, int size ) { 1.160 +static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int src_hi, int dst_lo, int dst_hi, 1.161 + int offset, int size, outputStream* st ) { 1.162 if( src_lo != FPR1L_num ) { // Move value to top of FP stack, if not already there 1.163 if( cbuf ) { 1.164 emit_opcode( *cbuf, 0xD9 ); // FLD (i.e., push it) 1.165 emit_d8( *cbuf, 0xC0-1+Matcher::_regEncode[src_lo] ); 1.166 #ifndef PRODUCT 1.167 } else if( !do_size ) { 1.168 - if( size != 0 ) tty->print("\n\t"); 1.169 - tty->print("FLD %s",Matcher::regName[src_lo]); 1.170 + if( size != 0 ) st->print("\n\t"); 1.171 + st->print("FLD %s",Matcher::regName[src_lo]); 1.172 #endif 1.173 } 1.174 size += 2; 1.175 @@ -864,7 +866,7 @@ 1.176 assert( !OptoReg::is_valid(src_hi) && !OptoReg::is_valid(dst_hi), "no non-adjacent float-stores" ); 1.177 } 1.178 1.179 - return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size); 1.180 + return impl_helper(cbuf,do_size,false,offset,st_op,op,op_str,size, st); 1.181 } 1.182 1.183 uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const { 1.184 @@ -892,16 +894,16 @@ 1.185 if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { 1.186 if( src_second == dst_first ) { // overlapping stack copy ranges 1.187 assert( src_second_rc == rc_stack && dst_second_rc == rc_stack, "we only expect a stk-stk copy here" ); 1.188 - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); 1.189 - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); 1.190 + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); 1.191 + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); 1.192 src_second_rc = dst_second_rc = rc_bad; // flag as already moved the second bits 1.193 } 1.194 // move low bits 1.195 - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size); 1.196 - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size); 1.197 + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),ESI_num,0xFF,"PUSH ",size, st); 1.198 + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),EAX_num,0x8F,"POP ",size, st); 1.199 if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { // mov second bits 1.200 - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size); 1.201 - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size); 1.202 + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),ESI_num,0xFF,"PUSH ",size, st); 1.203 + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),EAX_num,0x8F,"POP ",size, st); 1.204 } 1.205 return size; 1.206 } 1.207 @@ -909,15 +911,15 @@ 1.208 // -------------------------------------- 1.209 // Check for integer reg-reg copy 1.210 if( src_first_rc == rc_int && dst_first_rc == rc_int ) 1.211 - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size); 1.212 + size = impl_mov_helper(cbuf,do_size,src_first,dst_first,size, st); 1.213 1.214 // Check for integer store 1.215 if( src_first_rc == rc_int && dst_first_rc == rc_stack ) 1.216 - size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size); 1.217 + size = impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first,0x89,"MOV ",size, st); 1.218 1.219 // Check for integer load 1.220 if( dst_first_rc == rc_int && src_first_rc == rc_stack ) 1.221 - size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size); 1.222 + size = impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first,0x8B,"MOV ",size, st); 1.223 1.224 // -------------------------------------- 1.225 // Check for float reg-reg copy 1.226 @@ -951,7 +953,7 @@ 1.227 1.228 // Check for float store 1.229 if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { 1.230 - return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size); 1.231 + return impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,ra_->reg2offset(dst_first),size, st); 1.232 } 1.233 1.234 // Check for float load 1.235 @@ -987,17 +989,17 @@ 1.236 assert( (src_second_rc == rc_bad && dst_second_rc == rc_bad) || 1.237 (src_first+1 == src_second && dst_first+1 == dst_second), 1.238 "no non-adjacent float-moves" ); 1.239 - return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size); 1.240 + return impl_movx_helper(cbuf,do_size,src_first,dst_first,src_second, dst_second, size, st); 1.241 } 1.242 1.243 // Check for xmm store 1.244 if( src_first_rc == rc_xmm && dst_first_rc == rc_stack ) { 1.245 - return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size); 1.246 + return impl_x_helper(cbuf,do_size,false,ra_->reg2offset(dst_first),src_first, src_second, size, st); 1.247 } 1.248 1.249 // Check for float xmm load 1.250 if( dst_first_rc == rc_xmm && src_first_rc == rc_stack ) { 1.251 - return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size); 1.252 + return impl_x_helper(cbuf,do_size,true ,ra_->reg2offset(src_first),dst_first, dst_second, size, st); 1.253 } 1.254 1.255 // Copy from float reg to xmm reg 1.256 @@ -1017,10 +1019,10 @@ 1.257 } 1.258 size += 4; 1.259 1.260 - size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size); 1.261 + size = impl_fp_store_helper(cbuf,do_size,src_first,src_second,dst_first,dst_second,0,size, st); 1.262 1.263 // Copy from the temp memory to the xmm reg. 1.264 - size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size); 1.265 + size = impl_x_helper(cbuf,do_size,true ,0,dst_first, dst_second, size, st); 1.266 1.267 if( cbuf ) { 1.268 emit_opcode(*cbuf,0x8D); // LEA ESP,[ESP+8] 1.269 @@ -1047,15 +1049,15 @@ 1.270 1.271 // Check for second word int-int move 1.272 if( src_second_rc == rc_int && dst_second_rc == rc_int ) 1.273 - return impl_mov_helper(cbuf,do_size,src_second,dst_second,size); 1.274 + return impl_mov_helper(cbuf,do_size,src_second,dst_second,size, st); 1.275 1.276 // Check for second word integer store 1.277 if( src_second_rc == rc_int && dst_second_rc == rc_stack ) 1.278 - return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size); 1.279 + return impl_helper(cbuf,do_size,false,ra_->reg2offset(dst_second),src_second,0x89,"MOV ",size, st); 1.280 1.281 // Check for second word integer load 1.282 if( dst_second_rc == rc_int && src_second_rc == rc_stack ) 1.283 - return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size); 1.284 + return impl_helper(cbuf,do_size,true ,ra_->reg2offset(src_second),dst_second,0x8B,"MOV ",size, st); 1.285 1.286 1.287 Unimplemented(); 1.288 @@ -1318,7 +1320,11 @@ 1.289 // 1.290 // NOTE: If the platform does not provide any short branch variants, then 1.291 // this method should return false for offset 0. 1.292 -bool Matcher::is_short_branch_offset(int offset) { 1.293 +bool Matcher::is_short_branch_offset(int rule, int offset) { 1.294 + // the short version of jmpConUCF2 contains multiple branches, 1.295 + // making the reach slightly less 1.296 + if (rule == jmpConUCF2_rule) 1.297 + return (-126 <= offset && offset <= 125); 1.298 return (-128 <= offset && offset <= 127); 1.299 } 1.300 1.301 @@ -5272,6 +5278,15 @@ 1.302 interface(REG_INTER); 1.303 %} 1.304 1.305 +operand eFlagsRegUCF() %{ 1.306 + constraint(ALLOC_IN_RC(int_flags)); 1.307 + match(RegFlags); 1.308 + predicate(false); 1.309 + 1.310 + format %{ "EFLAGS_U_CF" %} 1.311 + interface(REG_INTER); 1.312 +%} 1.313 + 1.314 // Condition Code Register used by long compare 1.315 operand flagsReg_long_LTGE() %{ 1.316 constraint(ALLOC_IN_RC(int_flags)); 1.317 @@ -5749,12 +5764,12 @@ 1.318 1.319 format %{ "" %} 1.320 interface(COND_INTER) %{ 1.321 - equal(0x4); 1.322 - not_equal(0x5); 1.323 - less(0xC); 1.324 - greater_equal(0xD); 1.325 - less_equal(0xE); 1.326 - greater(0xF); 1.327 + equal(0x4, "e"); 1.328 + not_equal(0x5, "ne"); 1.329 + less(0xC, "l"); 1.330 + greater_equal(0xD, "ge"); 1.331 + less_equal(0xE, "le"); 1.332 + greater(0xF, "g"); 1.333 %} 1.334 %} 1.335 1.336 @@ -5766,12 +5781,47 @@ 1.337 1.338 format %{ "" %} 1.339 interface(COND_INTER) %{ 1.340 - equal(0x4); 1.341 - not_equal(0x5); 1.342 - less(0x2); 1.343 - greater_equal(0x3); 1.344 - less_equal(0x6); 1.345 - greater(0x7); 1.346 + equal(0x4, "e"); 1.347 + not_equal(0x5, "ne"); 1.348 + less(0x2, "b"); 1.349 + greater_equal(0x3, "nb"); 1.350 + less_equal(0x6, "be"); 1.351 + greater(0x7, "nbe"); 1.352 + %} 1.353 +%} 1.354 + 1.355 +// Floating comparisons that don't require any fixup for the unordered case 1.356 +operand cmpOpUCF() %{ 1.357 + match(Bool); 1.358 + predicate(n->as_Bool()->_test._test == BoolTest::lt || 1.359 + n->as_Bool()->_test._test == BoolTest::ge || 1.360 + n->as_Bool()->_test._test == BoolTest::le || 1.361 + n->as_Bool()->_test._test == BoolTest::gt); 1.362 + format %{ "" %} 1.363 + interface(COND_INTER) %{ 1.364 + equal(0x4, "e"); 1.365 + not_equal(0x5, "ne"); 1.366 + less(0x2, "b"); 1.367 + greater_equal(0x3, "nb"); 1.368 + less_equal(0x6, "be"); 1.369 + greater(0x7, "nbe"); 1.370 + %} 1.371 +%} 1.372 + 1.373 + 1.374 +// Floating comparisons that can be fixed up with extra conditional jumps 1.375 +operand cmpOpUCF2() %{ 1.376 + match(Bool); 1.377 + predicate(n->as_Bool()->_test._test == BoolTest::ne || 1.378 + n->as_Bool()->_test._test == BoolTest::eq); 1.379 + format %{ "" %} 1.380 + interface(COND_INTER) %{ 1.381 + equal(0x4, "e"); 1.382 + not_equal(0x5, "ne"); 1.383 + less(0x2, "b"); 1.384 + greater_equal(0x3, "nb"); 1.385 + less_equal(0x6, "be"); 1.386 + greater(0x7, "nbe"); 1.387 %} 1.388 %} 1.389 1.390 @@ -5796,12 +5846,12 @@ 1.391 1.392 format %{ "" %} 1.393 interface(COND_INTER) %{ 1.394 - equal(0x4); 1.395 - not_equal(0x5); 1.396 - less(0xF); 1.397 - greater_equal(0xE); 1.398 - less_equal(0xD); 1.399 - greater(0xC); 1.400 + equal(0x4, "e"); 1.401 + not_equal(0x5, "ne"); 1.402 + less(0xF, "g"); 1.403 + greater_equal(0xE, "le"); 1.404 + less_equal(0xD, "ge"); 1.405 + greater(0xC, "l"); 1.406 %} 1.407 %} 1.408 1.409 @@ -7357,7 +7407,7 @@ 1.410 ins_pipe( pipe_cmov_reg ); 1.411 %} 1.412 1.413 -instruct cmovI_regU( eRegI dst, eRegI src, eFlagsRegU cr, cmpOpU cop ) %{ 1.414 +instruct cmovI_regU( cmpOpU cop, eFlagsRegU cr, eRegI dst, eRegI src ) %{ 1.415 predicate(VM_Version::supports_cmov() ); 1.416 match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); 1.417 ins_cost(200); 1.418 @@ -7367,6 +7417,15 @@ 1.419 ins_pipe( pipe_cmov_reg ); 1.420 %} 1.421 1.422 +instruct cmovI_regUCF( cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, eRegI src ) %{ 1.423 + predicate(VM_Version::supports_cmov() ); 1.424 + match(Set dst (CMoveI (Binary cop cr) (Binary dst src))); 1.425 + ins_cost(200); 1.426 + expand %{ 1.427 + cmovI_regU(cop, cr, dst, src); 1.428 + %} 1.429 +%} 1.430 + 1.431 // Conditional move 1.432 instruct cmovI_mem(cmpOp cop, eFlagsReg cr, eRegI dst, memory src) %{ 1.433 predicate(VM_Version::supports_cmov() ); 1.434 @@ -7379,7 +7438,7 @@ 1.435 %} 1.436 1.437 // Conditional move 1.438 -instruct cmovI_memu(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ 1.439 +instruct cmovI_memU(cmpOpU cop, eFlagsRegU cr, eRegI dst, memory src) %{ 1.440 predicate(VM_Version::supports_cmov() ); 1.441 match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); 1.442 ins_cost(250); 1.443 @@ -7389,6 +7448,15 @@ 1.444 ins_pipe( pipe_cmov_mem ); 1.445 %} 1.446 1.447 +instruct cmovI_memUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegI dst, memory src) %{ 1.448 + predicate(VM_Version::supports_cmov() ); 1.449 + match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src)))); 1.450 + ins_cost(250); 1.451 + expand %{ 1.452 + cmovI_memU(cop, cr, dst, src); 1.453 + %} 1.454 +%} 1.455 + 1.456 // Conditional move 1.457 instruct cmovP_reg(eRegP dst, eRegP src, eFlagsReg cr, cmpOp cop ) %{ 1.458 predicate(VM_Version::supports_cmov() ); 1.459 @@ -7416,7 +7484,7 @@ 1.460 %} 1.461 1.462 // Conditional move 1.463 -instruct cmovP_regU(eRegP dst, eRegP src, eFlagsRegU cr, cmpOpU cop ) %{ 1.464 +instruct cmovP_regU(cmpOpU cop, eFlagsRegU cr, eRegP dst, eRegP src ) %{ 1.465 predicate(VM_Version::supports_cmov() ); 1.466 match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); 1.467 ins_cost(200); 1.468 @@ -7426,6 +7494,15 @@ 1.469 ins_pipe( pipe_cmov_reg ); 1.470 %} 1.471 1.472 +instruct cmovP_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegP dst, eRegP src ) %{ 1.473 + predicate(VM_Version::supports_cmov() ); 1.474 + match(Set dst (CMoveP (Binary cop cr) (Binary dst src))); 1.475 + ins_cost(200); 1.476 + expand %{ 1.477 + cmovP_regU(cop, cr, dst, src); 1.478 + %} 1.479 +%} 1.480 + 1.481 // DISABLED: Requires the ADLC to emit a bottom_type call that 1.482 // correctly meets the two pointer arguments; one is an incoming 1.483 // register but the other is a memory operand. ALSO appears to 1.484 @@ -7555,6 +7632,15 @@ 1.485 ins_pipe( pipe_slow ); 1.486 %} 1.487 1.488 +instruct fcmovX_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regX dst, regX src) %{ 1.489 + predicate (UseSSE>=1); 1.490 + match(Set dst (CMoveF (Binary cop cr) (Binary dst src))); 1.491 + ins_cost(200); 1.492 + expand %{ 1.493 + fcmovX_regU(cop, cr, dst, src); 1.494 + %} 1.495 +%} 1.496 + 1.497 // unsigned version 1.498 instruct fcmovXD_regU(cmpOpU cop, eFlagsRegU cr, regXD dst, regXD src) %{ 1.499 predicate (UseSSE>=2); 1.500 @@ -7573,6 +7659,15 @@ 1.501 ins_pipe( pipe_slow ); 1.502 %} 1.503 1.504 +instruct fcmovXD_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, regXD dst, regXD src) %{ 1.505 + predicate (UseSSE>=2); 1.506 + match(Set dst (CMoveD (Binary cop cr) (Binary dst src))); 1.507 + ins_cost(200); 1.508 + expand %{ 1.509 + fcmovXD_regU(cop, cr, dst, src); 1.510 + %} 1.511 +%} 1.512 + 1.513 instruct cmovL_reg(cmpOp cop, eFlagsReg cr, eRegL dst, eRegL src) %{ 1.514 predicate(VM_Version::supports_cmov() ); 1.515 match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); 1.516 @@ -7595,6 +7690,15 @@ 1.517 ins_pipe( pipe_cmov_reg_long ); 1.518 %} 1.519 1.520 +instruct cmovL_regUCF(cmpOpUCF cop, eFlagsRegUCF cr, eRegL dst, eRegL src) %{ 1.521 + predicate(VM_Version::supports_cmov() ); 1.522 + match(Set dst (CMoveL (Binary cop cr) (Binary dst src))); 1.523 + ins_cost(200); 1.524 + expand %{ 1.525 + cmovL_regU(cop, cr, dst, src); 1.526 + %} 1.527 +%} 1.528 + 1.529 //----------Arithmetic Instructions-------------------------------------------- 1.530 //----------Addition Instructions---------------------------------------------- 1.531 // Integer Addition Instructions 1.532 @@ -9200,6 +9304,18 @@ 1.533 ins_pipe( pipe_slow ); 1.534 %} 1.535 1.536 +instruct cmpD_cc_P6CF(eFlagsRegUCF cr, regD src1, regD src2) %{ 1.537 + predicate(VM_Version::supports_cmov() && UseSSE <=1); 1.538 + match(Set cr (CmpD src1 src2)); 1.539 + ins_cost(150); 1.540 + format %{ "FLD $src1\n\t" 1.541 + "FUCOMIP ST,$src2 // P6 instruction" %} 1.542 + opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ 1.543 + ins_encode( Push_Reg_D(src1), 1.544 + OpcP, RegOpc(src2)); 1.545 + ins_pipe( pipe_slow ); 1.546 +%} 1.547 + 1.548 // Compare & branch 1.549 instruct cmpD_cc(eFlagsRegU cr, regD src1, regD src2, eAXRegI rax) %{ 1.550 predicate(UseSSE<=1); 1.551 @@ -9264,6 +9380,16 @@ 1.552 ins_pipe( pipe_slow ); 1.553 %} 1.554 1.555 +instruct cmpXD_ccCF(eFlagsRegUCF cr, regXD dst, regXD src) %{ 1.556 + predicate(UseSSE>=2); 1.557 + match(Set cr (CmpD dst src)); 1.558 + ins_cost(100); 1.559 + format %{ "COMISD $dst,$src" %} 1.560 + opcode(0x66, 0x0F, 0x2F); 1.561 + ins_encode(OpcP, OpcS, Opcode(tertiary), RegReg(dst, src)); 1.562 + ins_pipe( pipe_slow ); 1.563 +%} 1.564 + 1.565 // float compare and set condition codes in EFLAGS by XMM regs 1.566 instruct cmpXD_ccmem(eFlagsRegU cr, regXD dst, memory src, eAXRegI rax) %{ 1.567 predicate(UseSSE>=2); 1.568 @@ -9280,6 +9406,16 @@ 1.569 ins_pipe( pipe_slow ); 1.570 %} 1.571 1.572 +instruct cmpXD_ccmemCF(eFlagsRegUCF cr, regXD dst, memory src) %{ 1.573 + predicate(UseSSE>=2); 1.574 + match(Set cr (CmpD dst (LoadD src))); 1.575 + ins_cost(100); 1.576 + format %{ "COMISD $dst,$src" %} 1.577 + opcode(0x66, 0x0F, 0x2F); 1.578 + ins_encode(OpcP, OpcS, Opcode(tertiary), RegMem(dst, src)); 1.579 + ins_pipe( pipe_slow ); 1.580 +%} 1.581 + 1.582 // Compare into -1,0,1 in XMM 1.583 instruct cmpXD_reg(eRegI dst, regXD src1, regXD src2, eFlagsReg cr) %{ 1.584 predicate(UseSSE>=2); 1.585 @@ -10167,6 +10303,18 @@ 1.586 ins_pipe( pipe_slow ); 1.587 %} 1.588 1.589 +instruct cmpF_cc_P6CF(eFlagsRegUCF cr, regF src1, regF src2) %{ 1.590 + predicate(VM_Version::supports_cmov() && UseSSE == 0); 1.591 + match(Set cr (CmpF src1 src2)); 1.592 + ins_cost(100); 1.593 + format %{ "FLD $src1\n\t" 1.594 + "FUCOMIP ST,$src2 // P6 instruction" %} 1.595 + opcode(0xDF, 0x05); /* DF E8+i or DF /5 */ 1.596 + ins_encode( Push_Reg_D(src1), 1.597 + OpcP, RegOpc(src2)); 1.598 + ins_pipe( pipe_slow ); 1.599 +%} 1.600 + 1.601 1.602 // Compare & branch 1.603 instruct cmpF_cc(eFlagsRegU cr, regF src1, regF src2, eAXRegI rax) %{ 1.604 @@ -10232,6 +10380,16 @@ 1.605 ins_pipe( pipe_slow ); 1.606 %} 1.607 1.608 +instruct cmpX_ccCF(eFlagsRegUCF cr, regX dst, regX src) %{ 1.609 + predicate(UseSSE>=1); 1.610 + match(Set cr (CmpF dst src)); 1.611 + ins_cost(100); 1.612 + format %{ "COMISS $dst,$src" %} 1.613 + opcode(0x0F, 0x2F); 1.614 + ins_encode(OpcP, OpcS, RegReg(dst, src)); 1.615 + ins_pipe( pipe_slow ); 1.616 +%} 1.617 + 1.618 // float compare and set condition codes in EFLAGS by XMM regs 1.619 instruct cmpX_ccmem(eFlagsRegU cr, regX dst, memory src, eAXRegI rax) %{ 1.620 predicate(UseSSE>=1); 1.621 @@ -10248,6 +10406,16 @@ 1.622 ins_pipe( pipe_slow ); 1.623 %} 1.624 1.625 +instruct cmpX_ccmemCF(eFlagsRegUCF cr, regX dst, memory src) %{ 1.626 + predicate(UseSSE>=1); 1.627 + match(Set cr (CmpF dst (LoadF src))); 1.628 + ins_cost(100); 1.629 + format %{ "COMISS $dst,$src" %} 1.630 + opcode(0x0F, 0x2F); 1.631 + ins_encode(OpcP, OpcS, RegMem(dst, src)); 1.632 + ins_pipe( pipe_slow ); 1.633 +%} 1.634 + 1.635 // Compare into -1,0,1 in XMM 1.636 instruct cmpX_reg(eRegI dst, regX src1, regX src2, eFlagsReg cr) %{ 1.637 predicate(UseSSE>=1); 1.638 @@ -12099,6 +12267,19 @@ 1.639 ins_pc_relative(1); 1.640 %} 1.641 1.642 +instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ 1.643 + match(CountedLoopEnd cop cmp); 1.644 + effect(USE labl); 1.645 + 1.646 + ins_cost(200); 1.647 + format %{ "J$cop,u $labl\t# Loop end" %} 1.648 + size(6); 1.649 + opcode(0x0F, 0x80); 1.650 + ins_encode( Jcc( cop, labl) ); 1.651 + ins_pipe( pipe_jcc ); 1.652 + ins_pc_relative(1); 1.653 +%} 1.654 + 1.655 // Jump Direct Conditional - using unsigned comparison 1.656 instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ 1.657 match(If cop cmp); 1.658 @@ -12108,8 +12289,63 @@ 1.659 format %{ "J$cop,u $labl" %} 1.660 size(6); 1.661 opcode(0x0F, 0x80); 1.662 - ins_encode( Jcc( cop, labl) ); 1.663 - ins_pipe( pipe_jcc ); 1.664 + ins_encode(Jcc(cop, labl)); 1.665 + ins_pipe(pipe_jcc); 1.666 + ins_pc_relative(1); 1.667 +%} 1.668 + 1.669 +instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ 1.670 + match(If cop cmp); 1.671 + effect(USE labl); 1.672 + 1.673 + ins_cost(200); 1.674 + format %{ "J$cop,u $labl" %} 1.675 + size(6); 1.676 + opcode(0x0F, 0x80); 1.677 + ins_encode(Jcc(cop, labl)); 1.678 + ins_pipe(pipe_jcc); 1.679 + ins_pc_relative(1); 1.680 +%} 1.681 + 1.682 +instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ 1.683 + match(If cop cmp); 1.684 + effect(USE labl); 1.685 + 1.686 + ins_cost(200); 1.687 + format %{ $$template 1.688 + if ($cop$$cmpcode == Assembler::notEqual) { 1.689 + $$emit$$"JP,u $labl\n\t" 1.690 + $$emit$$"J$cop,u $labl" 1.691 + } else { 1.692 + $$emit$$"JP,u done\n\t" 1.693 + $$emit$$"J$cop,u $labl\n\t" 1.694 + $$emit$$"done:" 1.695 + } 1.696 + %} 1.697 + size(12); 1.698 + opcode(0x0F, 0x80); 1.699 + ins_encode %{ 1.700 + Label* l = $labl$$label; 1.701 + $$$emit8$primary; 1.702 + emit_cc(cbuf, $secondary, Assembler::parity); 1.703 + int parity_disp = -1; 1.704 + bool ok = false; 1.705 + if ($cop$$cmpcode == Assembler::notEqual) { 1.706 + // the two jumps 6 bytes apart so the jump distances are too 1.707 + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; 1.708 + } else if ($cop$$cmpcode == Assembler::equal) { 1.709 + parity_disp = 6; 1.710 + ok = true; 1.711 + } else { 1.712 + ShouldNotReachHere(); 1.713 + } 1.714 + emit_d32(cbuf, parity_disp); 1.715 + $$$emit8$primary; 1.716 + emit_cc(cbuf, $secondary, $cop$$cmpcode); 1.717 + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 4)) : 0; 1.718 + emit_d32(cbuf, disp); 1.719 + %} 1.720 + ins_pipe(pipe_jcc); 1.721 ins_pc_relative(1); 1.722 %} 1.723 1.724 @@ -12208,7 +12444,7 @@ 1.725 effect(USE labl); 1.726 1.727 ins_cost(300); 1.728 - format %{ "J$cop,s $labl" %} 1.729 + format %{ "J$cop,s $labl\t# Loop end" %} 1.730 size(2); 1.731 opcode(0x70); 1.732 ins_encode( JccShort( cop, labl) ); 1.733 @@ -12223,6 +12459,35 @@ 1.734 effect(USE labl); 1.735 1.736 ins_cost(300); 1.737 + format %{ "J$cop,us $labl\t# Loop end" %} 1.738 + size(2); 1.739 + opcode(0x70); 1.740 + ins_encode( JccShort( cop, labl) ); 1.741 + ins_pipe( pipe_jcc ); 1.742 + ins_pc_relative(1); 1.743 + ins_short_branch(1); 1.744 +%} 1.745 + 1.746 +instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ 1.747 + match(CountedLoopEnd cop cmp); 1.748 + effect(USE labl); 1.749 + 1.750 + ins_cost(300); 1.751 + format %{ "J$cop,us $labl\t# Loop end" %} 1.752 + size(2); 1.753 + opcode(0x70); 1.754 + ins_encode( JccShort( cop, labl) ); 1.755 + ins_pipe( pipe_jcc ); 1.756 + ins_pc_relative(1); 1.757 + ins_short_branch(1); 1.758 +%} 1.759 + 1.760 +// Jump Direct Conditional - using unsigned comparison 1.761 +instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ 1.762 + match(If cop cmp); 1.763 + effect(USE labl); 1.764 + 1.765 + ins_cost(300); 1.766 format %{ "J$cop,us $labl" %} 1.767 size(2); 1.768 opcode(0x70); 1.769 @@ -12232,8 +12497,7 @@ 1.770 ins_short_branch(1); 1.771 %} 1.772 1.773 -// Jump Direct Conditional - using unsigned comparison 1.774 -instruct jmpConU_short(cmpOpU cop, eFlagsRegU cmp, label labl) %{ 1.775 +instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ 1.776 match(If cop cmp); 1.777 effect(USE labl); 1.778 1.779 @@ -12247,6 +12511,46 @@ 1.780 ins_short_branch(1); 1.781 %} 1.782 1.783 +instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ 1.784 + match(If cop cmp); 1.785 + effect(USE labl); 1.786 + 1.787 + ins_cost(300); 1.788 + format %{ $$template 1.789 + if ($cop$$cmpcode == Assembler::notEqual) { 1.790 + $$emit$$"JP,u,s $labl\n\t" 1.791 + $$emit$$"J$cop,u,s $labl" 1.792 + } else { 1.793 + $$emit$$"JP,u,s done\n\t" 1.794 + $$emit$$"J$cop,u,s $labl\n\t" 1.795 + $$emit$$"done:" 1.796 + } 1.797 + %} 1.798 + size(4); 1.799 + opcode(0x70); 1.800 + ins_encode %{ 1.801 + Label* l = $labl$$label; 1.802 + emit_cc(cbuf, $primary, Assembler::parity); 1.803 + int parity_disp = -1; 1.804 + if ($cop$$cmpcode == Assembler::notEqual) { 1.805 + parity_disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; 1.806 + } else if ($cop$$cmpcode == Assembler::equal) { 1.807 + parity_disp = 2; 1.808 + } else { 1.809 + ShouldNotReachHere(); 1.810 + } 1.811 + emit_d8(cbuf, parity_disp); 1.812 + emit_cc(cbuf, $primary, $cop$$cmpcode); 1.813 + int disp = l ? (l->loc_pos() - (cbuf.code_size() + 1)) : 0; 1.814 + emit_d8(cbuf, disp); 1.815 + assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); 1.816 + assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp"); 1.817 + %} 1.818 + ins_pipe(pipe_jcc); 1.819 + ins_pc_relative(1); 1.820 + ins_short_branch(1); 1.821 +%} 1.822 + 1.823 // ============================================================================ 1.824 // Long Compare 1.825 //