src/cpu/x86/vm/x86_32.ad
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 7063628_1 Sdiff src/cpu/x86/vm

src/cpu/x86/vm/x86_32.ad

Print this page




1698     emit_opcode(cbuf, ((con >= -128) && (con <= 127)) ? ($primary | 0x02) : $primary);
1699     // Emit r/m byte with secondary opcode, after primary opcode.
1700     emit_rm(cbuf, 0x3, $secondary, $dst$$reg);
1701     if ((con >= -128) && (con <= 127)) emit_d8 (cbuf,con);
1702     else                               emit_d32(cbuf,con);
1703   %}
1704 
1705   enc_class Long_OpcSErm_Hi(eRegL dst, immL imm) %{
1706     // Emit primary opcode and set sign-extend bit
1707     // Check for 8-bit immediate, and set sign extend bit in opcode
1708     int con = (int)($imm$$constant >> 32); // Throw away bottom bits
1709     emit_opcode(cbuf, ((con >= -128) && (con <= 127)) ? ($primary | 0x02) : $primary);
1710     // Emit r/m byte with tertiary opcode, after primary opcode.
1711     emit_rm(cbuf, 0x3, $tertiary, HIGH_FROM_LOW($dst$$reg));
1712     if ((con >= -128) && (con <= 127)) emit_d8 (cbuf,con);
1713     else                               emit_d32(cbuf,con);
1714   %}
1715 
1716   enc_class Lbl (label labl) %{ // GOTO
1717     Label *l = $labl$$label;
1718     assert(l != NULL, "need Label");
1719     emit_d32(cbuf, l ? (l->loc_pos() - (cbuf.insts_size()+4)) : 0);
1720   %}
1721 
1722   enc_class LblShort (label labl) %{ // GOTO
1723     Label *l = $labl$$label;
1724     assert(l != NULL, "need Label");
1725     int disp = l ? (l->loc_pos() - (cbuf.insts_size()+1)) : 0;
1726     assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
1727     emit_d8(cbuf, disp);
1728   %}
1729 
1730   enc_class OpcSReg (eRegI dst) %{    // BSWAP
1731     emit_cc(cbuf, $secondary, $dst$$reg );
1732   %}
1733 
1734   enc_class bswap_long_bytes(eRegL dst) %{ // BSWAP
1735     int destlo = $dst$$reg;
1736     int desthi = HIGH_FROM_LOW(destlo);
1737     // bswap lo
1738     emit_opcode(cbuf, 0x0F);
1739     emit_cc(cbuf, 0xC8, destlo);
1740     // bswap hi
1741     emit_opcode(cbuf, 0x0F);
1742     emit_cc(cbuf, 0xC8, desthi);
1743     // xchg lo and hi
1744     emit_opcode(cbuf, 0x87);
1745     emit_rm(cbuf, 0x3, destlo, desthi);
1746   %}
1747 
1748   enc_class RegOpc (eRegI div) %{    // IDIV, IMOD, JMP indirect, ...
1749     emit_rm(cbuf, 0x3, $secondary, $div$$reg );
1750   %}
1751 
1752   enc_class Jcc (cmpOp cop, label labl) %{    // JCC
1753     Label *l = $labl$$label;
1754     assert(l != NULL, "need Label");
1755     $$$emit8$primary;
1756     emit_cc(cbuf, $secondary, $cop$$cmpcode);
1757     emit_d32(cbuf, l ? (l->loc_pos() - (cbuf.insts_size()+4)) : 0);
1758   %}
1759 
1760   enc_class JccShort (cmpOp cop, label labl) %{    // JCC
1761     Label *l = $labl$$label;
1762     assert(l != NULL, "need Label");
1763     emit_cc(cbuf, $primary, $cop$$cmpcode);
1764     int disp = l ? (l->loc_pos() - (cbuf.insts_size()+1)) : 0;
1765     assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
1766     emit_d8(cbuf, disp);
1767   %}
1768 
1769   enc_class enc_cmov(cmpOp cop ) %{ // CMOV
1770     $$$emit8$primary;
1771     emit_cc(cbuf, $secondary, $cop$$cmpcode);
1772   %}
1773 
1774   enc_class enc_cmov_d(cmpOp cop, regD src ) %{ // CMOV
1775     int op = 0xDA00 + $cop$$cmpcode + ($src$$reg-1);
1776     emit_d8(cbuf, op >> 8 );
1777     emit_d8(cbuf, op & 255);
1778   %}
1779 
1780   // emulate a CMOV with a conditional branch around a MOV
1781   enc_class enc_cmov_branch( cmpOp cop, immI brOffs ) %{ // CMOV
1782     // Invert sense of branch from sense of CMOV
1783     emit_cc( cbuf, 0x70, ($cop$$cmpcode^1) );
1784     emit_d8( cbuf, $brOffs$$constant );


13160     if ($cop$$cmpcode == Assembler::notEqual) {
13161       $$emit$$"JP,u   $labl\n\t"
13162       $$emit$$"J$cop,u   $labl"
13163     } else {
13164       $$emit$$"JP,u   done\n\t"
13165       $$emit$$"J$cop,u   $labl\n\t"
13166       $$emit$$"done:"
13167     }
13168   %}
13169   size(12);
13170   opcode(0x0F, 0x80);
13171   ins_encode %{
13172     Label* l = $labl$$label;
13173     assert(l != NULL, "need Label");
13174     $$$emit8$primary;
13175     emit_cc(cbuf, $secondary, Assembler::parity);
13176     int parity_disp = -1;
13177     bool ok = false;
13178     if ($cop$$cmpcode == Assembler::notEqual) {
13179        // the two jumps 6 bytes apart so the jump distances are too
13180        parity_disp = l ? (l->loc_pos() - (cbuf.insts_size() + 4)) : 0;
13181     } else if ($cop$$cmpcode == Assembler::equal) {
13182        parity_disp = 6;
13183        ok = true;
13184     } else {
13185        ShouldNotReachHere();
13186     }
13187     emit_d32(cbuf, parity_disp);
13188     $$$emit8$primary;
13189     emit_cc(cbuf, $secondary, $cop$$cmpcode);
13190     int disp = l ? (l->loc_pos() - (cbuf.insts_size() + 4)) : 0;
13191     emit_d32(cbuf, disp);
13192   %}
13193   ins_pipe(pipe_jcc);
13194   ins_pc_relative(1);
13195 %}
13196 
13197 // ============================================================================
13198 // The 2nd slow-half of a subtype check.  Scan the subklass's 2ndary superklass
13199 // array for an instance of the superklass.  Set a hidden internal cache on a
13200 // hit (cache is checked with exposed code in gen_subtype_check()).  Return
13201 // NZ for a miss or zero for a hit.  The encoding ALSO sets flags.
13202 instruct partialSubtypeCheck( eDIRegP result, eSIRegP sub, eAXRegP super, eCXRegI rcx, eFlagsReg cr ) %{
13203   match(Set result (PartialSubtypeCheck sub super));
13204   effect( KILL rcx, KILL cr );
13205 
13206   ins_cost(1100);  // slightly larger than the next version
13207   format %{ "MOV    EDI,[$sub+Klass::secondary_supers]\n\t"
13208             "MOV    ECX,[EDI+arrayKlass::length]\t# length to scan\n\t"
13209             "ADD    EDI,arrayKlass::base_offset\t# Skip to start of data; set NZ in case count is zero\n\t"
13210             "REPNE SCASD\t# Scan *EDI++ for a match with EAX while CX-- != 0\n\t"


13357 
13358   ins_cost(300);
13359   format %{ $$template
13360     if ($cop$$cmpcode == Assembler::notEqual) {
13361       $$emit$$"JP,u,s   $labl\n\t"
13362       $$emit$$"J$cop,u,s   $labl"
13363     } else {
13364       $$emit$$"JP,u,s   done\n\t"
13365       $$emit$$"J$cop,u,s  $labl\n\t"
13366       $$emit$$"done:"
13367     }
13368   %}
13369   size(4);
13370   opcode(0x70);
13371   ins_encode %{
13372     Label* l = $labl$$label;
13373     assert(l != NULL, "need Label");
13374     emit_cc(cbuf, $primary, Assembler::parity);
13375     int parity_disp = -1;
13376     if ($cop$$cmpcode == Assembler::notEqual) {
13377       parity_disp = l ? (l->loc_pos() - (cbuf.insts_size() + 1)) : 0;
13378     } else if ($cop$$cmpcode == Assembler::equal) {
13379       parity_disp = 2;
13380     } else {
13381       ShouldNotReachHere();
13382     }
13383     emit_d8(cbuf, parity_disp);
13384     emit_cc(cbuf, $primary, $cop$$cmpcode);
13385     int disp = l ? (l->loc_pos() - (cbuf.insts_size() + 1)) : 0;
13386     emit_d8(cbuf, disp);
13387     assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
13388     assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp");
13389   %}
13390   ins_pipe(pipe_jcc);
13391   ins_pc_relative(1);
13392   ins_short_branch(1);
13393 %}
13394 
13395 // ============================================================================
13396 // Long Compare
13397 //
13398 // Currently we hold longs in 2 registers.  Comparing such values efficiently
13399 // is tricky.  The flavor of compare used depends on whether we are testing
13400 // for LT, LE, or EQ.  For a simple LT test we can check just the sign bit.
13401 // The GE test is the negated LT test.  The LE test can be had by commuting
13402 // the operands (yielding a GE test) and then negating; negate again for the
13403 // GT test.  The EQ test is done by ORcc'ing the high and low halves, and the
13404 // NE test is negated from that.
13405 




1698     emit_opcode(cbuf, ((con >= -128) && (con <= 127)) ? ($primary | 0x02) : $primary);
1699     // Emit r/m byte with secondary opcode, after primary opcode.
1700     emit_rm(cbuf, 0x3, $secondary, $dst$$reg);
1701     if ((con >= -128) && (con <= 127)) emit_d8 (cbuf,con);
1702     else                               emit_d32(cbuf,con);
1703   %}
1704 
1705   enc_class Long_OpcSErm_Hi(eRegL dst, immL imm) %{
1706     // Emit primary opcode and set sign-extend bit
1707     // Check for 8-bit immediate, and set sign extend bit in opcode
1708     int con = (int)($imm$$constant >> 32); // Throw away bottom bits
1709     emit_opcode(cbuf, ((con >= -128) && (con <= 127)) ? ($primary | 0x02) : $primary);
1710     // Emit r/m byte with tertiary opcode, after primary opcode.
1711     emit_rm(cbuf, 0x3, $tertiary, HIGH_FROM_LOW($dst$$reg));
1712     if ((con >= -128) && (con <= 127)) emit_d8 (cbuf,con);
1713     else                               emit_d32(cbuf,con);
1714   %}
1715 
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
1729     emit_cc(cbuf, $secondary, $dst$$reg );
1730   %}
1731 
1732   enc_class bswap_long_bytes(eRegL dst) %{ // BSWAP
1733     int destlo = $dst$$reg;
1734     int desthi = HIGH_FROM_LOW(destlo);
1735     // bswap lo
1736     emit_opcode(cbuf, 0x0F);
1737     emit_cc(cbuf, 0xC8, destlo);
1738     // bswap hi
1739     emit_opcode(cbuf, 0x0F);
1740     emit_cc(cbuf, 0xC8, desthi);
1741     // xchg lo and hi
1742     emit_opcode(cbuf, 0x87);
1743     emit_rm(cbuf, 0x3, destlo, desthi);
1744   %}
1745 
1746   enc_class RegOpc (eRegI div) %{    // IDIV, IMOD, JMP indirect, ...
1747     emit_rm(cbuf, 0x3, $secondary, $div$$reg );
1748   %}
1749 
1750   enc_class Jcc (cmpOp cop, label labl) %{    // JCC
1751     Label *l = $labl$$label;
1752     assert(l != NULL, "need Label");
1753     $$$emit8$primary;
1754     emit_cc(cbuf, $secondary, $cop$$cmpcode);
1755     emit_d32(cbuf, (l->loc_pos() - (cbuf.insts_size()+4)));
1756   %}
1757 
1758   enc_class JccShort (cmpOp cop, label labl) %{    // JCC
1759     Label *l = $labl$$label;
1760     assert(l != NULL, "need Label");
1761     emit_cc(cbuf, $primary, $cop$$cmpcode);
1762     int disp = l->loc_pos() - (cbuf.insts_size()+1);
1763     assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
1764     emit_d8(cbuf, disp);
1765   %}
1766 
1767   enc_class enc_cmov(cmpOp cop ) %{ // CMOV
1768     $$$emit8$primary;
1769     emit_cc(cbuf, $secondary, $cop$$cmpcode);
1770   %}
1771 
1772   enc_class enc_cmov_d(cmpOp cop, regD src ) %{ // CMOV
1773     int op = 0xDA00 + $cop$$cmpcode + ($src$$reg-1);
1774     emit_d8(cbuf, op >> 8 );
1775     emit_d8(cbuf, op & 255);
1776   %}
1777 
1778   // emulate a CMOV with a conditional branch around a MOV
1779   enc_class enc_cmov_branch( cmpOp cop, immI brOffs ) %{ // CMOV
1780     // Invert sense of branch from sense of CMOV
1781     emit_cc( cbuf, 0x70, ($cop$$cmpcode^1) );
1782     emit_d8( cbuf, $brOffs$$constant );


13158     if ($cop$$cmpcode == Assembler::notEqual) {
13159       $$emit$$"JP,u   $labl\n\t"
13160       $$emit$$"J$cop,u   $labl"
13161     } else {
13162       $$emit$$"JP,u   done\n\t"
13163       $$emit$$"J$cop,u   $labl\n\t"
13164       $$emit$$"done:"
13165     }
13166   %}
13167   size(12);
13168   opcode(0x0F, 0x80);
13169   ins_encode %{
13170     Label* l = $labl$$label;
13171     assert(l != NULL, "need Label");
13172     $$$emit8$primary;
13173     emit_cc(cbuf, $secondary, Assembler::parity);
13174     int parity_disp = -1;
13175     bool ok = false;
13176     if ($cop$$cmpcode == Assembler::notEqual) {
13177        // the two jumps 6 bytes apart so the jump distances are too
13178        parity_disp = l->loc_pos() - (cbuf.insts_size() + 4);
13179     } else if ($cop$$cmpcode == Assembler::equal) {
13180        parity_disp = 6;
13181        ok = true;
13182     } else {
13183        ShouldNotReachHere();
13184     }
13185     emit_d32(cbuf, parity_disp);
13186     $$$emit8$primary;
13187     emit_cc(cbuf, $secondary, $cop$$cmpcode);
13188     int disp = l->loc_pos() - (cbuf.insts_size() + 4);
13189     emit_d32(cbuf, disp);
13190   %}
13191   ins_pipe(pipe_jcc);
13192   ins_pc_relative(1);
13193 %}
13194 
13195 // ============================================================================
13196 // The 2nd slow-half of a subtype check.  Scan the subklass's 2ndary superklass
13197 // array for an instance of the superklass.  Set a hidden internal cache on a
13198 // hit (cache is checked with exposed code in gen_subtype_check()).  Return
13199 // NZ for a miss or zero for a hit.  The encoding ALSO sets flags.
13200 instruct partialSubtypeCheck( eDIRegP result, eSIRegP sub, eAXRegP super, eCXRegI rcx, eFlagsReg cr ) %{
13201   match(Set result (PartialSubtypeCheck sub super));
13202   effect( KILL rcx, KILL cr );
13203 
13204   ins_cost(1100);  // slightly larger than the next version
13205   format %{ "MOV    EDI,[$sub+Klass::secondary_supers]\n\t"
13206             "MOV    ECX,[EDI+arrayKlass::length]\t# length to scan\n\t"
13207             "ADD    EDI,arrayKlass::base_offset\t# Skip to start of data; set NZ in case count is zero\n\t"
13208             "REPNE SCASD\t# Scan *EDI++ for a match with EAX while CX-- != 0\n\t"


13355 
13356   ins_cost(300);
13357   format %{ $$template
13358     if ($cop$$cmpcode == Assembler::notEqual) {
13359       $$emit$$"JP,u,s   $labl\n\t"
13360       $$emit$$"J$cop,u,s   $labl"
13361     } else {
13362       $$emit$$"JP,u,s   done\n\t"
13363       $$emit$$"J$cop,u,s  $labl\n\t"
13364       $$emit$$"done:"
13365     }
13366   %}
13367   size(4);
13368   opcode(0x70);
13369   ins_encode %{
13370     Label* l = $labl$$label;
13371     assert(l != NULL, "need Label");
13372     emit_cc(cbuf, $primary, Assembler::parity);
13373     int parity_disp = -1;
13374     if ($cop$$cmpcode == Assembler::notEqual) {
13375       parity_disp = l->loc_pos() - (cbuf.insts_size() + 1);
13376     } else if ($cop$$cmpcode == Assembler::equal) {
13377       parity_disp = 2;
13378     } else {
13379       ShouldNotReachHere();
13380     }
13381     emit_d8(cbuf, parity_disp);
13382     emit_cc(cbuf, $primary, $cop$$cmpcode);
13383     int disp = l->loc_pos() - (cbuf.insts_size() + 1);
13384     emit_d8(cbuf, disp);
13385     assert(-128 <= disp && disp <= 127, "Displacement too large for short jmp");
13386     assert(-128 <= parity_disp && parity_disp <= 127, "Displacement too large for short jmp");
13387   %}
13388   ins_pipe(pipe_jcc);
13389   ins_pc_relative(1);
13390   ins_short_branch(1);
13391 %}
13392 
13393 // ============================================================================
13394 // Long Compare
13395 //
13396 // Currently we hold longs in 2 registers.  Comparing such values efficiently
13397 // is tricky.  The flavor of compare used depends on whether we are testing
13398 // for LT, LE, or EQ.  For a simple LT test we can check just the sign bit.
13399 // The GE test is the negated LT test.  The LE test can be had by commuting
13400 // the operands (yielding a GE test) and then negating; negate again for the
13401 // GT test.  The EQ test is done by ORcc'ing the high and low halves, and the
13402 // NE test is negated from that.
13403 


src/cpu/x86/vm/x86_32.ad
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File