Mercurial > hg > graal-compiler
comparison src/cpu/x86/vm/x86_32.ad @ 2008:2f644f85485d
6961690: load oops from constant table on SPARC
Summary: oops should be loaded from the constant table of an nmethod instead of materializing them with a long code sequence.
Reviewed-by: never, kvn
author | twisti |
---|---|
date | Fri, 03 Dec 2010 01:34:31 -0800 |
parents | 2fe998383789 |
children | 6bbaedb03534 |
comparison
equal
deleted
inserted
replaced
2007:5ddfcf4b079e | 2008:2f644f85485d |
---|---|
505 } | 505 } |
506 } | 506 } |
507 | 507 |
508 | 508 |
509 //============================================================================= | 509 //============================================================================= |
510 const bool Matcher::constant_table_absolute_addressing = true; | |
511 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; | |
512 | |
513 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { | |
514 // Empty encoding | |
515 } | |
516 | |
517 uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const { | |
518 return 0; | |
519 } | |
520 | |
521 #ifndef PRODUCT | |
522 void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const { | |
523 st->print("# MachConstantBaseNode (empty encoding)"); | |
524 } | |
525 #endif | |
526 | |
527 | |
528 //============================================================================= | |
510 #ifndef PRODUCT | 529 #ifndef PRODUCT |
511 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { | 530 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { |
512 Compile* C = ra_->C; | 531 Compile* C = ra_->C; |
513 if( C->in_24_bit_fp_mode() ) { | 532 if( C->in_24_bit_fp_mode() ) { |
514 st->print("FLDCW 24 bit fpu control word"); | 533 st->print("FLDCW 24 bit fpu control word"); |
1318 __ end_a_stub(); | 1337 __ end_a_stub(); |
1319 return offset; | 1338 return offset; |
1320 } | 1339 } |
1321 | 1340 |
1322 | 1341 |
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) { | 1342 const bool Matcher::match_rule_supported(int opcode) { |
1347 if (!has_match_rule(opcode)) | 1343 if (!has_match_rule(opcode)) |
1348 return false; | 1344 return false; |
1349 | 1345 |
1350 return true; // Per default match rules are supported. | 1346 return true; // Per default match rules are supported. |
1351 } | 1347 } |
1352 | 1348 |
1353 int Matcher::regnum_to_fpu_offset(int regnum) { | 1349 int Matcher::regnum_to_fpu_offset(int regnum) { |
1354 return regnum - 32; // The FP registers are in the second chunk | 1350 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 } | 1351 } |
1372 | 1352 |
1373 // This is UltraSparc specific, true just means we have fast l2f conversion | 1353 // This is UltraSparc specific, true just means we have fast l2f conversion |
1374 const bool Matcher::convL2FSupported(void) { | 1354 const bool Matcher::convL2FSupported(void) { |
1375 return true; | 1355 return true; |
2031 emit_rm(cbuf, 0x3, dst_enc, dst_enc); | 2011 emit_rm(cbuf, 0x3, dst_enc, dst_enc); |
2032 } else { | 2012 } else { |
2033 emit_opcode(cbuf, $primary + dst_enc); | 2013 emit_opcode(cbuf, $primary + dst_enc); |
2034 emit_d32(cbuf, src_con); | 2014 emit_d32(cbuf, src_con); |
2035 } | 2015 } |
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 %} | 2016 %} |
2098 | 2017 |
2099 | 2018 |
2100 enc_class MovI2X_reg(regX dst, eRegI src) %{ | 2019 enc_class MovI2X_reg(regX dst, eRegI src) %{ |
2101 emit_opcode(cbuf, 0x66 ); // MOVD dst,src | 2020 emit_opcode(cbuf, 0x66 ); // MOVD dst,src |
4799 op_cost(5); | 4718 op_cost(5); |
4800 format %{ %} | 4719 format %{ %} |
4801 interface(CONST_INTER); | 4720 interface(CONST_INTER); |
4802 %} | 4721 %} |
4803 | 4722 |
4804 // Double Immediate | 4723 // Double Immediate one |
4805 operand immD1() %{ | 4724 operand immD1() %{ |
4806 predicate( UseSSE<=1 && n->getd() == 1.0 ); | 4725 predicate( UseSSE<=1 && n->getd() == 1.0 ); |
4807 match(ConD); | 4726 match(ConD); |
4808 | 4727 |
4809 op_cost(5); | 4728 op_cost(5); |
4842 interface(CONST_INTER); | 4761 interface(CONST_INTER); |
4843 %} | 4762 %} |
4844 | 4763 |
4845 // Float Immediate zero | 4764 // Float Immediate zero |
4846 operand immF0() %{ | 4765 operand immF0() %{ |
4847 predicate( UseSSE == 0 && n->getf() == 0.0 ); | 4766 predicate(UseSSE == 0 && n->getf() == 0.0F); |
4767 match(ConF); | |
4768 | |
4769 op_cost(5); | |
4770 format %{ %} | |
4771 interface(CONST_INTER); | |
4772 %} | |
4773 | |
4774 // Float Immediate one | |
4775 operand immF1() %{ | |
4776 predicate(UseSSE == 0 && n->getf() == 1.0F); | |
4848 match(ConF); | 4777 match(ConF); |
4849 | 4778 |
4850 op_cost(5); | 4779 op_cost(5); |
4851 format %{ %} | 4780 format %{ %} |
4852 interface(CONST_INTER); | 4781 interface(CONST_INTER); |
7213 ins_encode( RegReg_Lo(dst,dst), RegReg_Hi(dst, dst) ); | 7142 ins_encode( RegReg_Lo(dst,dst), RegReg_Hi(dst, dst) ); |
7214 ins_pipe( ialu_reg_long ); | 7143 ins_pipe( ialu_reg_long ); |
7215 %} | 7144 %} |
7216 | 7145 |
7217 // The instruction usage is guarded by predicate in operand immF(). | 7146 // The instruction usage is guarded by predicate in operand immF(). |
7218 instruct loadConF(regF dst, immF src) %{ | 7147 instruct loadConF(regF dst, immF con) %{ |
7219 match(Set dst src); | 7148 match(Set dst con); |
7220 ins_cost(125); | 7149 ins_cost(125); |
7221 | 7150 format %{ "FLD_S ST,[$constantaddress]\t# load from constant table: float=$con\n\t" |
7222 format %{ "FLD_S ST,$src\n\t" | |
7223 "FSTP $dst" %} | 7151 "FSTP $dst" %} |
7224 opcode(0xD9, 0x00); /* D9 /0 */ | 7152 ins_encode %{ |
7225 ins_encode(LdImmF(src), Pop_Reg_F(dst) ); | 7153 __ fld_s($constantaddress($con)); |
7226 ins_pipe( fpu_reg_con ); | 7154 __ fstp_d($dst$$reg); |
7155 %} | |
7156 ins_pipe(fpu_reg_con); | |
7157 %} | |
7158 | |
7159 // The instruction usage is guarded by predicate in operand immF0(). | |
7160 instruct loadConF0(regF dst, immF0 con) %{ | |
7161 match(Set dst con); | |
7162 ins_cost(125); | |
7163 format %{ "FLDZ ST\n\t" | |
7164 "FSTP $dst" %} | |
7165 ins_encode %{ | |
7166 __ fldz(); | |
7167 __ fstp_d($dst$$reg); | |
7168 %} | |
7169 ins_pipe(fpu_reg_con); | |
7170 %} | |
7171 | |
7172 // The instruction usage is guarded by predicate in operand immF1(). | |
7173 instruct loadConF1(regF dst, immF1 con) %{ | |
7174 match(Set dst con); | |
7175 ins_cost(125); | |
7176 format %{ "FLD1 ST\n\t" | |
7177 "FSTP $dst" %} | |
7178 ins_encode %{ | |
7179 __ fld1(); | |
7180 __ fstp_d($dst$$reg); | |
7181 %} | |
7182 ins_pipe(fpu_reg_con); | |
7227 %} | 7183 %} |
7228 | 7184 |
7229 // The instruction usage is guarded by predicate in operand immXF(). | 7185 // The instruction usage is guarded by predicate in operand immXF(). |
7230 instruct loadConX(regX dst, immXF con) %{ | 7186 instruct loadConX(regX dst, immXF con) %{ |
7231 match(Set dst con); | 7187 match(Set dst con); |
7232 ins_cost(125); | 7188 ins_cost(125); |
7233 format %{ "MOVSS $dst,[$con]" %} | 7189 format %{ "MOVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} |
7234 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), LdImmX(dst, con)); | 7190 ins_encode %{ |
7235 ins_pipe( pipe_slow ); | 7191 __ movflt($dst$$XMMRegister, $constantaddress($con)); |
7192 %} | |
7193 ins_pipe(pipe_slow); | |
7236 %} | 7194 %} |
7237 | 7195 |
7238 // The instruction usage is guarded by predicate in operand immXF0(). | 7196 // The instruction usage is guarded by predicate in operand immXF0(). |
7239 instruct loadConX0(regX dst, immXF0 src) %{ | 7197 instruct loadConX0(regX dst, immXF0 src) %{ |
7240 match(Set dst src); | 7198 match(Set dst src); |
7241 ins_cost(100); | 7199 ins_cost(100); |
7242 format %{ "XORPS $dst,$dst\t# float 0.0" %} | 7200 format %{ "XORPS $dst,$dst\t# float 0.0" %} |
7243 ins_encode( Opcode(0x0F), Opcode(0x57), RegReg(dst,dst)); | 7201 ins_encode %{ |
7244 ins_pipe( pipe_slow ); | 7202 __ xorps($dst$$XMMRegister, $dst$$XMMRegister); |
7203 %} | |
7204 ins_pipe(pipe_slow); | |
7245 %} | 7205 %} |
7246 | 7206 |
7247 // The instruction usage is guarded by predicate in operand immD(). | 7207 // The instruction usage is guarded by predicate in operand immD(). |
7248 instruct loadConD(regD dst, immD src) %{ | 7208 instruct loadConD(regD dst, immD con) %{ |
7249 match(Set dst src); | 7209 match(Set dst con); |
7250 ins_cost(125); | 7210 ins_cost(125); |
7251 | 7211 |
7252 format %{ "FLD_D ST,$src\n\t" | 7212 format %{ "FLD_D ST,[$constantaddress]\t# load from constant table: double=$con\n\t" |
7253 "FSTP $dst" %} | 7213 "FSTP $dst" %} |
7254 ins_encode(LdImmD(src), Pop_Reg_D(dst) ); | 7214 ins_encode %{ |
7255 ins_pipe( fpu_reg_con ); | 7215 __ fld_d($constantaddress($con)); |
7216 __ fstp_d($dst$$reg); | |
7217 %} | |
7218 ins_pipe(fpu_reg_con); | |
7219 %} | |
7220 | |
7221 // The instruction usage is guarded by predicate in operand immD0(). | |
7222 instruct loadConD0(regD dst, immD0 con) %{ | |
7223 match(Set dst con); | |
7224 ins_cost(125); | |
7225 | |
7226 format %{ "FLDZ ST\n\t" | |
7227 "FSTP $dst" %} | |
7228 ins_encode %{ | |
7229 __ fldz(); | |
7230 __ fstp_d($dst$$reg); | |
7231 %} | |
7232 ins_pipe(fpu_reg_con); | |
7233 %} | |
7234 | |
7235 // The instruction usage is guarded by predicate in operand immD1(). | |
7236 instruct loadConD1(regD dst, immD1 con) %{ | |
7237 match(Set dst con); | |
7238 ins_cost(125); | |
7239 | |
7240 format %{ "FLD1 ST\n\t" | |
7241 "FSTP $dst" %} | |
7242 ins_encode %{ | |
7243 __ fld1(); | |
7244 __ fstp_d($dst$$reg); | |
7245 %} | |
7246 ins_pipe(fpu_reg_con); | |
7256 %} | 7247 %} |
7257 | 7248 |
7258 // The instruction usage is guarded by predicate in operand immXD(). | 7249 // The instruction usage is guarded by predicate in operand immXD(). |
7259 instruct loadConXD(regXD dst, immXD con) %{ | 7250 instruct loadConXD(regXD dst, immXD con) %{ |
7260 match(Set dst con); | 7251 match(Set dst con); |
7261 ins_cost(125); | 7252 ins_cost(125); |
7262 format %{ "MOVSD $dst,[$con]" %} | 7253 format %{ "MOVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} |
7263 ins_encode(load_conXD(dst, con)); | 7254 ins_encode %{ |
7264 ins_pipe( pipe_slow ); | 7255 __ movdbl($dst$$XMMRegister, $constantaddress($con)); |
7256 %} | |
7257 ins_pipe(pipe_slow); | |
7265 %} | 7258 %} |
7266 | 7259 |
7267 // The instruction usage is guarded by predicate in operand immXD0(). | 7260 // The instruction usage is guarded by predicate in operand immXD0(). |
7268 instruct loadConXD0(regXD dst, immXD0 src) %{ | 7261 instruct loadConXD0(regXD dst, immXD0 src) %{ |
7269 match(Set dst src); | 7262 match(Set dst src); |
10301 set_instruction_start, | 10294 set_instruction_start, |
10302 Opcode(0xDD), RMopc_Mem(0x03,dst) ); | 10295 Opcode(0xDD), RMopc_Mem(0x03,dst) ); |
10303 ins_pipe( fpu_reg_mem ); | 10296 ins_pipe( fpu_reg_mem ); |
10304 %} | 10297 %} |
10305 | 10298 |
10306 instruct addD_reg_imm1(regD dst, immD1 src) %{ | 10299 instruct addD_reg_imm1(regD dst, immD1 con) %{ |
10307 predicate(UseSSE<=1); | 10300 predicate(UseSSE<=1); |
10308 match(Set dst (AddD dst src)); | 10301 match(Set dst (AddD dst con)); |
10309 ins_cost(125); | 10302 ins_cost(125); |
10310 format %{ "FLD1\n\t" | 10303 format %{ "FLD1\n\t" |
10311 "DADDp $dst,ST" %} | 10304 "DADDp $dst,ST" %} |
10312 opcode(0xDE, 0x00); | 10305 ins_encode %{ |
10313 ins_encode( LdImmD(src), | 10306 __ fld1(); |
10314 OpcP, RegOpc(dst) ); | 10307 __ faddp($dst$$reg); |
10315 ins_pipe( fpu_reg ); | 10308 %} |
10316 %} | 10309 ins_pipe(fpu_reg); |
10317 | 10310 %} |
10318 instruct addD_reg_imm(regD dst, immD src) %{ | 10311 |
10312 instruct addD_reg_imm(regD dst, immD con) %{ | |
10319 predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 ); | 10313 predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 ); |
10320 match(Set dst (AddD dst src)); | 10314 match(Set dst (AddD dst con)); |
10321 ins_cost(200); | 10315 ins_cost(200); |
10322 format %{ "FLD_D [$src]\n\t" | 10316 format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t" |
10323 "DADDp $dst,ST" %} | 10317 "DADDp $dst,ST" %} |
10324 opcode(0xDE, 0x00); /* DE /0 */ | 10318 ins_encode %{ |
10325 ins_encode( LdImmD(src), | 10319 __ fld_d($constantaddress($con)); |
10326 OpcP, RegOpc(dst)); | 10320 __ faddp($dst$$reg); |
10327 ins_pipe( fpu_reg_mem ); | 10321 %} |
10322 ins_pipe(fpu_reg_mem); | |
10328 %} | 10323 %} |
10329 | 10324 |
10330 instruct addD_reg_imm_round(stackSlotD dst, regD src, immD con) %{ | 10325 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 ); | 10326 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))); | 10327 match(Set dst (RoundDouble (AddD src con))); |
10333 ins_cost(200); | 10328 ins_cost(200); |
10334 format %{ "FLD_D [$con]\n\t" | 10329 format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t" |
10335 "DADD ST,$src\n\t" | 10330 "DADD ST,$src\n\t" |
10336 "FSTP_D $dst\t# D-round" %} | 10331 "FSTP_D $dst\t# D-round" %} |
10337 opcode(0xD8, 0x00); /* D8 /0 */ | 10332 ins_encode %{ |
10338 ins_encode( LdImmD(con), | 10333 __ fld_d($constantaddress($con)); |
10339 OpcP, RegOpc(src), Pop_Mem_D(dst)); | 10334 __ fadd($src$$reg); |
10340 ins_pipe( fpu_mem_reg_con ); | 10335 __ fstp_d(Address(rsp, $dst$$disp)); |
10336 %} | |
10337 ins_pipe(fpu_mem_reg_con); | |
10341 %} | 10338 %} |
10342 | 10339 |
10343 // Add two double precision floating point values in xmm | 10340 // Add two double precision floating point values in xmm |
10344 instruct addXD_reg(regXD dst, regXD src) %{ | 10341 instruct addXD_reg(regXD dst, regXD src) %{ |
10345 predicate(UseSSE>=2); | 10342 predicate(UseSSE>=2); |
10350 %} | 10347 %} |
10351 | 10348 |
10352 instruct addXD_imm(regXD dst, immXD con) %{ | 10349 instruct addXD_imm(regXD dst, immXD con) %{ |
10353 predicate(UseSSE>=2); | 10350 predicate(UseSSE>=2); |
10354 match(Set dst (AddD dst con)); | 10351 match(Set dst (AddD dst con)); |
10355 format %{ "ADDSD $dst,[$con]" %} | 10352 format %{ "ADDSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} |
10356 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), LdImmXD(dst, con) ); | 10353 ins_encode %{ |
10357 ins_pipe( pipe_slow ); | 10354 __ addsd($dst$$XMMRegister, $constantaddress($con)); |
10355 %} | |
10356 ins_pipe(pipe_slow); | |
10358 %} | 10357 %} |
10359 | 10358 |
10360 instruct addXD_mem(regXD dst, memory mem) %{ | 10359 instruct addXD_mem(regXD dst, memory mem) %{ |
10361 predicate(UseSSE>=2); | 10360 predicate(UseSSE>=2); |
10362 match(Set dst (AddD dst (LoadD mem))); | 10361 match(Set dst (AddD dst (LoadD mem))); |
10375 %} | 10374 %} |
10376 | 10375 |
10377 instruct subXD_imm(regXD dst, immXD con) %{ | 10376 instruct subXD_imm(regXD dst, immXD con) %{ |
10378 predicate(UseSSE>=2); | 10377 predicate(UseSSE>=2); |
10379 match(Set dst (SubD dst con)); | 10378 match(Set dst (SubD dst con)); |
10380 format %{ "SUBSD $dst,[$con]" %} | 10379 format %{ "SUBSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} |
10381 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), LdImmXD(dst, con) ); | 10380 ins_encode %{ |
10382 ins_pipe( pipe_slow ); | 10381 __ subsd($dst$$XMMRegister, $constantaddress($con)); |
10382 %} | |
10383 ins_pipe(pipe_slow); | |
10383 %} | 10384 %} |
10384 | 10385 |
10385 instruct subXD_mem(regXD dst, memory mem) %{ | 10386 instruct subXD_mem(regXD dst, memory mem) %{ |
10386 predicate(UseSSE>=2); | 10387 predicate(UseSSE>=2); |
10387 match(Set dst (SubD dst (LoadD mem))); | 10388 match(Set dst (SubD dst (LoadD mem))); |
10400 %} | 10401 %} |
10401 | 10402 |
10402 instruct mulXD_imm(regXD dst, immXD con) %{ | 10403 instruct mulXD_imm(regXD dst, immXD con) %{ |
10403 predicate(UseSSE>=2); | 10404 predicate(UseSSE>=2); |
10404 match(Set dst (MulD dst con)); | 10405 match(Set dst (MulD dst con)); |
10405 format %{ "MULSD $dst,[$con]" %} | 10406 format %{ "MULSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} |
10406 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), LdImmXD(dst, con) ); | 10407 ins_encode %{ |
10407 ins_pipe( pipe_slow ); | 10408 __ mulsd($dst$$XMMRegister, $constantaddress($con)); |
10409 %} | |
10410 ins_pipe(pipe_slow); | |
10408 %} | 10411 %} |
10409 | 10412 |
10410 instruct mulXD_mem(regXD dst, memory mem) %{ | 10413 instruct mulXD_mem(regXD dst, memory mem) %{ |
10411 predicate(UseSSE>=2); | 10414 predicate(UseSSE>=2); |
10412 match(Set dst (MulD dst (LoadD mem))); | 10415 match(Set dst (MulD dst (LoadD mem))); |
10426 %} | 10429 %} |
10427 | 10430 |
10428 instruct divXD_imm(regXD dst, immXD con) %{ | 10431 instruct divXD_imm(regXD dst, immXD con) %{ |
10429 predicate(UseSSE>=2); | 10432 predicate(UseSSE>=2); |
10430 match(Set dst (DivD dst con)); | 10433 match(Set dst (DivD dst con)); |
10431 format %{ "DIVSD $dst,[$con]" %} | 10434 format %{ "DIVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %} |
10432 ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), LdImmXD(dst, con)); | 10435 ins_encode %{ |
10433 ins_pipe( pipe_slow ); | 10436 __ divsd($dst$$XMMRegister, $constantaddress($con)); |
10437 %} | |
10438 ins_pipe(pipe_slow); | |
10434 %} | 10439 %} |
10435 | 10440 |
10436 instruct divXD_mem(regXD dst, memory mem) %{ | 10441 instruct divXD_mem(regXD dst, memory mem) %{ |
10437 predicate(UseSSE>=2); | 10442 predicate(UseSSE>=2); |
10438 match(Set dst (DivD dst (LoadD mem))); | 10443 match(Set dst (DivD dst (LoadD mem))); |
10479 OpcP, RegOpc(dst), | 10484 OpcP, RegOpc(dst), |
10480 strictfp_bias2(dst) ); | 10485 strictfp_bias2(dst) ); |
10481 ins_pipe( fpu_reg_reg ); | 10486 ins_pipe( fpu_reg_reg ); |
10482 %} | 10487 %} |
10483 | 10488 |
10484 instruct mulD_reg_imm(regD dst, immD src) %{ | 10489 instruct mulD_reg_imm(regD dst, immD con) %{ |
10485 predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 ); | 10490 predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 ); |
10486 match(Set dst (MulD dst src)); | 10491 match(Set dst (MulD dst con)); |
10487 ins_cost(200); | 10492 ins_cost(200); |
10488 format %{ "FLD_D [$src]\n\t" | 10493 format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t" |
10489 "DMULp $dst,ST" %} | 10494 "DMULp $dst,ST" %} |
10490 opcode(0xDE, 0x1); /* DE /1 */ | 10495 ins_encode %{ |
10491 ins_encode( LdImmD(src), | 10496 __ fld_d($constantaddress($con)); |
10492 OpcP, RegOpc(dst) ); | 10497 __ fmulp($dst$$reg); |
10493 ins_pipe( fpu_reg_mem ); | 10498 %} |
10499 ins_pipe(fpu_reg_mem); | |
10494 %} | 10500 %} |
10495 | 10501 |
10496 | 10502 |
10497 instruct mulD_reg_mem(regD dst, memory src) %{ | 10503 instruct mulD_reg_mem(regD dst, memory src) %{ |
10498 predicate( UseSSE<=1 ); | 10504 predicate( UseSSE<=1 ); |
11222 %} | 11228 %} |
11223 | 11229 |
11224 instruct addX_imm(regX dst, immXF con) %{ | 11230 instruct addX_imm(regX dst, immXF con) %{ |
11225 predicate(UseSSE>=1); | 11231 predicate(UseSSE>=1); |
11226 match(Set dst (AddF dst con)); | 11232 match(Set dst (AddF dst con)); |
11227 format %{ "ADDSS $dst,[$con]" %} | 11233 format %{ "ADDSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} |
11228 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), LdImmX(dst, con) ); | 11234 ins_encode %{ |
11229 ins_pipe( pipe_slow ); | 11235 __ addss($dst$$XMMRegister, $constantaddress($con)); |
11236 %} | |
11237 ins_pipe(pipe_slow); | |
11230 %} | 11238 %} |
11231 | 11239 |
11232 instruct addX_mem(regX dst, memory mem) %{ | 11240 instruct addX_mem(regX dst, memory mem) %{ |
11233 predicate(UseSSE>=1); | 11241 predicate(UseSSE>=1); |
11234 match(Set dst (AddF dst (LoadF mem))); | 11242 match(Set dst (AddF dst (LoadF mem))); |
11247 %} | 11255 %} |
11248 | 11256 |
11249 instruct subX_imm(regX dst, immXF con) %{ | 11257 instruct subX_imm(regX dst, immXF con) %{ |
11250 predicate(UseSSE>=1); | 11258 predicate(UseSSE>=1); |
11251 match(Set dst (SubF dst con)); | 11259 match(Set dst (SubF dst con)); |
11252 format %{ "SUBSS $dst,[$con]" %} | 11260 format %{ "SUBSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} |
11253 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), LdImmX(dst, con) ); | 11261 ins_encode %{ |
11254 ins_pipe( pipe_slow ); | 11262 __ subss($dst$$XMMRegister, $constantaddress($con)); |
11263 %} | |
11264 ins_pipe(pipe_slow); | |
11255 %} | 11265 %} |
11256 | 11266 |
11257 instruct subX_mem(regX dst, memory mem) %{ | 11267 instruct subX_mem(regX dst, memory mem) %{ |
11258 predicate(UseSSE>=1); | 11268 predicate(UseSSE>=1); |
11259 match(Set dst (SubF dst (LoadF mem))); | 11269 match(Set dst (SubF dst (LoadF mem))); |
11272 %} | 11282 %} |
11273 | 11283 |
11274 instruct mulX_imm(regX dst, immXF con) %{ | 11284 instruct mulX_imm(regX dst, immXF con) %{ |
11275 predicate(UseSSE>=1); | 11285 predicate(UseSSE>=1); |
11276 match(Set dst (MulF dst con)); | 11286 match(Set dst (MulF dst con)); |
11277 format %{ "MULSS $dst,[$con]" %} | 11287 format %{ "MULSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} |
11278 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), LdImmX(dst, con) ); | 11288 ins_encode %{ |
11279 ins_pipe( pipe_slow ); | 11289 __ mulss($dst$$XMMRegister, $constantaddress($con)); |
11290 %} | |
11291 ins_pipe(pipe_slow); | |
11280 %} | 11292 %} |
11281 | 11293 |
11282 instruct mulX_mem(regX dst, memory mem) %{ | 11294 instruct mulX_mem(regX dst, memory mem) %{ |
11283 predicate(UseSSE>=1); | 11295 predicate(UseSSE>=1); |
11284 match(Set dst (MulF dst (LoadF mem))); | 11296 match(Set dst (MulF dst (LoadF mem))); |
11297 %} | 11309 %} |
11298 | 11310 |
11299 instruct divX_imm(regX dst, immXF con) %{ | 11311 instruct divX_imm(regX dst, immXF con) %{ |
11300 predicate(UseSSE>=1); | 11312 predicate(UseSSE>=1); |
11301 match(Set dst (DivF dst con)); | 11313 match(Set dst (DivF dst con)); |
11302 format %{ "DIVSS $dst,[$con]" %} | 11314 format %{ "DIVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %} |
11303 ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), LdImmX(dst, con) ); | 11315 ins_encode %{ |
11304 ins_pipe( pipe_slow ); | 11316 __ divss($dst$$XMMRegister, $constantaddress($con)); |
11317 %} | |
11318 ins_pipe(pipe_slow); | |
11305 %} | 11319 %} |
11306 | 11320 |
11307 instruct divX_mem(regX dst, memory mem) %{ | 11321 instruct divX_mem(regX dst, memory mem) %{ |
11308 predicate(UseSSE>=1); | 11322 predicate(UseSSE>=1); |
11309 match(Set dst (DivF dst (LoadF mem))); | 11323 match(Set dst (DivF dst (LoadF mem))); |
11454 ins_pipe( fpu_mem_mem_mem ); | 11468 ins_pipe( fpu_mem_mem_mem ); |
11455 %} | 11469 %} |
11456 | 11470 |
11457 | 11471 |
11458 // Spill to obtain 24-bit precision | 11472 // Spill to obtain 24-bit precision |
11459 instruct addF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{ | 11473 instruct addF24_reg_imm(stackSlotF dst, regF src, immF con) %{ |
11460 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); | 11474 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); |
11461 match(Set dst (AddF src1 src2)); | 11475 match(Set dst (AddF src con)); |
11462 format %{ "FLD $src1\n\t" | 11476 format %{ "FLD $src\n\t" |
11463 "FADD $src2\n\t" | 11477 "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t" |
11464 "FSTP_S $dst" %} | 11478 "FSTP_S $dst" %} |
11465 opcode(0xD8, 0x00); /* D8 /0 */ | 11479 ins_encode %{ |
11466 ins_encode( Push_Reg_F(src1), | 11480 __ fld_s($src$$reg - 1); // FLD ST(i-1) |
11467 Opc_MemImm_F(src2), | 11481 __ fadd_s($constantaddress($con)); |
11468 Pop_Mem_F(dst)); | 11482 __ fstp_s(Address(rsp, $dst$$disp)); |
11469 ins_pipe( fpu_mem_reg_con ); | 11483 %} |
11484 ins_pipe(fpu_mem_reg_con); | |
11470 %} | 11485 %} |
11471 // | 11486 // |
11472 // This instruction does not round to 24-bits | 11487 // This instruction does not round to 24-bits |
11473 instruct addF_reg_imm(regF dst, regF src1, immF src2) %{ | 11488 instruct addF_reg_imm(regF dst, regF src, immF con) %{ |
11474 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr()); | 11489 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr()); |
11475 match(Set dst (AddF src1 src2)); | 11490 match(Set dst (AddF src con)); |
11476 format %{ "FLD $src1\n\t" | 11491 format %{ "FLD $src\n\t" |
11477 "FADD $src2\n\t" | 11492 "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t" |
11478 "FSTP_S $dst" %} | 11493 "FSTP $dst" %} |
11479 opcode(0xD8, 0x00); /* D8 /0 */ | 11494 ins_encode %{ |
11480 ins_encode( Push_Reg_F(src1), | 11495 __ fld_s($src$$reg - 1); // FLD ST(i-1) |
11481 Opc_MemImm_F(src2), | 11496 __ fadd_s($constantaddress($con)); |
11482 Pop_Reg_F(dst)); | 11497 __ fstp_d($dst$$reg); |
11483 ins_pipe( fpu_reg_reg_con ); | 11498 %} |
11499 ins_pipe(fpu_reg_reg_con); | |
11484 %} | 11500 %} |
11485 | 11501 |
11486 // Spill to obtain 24-bit precision | 11502 // Spill to obtain 24-bit precision |
11487 instruct mulF24_reg(stackSlotF dst, regF src1, regF src2) %{ | 11503 instruct mulF24_reg(stackSlotF dst, regF src1, regF src2) %{ |
11488 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); | 11504 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); |
11557 Pop_Mem_F(dst) ); | 11573 Pop_Mem_F(dst) ); |
11558 ins_pipe( fpu_mem_mem_mem ); | 11574 ins_pipe( fpu_mem_mem_mem ); |
11559 %} | 11575 %} |
11560 | 11576 |
11561 // Spill to obtain 24-bit precision | 11577 // Spill to obtain 24-bit precision |
11562 instruct mulF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{ | 11578 instruct mulF24_reg_imm(stackSlotF dst, regF src, immF con) %{ |
11563 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); | 11579 predicate(UseSSE==0 && Compile::current()->select_24_bit_instr()); |
11564 match(Set dst (MulF src1 src2)); | 11580 match(Set dst (MulF src con)); |
11565 | 11581 |
11566 format %{ "FMULc $dst,$src1,$src2" %} | 11582 format %{ "FLD $src\n\t" |
11567 opcode(0xD8, 0x1); /* D8 /1*/ | 11583 "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t" |
11568 ins_encode( Push_Reg_F(src1), | 11584 "FSTP_S $dst" %} |
11569 Opc_MemImm_F(src2), | 11585 ins_encode %{ |
11570 Pop_Mem_F(dst)); | 11586 __ fld_s($src$$reg - 1); // FLD ST(i-1) |
11571 ins_pipe( fpu_mem_reg_con ); | 11587 __ fmul_s($constantaddress($con)); |
11588 __ fstp_s(Address(rsp, $dst$$disp)); | |
11589 %} | |
11590 ins_pipe(fpu_mem_reg_con); | |
11572 %} | 11591 %} |
11573 // | 11592 // |
11574 // This instruction does not round to 24-bits | 11593 // This instruction does not round to 24-bits |
11575 instruct mulF_reg_imm(regF dst, regF src1, immF src2) %{ | 11594 instruct mulF_reg_imm(regF dst, regF src, immF con) %{ |
11576 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr()); | 11595 predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr()); |
11577 match(Set dst (MulF src1 src2)); | 11596 match(Set dst (MulF src con)); |
11578 | 11597 |
11579 format %{ "FMULc $dst. $src1, $src2" %} | 11598 format %{ "FLD $src\n\t" |
11580 opcode(0xD8, 0x1); /* D8 /1*/ | 11599 "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t" |
11581 ins_encode( Push_Reg_F(src1), | 11600 "FSTP $dst" %} |
11582 Opc_MemImm_F(src2), | 11601 ins_encode %{ |
11583 Pop_Reg_F(dst)); | 11602 __ fld_s($src$$reg - 1); // FLD ST(i-1) |
11584 ins_pipe( fpu_reg_reg_con ); | 11603 __ fmul_s($constantaddress($con)); |
11604 __ fstp_d($dst$$reg); | |
11605 %} | |
11606 ins_pipe(fpu_reg_reg_con); | |
11585 %} | 11607 %} |
11586 | 11608 |
11587 | 11609 |
11588 // | 11610 // |
11589 // MACRO1 -- subsume unshared load into mulF | 11611 // MACRO1 -- subsume unshared load into mulF |
12937 // Branch Instructions | 12959 // Branch Instructions |
12938 // Jump Table | 12960 // Jump Table |
12939 instruct jumpXtnd(eRegI switch_val) %{ | 12961 instruct jumpXtnd(eRegI switch_val) %{ |
12940 match(Jump switch_val); | 12962 match(Jump switch_val); |
12941 ins_cost(350); | 12963 ins_cost(350); |
12942 | 12964 format %{ "JMP [$constantaddress](,$switch_val,1)\n\t" %} |
12943 format %{ "JMP [table_base](,$switch_val,1)\n\t" %} | |
12944 | |
12945 ins_encode %{ | 12965 ins_encode %{ |
12946 address table_base = __ address_table_constant(_index2label); | |
12947 | |
12948 // Jump to Address(table_base + switch_reg) | 12966 // Jump to Address(table_base + switch_reg) |
12949 InternalAddress table(table_base); | |
12950 Address index(noreg, $switch_val$$Register, Address::times_1); | 12967 Address index(noreg, $switch_val$$Register, Address::times_1); |
12951 __ jump(ArrayAddress(table, index)); | 12968 __ jump(ArrayAddress($constantaddress, index)); |
12952 %} | 12969 %} |
12953 ins_pc_relative(1); | 12970 ins_pc_relative(1); |
12954 ins_pipe(pipe_jmp); | 12971 ins_pipe(pipe_jmp); |
12955 %} | 12972 %} |
12956 | 12973 |