490 if( dst_encoding == src_encoding ) {
491 // reg-reg copy, use an empty encoding
492 } else {
493 emit_opcode( cbuf, 0x8B );
494 emit_rm(cbuf, 0x3, dst_encoding, src_encoding );
495 }
496 }
497
498 void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) {
499 if( dst_encoding == src_encoding ) {
500 // reg-reg copy, use an empty encoding
501 } else {
502 MacroAssembler _masm(&cbuf);
503
504 __ movdqa(as_XMMRegister(dst_encoding), as_XMMRegister(src_encoding));
505 }
506 }
507
508
509 //=============================================================================
510 #ifndef PRODUCT
511 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
512 Compile* C = ra_->C;
513 if( C->in_24_bit_fp_mode() ) {
514 st->print("FLDCW 24 bit fpu control word");
515 st->print_cr(""); st->print("\t");
516 }
517
518 int framesize = C->frame_slots() << LogBytesPerInt;
519 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
520 // Remove two words for return addr and rbp,
521 framesize -= 2*wordSize;
522
523 // Calls to C2R adapters often do not accept exceptional returns.
524 // We require that their callers must bang for them. But be careful, because
525 // some VM calls (such as call site linkage) can use several kilobytes of
526 // stack. But the stack safety zone should account for that.
527 // See bugs 4446381, 4468289, 4497237.
528 if (C->need_stack_bang(framesize)) {
529 st->print_cr("# stack bang"); st->print("\t");
1303 // Emit deopt handler code.
1304 int emit_deopt_handler(CodeBuffer& cbuf) {
1305
1306 // Note that the code buffer's insts_mark is always relative to insts.
1307 // That's why we must use the macroassembler to generate a handler.
1308 MacroAssembler _masm(&cbuf);
1309 address base =
1310 __ start_a_stub(size_exception_handler());
1311 if (base == NULL) return 0; // CodeBuffer::expand failed
1312 int offset = __ offset();
1313 InternalAddress here(__ pc());
1314 __ pushptr(here.addr());
1315
1316 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
1317 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
1318 __ end_a_stub();
1319 return offset;
1320 }
1321
1322
1323 static void emit_double_constant(CodeBuffer& cbuf, double x) {
1324 int mark = cbuf.insts()->mark_off();
1325 MacroAssembler _masm(&cbuf);
1326 address double_address = __ double_constant(x);
1327 cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
1328 emit_d32_reloc(cbuf,
1329 (int)double_address,
1330 internal_word_Relocation::spec(double_address),
1331 RELOC_DISP32);
1332 }
1333
1334 static void emit_float_constant(CodeBuffer& cbuf, float x) {
1335 int mark = cbuf.insts()->mark_off();
1336 MacroAssembler _masm(&cbuf);
1337 address float_address = __ float_constant(x);
1338 cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
1339 emit_d32_reloc(cbuf,
1340 (int)float_address,
1341 internal_word_Relocation::spec(float_address),
1342 RELOC_DISP32);
1343 }
1344
1345
1346 const bool Matcher::match_rule_supported(int opcode) {
1347 if (!has_match_rule(opcode))
1348 return false;
1349
1350 return true; // Per default match rules are supported.
1351 }
1352
1353 int Matcher::regnum_to_fpu_offset(int regnum) {
1354 return regnum - 32; // The FP registers are in the second chunk
1355 }
1356
1357 bool is_positive_zero_float(jfloat f) {
1358 return jint_cast(f) == jint_cast(0.0F);
1359 }
1360
1361 bool is_positive_one_float(jfloat f) {
1362 return jint_cast(f) == jint_cast(1.0F);
1363 }
1364
1365 bool is_positive_zero_double(jdouble d) {
1366 return jlong_cast(d) == jlong_cast(0.0);
1367 }
1368
1369 bool is_positive_one_double(jdouble d) {
1370 return jlong_cast(d) == jlong_cast(1.0);
1371 }
1372
1373 // This is UltraSparc specific, true just means we have fast l2f conversion
1374 const bool Matcher::convL2FSupported(void) {
1375 return true;
1376 }
1377
1378 // Vector width in bytes
1379 const uint Matcher::vector_width_in_bytes(void) {
1380 return UseSSE >= 2 ? 8 : 0;
1381 }
1382
1383 // Vector ideal reg
1384 const uint Matcher::vector_ideal_reg(void) {
1385 return Op_RegD;
1386 }
1387
1388 // Is this branch offset short enough that a short branch can be used?
1389 //
1390 // NOTE: If the platform does not provide any short branch variants, then
1391 // this method should return false for offset 0.
1392 bool Matcher::is_short_branch_offset(int rule, int offset) {
2019 emit_d32(cbuf, src_con);
2020 }
2021 %}
2022
2023 enc_class LdImmL_Hi( eRegL dst, immL src) %{ // Load Immediate
2024 // Load immediate does not have a zero or sign extended version
2025 // for 8-bit immediates
2026 int dst_enc = $dst$$reg + 2;
2027 int src_con = ((julong)($src$$constant)) >> 32;
2028 if (src_con == 0) {
2029 // xor dst, dst
2030 emit_opcode(cbuf, 0x33);
2031 emit_rm(cbuf, 0x3, dst_enc, dst_enc);
2032 } else {
2033 emit_opcode(cbuf, $primary + dst_enc);
2034 emit_d32(cbuf, src_con);
2035 }
2036 %}
2037
2038
2039 enc_class LdImmD (immD src) %{ // Load Immediate
2040 if( is_positive_zero_double($src$$constant)) {
2041 // FLDZ
2042 emit_opcode(cbuf,0xD9);
2043 emit_opcode(cbuf,0xEE);
2044 } else if( is_positive_one_double($src$$constant)) {
2045 // FLD1
2046 emit_opcode(cbuf,0xD9);
2047 emit_opcode(cbuf,0xE8);
2048 } else {
2049 emit_opcode(cbuf,0xDD);
2050 emit_rm(cbuf, 0x0, 0x0, 0x5);
2051 emit_double_constant(cbuf, $src$$constant);
2052 }
2053 %}
2054
2055
2056 enc_class LdImmF (immF src) %{ // Load Immediate
2057 if( is_positive_zero_float($src$$constant)) {
2058 emit_opcode(cbuf,0xD9);
2059 emit_opcode(cbuf,0xEE);
2060 } else if( is_positive_one_float($src$$constant)) {
2061 emit_opcode(cbuf,0xD9);
2062 emit_opcode(cbuf,0xE8);
2063 } else {
2064 $$$emit8$primary;
2065 // Load immediate does not have a zero or sign extended version
2066 // for 8-bit immediates
2067 // First load to TOS, then move to dst
2068 emit_rm(cbuf, 0x0, 0x0, 0x5);
2069 emit_float_constant(cbuf, $src$$constant);
2070 }
2071 %}
2072
2073 enc_class LdImmX (regX dst, immXF con) %{ // Load Immediate
2074 emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
2075 emit_float_constant(cbuf, $con$$constant);
2076 %}
2077
2078 enc_class LdImmXD (regXD dst, immXD con) %{ // Load Immediate
2079 emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
2080 emit_double_constant(cbuf, $con$$constant);
2081 %}
2082
2083 enc_class load_conXD (regXD dst, immXD con) %{ // Load double constant
2084 // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
2085 emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
2086 emit_opcode(cbuf, 0x0F);
2087 emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
2088 emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
2089 emit_double_constant(cbuf, $con$$constant);
2090 %}
2091
2092 enc_class Opc_MemImm_F(immF src) %{
2093 cbuf.set_insts_mark();
2094 $$$emit8$primary;
2095 emit_rm(cbuf, 0x0, $secondary, 0x5);
2096 emit_float_constant(cbuf, $src$$constant);
2097 %}
2098
2099
2100 enc_class MovI2X_reg(regX dst, eRegI src) %{
2101 emit_opcode(cbuf, 0x66 ); // MOVD dst,src
2102 emit_opcode(cbuf, 0x0F );
2103 emit_opcode(cbuf, 0x6E );
2104 emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg);
2105 %}
2106
2107 enc_class MovX2I_reg(eRegI dst, regX src) %{
2108 emit_opcode(cbuf, 0x66 ); // MOVD dst,src
2109 emit_opcode(cbuf, 0x0F );
2110 emit_opcode(cbuf, 0x7E );
2111 emit_rm(cbuf, 0x3, $src$$reg, $dst$$reg);
2112 %}
2113
2114 enc_class MovL2XD_reg(regXD dst, eRegL src, regXD tmp) %{
2115 { // MOVD $dst,$src.lo
2116 emit_opcode(cbuf,0x66);
2117 emit_opcode(cbuf,0x0F);
2118 emit_opcode(cbuf,0x6E);
2119 emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg);
4784 predicate(n->get_long() == (int)(n->get_long()));
4785 match(ConL);
4786 op_cost(20);
4787
4788 format %{ %}
4789 interface(CONST_INTER);
4790 %}
4791
4792 //Double Immediate zero
4793 operand immD0() %{
4794 // Do additional (and counter-intuitive) test against NaN to work around VC++
4795 // bug that generates code such that NaNs compare equal to 0.0
4796 predicate( UseSSE<=1 && n->getd() == 0.0 && !g_isnan(n->getd()) );
4797 match(ConD);
4798
4799 op_cost(5);
4800 format %{ %}
4801 interface(CONST_INTER);
4802 %}
4803
4804 // Double Immediate
4805 operand immD1() %{
4806 predicate( UseSSE<=1 && n->getd() == 1.0 );
4807 match(ConD);
4808
4809 op_cost(5);
4810 format %{ %}
4811 interface(CONST_INTER);
4812 %}
4813
4814 // Double Immediate
4815 operand immD() %{
4816 predicate(UseSSE<=1);
4817 match(ConD);
4818
4819 op_cost(5);
4820 format %{ %}
4821 interface(CONST_INTER);
4822 %}
4823
4824 operand immXD() %{
4827
4828 op_cost(5);
4829 format %{ %}
4830 interface(CONST_INTER);
4831 %}
4832
4833 // Double Immediate zero
4834 operand immXD0() %{
4835 // Do additional (and counter-intuitive) test against NaN to work around VC++
4836 // bug that generates code such that NaNs compare equal to 0.0 AND do not
4837 // compare equal to -0.0.
4838 predicate( UseSSE>=2 && jlong_cast(n->getd()) == 0 );
4839 match(ConD);
4840
4841 format %{ %}
4842 interface(CONST_INTER);
4843 %}
4844
4845 // Float Immediate zero
4846 operand immF0() %{
4847 predicate( UseSSE == 0 && n->getf() == 0.0 );
4848 match(ConF);
4849
4850 op_cost(5);
4851 format %{ %}
4852 interface(CONST_INTER);
4853 %}
4854
4855 // Float Immediate
4856 operand immF() %{
4857 predicate( UseSSE == 0 );
4858 match(ConF);
4859
4860 op_cost(5);
4861 format %{ %}
4862 interface(CONST_INTER);
4863 %}
4864
4865 // Float Immediate
4866 operand immXF() %{
4867 predicate(UseSSE >= 1);
7198 ins_cost(200);
7199 format %{ "MOV $dst.lo,$src.lo\n\t"
7200 "MOV $dst.hi,$src.hi" %}
7201 opcode(0xB8);
7202 ins_encode( LdImmL_Lo(dst, src), LdImmL_Hi(dst, src) );
7203 ins_pipe( ialu_reg_long_fat );
7204 %}
7205
7206 instruct loadConL0(eRegL dst, immL0 src, eFlagsReg cr) %{
7207 match(Set dst src);
7208 effect(KILL cr);
7209 ins_cost(150);
7210 format %{ "XOR $dst.lo,$dst.lo\n\t"
7211 "XOR $dst.hi,$dst.hi" %}
7212 opcode(0x33,0x33);
7213 ins_encode( RegReg_Lo(dst,dst), RegReg_Hi(dst, dst) );
7214 ins_pipe( ialu_reg_long );
7215 %}
7216
7217 // The instruction usage is guarded by predicate in operand immF().
7218 instruct loadConF(regF dst, immF src) %{
7219 match(Set dst src);
7220 ins_cost(125);
7221
7222 format %{ "FLD_S ST,$src\n\t"
7223 "FSTP $dst" %}
7224 opcode(0xD9, 0x00); /* D9 /0 */
7225 ins_encode(LdImmF(src), Pop_Reg_F(dst) );
7226 ins_pipe( fpu_reg_con );
7227 %}
7228
7229 // The instruction usage is guarded by predicate in operand immXF().
7230 instruct loadConX(regX dst, immXF con) %{
7231 match(Set dst con);
7232 ins_cost(125);
7233 format %{ "MOVSS $dst,[$con]" %}
7234 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), LdImmX(dst, con));
7235 ins_pipe( pipe_slow );
7236 %}
7237
7238 // The instruction usage is guarded by predicate in operand immXF0().
7239 instruct loadConX0(regX dst, immXF0 src) %{
7240 match(Set dst src);
7241 ins_cost(100);
7242 format %{ "XORPS $dst,$dst\t# float 0.0" %}
7243 ins_encode( Opcode(0x0F), Opcode(0x57), RegReg(dst,dst));
7244 ins_pipe( pipe_slow );
7245 %}
7246
7247 // The instruction usage is guarded by predicate in operand immD().
7248 instruct loadConD(regD dst, immD src) %{
7249 match(Set dst src);
7250 ins_cost(125);
7251
7252 format %{ "FLD_D ST,$src\n\t"
7253 "FSTP $dst" %}
7254 ins_encode(LdImmD(src), Pop_Reg_D(dst) );
7255 ins_pipe( fpu_reg_con );
7256 %}
7257
7258 // The instruction usage is guarded by predicate in operand immXD().
7259 instruct loadConXD(regXD dst, immXD con) %{
7260 match(Set dst con);
7261 ins_cost(125);
7262 format %{ "MOVSD $dst,[$con]" %}
7263 ins_encode(load_conXD(dst, con));
7264 ins_pipe( pipe_slow );
7265 %}
7266
7267 // The instruction usage is guarded by predicate in operand immXD0().
7268 instruct loadConXD0(regXD dst, immXD0 src) %{
7269 match(Set dst src);
7270 ins_cost(100);
7271 format %{ "XORPD $dst,$dst\t# double 0.0" %}
7272 ins_encode( Opcode(0x66), Opcode(0x0F), Opcode(0x57), RegReg(dst,dst));
7273 ins_pipe( pipe_slow );
7274 %}
7275
7276 // Load Stack Slot
7277 instruct loadSSI(eRegI dst, stackSlotI src) %{
7278 match(Set dst src);
7279 ins_cost(125);
7280
7281 format %{ "MOV $dst,$src" %}
7282 opcode(0x8B);
7283 ins_encode( OpcP, RegMem(dst,src));
7284 ins_pipe( ialu_reg_mem );
10286 ins_pipe( fpu_reg_mem );
10287 %}
10288
10289 // add-to-memory
10290 instruct addD_mem_reg(memory dst, regD src) %{
10291 predicate(UseSSE<=1);
10292 match(Set dst (StoreD dst (RoundDouble (AddD (LoadD dst) src))));
10293 ins_cost(150);
10294
10295 format %{ "FLD_D $dst\n\t"
10296 "DADD ST,$src\n\t"
10297 "FST_D $dst" %}
10298 opcode(0xDD, 0x0);
10299 ins_encode( Opcode(0xDD), RMopc_Mem(0x00,dst),
10300 Opcode(0xD8), RegOpc(src),
10301 set_instruction_start,
10302 Opcode(0xDD), RMopc_Mem(0x03,dst) );
10303 ins_pipe( fpu_reg_mem );
10304 %}
10305
10306 instruct addD_reg_imm1(regD dst, immD1 src) %{
10307 predicate(UseSSE<=1);
10308 match(Set dst (AddD dst src));
10309 ins_cost(125);
10310 format %{ "FLD1\n\t"
10311 "DADDp $dst,ST" %}
10312 opcode(0xDE, 0x00);
10313 ins_encode( LdImmD(src),
10314 OpcP, RegOpc(dst) );
10315 ins_pipe( fpu_reg );
10316 %}
10317
10318 instruct addD_reg_imm(regD dst, immD src) %{
10319 predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
10320 match(Set dst (AddD dst src));
10321 ins_cost(200);
10322 format %{ "FLD_D [$src]\n\t"
10323 "DADDp $dst,ST" %}
10324 opcode(0xDE, 0x00); /* DE /0 */
10325 ins_encode( LdImmD(src),
10326 OpcP, RegOpc(dst));
10327 ins_pipe( fpu_reg_mem );
10328 %}
10329
10330 instruct addD_reg_imm_round(stackSlotD dst, regD src, immD con) %{
10331 predicate(UseSSE<=1 && _kids[0]->_kids[1]->_leaf->getd() != 0.0 && _kids[0]->_kids[1]->_leaf->getd() != 1.0 );
10332 match(Set dst (RoundDouble (AddD src con)));
10333 ins_cost(200);
10334 format %{ "FLD_D [$con]\n\t"
10335 "DADD ST,$src\n\t"
10336 "FSTP_D $dst\t# D-round" %}
10337 opcode(0xD8, 0x00); /* D8 /0 */
10338 ins_encode( LdImmD(con),
10339 OpcP, RegOpc(src), Pop_Mem_D(dst));
10340 ins_pipe( fpu_mem_reg_con );
10341 %}
10342
10343 // Add two double precision floating point values in xmm
10344 instruct addXD_reg(regXD dst, regXD src) %{
10345 predicate(UseSSE>=2);
10346 match(Set dst (AddD dst src));
10347 format %{ "ADDSD $dst,$src" %}
10348 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), RegReg(dst, src));
10349 ins_pipe( pipe_slow );
10350 %}
10351
10352 instruct addXD_imm(regXD dst, immXD con) %{
10353 predicate(UseSSE>=2);
10354 match(Set dst (AddD dst con));
10355 format %{ "ADDSD $dst,[$con]" %}
10356 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), LdImmXD(dst, con) );
10357 ins_pipe( pipe_slow );
10358 %}
10359
10360 instruct addXD_mem(regXD dst, memory mem) %{
10361 predicate(UseSSE>=2);
10362 match(Set dst (AddD dst (LoadD mem)));
10363 format %{ "ADDSD $dst,$mem" %}
10364 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), RegMem(dst,mem));
10365 ins_pipe( pipe_slow );
10366 %}
10367
10368 // Sub two double precision floating point values in xmm
10369 instruct subXD_reg(regXD dst, regXD src) %{
10370 predicate(UseSSE>=2);
10371 match(Set dst (SubD dst src));
10372 format %{ "SUBSD $dst,$src" %}
10373 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), RegReg(dst, src));
10374 ins_pipe( pipe_slow );
10375 %}
10376
10377 instruct subXD_imm(regXD dst, immXD con) %{
10378 predicate(UseSSE>=2);
10379 match(Set dst (SubD dst con));
10380 format %{ "SUBSD $dst,[$con]" %}
10381 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), LdImmXD(dst, con) );
10382 ins_pipe( pipe_slow );
10383 %}
10384
10385 instruct subXD_mem(regXD dst, memory mem) %{
10386 predicate(UseSSE>=2);
10387 match(Set dst (SubD dst (LoadD mem)));
10388 format %{ "SUBSD $dst,$mem" %}
10389 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), RegMem(dst,mem));
10390 ins_pipe( pipe_slow );
10391 %}
10392
10393 // Mul two double precision floating point values in xmm
10394 instruct mulXD_reg(regXD dst, regXD src) %{
10395 predicate(UseSSE>=2);
10396 match(Set dst (MulD dst src));
10397 format %{ "MULSD $dst,$src" %}
10398 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), RegReg(dst, src));
10399 ins_pipe( pipe_slow );
10400 %}
10401
10402 instruct mulXD_imm(regXD dst, immXD con) %{
10403 predicate(UseSSE>=2);
10404 match(Set dst (MulD dst con));
10405 format %{ "MULSD $dst,[$con]" %}
10406 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), LdImmXD(dst, con) );
10407 ins_pipe( pipe_slow );
10408 %}
10409
10410 instruct mulXD_mem(regXD dst, memory mem) %{
10411 predicate(UseSSE>=2);
10412 match(Set dst (MulD dst (LoadD mem)));
10413 format %{ "MULSD $dst,$mem" %}
10414 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), RegMem(dst,mem));
10415 ins_pipe( pipe_slow );
10416 %}
10417
10418 // Div two double precision floating point values in xmm
10419 instruct divXD_reg(regXD dst, regXD src) %{
10420 predicate(UseSSE>=2);
10421 match(Set dst (DivD dst src));
10422 format %{ "DIVSD $dst,$src" %}
10423 opcode(0xF2, 0x0F, 0x5E);
10424 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), RegReg(dst, src));
10425 ins_pipe( pipe_slow );
10426 %}
10427
10428 instruct divXD_imm(regXD dst, immXD con) %{
10429 predicate(UseSSE>=2);
10430 match(Set dst (DivD dst con));
10431 format %{ "DIVSD $dst,[$con]" %}
10432 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), LdImmXD(dst, con));
10433 ins_pipe( pipe_slow );
10434 %}
10435
10436 instruct divXD_mem(regXD dst, memory mem) %{
10437 predicate(UseSSE>=2);
10438 match(Set dst (DivD dst (LoadD mem)));
10439 format %{ "DIVSD $dst,$mem" %}
10440 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), RegMem(dst,mem));
10441 ins_pipe( pipe_slow );
10442 %}
10443
10444
10445 instruct mulD_reg(regD dst, regD src) %{
10446 predicate(UseSSE<=1);
10447 match(Set dst (MulD dst src));
10448 format %{ "FLD $src\n\t"
10449 "DMULp $dst,ST" %}
10450 opcode(0xDE, 0x1); /* DE C8+i or DE /1*/
10451 ins_cost(150);
10452 ins_encode( Push_Reg_D(src),
10453 OpcP, RegOpc(dst) );
10464 //
10465 instruct strictfp_mulD_reg(regDPR1 dst, regnotDPR1 src) %{
10466 predicate( UseSSE<=1 && Compile::current()->has_method() && Compile::current()->method()->is_strict() );
10467 match(Set dst (MulD dst src));
10468 ins_cost(1); // Select this instruction for all strict FP double multiplies
10469
10470 format %{ "FLD StubRoutines::_fpu_subnormal_bias1\n\t"
10471 "DMULp $dst,ST\n\t"
10472 "FLD $src\n\t"
10473 "DMULp $dst,ST\n\t"
10474 "FLD StubRoutines::_fpu_subnormal_bias2\n\t"
10475 "DMULp $dst,ST\n\t" %}
10476 opcode(0xDE, 0x1); /* DE C8+i or DE /1*/
10477 ins_encode( strictfp_bias1(dst),
10478 Push_Reg_D(src),
10479 OpcP, RegOpc(dst),
10480 strictfp_bias2(dst) );
10481 ins_pipe( fpu_reg_reg );
10482 %}
10483
10484 instruct mulD_reg_imm(regD dst, immD src) %{
10485 predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
10486 match(Set dst (MulD dst src));
10487 ins_cost(200);
10488 format %{ "FLD_D [$src]\n\t"
10489 "DMULp $dst,ST" %}
10490 opcode(0xDE, 0x1); /* DE /1 */
10491 ins_encode( LdImmD(src),
10492 OpcP, RegOpc(dst) );
10493 ins_pipe( fpu_reg_mem );
10494 %}
10495
10496
10497 instruct mulD_reg_mem(regD dst, memory src) %{
10498 predicate( UseSSE<=1 );
10499 match(Set dst (MulD dst (LoadD src)));
10500 ins_cost(200);
10501 format %{ "FLD_D $src\n\t"
10502 "DMULp $dst,ST" %}
10503 opcode(0xDE, 0x1, 0xDD); /* DE C8+i or DE /1*/ /* LoadD DD /0 */
10504 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,src),
10505 OpcP, RegOpc(dst) );
10506 ins_pipe( fpu_reg_mem );
10507 %}
10508
10509 //
10510 // Cisc-alternate to reg-reg multiply
10511 instruct mulD_reg_mem_cisc(regD dst, regD src, memory mem) %{
10512 predicate( UseSSE<=1 );
10513 match(Set dst (MulD src (LoadD mem)));
11207 format %{ "FLD $src\n\t"
11208 "FADDp $dst,ST" %}
11209 opcode(0xDE, 0x0); /* DE C0+i or DE /0*/
11210 ins_encode( Push_Reg_F(src),
11211 OpcP, RegOpc(dst) );
11212 ins_pipe( fpu_reg_reg );
11213 %}
11214
11215 // Add two single precision floating point values in xmm
11216 instruct addX_reg(regX dst, regX src) %{
11217 predicate(UseSSE>=1);
11218 match(Set dst (AddF dst src));
11219 format %{ "ADDSS $dst,$src" %}
11220 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), RegReg(dst, src));
11221 ins_pipe( pipe_slow );
11222 %}
11223
11224 instruct addX_imm(regX dst, immXF con) %{
11225 predicate(UseSSE>=1);
11226 match(Set dst (AddF dst con));
11227 format %{ "ADDSS $dst,[$con]" %}
11228 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), LdImmX(dst, con) );
11229 ins_pipe( pipe_slow );
11230 %}
11231
11232 instruct addX_mem(regX dst, memory mem) %{
11233 predicate(UseSSE>=1);
11234 match(Set dst (AddF dst (LoadF mem)));
11235 format %{ "ADDSS $dst,$mem" %}
11236 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), RegMem(dst, mem));
11237 ins_pipe( pipe_slow );
11238 %}
11239
11240 // Subtract two single precision floating point values in xmm
11241 instruct subX_reg(regX dst, regX src) %{
11242 predicate(UseSSE>=1);
11243 match(Set dst (SubF dst src));
11244 format %{ "SUBSS $dst,$src" %}
11245 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), RegReg(dst, src));
11246 ins_pipe( pipe_slow );
11247 %}
11248
11249 instruct subX_imm(regX dst, immXF con) %{
11250 predicate(UseSSE>=1);
11251 match(Set dst (SubF dst con));
11252 format %{ "SUBSS $dst,[$con]" %}
11253 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), LdImmX(dst, con) );
11254 ins_pipe( pipe_slow );
11255 %}
11256
11257 instruct subX_mem(regX dst, memory mem) %{
11258 predicate(UseSSE>=1);
11259 match(Set dst (SubF dst (LoadF mem)));
11260 format %{ "SUBSS $dst,$mem" %}
11261 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), RegMem(dst,mem));
11262 ins_pipe( pipe_slow );
11263 %}
11264
11265 // Multiply two single precision floating point values in xmm
11266 instruct mulX_reg(regX dst, regX src) %{
11267 predicate(UseSSE>=1);
11268 match(Set dst (MulF dst src));
11269 format %{ "MULSS $dst,$src" %}
11270 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), RegReg(dst, src));
11271 ins_pipe( pipe_slow );
11272 %}
11273
11274 instruct mulX_imm(regX dst, immXF con) %{
11275 predicate(UseSSE>=1);
11276 match(Set dst (MulF dst con));
11277 format %{ "MULSS $dst,[$con]" %}
11278 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), LdImmX(dst, con) );
11279 ins_pipe( pipe_slow );
11280 %}
11281
11282 instruct mulX_mem(regX dst, memory mem) %{
11283 predicate(UseSSE>=1);
11284 match(Set dst (MulF dst (LoadF mem)));
11285 format %{ "MULSS $dst,$mem" %}
11286 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), RegMem(dst,mem));
11287 ins_pipe( pipe_slow );
11288 %}
11289
11290 // Divide two single precision floating point values in xmm
11291 instruct divX_reg(regX dst, regX src) %{
11292 predicate(UseSSE>=1);
11293 match(Set dst (DivF dst src));
11294 format %{ "DIVSS $dst,$src" %}
11295 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), RegReg(dst, src));
11296 ins_pipe( pipe_slow );
11297 %}
11298
11299 instruct divX_imm(regX dst, immXF con) %{
11300 predicate(UseSSE>=1);
11301 match(Set dst (DivF dst con));
11302 format %{ "DIVSS $dst,[$con]" %}
11303 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), LdImmX(dst, con) );
11304 ins_pipe( pipe_slow );
11305 %}
11306
11307 instruct divX_mem(regX dst, memory mem) %{
11308 predicate(UseSSE>=1);
11309 match(Set dst (DivF dst (LoadF mem)));
11310 format %{ "DIVSS $dst,$mem" %}
11311 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), RegMem(dst,mem));
11312 ins_pipe( pipe_slow );
11313 %}
11314
11315 // Get the square root of a single precision floating point values in xmm
11316 instruct sqrtX_reg(regX dst, regX src) %{
11317 predicate(UseSSE>=1);
11318 match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
11319 format %{ "SQRTSS $dst,$src" %}
11320 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x51), RegReg(dst, src));
11321 ins_pipe( pipe_slow );
11322 %}
11323
11324 instruct sqrtX_mem(regX dst, memory mem) %{
11439 Pop_Mem_F(dst) );
11440 ins_pipe( fpu_mem_mem_mem );
11441 %}
11442
11443 // Spill to obtain 24-bit precision
11444 instruct addF24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
11445 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11446 match(Set dst (AddF src1 src2));
11447
11448 format %{ "FADD $dst,$src1,$src2" %}
11449 opcode(0xD8, 0x0, 0xD9); /* D8 /0 */ /* LoadF D9 /0 */
11450 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,src2),
11451 set_instruction_start,
11452 OpcP, RMopc_Mem(secondary,src1),
11453 Pop_Mem_F(dst) );
11454 ins_pipe( fpu_mem_mem_mem );
11455 %}
11456
11457
11458 // Spill to obtain 24-bit precision
11459 instruct addF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
11460 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11461 match(Set dst (AddF src1 src2));
11462 format %{ "FLD $src1\n\t"
11463 "FADD $src2\n\t"
11464 "FSTP_S $dst" %}
11465 opcode(0xD8, 0x00); /* D8 /0 */
11466 ins_encode( Push_Reg_F(src1),
11467 Opc_MemImm_F(src2),
11468 Pop_Mem_F(dst));
11469 ins_pipe( fpu_mem_reg_con );
11470 %}
11471 //
11472 // This instruction does not round to 24-bits
11473 instruct addF_reg_imm(regF dst, regF src1, immF src2) %{
11474 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11475 match(Set dst (AddF src1 src2));
11476 format %{ "FLD $src1\n\t"
11477 "FADD $src2\n\t"
11478 "FSTP_S $dst" %}
11479 opcode(0xD8, 0x00); /* D8 /0 */
11480 ins_encode( Push_Reg_F(src1),
11481 Opc_MemImm_F(src2),
11482 Pop_Reg_F(dst));
11483 ins_pipe( fpu_reg_reg_con );
11484 %}
11485
11486 // Spill to obtain 24-bit precision
11487 instruct mulF24_reg(stackSlotF dst, regF src1, regF src2) %{
11488 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11489 match(Set dst (MulF src1 src2));
11490
11491 format %{ "FLD $src1\n\t"
11492 "FMUL $src2\n\t"
11493 "FSTP_S $dst" %}
11494 opcode(0xD8, 0x1); /* D8 C8+i or D8 /1 ;; result in TOS */
11495 ins_encode( Push_Reg_F(src1),
11496 OpcReg_F(src2),
11497 Pop_Mem_F(dst) );
11498 ins_pipe( fpu_mem_reg_reg );
11499 %}
11500 //
11501 // This instruction does not round to 24-bits
11502 instruct mulF_reg(regF dst, regF src1, regF src2) %{
11503 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11542 OpcReg_F(src1),
11543 Pop_Reg_F(dst) );
11544 ins_pipe( fpu_reg_reg_mem );
11545 %}
11546
11547 // Spill to obtain 24-bit precision
11548 instruct mulF24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
11549 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11550 match(Set dst (MulF src1 src2));
11551
11552 format %{ "FMUL $dst,$src1,$src2" %}
11553 opcode(0xD8, 0x1, 0xD9); /* D8 /1 */ /* LoadF D9 /0 */
11554 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,src2),
11555 set_instruction_start,
11556 OpcP, RMopc_Mem(secondary,src1),
11557 Pop_Mem_F(dst) );
11558 ins_pipe( fpu_mem_mem_mem );
11559 %}
11560
11561 // Spill to obtain 24-bit precision
11562 instruct mulF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
11563 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11564 match(Set dst (MulF src1 src2));
11565
11566 format %{ "FMULc $dst,$src1,$src2" %}
11567 opcode(0xD8, 0x1); /* D8 /1*/
11568 ins_encode( Push_Reg_F(src1),
11569 Opc_MemImm_F(src2),
11570 Pop_Mem_F(dst));
11571 ins_pipe( fpu_mem_reg_con );
11572 %}
11573 //
11574 // This instruction does not round to 24-bits
11575 instruct mulF_reg_imm(regF dst, regF src1, immF src2) %{
11576 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11577 match(Set dst (MulF src1 src2));
11578
11579 format %{ "FMULc $dst. $src1, $src2" %}
11580 opcode(0xD8, 0x1); /* D8 /1*/
11581 ins_encode( Push_Reg_F(src1),
11582 Opc_MemImm_F(src2),
11583 Pop_Reg_F(dst));
11584 ins_pipe( fpu_reg_reg_con );
11585 %}
11586
11587
11588 //
11589 // MACRO1 -- subsume unshared load into mulF
11590 // This instruction does not round to 24-bits
11591 instruct mulF_reg_load1(regF dst, regF src, memory mem1 ) %{
11592 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11593 match(Set dst (MulF (LoadF mem1) src));
11594
11595 format %{ "FLD $mem1 ===MACRO1===\n\t"
11596 "FMUL ST,$src\n\t"
11597 "FSTP $dst" %}
11598 opcode(0xD8, 0x1, 0xD9); /* D8 C8+i or D8 /1 */ /* LoadF D9 /0 */
11599 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,mem1),
11600 OpcReg_F(src),
11601 Pop_Reg_F(dst) );
11602 ins_pipe( fpu_reg_reg_mem );
11603 %}
11604 //
12922 //%}
12923
12924 // Max Register with Register (generic version)
12925 instruct maxI_eReg(eRegI dst, eRegI src, eFlagsReg flags) %{
12926 match(Set dst (MaxI dst src));
12927 effect(KILL flags);
12928 ins_cost(300);
12929
12930 format %{ "MAX $dst,$src" %}
12931 opcode(0xCC);
12932 ins_encode( max_enc(dst,src) );
12933 ins_pipe( pipe_slow );
12934 %}
12935
12936 // ============================================================================
12937 // Branch Instructions
12938 // Jump Table
12939 instruct jumpXtnd(eRegI switch_val) %{
12940 match(Jump switch_val);
12941 ins_cost(350);
12942
12943 format %{ "JMP [table_base](,$switch_val,1)\n\t" %}
12944
12945 ins_encode %{
12946 address table_base = __ address_table_constant(_index2label);
12947
12948 // Jump to Address(table_base + switch_reg)
12949 InternalAddress table(table_base);
12950 Address index(noreg, $switch_val$$Register, Address::times_1);
12951 __ jump(ArrayAddress(table, index));
12952 %}
12953 ins_pc_relative(1);
12954 ins_pipe(pipe_jmp);
12955 %}
12956
12957 // Jump Direct - Label defines a relative address from JMP+1
12958 instruct jmpDir(label labl) %{
12959 match(Goto);
12960 effect(USE labl);
12961
12962 ins_cost(300);
12963 format %{ "JMP $labl" %}
12964 size(5);
12965 opcode(0xE9);
12966 ins_encode( OpcP, Lbl( labl ) );
12967 ins_pipe( pipe_jmp );
12968 ins_pc_relative(1);
12969 %}
12970
12971 // Jump Direct Conditional - Label defines a relative address from Jcc+1
|
490 if( dst_encoding == src_encoding ) {
491 // reg-reg copy, use an empty encoding
492 } else {
493 emit_opcode( cbuf, 0x8B );
494 emit_rm(cbuf, 0x3, dst_encoding, src_encoding );
495 }
496 }
497
498 void encode_CopyXD( CodeBuffer &cbuf, int dst_encoding, int src_encoding ) {
499 if( dst_encoding == src_encoding ) {
500 // reg-reg copy, use an empty encoding
501 } else {
502 MacroAssembler _masm(&cbuf);
503
504 __ movdqa(as_XMMRegister(dst_encoding), as_XMMRegister(src_encoding));
505 }
506 }
507
508
509 //=============================================================================
510 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
511
512 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
513 emit_constant_table(cbuf);
514 set_table_base_offset(0);
515 // Empty encoding
516 }
517
518 uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
519 // Compute the size (even if it's zero) since
520 // Compile::Shorten_branches needs the table to be emitted (which
521 // happens in Compile::scratch_emit_size) to calculate the size for
522 // MachConstantNode's.
523 return MachNode::size(ra_);
524 }
525
526 #ifndef PRODUCT
527 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
528 st->print("# MachConstantBaseNode (empty encoding)");
529 }
530 #endif
531
532
533 //=============================================================================
534 #ifndef PRODUCT
535 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
536 Compile* C = ra_->C;
537 if( C->in_24_bit_fp_mode() ) {
538 st->print("FLDCW 24 bit fpu control word");
539 st->print_cr(""); st->print("\t");
540 }
541
542 int framesize = C->frame_slots() << LogBytesPerInt;
543 assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
544 // Remove two words for return addr and rbp,
545 framesize -= 2*wordSize;
546
547 // Calls to C2R adapters often do not accept exceptional returns.
548 // We require that their callers must bang for them. But be careful, because
549 // some VM calls (such as call site linkage) can use several kilobytes of
550 // stack. But the stack safety zone should account for that.
551 // See bugs 4446381, 4468289, 4497237.
552 if (C->need_stack_bang(framesize)) {
553 st->print_cr("# stack bang"); st->print("\t");
1327 // Emit deopt handler code.
1328 int emit_deopt_handler(CodeBuffer& cbuf) {
1329
1330 // Note that the code buffer's insts_mark is always relative to insts.
1331 // That's why we must use the macroassembler to generate a handler.
1332 MacroAssembler _masm(&cbuf);
1333 address base =
1334 __ start_a_stub(size_exception_handler());
1335 if (base == NULL) return 0; // CodeBuffer::expand failed
1336 int offset = __ offset();
1337 InternalAddress here(__ pc());
1338 __ pushptr(here.addr());
1339
1340 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
1341 assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
1342 __ end_a_stub();
1343 return offset;
1344 }
1345
1346
1347 const bool Matcher::match_rule_supported(int opcode) {
1348 if (!has_match_rule(opcode))
1349 return false;
1350
1351 return true; // Per default match rules are supported.
1352 }
1353
1354 int Matcher::regnum_to_fpu_offset(int regnum) {
1355 return regnum - 32; // The FP registers are in the second chunk
1356 }
1357
1358 // This is UltraSparc specific, true just means we have fast l2f conversion
1359 const bool Matcher::convL2FSupported(void) {
1360 return true;
1361 }
1362
1363 // Vector width in bytes
1364 const uint Matcher::vector_width_in_bytes(void) {
1365 return UseSSE >= 2 ? 8 : 0;
1366 }
1367
1368 // Vector ideal reg
1369 const uint Matcher::vector_ideal_reg(void) {
1370 return Op_RegD;
1371 }
1372
1373 // Is this branch offset short enough that a short branch can be used?
1374 //
1375 // NOTE: If the platform does not provide any short branch variants, then
1376 // this method should return false for offset 0.
1377 bool Matcher::is_short_branch_offset(int rule, int offset) {
2004 emit_d32(cbuf, src_con);
2005 }
2006 %}
2007
2008 enc_class LdImmL_Hi( eRegL dst, immL src) %{ // Load Immediate
2009 // Load immediate does not have a zero or sign extended version
2010 // for 8-bit immediates
2011 int dst_enc = $dst$$reg + 2;
2012 int src_con = ((julong)($src$$constant)) >> 32;
2013 if (src_con == 0) {
2014 // xor dst, dst
2015 emit_opcode(cbuf, 0x33);
2016 emit_rm(cbuf, 0x3, dst_enc, dst_enc);
2017 } else {
2018 emit_opcode(cbuf, $primary + dst_enc);
2019 emit_d32(cbuf, src_con);
2020 }
2021 %}
2022
2023
2024 enc_class MovI2X_reg(regX dst, eRegI src) %{
2025 emit_opcode(cbuf, 0x66 ); // MOVD dst,src
2026 emit_opcode(cbuf, 0x0F );
2027 emit_opcode(cbuf, 0x6E );
2028 emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg);
2029 %}
2030
2031 enc_class MovX2I_reg(eRegI dst, regX src) %{
2032 emit_opcode(cbuf, 0x66 ); // MOVD dst,src
2033 emit_opcode(cbuf, 0x0F );
2034 emit_opcode(cbuf, 0x7E );
2035 emit_rm(cbuf, 0x3, $src$$reg, $dst$$reg);
2036 %}
2037
2038 enc_class MovL2XD_reg(regXD dst, eRegL src, regXD tmp) %{
2039 { // MOVD $dst,$src.lo
2040 emit_opcode(cbuf,0x66);
2041 emit_opcode(cbuf,0x0F);
2042 emit_opcode(cbuf,0x6E);
2043 emit_rm(cbuf, 0x3, $dst$$reg, $src$$reg);
4708 predicate(n->get_long() == (int)(n->get_long()));
4709 match(ConL);
4710 op_cost(20);
4711
4712 format %{ %}
4713 interface(CONST_INTER);
4714 %}
4715
4716 //Double Immediate zero
4717 operand immD0() %{
4718 // Do additional (and counter-intuitive) test against NaN to work around VC++
4719 // bug that generates code such that NaNs compare equal to 0.0
4720 predicate( UseSSE<=1 && n->getd() == 0.0 && !g_isnan(n->getd()) );
4721 match(ConD);
4722
4723 op_cost(5);
4724 format %{ %}
4725 interface(CONST_INTER);
4726 %}
4727
4728 // Double Immediate one
4729 operand immD1() %{
4730 predicate( UseSSE<=1 && n->getd() == 1.0 );
4731 match(ConD);
4732
4733 op_cost(5);
4734 format %{ %}
4735 interface(CONST_INTER);
4736 %}
4737
4738 // Double Immediate
4739 operand immD() %{
4740 predicate(UseSSE<=1);
4741 match(ConD);
4742
4743 op_cost(5);
4744 format %{ %}
4745 interface(CONST_INTER);
4746 %}
4747
4748 operand immXD() %{
4751
4752 op_cost(5);
4753 format %{ %}
4754 interface(CONST_INTER);
4755 %}
4756
4757 // Double Immediate zero
4758 operand immXD0() %{
4759 // Do additional (and counter-intuitive) test against NaN to work around VC++
4760 // bug that generates code such that NaNs compare equal to 0.0 AND do not
4761 // compare equal to -0.0.
4762 predicate( UseSSE>=2 && jlong_cast(n->getd()) == 0 );
4763 match(ConD);
4764
4765 format %{ %}
4766 interface(CONST_INTER);
4767 %}
4768
4769 // Float Immediate zero
4770 operand immF0() %{
4771 predicate(UseSSE == 0 && n->getf() == 0.0F);
4772 match(ConF);
4773
4774 op_cost(5);
4775 format %{ %}
4776 interface(CONST_INTER);
4777 %}
4778
4779 // Float Immediate one
4780 operand immF1() %{
4781 predicate(UseSSE == 0 && n->getf() == 1.0F);
4782 match(ConF);
4783
4784 op_cost(5);
4785 format %{ %}
4786 interface(CONST_INTER);
4787 %}
4788
4789 // Float Immediate
4790 operand immF() %{
4791 predicate( UseSSE == 0 );
4792 match(ConF);
4793
4794 op_cost(5);
4795 format %{ %}
4796 interface(CONST_INTER);
4797 %}
4798
4799 // Float Immediate
4800 operand immXF() %{
4801 predicate(UseSSE >= 1);
7132 ins_cost(200);
7133 format %{ "MOV $dst.lo,$src.lo\n\t"
7134 "MOV $dst.hi,$src.hi" %}
7135 opcode(0xB8);
7136 ins_encode( LdImmL_Lo(dst, src), LdImmL_Hi(dst, src) );
7137 ins_pipe( ialu_reg_long_fat );
7138 %}
7139
7140 instruct loadConL0(eRegL dst, immL0 src, eFlagsReg cr) %{
7141 match(Set dst src);
7142 effect(KILL cr);
7143 ins_cost(150);
7144 format %{ "XOR $dst.lo,$dst.lo\n\t"
7145 "XOR $dst.hi,$dst.hi" %}
7146 opcode(0x33,0x33);
7147 ins_encode( RegReg_Lo(dst,dst), RegReg_Hi(dst, dst) );
7148 ins_pipe( ialu_reg_long );
7149 %}
7150
7151 // The instruction usage is guarded by predicate in operand immF().
7152 instruct loadConF(regF dst, immF con) %{
7153 match(Set dst con);
7154 ins_cost(125);
7155 format %{ "FLD_S ST,[$constantaddress]\t# load from constant table: float=$con\n\t"
7156 "FSTP $dst" %}
7157 ins_encode %{
7158 __ fld_s($constantaddress($con));
7159 __ fstp_d($dst$$reg);
7160 %}
7161 ins_pipe(fpu_reg_con);
7162 %}
7163
7164 // The instruction usage is guarded by predicate in operand immF0().
7165 instruct loadConF0(regF dst, immF0 con) %{
7166 match(Set dst con);
7167 ins_cost(125);
7168 format %{ "FLDZ ST\n\t"
7169 "FSTP $dst" %}
7170 ins_encode %{
7171 __ fldz();
7172 __ fstp_d($dst$$reg);
7173 %}
7174 ins_pipe(fpu_reg_con);
7175 %}
7176
7177 // The instruction usage is guarded by predicate in operand immF1().
7178 instruct loadConF1(regF dst, immF1 con) %{
7179 match(Set dst con);
7180 ins_cost(125);
7181 format %{ "FLD1 ST\n\t"
7182 "FSTP $dst" %}
7183 ins_encode %{
7184 __ fld1();
7185 __ fstp_d($dst$$reg);
7186 %}
7187 ins_pipe(fpu_reg_con);
7188 %}
7189
7190 // The instruction usage is guarded by predicate in operand immXF().
7191 instruct loadConX(regX dst, immXF con) %{
7192 match(Set dst con);
7193 ins_cost(125);
7194 format %{ "MOVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
7195 ins_encode %{
7196 __ movflt($dst$$XMMRegister, $constantaddress($con));
7197 %}
7198 ins_pipe(pipe_slow);
7199 %}
7200
7201 // The instruction usage is guarded by predicate in operand immXF0().
7202 instruct loadConX0(regX dst, immXF0 src) %{
7203 match(Set dst src);
7204 ins_cost(100);
7205 format %{ "XORPS $dst,$dst\t# float 0.0" %}
7206 ins_encode %{
7207 __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
7208 %}
7209 ins_pipe(pipe_slow);
7210 %}
7211
7212 // The instruction usage is guarded by predicate in operand immD().
7213 instruct loadConD(regD dst, immD con) %{
7214 match(Set dst con);
7215 ins_cost(125);
7216
7217 format %{ "FLD_D ST,[$constantaddress]\t# load from constant table: double=$con\n\t"
7218 "FSTP $dst" %}
7219 ins_encode %{
7220 __ fld_d($constantaddress($con));
7221 __ fstp_d($dst$$reg);
7222 %}
7223 ins_pipe(fpu_reg_con);
7224 %}
7225
7226 // The instruction usage is guarded by predicate in operand immD0().
7227 instruct loadConD0(regD dst, immD0 con) %{
7228 match(Set dst con);
7229 ins_cost(125);
7230
7231 format %{ "FLDZ ST\n\t"
7232 "FSTP $dst" %}
7233 ins_encode %{
7234 __ fldz();
7235 __ fstp_d($dst$$reg);
7236 %}
7237 ins_pipe(fpu_reg_con);
7238 %}
7239
7240 // The instruction usage is guarded by predicate in operand immD1().
7241 instruct loadConD1(regD dst, immD1 con) %{
7242 match(Set dst con);
7243 ins_cost(125);
7244
7245 format %{ "FLD1 ST\n\t"
7246 "FSTP $dst" %}
7247 ins_encode %{
7248 __ fld1();
7249 __ fstp_d($dst$$reg);
7250 %}
7251 ins_pipe(fpu_reg_con);
7252 %}
7253
7254 // The instruction usage is guarded by predicate in operand immXD().
7255 instruct loadConXD(regXD dst, immXD con) %{
7256 match(Set dst con);
7257 ins_cost(125);
7258 format %{ "MOVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
7259 ins_encode %{
7260 __ movdbl($dst$$XMMRegister, $constantaddress($con));
7261 %}
7262 ins_pipe(pipe_slow);
7263 %}
7264
7265 // The instruction usage is guarded by predicate in operand immXD0().
7266 instruct loadConXD0(regXD dst, immXD0 src) %{
7267 match(Set dst src);
7268 ins_cost(100);
7269 format %{ "XORPD $dst,$dst\t# double 0.0" %}
7270 ins_encode( Opcode(0x66), Opcode(0x0F), Opcode(0x57), RegReg(dst,dst));
7271 ins_pipe( pipe_slow );
7272 %}
7273
7274 // Load Stack Slot
7275 instruct loadSSI(eRegI dst, stackSlotI src) %{
7276 match(Set dst src);
7277 ins_cost(125);
7278
7279 format %{ "MOV $dst,$src" %}
7280 opcode(0x8B);
7281 ins_encode( OpcP, RegMem(dst,src));
7282 ins_pipe( ialu_reg_mem );
10284 ins_pipe( fpu_reg_mem );
10285 %}
10286
10287 // add-to-memory
10288 instruct addD_mem_reg(memory dst, regD src) %{
10289 predicate(UseSSE<=1);
10290 match(Set dst (StoreD dst (RoundDouble (AddD (LoadD dst) src))));
10291 ins_cost(150);
10292
10293 format %{ "FLD_D $dst\n\t"
10294 "DADD ST,$src\n\t"
10295 "FST_D $dst" %}
10296 opcode(0xDD, 0x0);
10297 ins_encode( Opcode(0xDD), RMopc_Mem(0x00,dst),
10298 Opcode(0xD8), RegOpc(src),
10299 set_instruction_start,
10300 Opcode(0xDD), RMopc_Mem(0x03,dst) );
10301 ins_pipe( fpu_reg_mem );
10302 %}
10303
10304 instruct addD_reg_imm1(regD dst, immD1 con) %{
10305 predicate(UseSSE<=1);
10306 match(Set dst (AddD dst con));
10307 ins_cost(125);
10308 format %{ "FLD1\n\t"
10309 "DADDp $dst,ST" %}
10310 ins_encode %{
10311 __ fld1();
10312 __ faddp($dst$$reg);
10313 %}
10314 ins_pipe(fpu_reg);
10315 %}
10316
10317 instruct addD_reg_imm(regD dst, immD con) %{
10318 predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
10319 match(Set dst (AddD dst con));
10320 ins_cost(200);
10321 format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
10322 "DADDp $dst,ST" %}
10323 ins_encode %{
10324 __ fld_d($constantaddress($con));
10325 __ faddp($dst$$reg);
10326 %}
10327 ins_pipe(fpu_reg_mem);
10328 %}
10329
10330 instruct addD_reg_imm_round(stackSlotD dst, regD src, immD con) %{
10331 predicate(UseSSE<=1 && _kids[0]->_kids[1]->_leaf->getd() != 0.0 && _kids[0]->_kids[1]->_leaf->getd() != 1.0 );
10332 match(Set dst (RoundDouble (AddD src con)));
10333 ins_cost(200);
10334 format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
10335 "DADD ST,$src\n\t"
10336 "FSTP_D $dst\t# D-round" %}
10337 ins_encode %{
10338 __ fld_d($constantaddress($con));
10339 __ fadd($src$$reg);
10340 __ fstp_d(Address(rsp, $dst$$disp));
10341 %}
10342 ins_pipe(fpu_mem_reg_con);
10343 %}
10344
10345 // Add two double precision floating point values in xmm
10346 instruct addXD_reg(regXD dst, regXD src) %{
10347 predicate(UseSSE>=2);
10348 match(Set dst (AddD dst src));
10349 format %{ "ADDSD $dst,$src" %}
10350 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), RegReg(dst, src));
10351 ins_pipe( pipe_slow );
10352 %}
10353
10354 instruct addXD_imm(regXD dst, immXD con) %{
10355 predicate(UseSSE>=2);
10356 match(Set dst (AddD dst con));
10357 format %{ "ADDSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
10358 ins_encode %{
10359 __ addsd($dst$$XMMRegister, $constantaddress($con));
10360 %}
10361 ins_pipe(pipe_slow);
10362 %}
10363
10364 instruct addXD_mem(regXD dst, memory mem) %{
10365 predicate(UseSSE>=2);
10366 match(Set dst (AddD dst (LoadD mem)));
10367 format %{ "ADDSD $dst,$mem" %}
10368 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), RegMem(dst,mem));
10369 ins_pipe( pipe_slow );
10370 %}
10371
10372 // Sub two double precision floating point values in xmm
10373 instruct subXD_reg(regXD dst, regXD src) %{
10374 predicate(UseSSE>=2);
10375 match(Set dst (SubD dst src));
10376 format %{ "SUBSD $dst,$src" %}
10377 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), RegReg(dst, src));
10378 ins_pipe( pipe_slow );
10379 %}
10380
10381 instruct subXD_imm(regXD dst, immXD con) %{
10382 predicate(UseSSE>=2);
10383 match(Set dst (SubD dst con));
10384 format %{ "SUBSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
10385 ins_encode %{
10386 __ subsd($dst$$XMMRegister, $constantaddress($con));
10387 %}
10388 ins_pipe(pipe_slow);
10389 %}
10390
10391 instruct subXD_mem(regXD dst, memory mem) %{
10392 predicate(UseSSE>=2);
10393 match(Set dst (SubD dst (LoadD mem)));
10394 format %{ "SUBSD $dst,$mem" %}
10395 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), RegMem(dst,mem));
10396 ins_pipe( pipe_slow );
10397 %}
10398
10399 // Mul two double precision floating point values in xmm
10400 instruct mulXD_reg(regXD dst, regXD src) %{
10401 predicate(UseSSE>=2);
10402 match(Set dst (MulD dst src));
10403 format %{ "MULSD $dst,$src" %}
10404 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), RegReg(dst, src));
10405 ins_pipe( pipe_slow );
10406 %}
10407
10408 instruct mulXD_imm(regXD dst, immXD con) %{
10409 predicate(UseSSE>=2);
10410 match(Set dst (MulD dst con));
10411 format %{ "MULSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
10412 ins_encode %{
10413 __ mulsd($dst$$XMMRegister, $constantaddress($con));
10414 %}
10415 ins_pipe(pipe_slow);
10416 %}
10417
10418 instruct mulXD_mem(regXD dst, memory mem) %{
10419 predicate(UseSSE>=2);
10420 match(Set dst (MulD dst (LoadD mem)));
10421 format %{ "MULSD $dst,$mem" %}
10422 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), RegMem(dst,mem));
10423 ins_pipe( pipe_slow );
10424 %}
10425
10426 // Div two double precision floating point values in xmm
10427 instruct divXD_reg(regXD dst, regXD src) %{
10428 predicate(UseSSE>=2);
10429 match(Set dst (DivD dst src));
10430 format %{ "DIVSD $dst,$src" %}
10431 opcode(0xF2, 0x0F, 0x5E);
10432 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), RegReg(dst, src));
10433 ins_pipe( pipe_slow );
10434 %}
10435
10436 instruct divXD_imm(regXD dst, immXD con) %{
10437 predicate(UseSSE>=2);
10438 match(Set dst (DivD dst con));
10439 format %{ "DIVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
10440 ins_encode %{
10441 __ divsd($dst$$XMMRegister, $constantaddress($con));
10442 %}
10443 ins_pipe(pipe_slow);
10444 %}
10445
10446 instruct divXD_mem(regXD dst, memory mem) %{
10447 predicate(UseSSE>=2);
10448 match(Set dst (DivD dst (LoadD mem)));
10449 format %{ "DIVSD $dst,$mem" %}
10450 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), RegMem(dst,mem));
10451 ins_pipe( pipe_slow );
10452 %}
10453
10454
10455 instruct mulD_reg(regD dst, regD src) %{
10456 predicate(UseSSE<=1);
10457 match(Set dst (MulD dst src));
10458 format %{ "FLD $src\n\t"
10459 "DMULp $dst,ST" %}
10460 opcode(0xDE, 0x1); /* DE C8+i or DE /1*/
10461 ins_cost(150);
10462 ins_encode( Push_Reg_D(src),
10463 OpcP, RegOpc(dst) );
10474 //
10475 instruct strictfp_mulD_reg(regDPR1 dst, regnotDPR1 src) %{
10476 predicate( UseSSE<=1 && Compile::current()->has_method() && Compile::current()->method()->is_strict() );
10477 match(Set dst (MulD dst src));
10478 ins_cost(1); // Select this instruction for all strict FP double multiplies
10479
10480 format %{ "FLD StubRoutines::_fpu_subnormal_bias1\n\t"
10481 "DMULp $dst,ST\n\t"
10482 "FLD $src\n\t"
10483 "DMULp $dst,ST\n\t"
10484 "FLD StubRoutines::_fpu_subnormal_bias2\n\t"
10485 "DMULp $dst,ST\n\t" %}
10486 opcode(0xDE, 0x1); /* DE C8+i or DE /1*/
10487 ins_encode( strictfp_bias1(dst),
10488 Push_Reg_D(src),
10489 OpcP, RegOpc(dst),
10490 strictfp_bias2(dst) );
10491 ins_pipe( fpu_reg_reg );
10492 %}
10493
10494 instruct mulD_reg_imm(regD dst, immD con) %{
10495 predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
10496 match(Set dst (MulD dst con));
10497 ins_cost(200);
10498 format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
10499 "DMULp $dst,ST" %}
10500 ins_encode %{
10501 __ fld_d($constantaddress($con));
10502 __ fmulp($dst$$reg);
10503 %}
10504 ins_pipe(fpu_reg_mem);
10505 %}
10506
10507
10508 instruct mulD_reg_mem(regD dst, memory src) %{
10509 predicate( UseSSE<=1 );
10510 match(Set dst (MulD dst (LoadD src)));
10511 ins_cost(200);
10512 format %{ "FLD_D $src\n\t"
10513 "DMULp $dst,ST" %}
10514 opcode(0xDE, 0x1, 0xDD); /* DE C8+i or DE /1*/ /* LoadD DD /0 */
10515 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,src),
10516 OpcP, RegOpc(dst) );
10517 ins_pipe( fpu_reg_mem );
10518 %}
10519
10520 //
10521 // Cisc-alternate to reg-reg multiply
10522 instruct mulD_reg_mem_cisc(regD dst, regD src, memory mem) %{
10523 predicate( UseSSE<=1 );
10524 match(Set dst (MulD src (LoadD mem)));
11218 format %{ "FLD $src\n\t"
11219 "FADDp $dst,ST" %}
11220 opcode(0xDE, 0x0); /* DE C0+i or DE /0*/
11221 ins_encode( Push_Reg_F(src),
11222 OpcP, RegOpc(dst) );
11223 ins_pipe( fpu_reg_reg );
11224 %}
11225
11226 // Add two single precision floating point values in xmm
11227 instruct addX_reg(regX dst, regX src) %{
11228 predicate(UseSSE>=1);
11229 match(Set dst (AddF dst src));
11230 format %{ "ADDSS $dst,$src" %}
11231 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), RegReg(dst, src));
11232 ins_pipe( pipe_slow );
11233 %}
11234
11235 instruct addX_imm(regX dst, immXF con) %{
11236 predicate(UseSSE>=1);
11237 match(Set dst (AddF dst con));
11238 format %{ "ADDSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
11239 ins_encode %{
11240 __ addss($dst$$XMMRegister, $constantaddress($con));
11241 %}
11242 ins_pipe(pipe_slow);
11243 %}
11244
11245 instruct addX_mem(regX dst, memory mem) %{
11246 predicate(UseSSE>=1);
11247 match(Set dst (AddF dst (LoadF mem)));
11248 format %{ "ADDSS $dst,$mem" %}
11249 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), RegMem(dst, mem));
11250 ins_pipe( pipe_slow );
11251 %}
11252
11253 // Subtract two single precision floating point values in xmm
11254 instruct subX_reg(regX dst, regX src) %{
11255 predicate(UseSSE>=1);
11256 match(Set dst (SubF dst src));
11257 format %{ "SUBSS $dst,$src" %}
11258 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), RegReg(dst, src));
11259 ins_pipe( pipe_slow );
11260 %}
11261
11262 instruct subX_imm(regX dst, immXF con) %{
11263 predicate(UseSSE>=1);
11264 match(Set dst (SubF dst con));
11265 format %{ "SUBSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
11266 ins_encode %{
11267 __ subss($dst$$XMMRegister, $constantaddress($con));
11268 %}
11269 ins_pipe(pipe_slow);
11270 %}
11271
11272 instruct subX_mem(regX dst, memory mem) %{
11273 predicate(UseSSE>=1);
11274 match(Set dst (SubF dst (LoadF mem)));
11275 format %{ "SUBSS $dst,$mem" %}
11276 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), RegMem(dst,mem));
11277 ins_pipe( pipe_slow );
11278 %}
11279
11280 // Multiply two single precision floating point values in xmm
11281 instruct mulX_reg(regX dst, regX src) %{
11282 predicate(UseSSE>=1);
11283 match(Set dst (MulF dst src));
11284 format %{ "MULSS $dst,$src" %}
11285 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), RegReg(dst, src));
11286 ins_pipe( pipe_slow );
11287 %}
11288
11289 instruct mulX_imm(regX dst, immXF con) %{
11290 predicate(UseSSE>=1);
11291 match(Set dst (MulF dst con));
11292 format %{ "MULSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
11293 ins_encode %{
11294 __ mulss($dst$$XMMRegister, $constantaddress($con));
11295 %}
11296 ins_pipe(pipe_slow);
11297 %}
11298
11299 instruct mulX_mem(regX dst, memory mem) %{
11300 predicate(UseSSE>=1);
11301 match(Set dst (MulF dst (LoadF mem)));
11302 format %{ "MULSS $dst,$mem" %}
11303 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), RegMem(dst,mem));
11304 ins_pipe( pipe_slow );
11305 %}
11306
11307 // Divide two single precision floating point values in xmm
11308 instruct divX_reg(regX dst, regX src) %{
11309 predicate(UseSSE>=1);
11310 match(Set dst (DivF dst src));
11311 format %{ "DIVSS $dst,$src" %}
11312 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), RegReg(dst, src));
11313 ins_pipe( pipe_slow );
11314 %}
11315
11316 instruct divX_imm(regX dst, immXF con) %{
11317 predicate(UseSSE>=1);
11318 match(Set dst (DivF dst con));
11319 format %{ "DIVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
11320 ins_encode %{
11321 __ divss($dst$$XMMRegister, $constantaddress($con));
11322 %}
11323 ins_pipe(pipe_slow);
11324 %}
11325
11326 instruct divX_mem(regX dst, memory mem) %{
11327 predicate(UseSSE>=1);
11328 match(Set dst (DivF dst (LoadF mem)));
11329 format %{ "DIVSS $dst,$mem" %}
11330 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), RegMem(dst,mem));
11331 ins_pipe( pipe_slow );
11332 %}
11333
11334 // Get the square root of a single precision floating point values in xmm
11335 instruct sqrtX_reg(regX dst, regX src) %{
11336 predicate(UseSSE>=1);
11337 match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
11338 format %{ "SQRTSS $dst,$src" %}
11339 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x51), RegReg(dst, src));
11340 ins_pipe( pipe_slow );
11341 %}
11342
11343 instruct sqrtX_mem(regX dst, memory mem) %{
11458 Pop_Mem_F(dst) );
11459 ins_pipe( fpu_mem_mem_mem );
11460 %}
11461
11462 // Spill to obtain 24-bit precision
11463 instruct addF24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
11464 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11465 match(Set dst (AddF src1 src2));
11466
11467 format %{ "FADD $dst,$src1,$src2" %}
11468 opcode(0xD8, 0x0, 0xD9); /* D8 /0 */ /* LoadF D9 /0 */
11469 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,src2),
11470 set_instruction_start,
11471 OpcP, RMopc_Mem(secondary,src1),
11472 Pop_Mem_F(dst) );
11473 ins_pipe( fpu_mem_mem_mem );
11474 %}
11475
11476
11477 // Spill to obtain 24-bit precision
11478 instruct addF24_reg_imm(stackSlotF dst, regF src, immF con) %{
11479 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11480 match(Set dst (AddF src con));
11481 format %{ "FLD $src\n\t"
11482 "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
11483 "FSTP_S $dst" %}
11484 ins_encode %{
11485 __ fld_s($src$$reg - 1); // FLD ST(i-1)
11486 __ fadd_s($constantaddress($con));
11487 __ fstp_s(Address(rsp, $dst$$disp));
11488 %}
11489 ins_pipe(fpu_mem_reg_con);
11490 %}
11491 //
11492 // This instruction does not round to 24-bits
11493 instruct addF_reg_imm(regF dst, regF src, immF con) %{
11494 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11495 match(Set dst (AddF src con));
11496 format %{ "FLD $src\n\t"
11497 "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
11498 "FSTP $dst" %}
11499 ins_encode %{
11500 __ fld_s($src$$reg - 1); // FLD ST(i-1)
11501 __ fadd_s($constantaddress($con));
11502 __ fstp_d($dst$$reg);
11503 %}
11504 ins_pipe(fpu_reg_reg_con);
11505 %}
11506
11507 // Spill to obtain 24-bit precision
11508 instruct mulF24_reg(stackSlotF dst, regF src1, regF src2) %{
11509 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11510 match(Set dst (MulF src1 src2));
11511
11512 format %{ "FLD $src1\n\t"
11513 "FMUL $src2\n\t"
11514 "FSTP_S $dst" %}
11515 opcode(0xD8, 0x1); /* D8 C8+i or D8 /1 ;; result in TOS */
11516 ins_encode( Push_Reg_F(src1),
11517 OpcReg_F(src2),
11518 Pop_Mem_F(dst) );
11519 ins_pipe( fpu_mem_reg_reg );
11520 %}
11521 //
11522 // This instruction does not round to 24-bits
11523 instruct mulF_reg(regF dst, regF src1, regF src2) %{
11524 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11563 OpcReg_F(src1),
11564 Pop_Reg_F(dst) );
11565 ins_pipe( fpu_reg_reg_mem );
11566 %}
11567
11568 // Spill to obtain 24-bit precision
11569 instruct mulF24_mem_mem(stackSlotF dst, memory src1, memory src2) %{
11570 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11571 match(Set dst (MulF src1 src2));
11572
11573 format %{ "FMUL $dst,$src1,$src2" %}
11574 opcode(0xD8, 0x1, 0xD9); /* D8 /1 */ /* LoadF D9 /0 */
11575 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,src2),
11576 set_instruction_start,
11577 OpcP, RMopc_Mem(secondary,src1),
11578 Pop_Mem_F(dst) );
11579 ins_pipe( fpu_mem_mem_mem );
11580 %}
11581
11582 // Spill to obtain 24-bit precision
11583 instruct mulF24_reg_imm(stackSlotF dst, regF src, immF con) %{
11584 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
11585 match(Set dst (MulF src con));
11586
11587 format %{ "FLD $src\n\t"
11588 "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
11589 "FSTP_S $dst" %}
11590 ins_encode %{
11591 __ fld_s($src$$reg - 1); // FLD ST(i-1)
11592 __ fmul_s($constantaddress($con));
11593 __ fstp_s(Address(rsp, $dst$$disp));
11594 %}
11595 ins_pipe(fpu_mem_reg_con);
11596 %}
11597 //
11598 // This instruction does not round to 24-bits
11599 instruct mulF_reg_imm(regF dst, regF src, immF con) %{
11600 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11601 match(Set dst (MulF src con));
11602
11603 format %{ "FLD $src\n\t"
11604 "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
11605 "FSTP $dst" %}
11606 ins_encode %{
11607 __ fld_s($src$$reg - 1); // FLD ST(i-1)
11608 __ fmul_s($constantaddress($con));
11609 __ fstp_d($dst$$reg);
11610 %}
11611 ins_pipe(fpu_reg_reg_con);
11612 %}
11613
11614
11615 //
11616 // MACRO1 -- subsume unshared load into mulF
11617 // This instruction does not round to 24-bits
11618 instruct mulF_reg_load1(regF dst, regF src, memory mem1 ) %{
11619 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
11620 match(Set dst (MulF (LoadF mem1) src));
11621
11622 format %{ "FLD $mem1 ===MACRO1===\n\t"
11623 "FMUL ST,$src\n\t"
11624 "FSTP $dst" %}
11625 opcode(0xD8, 0x1, 0xD9); /* D8 C8+i or D8 /1 */ /* LoadF D9 /0 */
11626 ins_encode( Opcode(tertiary), RMopc_Mem(0x00,mem1),
11627 OpcReg_F(src),
11628 Pop_Reg_F(dst) );
11629 ins_pipe( fpu_reg_reg_mem );
11630 %}
11631 //
12949 //%}
12950
12951 // Max Register with Register (generic version)
12952 instruct maxI_eReg(eRegI dst, eRegI src, eFlagsReg flags) %{
12953 match(Set dst (MaxI dst src));
12954 effect(KILL flags);
12955 ins_cost(300);
12956
12957 format %{ "MAX $dst,$src" %}
12958 opcode(0xCC);
12959 ins_encode( max_enc(dst,src) );
12960 ins_pipe( pipe_slow );
12961 %}
12962
12963 // ============================================================================
12964 // Branch Instructions
12965 // Jump Table
12966 instruct jumpXtnd(eRegI switch_val) %{
12967 match(Jump switch_val);
12968 ins_cost(350);
12969 format %{ "JMP [$constantaddress](,$switch_val,1)\n\t" %}
12970 ins_encode %{
12971 // Jump to Address(table_base + switch_reg)
12972 Address index(noreg, $switch_val$$Register, Address::times_1);
12973 __ jump(ArrayAddress($constantaddress, index));
12974 %}
12975 ins_pc_relative(1);
12976 ins_pipe(pipe_jmp);
12977 %}
12978
12979 // Jump Direct - Label defines a relative address from JMP+1
12980 instruct jmpDir(label labl) %{
12981 match(Goto);
12982 effect(USE labl);
12983
12984 ins_cost(300);
12985 format %{ "JMP $labl" %}
12986 size(5);
12987 opcode(0xE9);
12988 ins_encode( OpcP, Lbl( labl ) );
12989 ins_pipe( pipe_jmp );
12990 ins_pc_relative(1);
12991 %}
12992
12993 // Jump Direct Conditional - Label defines a relative address from Jcc+1
|