src/cpu/sparc/vm/assembler_sparc.hpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/cpu/sparc/vm/assembler_sparc.hpp	Fri Jul 15 18:49:35 2011
--- new/src/cpu/sparc/vm/assembler_sparc.hpp	Fri Jul 15 18:49:34 2011

*** 759,769 **** --- 759,769 ---- mstosw_opf = 0x113, mxtod_opf = 0x118, mwtos_opf = 0x119 }; ! enum RCondition { rc_z = 1, rc_lez = 2, rc_lz = 3, rc_nz = 5, rc_gz = 6, rc_gez = 7, rc_last = rc_gez }; enum Condition { // for FBfcc & FBPfcc instruction f_never = 0, f_notEqual = 1,
*** 864,876 **** --- 864,885 ---- static bool is_in_wdisp_range(address a, address b, int nbits) { intptr_t d = intptr_t(b) - intptr_t(a); return is_simm(d, nbits + 2); } + address target_distance(Label& L) { + // Assembler::target(L) should be called only when + // a branch instruction is emitted since non-bound + // labels record current pc() as a branch address. + if (L.is_bound()) return target(L); + // Return current address for non-bound labels. + return pc(); + } + // test if label is in simm16 range in words (wdisp16). bool is_in_wdisp16_range(Label& L) { ! return is_in_wdisp_range(target_distance(L), pc(), 16); } // test if the distance between two addresses fits in simm30 range in words static bool is_in_wdisp30_range(address a, address b) { return is_in_wdisp_range(a, b, 30); }
*** 973,982 **** --- 982,1005 ---- static int opf_low5( int w) { return u_field(w, 9, 5); } static int trapcc( CC cc) { return u_field(cc, 12, 11); } static int sx( int i) { return u_field(i, 12, 12); } // shift x=1 means 64-bit static int opf( int x) { return u_field(x, 13, 5); } + static bool is_cbcond( int x ) { + return (VM_Version::has_cbcond() && (inv_cond(x) > rc_last) && + inv_op(x) == branch_op && inv_op2(x) == bpr_op2); + } + static bool is_cxb( int x ) { + assert(is_cbcond(x), "wrong instruction"); + return (x & (1<<21)) != 0; + } + static int cond_cbcond( int x) { return u_field((((x & 8)<<1) + 8 + (x & 7)), 29, 25); } + static int inv_cond_cbcond(int x) { + assert(is_cbcond(x), "wrong instruction"); + return inv_u_field(x, 27, 25) | (inv_u_field(x, 29, 29)<<3); + } + static int opf_cc( CC c, bool useFloat ) { return u_field((useFloat ? 0 : 4) + c, 13, 11); } static int mov_cc( CC c, bool useFloat ) { return u_field(useFloat ? 0 : 1, 18, 18) | u_field(c, 12, 11); } static int fd( FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 29, 25); }; static int fs1(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 18, 14); };
*** 1024,1034 **** --- 1047,1077 ---- | ( ( (xx>>(2+14)) & 3 ) << 20 ); assert( inv_wdisp16(r, off) == x, "inverse is not inverse"); return r; } + // compute inverse of wdisp10 + static intptr_t inv_wdisp10(int x, intptr_t pos) { + assert(is_cbcond(x), "wrong instruction"); + int lo = inv_u_field(x, 12, 5); + int hi = (x >> 19) & 3; + if (hi >= 2) hi |= ~1; + return (((hi << 8) | lo) << 2) + pos; + } + // word offset for cbcond, 8 bits at [B12,B5], 2 bits at [B20,B19] + static int wdisp10(intptr_t x, intptr_t off) { + assert(VM_Version::has_cbcond(), "This CPU does not have CBCOND instruction"); + intptr_t xx = x - off; + assert_signed_word_disp_range(xx, 10); + int r = ( ( (xx >> 2 ) & ((1 << 8) - 1) ) << 5 ) + | ( ( (xx >> (2+8)) & 3 ) << 19 ); + // Have to fake cbcond instruction to pass assert in inv_wdisp10() + assert(inv_wdisp10((r | op(branch_op) | cond_cbcond(rc_last+1) | op2(bpr_op2)), off) == x, "inverse is not inverse"); + return r; + } + // word displacement in low-order nbits bits static intptr_t inv_wdisp( int x, intptr_t pos, int nbits ) { int pre_sign_extend = x & (( 1 << nbits ) - 1); int r = pre_sign_extend >= ( 1 << (nbits-1) )
*** 1136,1145 **** --- 1179,1206 ---- assert_not_delayed("just checking"); delay_state = at_delay_slot; #endif } + // cbcond instruction should not be generated one after an other + bool cbcond_before() { + if (offset() == 0) return false; // it is first instruction + int x = *(int*)(intptr_t(pc()) - 4); // previous instruction + return is_cbcond(x); + } + + void no_cbcond_before() { + assert(offset() == 0 || !cbcond_before(), "cbcond should not follow an other cbcond"); + } + + bool use_cbcond(Label& L) { + if (!UseCBCond || cbcond_before()) return false; + intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc()); + assert( (x & 3) == 0, "not word aligned"); + return is_simm(x, 12); + } + public: // Tells assembler you know that next instruction is delayed Assembler* delayed() { #ifdef CHECK_DELAY assert ( delay_state == at_delay_slot, "delayed instruction is not in delay slot");
*** 1179,1192 **** --- 1240,1254 ---- void addc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | rs2(s2) ); } void addc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void addccc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void addccc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } + // pp 136 ! inline void bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none ); - inline void bpr( RCondition c, bool a, Predict p, Register s1, Label& L); ! inline void bpr(RCondition c, bool a, Predict p, Register s1, Label& L); protected: // use MacroAssembler::br instead // pp 138
*** 1196,1207 **** --- 1258,1267 ---- // pp 141 inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L ); public: // pp 144 inline void br( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); inline void br( Condition c, bool a, Label& L );
*** 1213,1227 **** --- 1273,1293 ---- // pp 121 (V8) inline void cb( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); inline void cb( Condition c, bool a, Label& L ); + // compare and branch + inline void cbcond(Condition c, CC cc, Register s1, Register s2, Label& L); + inline void cbcond(Condition c, CC cc, Register s1, int simm5, Label& L); + // pp 149 inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type ); + public: + // pp 150 // These instructions compare the contents of s2 with the contents of // memory at address in s1. If the values are equal, the contents of memory // at address s1 is swapped with the data in d. If the values are not equal,
*** 1860,1871 **** --- 1926,1937 ---- inline void br( Condition c, bool a, Predict p, Label& L ); inline void fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void fb( Condition c, bool a, Predict p, Label& L ); ! // compares register with zero (32 bit) and branches (V9 and V8 instructions) ! void br_zero( Condition c, bool a, Predict p, Register s1, Label& L); ! void cmp_zero_and_br( Condition c, Register s1, Label& L, bool a = false, Predict p = pn ); // Compares a pointer register with zero and branches on (not)null. // Does a test & branch on 32-bit systems and a register-branch on 64-bit. void br_null ( Register s1, bool a, Predict p, Label& L ); void br_notnull( Register s1, bool a, Predict p, Label& L );
*** 1873,1891 **** --- 1939,1977 ---- // this is what the routine above was meant to do, but it didn't (and // didn't cover both target address kinds.) void br_on_reg_cond( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none ); void br_on_reg_cond( RCondition c, bool a, Predict p, Register s1, Label& L); + // + // Compare registers and branch with nop in delay slot or cbcond without delay slot. + // + // ATTENTION: use these instructions with caution because cbcond instruction + // has very short distance: 512 instructions (2Kbyte). + + // Compare integer (32 bit) values (icc only). + void cmp_and_br_short(Register s1, Register s2, Condition c, Predict p, Label& L); + void cmp_and_br_short(Register s1, int simm13a, Condition c, Predict p, Label& L); + // Platform depending version for pointer compare (icc on !LP64 and xcc on LP64). + void cmp_and_brx_short(Register s1, Register s2, Condition c, Predict p, Label& L); + void cmp_and_brx_short(Register s1, int simm13a, Condition c, Predict p, Label& L); + + // Short branch version for compares a pointer pwith zero. + void br_null_short ( Register s1, Predict p, Label& L ); + void br_notnull_short( Register s1, Predict p, Label& L ); + + // unconditional short branch + void ba_short(Label& L); + inline void bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void bp( Condition c, bool a, CC cc, Predict p, Label& L ); // Branch that tests xcc in LP64 and icc in !LP64 inline void brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void brx( Condition c, bool a, Predict p, Label& L ); - // unconditional short branch - inline void ba( bool a, Label& L ); // Branch that tests fp condition codes inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L );
*** 2165,2175 **** --- 2251,2260 ---- // These are idioms to flag the need for care with accessing bools but on // this platform we assume byte size inline void stbool(Register d, const Address& a) { stb(d, a); } inline void ldbool(const Address& a, Register d) { ldsb(a, d); } inline void tstbool( Register s ) { tst(s); } inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); } // klass oop manipulations if compressed void load_klass(Register src_oop, Register klass); void store_klass(Register klass, Register dst_oop);
*** 2467,2478 **** --- 2552,2562 ---- Register temp_reg, Register temp2_reg, Label* L_success, Label* L_failure, Label* L_slow_path, ! RegisterOrConstant super_check_offset = RegisterOrConstant(-1), Register instanceof_hack = noreg); ! RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); // The rest of the type check; must be wired to a corresponding fast path. // It does not repeat the fast path logic, so don't use it standalone. // The temp_reg can be noreg, if no temps are available. // It can also be sub_klass or super_klass, meaning it's OK to kill that one.

src/cpu/sparc/vm/assembler_sparc.hpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File