1367 |
1367 |
1368 // Is this branch offset short enough that a short branch can be used? |
1368 // Is this branch offset short enough that a short branch can be used? |
1369 // |
1369 // |
1370 // NOTE: If the platform does not provide any short branch variants, then |
1370 // NOTE: If the platform does not provide any short branch variants, then |
1371 // this method should return false for offset 0. |
1371 // this method should return false for offset 0. |
1372 bool Matcher::is_short_branch_offset(int rule, int offset) { |
1372 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { |
|
1373 // The passed offset is relative to address of the branch. |
|
1374 // On 86 a branch displacement is calculated relative to address |
|
1375 // of a next instruction. |
|
1376 offset -= br_size; |
|
1377 |
1373 // the short version of jmpConUCF2 contains multiple branches, |
1378 // the short version of jmpConUCF2 contains multiple branches, |
1374 // making the reach slightly less |
1379 // making the reach slightly less |
1375 if (rule == jmpConUCF2_rule) |
1380 if (rule == jmpConUCF2_rule) |
1376 return (-126 <= offset && offset <= 125); |
1381 return (-126 <= offset && offset <= 125); |
1377 return (-128 <= offset && offset <= 127); |
1382 return (-128 <= offset && offset <= 127); |
1711 emit_rm(cbuf, 0x3, $tertiary, HIGH_FROM_LOW($dst$$reg)); |
1716 emit_rm(cbuf, 0x3, $tertiary, HIGH_FROM_LOW($dst$$reg)); |
1712 if ((con >= -128) && (con <= 127)) emit_d8 (cbuf,con); |
1717 if ((con >= -128) && (con <= 127)) emit_d8 (cbuf,con); |
1713 else emit_d32(cbuf,con); |
1718 else emit_d32(cbuf,con); |
1714 %} |
1719 %} |
1715 |
1720 |
1716 enc_class Lbl (label labl) %{ // GOTO |
|
1717 Label *l = $labl$$label; |
|
1718 emit_d32(cbuf, (l->loc_pos() - (cbuf.insts_size()+4))); |
|
1719 %} |
|
1720 |
|
1721 enc_class LblShort (label labl) %{ // GOTO |
|
1722 Label *l = $labl$$label; |
|
1723 int disp = l->loc_pos() - (cbuf.insts_size()+1); |
|
1724 assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); |
|
1725 emit_d8(cbuf, disp); |
|
1726 %} |
|
1727 |
|
1728 enc_class OpcSReg (eRegI dst) %{ // BSWAP |
1721 enc_class OpcSReg (eRegI dst) %{ // BSWAP |
1729 emit_cc(cbuf, $secondary, $dst$$reg ); |
1722 emit_cc(cbuf, $secondary, $dst$$reg ); |
1730 %} |
1723 %} |
1731 |
1724 |
1732 enc_class bswap_long_bytes(eRegL dst) %{ // BSWAP |
1725 enc_class bswap_long_bytes(eRegL dst) %{ // BSWAP |
1743 emit_rm(cbuf, 0x3, destlo, desthi); |
1736 emit_rm(cbuf, 0x3, destlo, desthi); |
1744 %} |
1737 %} |
1745 |
1738 |
1746 enc_class RegOpc (eRegI div) %{ // IDIV, IMOD, JMP indirect, ... |
1739 enc_class RegOpc (eRegI div) %{ // IDIV, IMOD, JMP indirect, ... |
1747 emit_rm(cbuf, 0x3, $secondary, $div$$reg ); |
1740 emit_rm(cbuf, 0x3, $secondary, $div$$reg ); |
1748 %} |
|
1749 |
|
1750 enc_class Jcc (cmpOp cop, label labl) %{ // JCC |
|
1751 Label *l = $labl$$label; |
|
1752 $$$emit8$primary; |
|
1753 emit_cc(cbuf, $secondary, $cop$$cmpcode); |
|
1754 emit_d32(cbuf, (l->loc_pos() - (cbuf.insts_size()+4))); |
|
1755 %} |
|
1756 |
|
1757 enc_class JccShort (cmpOp cop, label labl) %{ // JCC |
|
1758 Label *l = $labl$$label; |
|
1759 emit_cc(cbuf, $primary, $cop$$cmpcode); |
|
1760 int disp = l->loc_pos() - (cbuf.insts_size()+1); |
|
1761 assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); |
|
1762 emit_d8(cbuf, disp); |
|
1763 %} |
1741 %} |
1764 |
1742 |
1765 enc_class enc_cmov(cmpOp cop ) %{ // CMOV |
1743 enc_class enc_cmov(cmpOp cop ) %{ // CMOV |
1766 $$$emit8$primary; |
1744 $$$emit8$primary; |
1767 emit_cc(cbuf, $secondary, $cop$$cmpcode); |
1745 emit_cc(cbuf, $secondary, $cop$$cmpcode); |
13053 effect(USE labl); |
13031 effect(USE labl); |
13054 |
13032 |
13055 ins_cost(300); |
13033 ins_cost(300); |
13056 format %{ "JMP $labl" %} |
13034 format %{ "JMP $labl" %} |
13057 size(5); |
13035 size(5); |
13058 opcode(0xE9); |
13036 ins_encode %{ |
13059 ins_encode( OpcP, Lbl( labl ) ); |
13037 Label* L = $labl$$label; |
|
13038 __ jmp(*L, false); // Always long jump |
|
13039 %} |
13060 ins_pipe( pipe_jmp ); |
13040 ins_pipe( pipe_jmp ); |
13061 %} |
13041 %} |
13062 |
13042 |
13063 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13043 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13064 instruct jmpCon(cmpOp cop, eFlagsReg cr, label labl) %{ |
13044 instruct jmpCon(cmpOp cop, eFlagsReg cr, label labl) %{ |
13066 effect(USE labl); |
13046 effect(USE labl); |
13067 |
13047 |
13068 ins_cost(300); |
13048 ins_cost(300); |
13069 format %{ "J$cop $labl" %} |
13049 format %{ "J$cop $labl" %} |
13070 size(6); |
13050 size(6); |
13071 opcode(0x0F, 0x80); |
13051 ins_encode %{ |
13072 ins_encode( Jcc( cop, labl) ); |
13052 Label* L = $labl$$label; |
|
13053 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump |
|
13054 %} |
13073 ins_pipe( pipe_jcc ); |
13055 ins_pipe( pipe_jcc ); |
13074 %} |
13056 %} |
13075 |
13057 |
13076 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13058 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13077 instruct jmpLoopEnd(cmpOp cop, eFlagsReg cr, label labl) %{ |
13059 instruct jmpLoopEnd(cmpOp cop, eFlagsReg cr, label labl) %{ |
13079 effect(USE labl); |
13061 effect(USE labl); |
13080 |
13062 |
13081 ins_cost(300); |
13063 ins_cost(300); |
13082 format %{ "J$cop $labl\t# Loop end" %} |
13064 format %{ "J$cop $labl\t# Loop end" %} |
13083 size(6); |
13065 size(6); |
13084 opcode(0x0F, 0x80); |
13066 ins_encode %{ |
13085 ins_encode( Jcc( cop, labl) ); |
13067 Label* L = $labl$$label; |
|
13068 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump |
|
13069 %} |
13086 ins_pipe( pipe_jcc ); |
13070 ins_pipe( pipe_jcc ); |
13087 %} |
13071 %} |
13088 |
13072 |
13089 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13073 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13090 instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ |
13074 instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ |
13092 effect(USE labl); |
13076 effect(USE labl); |
13093 |
13077 |
13094 ins_cost(300); |
13078 ins_cost(300); |
13095 format %{ "J$cop,u $labl\t# Loop end" %} |
13079 format %{ "J$cop,u $labl\t# Loop end" %} |
13096 size(6); |
13080 size(6); |
13097 opcode(0x0F, 0x80); |
13081 ins_encode %{ |
13098 ins_encode( Jcc( cop, labl) ); |
13082 Label* L = $labl$$label; |
|
13083 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump |
|
13084 %} |
13099 ins_pipe( pipe_jcc ); |
13085 ins_pipe( pipe_jcc ); |
13100 %} |
13086 %} |
13101 |
13087 |
13102 instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13088 instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13103 match(CountedLoopEnd cop cmp); |
13089 match(CountedLoopEnd cop cmp); |
13104 effect(USE labl); |
13090 effect(USE labl); |
13105 |
13091 |
13106 ins_cost(200); |
13092 ins_cost(200); |
13107 format %{ "J$cop,u $labl\t# Loop end" %} |
13093 format %{ "J$cop,u $labl\t# Loop end" %} |
13108 size(6); |
13094 size(6); |
13109 opcode(0x0F, 0x80); |
13095 ins_encode %{ |
13110 ins_encode( Jcc( cop, labl) ); |
13096 Label* L = $labl$$label; |
|
13097 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump |
|
13098 %} |
13111 ins_pipe( pipe_jcc ); |
13099 ins_pipe( pipe_jcc ); |
13112 %} |
13100 %} |
13113 |
13101 |
13114 // Jump Direct Conditional - using unsigned comparison |
13102 // Jump Direct Conditional - using unsigned comparison |
13115 instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ |
13103 instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{ |
13117 effect(USE labl); |
13105 effect(USE labl); |
13118 |
13106 |
13119 ins_cost(300); |
13107 ins_cost(300); |
13120 format %{ "J$cop,u $labl" %} |
13108 format %{ "J$cop,u $labl" %} |
13121 size(6); |
13109 size(6); |
13122 opcode(0x0F, 0x80); |
13110 ins_encode %{ |
13123 ins_encode(Jcc(cop, labl)); |
13111 Label* L = $labl$$label; |
|
13112 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump |
|
13113 %} |
13124 ins_pipe(pipe_jcc); |
13114 ins_pipe(pipe_jcc); |
13125 %} |
13115 %} |
13126 |
13116 |
13127 instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13117 instruct jmpConUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13128 match(If cop cmp); |
13118 match(If cop cmp); |
13129 effect(USE labl); |
13119 effect(USE labl); |
13130 |
13120 |
13131 ins_cost(200); |
13121 ins_cost(200); |
13132 format %{ "J$cop,u $labl" %} |
13122 format %{ "J$cop,u $labl" %} |
13133 size(6); |
13123 size(6); |
13134 opcode(0x0F, 0x80); |
13124 ins_encode %{ |
13135 ins_encode(Jcc(cop, labl)); |
13125 Label* L = $labl$$label; |
|
13126 __ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump |
|
13127 %} |
13136 ins_pipe(pipe_jcc); |
13128 ins_pipe(pipe_jcc); |
13137 %} |
13129 %} |
13138 |
13130 |
13139 instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ |
13131 instruct jmpConUCF2(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ |
13140 match(If cop cmp); |
13132 match(If cop cmp); |
13149 $$emit$$"JP,u done\n\t" |
13141 $$emit$$"JP,u done\n\t" |
13150 $$emit$$"J$cop,u $labl\n\t" |
13142 $$emit$$"J$cop,u $labl\n\t" |
13151 $$emit$$"done:" |
13143 $$emit$$"done:" |
13152 } |
13144 } |
13153 %} |
13145 %} |
13154 size(12); |
|
13155 opcode(0x0F, 0x80); |
|
13156 ins_encode %{ |
13146 ins_encode %{ |
13157 Label* l = $labl$$label; |
13147 Label* l = $labl$$label; |
13158 $$$emit8$primary; |
|
13159 emit_cc(cbuf, $secondary, Assembler::parity); |
|
13160 int parity_disp = -1; |
|
13161 bool ok = false; |
|
13162 if ($cop$$cmpcode == Assembler::notEqual) { |
13148 if ($cop$$cmpcode == Assembler::notEqual) { |
13163 // the two jumps 6 bytes apart so the jump distances are too |
13149 __ jcc(Assembler::parity, *l, false); |
13164 parity_disp = l->loc_pos() - (cbuf.insts_size() + 4); |
13150 __ jcc(Assembler::notEqual, *l, false); |
13165 } else if ($cop$$cmpcode == Assembler::equal) { |
13151 } else if ($cop$$cmpcode == Assembler::equal) { |
13166 parity_disp = 6; |
13152 Label done; |
13167 ok = true; |
13153 __ jccb(Assembler::parity, done); |
|
13154 __ jcc(Assembler::equal, *l, false); |
|
13155 __ bind(done); |
13168 } else { |
13156 } else { |
13169 ShouldNotReachHere(); |
13157 ShouldNotReachHere(); |
13170 } |
13158 } |
13171 emit_d32(cbuf, parity_disp); |
|
13172 $$$emit8$primary; |
|
13173 emit_cc(cbuf, $secondary, $cop$$cmpcode); |
|
13174 int disp = l->loc_pos() - (cbuf.insts_size() + 4); |
|
13175 emit_d32(cbuf, disp); |
|
13176 %} |
13159 %} |
13177 ins_pipe(pipe_jcc); |
13160 ins_pipe(pipe_jcc); |
13178 %} |
13161 %} |
13179 |
13162 |
13180 // ============================================================================ |
13163 // ============================================================================ |
13237 effect(USE labl); |
13220 effect(USE labl); |
13238 |
13221 |
13239 ins_cost(300); |
13222 ins_cost(300); |
13240 format %{ "JMP,s $labl" %} |
13223 format %{ "JMP,s $labl" %} |
13241 size(2); |
13224 size(2); |
13242 opcode(0xEB); |
13225 ins_encode %{ |
13243 ins_encode( OpcP, LblShort( labl ) ); |
13226 Label* L = $labl$$label; |
|
13227 __ jmpb(*L); |
|
13228 %} |
13244 ins_pipe( pipe_jmp ); |
13229 ins_pipe( pipe_jmp ); |
13245 ins_short_branch(1); |
13230 ins_short_branch(1); |
13246 %} |
13231 %} |
13247 |
13232 |
13248 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13233 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13251 effect(USE labl); |
13236 effect(USE labl); |
13252 |
13237 |
13253 ins_cost(300); |
13238 ins_cost(300); |
13254 format %{ "J$cop,s $labl" %} |
13239 format %{ "J$cop,s $labl" %} |
13255 size(2); |
13240 size(2); |
13256 opcode(0x70); |
13241 ins_encode %{ |
13257 ins_encode( JccShort( cop, labl) ); |
13242 Label* L = $labl$$label; |
|
13243 __ jccb((Assembler::Condition)($cop$$cmpcode), *L); |
|
13244 %} |
13258 ins_pipe( pipe_jcc ); |
13245 ins_pipe( pipe_jcc ); |
13259 ins_short_branch(1); |
13246 ins_short_branch(1); |
13260 %} |
13247 %} |
13261 |
13248 |
13262 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13249 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13265 effect(USE labl); |
13252 effect(USE labl); |
13266 |
13253 |
13267 ins_cost(300); |
13254 ins_cost(300); |
13268 format %{ "J$cop,s $labl\t# Loop end" %} |
13255 format %{ "J$cop,s $labl\t# Loop end" %} |
13269 size(2); |
13256 size(2); |
13270 opcode(0x70); |
13257 ins_encode %{ |
13271 ins_encode( JccShort( cop, labl) ); |
13258 Label* L = $labl$$label; |
|
13259 __ jccb((Assembler::Condition)($cop$$cmpcode), *L); |
|
13260 %} |
13272 ins_pipe( pipe_jcc ); |
13261 ins_pipe( pipe_jcc ); |
13273 ins_short_branch(1); |
13262 ins_short_branch(1); |
13274 %} |
13263 %} |
13275 |
13264 |
13276 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13265 // Jump Direct Conditional - Label defines a relative address from Jcc+1 |
13279 effect(USE labl); |
13268 effect(USE labl); |
13280 |
13269 |
13281 ins_cost(300); |
13270 ins_cost(300); |
13282 format %{ "J$cop,us $labl\t# Loop end" %} |
13271 format %{ "J$cop,us $labl\t# Loop end" %} |
13283 size(2); |
13272 size(2); |
13284 opcode(0x70); |
13273 ins_encode %{ |
13285 ins_encode( JccShort( cop, labl) ); |
13274 Label* L = $labl$$label; |
|
13275 __ jccb((Assembler::Condition)($cop$$cmpcode), *L); |
|
13276 %} |
13286 ins_pipe( pipe_jcc ); |
13277 ins_pipe( pipe_jcc ); |
13287 ins_short_branch(1); |
13278 ins_short_branch(1); |
13288 %} |
13279 %} |
13289 |
13280 |
13290 instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13281 instruct jmpLoopEndUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13292 effect(USE labl); |
13283 effect(USE labl); |
13293 |
13284 |
13294 ins_cost(300); |
13285 ins_cost(300); |
13295 format %{ "J$cop,us $labl\t# Loop end" %} |
13286 format %{ "J$cop,us $labl\t# Loop end" %} |
13296 size(2); |
13287 size(2); |
13297 opcode(0x70); |
13288 ins_encode %{ |
13298 ins_encode( JccShort( cop, labl) ); |
13289 Label* L = $labl$$label; |
|
13290 __ jccb((Assembler::Condition)($cop$$cmpcode), *L); |
|
13291 %} |
13299 ins_pipe( pipe_jcc ); |
13292 ins_pipe( pipe_jcc ); |
13300 ins_short_branch(1); |
13293 ins_short_branch(1); |
13301 %} |
13294 %} |
13302 |
13295 |
13303 // Jump Direct Conditional - using unsigned comparison |
13296 // Jump Direct Conditional - using unsigned comparison |
13306 effect(USE labl); |
13299 effect(USE labl); |
13307 |
13300 |
13308 ins_cost(300); |
13301 ins_cost(300); |
13309 format %{ "J$cop,us $labl" %} |
13302 format %{ "J$cop,us $labl" %} |
13310 size(2); |
13303 size(2); |
13311 opcode(0x70); |
13304 ins_encode %{ |
13312 ins_encode( JccShort( cop, labl) ); |
13305 Label* L = $labl$$label; |
|
13306 __ jccb((Assembler::Condition)($cop$$cmpcode), *L); |
|
13307 %} |
13313 ins_pipe( pipe_jcc ); |
13308 ins_pipe( pipe_jcc ); |
13314 ins_short_branch(1); |
13309 ins_short_branch(1); |
13315 %} |
13310 %} |
13316 |
13311 |
13317 instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13312 instruct jmpConUCF_short(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{ |
13319 effect(USE labl); |
13314 effect(USE labl); |
13320 |
13315 |
13321 ins_cost(300); |
13316 ins_cost(300); |
13322 format %{ "J$cop,us $labl" %} |
13317 format %{ "J$cop,us $labl" %} |
13323 size(2); |
13318 size(2); |
13324 opcode(0x70); |
13319 ins_encode %{ |
13325 ins_encode( JccShort( cop, labl) ); |
13320 Label* L = $labl$$label; |
|
13321 __ jccb((Assembler::Condition)($cop$$cmpcode), *L); |
|
13322 %} |
13326 ins_pipe( pipe_jcc ); |
13323 ins_pipe( pipe_jcc ); |
13327 ins_short_branch(1); |
13324 ins_short_branch(1); |
13328 %} |
13325 %} |
13329 |
13326 |
13330 instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ |
13327 instruct jmpConUCF2_short(cmpOpUCF2 cop, eFlagsRegUCF cmp, label labl) %{ |
13341 $$emit$$"J$cop,u,s $labl\n\t" |
13338 $$emit$$"J$cop,u,s $labl\n\t" |
13342 $$emit$$"done:" |
13339 $$emit$$"done:" |
13343 } |
13340 } |
13344 %} |
13341 %} |
13345 size(4); |
13342 size(4); |
13346 opcode(0x70); |
|
13347 ins_encode %{ |
13343 ins_encode %{ |
13348 Label* l = $labl$$label; |
13344 Label* l = $labl$$label; |
13349 emit_cc(cbuf, $primary, Assembler::parity); |
|
13350 int parity_disp = -1; |
|
13351 if ($cop$$cmpcode == Assembler::notEqual) { |
13345 if ($cop$$cmpcode == Assembler::notEqual) { |
13352 parity_disp = l->loc_pos() - (cbuf.insts_size() + 1); |
13346 __ jccb(Assembler::parity, *l); |
|
13347 __ jccb(Assembler::notEqual, *l); |
13353 } else if ($cop$$cmpcode == Assembler::equal) { |
13348 } else if ($cop$$cmpcode == Assembler::equal) { |
13354 parity_disp = 2; |
13349 Label done; |
|
13350 __ jccb(Assembler::parity, done); |
|
13351 __ jccb(Assembler::equal, *l); |
|
13352 __ bind(done); |
13355 } else { |
13353 } else { |
13356 ShouldNotReachHere(); |
13354 ShouldNotReachHere(); |
13357 } |
13355 } |
13358 emit_d8(cbuf, parity_disp); |
|
13359 emit_cc(cbuf, $primary, $cop$$cmpcode); |
|
13360 int disp = l->loc_pos() - (cbuf.insts_size() + 1); |
|
13361 emit_d8(cbuf, disp); |
|
13362 assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp"); |
|
13363 assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp"); |
|
13364 %} |
13356 %} |
13365 ins_pipe(pipe_jcc); |
13357 ins_pipe(pipe_jcc); |
13366 ins_short_branch(1); |
13358 ins_short_branch(1); |
13367 %} |
13359 %} |
13368 |
13360 |