2020 __ ret(lr); |
2020 __ ret(lr); |
2021 |
2021 |
2022 return start; |
2022 return start; |
2023 } |
2023 } |
2024 |
2024 |
|
2025 // |
|
2026 // Generate stub for array fill. If "aligned" is true, the |
|
2027 // "to" address is assumed to be heapword aligned. |
|
2028 // |
|
2029 // Arguments for generated stub: |
|
2030 // to: c_rarg0 |
|
2031 // value: c_rarg1 |
|
2032 // count: c_rarg2 treated as signed |
|
2033 // |
|
2034 address generate_fill(BasicType t, bool aligned, const char *name) { |
|
2035 __ align(CodeEntryAlignment); |
|
2036 StubCodeMark mark(this, "StubRoutines", name); |
|
2037 address start = __ pc(); |
|
2038 |
|
2039 BLOCK_COMMENT("Entry:"); |
|
2040 |
|
2041 const Register to = c_rarg0; // source array address |
|
2042 const Register value = c_rarg1; // value |
|
2043 const Register count = c_rarg2; // elements count |
|
2044 const Register cnt_words = c_rarg3; // temp register |
|
2045 |
|
2046 __ enter(); |
|
2047 |
|
2048 Label L_fill_elements, L_exit1; |
|
2049 |
|
2050 int shift = -1; |
|
2051 switch (t) { |
|
2052 case T_BYTE: |
|
2053 shift = 0; |
|
2054 __ cmpw(count, 8 >> shift); // Short arrays (< 8 bytes) fill by element |
|
2055 __ bfi(value, value, 8, 8); // 8 bit -> 16 bit |
|
2056 __ bfi(value, value, 16, 16); // 16 bit -> 32 bit |
|
2057 __ br(Assembler::LO, L_fill_elements); |
|
2058 break; |
|
2059 case T_SHORT: |
|
2060 shift = 1; |
|
2061 __ cmpw(count, 8 >> shift); // Short arrays (< 8 bytes) fill by element |
|
2062 __ bfi(value, value, 16, 16); // 16 bit -> 32 bit |
|
2063 __ br(Assembler::LO, L_fill_elements); |
|
2064 break; |
|
2065 case T_INT: |
|
2066 shift = 2; |
|
2067 __ cmpw(count, 8 >> shift); // Short arrays (< 8 bytes) fill by element |
|
2068 __ br(Assembler::LO, L_fill_elements); |
|
2069 break; |
|
2070 default: ShouldNotReachHere(); |
|
2071 } |
|
2072 |
|
2073 // Align source address at 8 bytes address boundary. |
|
2074 Label L_skip_align1, L_skip_align2, L_skip_align4; |
|
2075 if (!aligned) { |
|
2076 switch (t) { |
|
2077 case T_BYTE: |
|
2078 // One byte misalignment happens only for byte arrays. |
|
2079 __ tbz(to, 0, L_skip_align1); |
|
2080 __ strb(value, Address(__ post(to, 1))); |
|
2081 __ subw(count, count, 1); |
|
2082 __ bind(L_skip_align1); |
|
2083 // Fallthrough |
|
2084 case T_SHORT: |
|
2085 // Two bytes misalignment happens only for byte and short (char) arrays. |
|
2086 __ tbz(to, 1, L_skip_align2); |
|
2087 __ strh(value, Address(__ post(to, 2))); |
|
2088 __ subw(count, count, 2 >> shift); |
|
2089 __ bind(L_skip_align2); |
|
2090 // Fallthrough |
|
2091 case T_INT: |
|
2092 // Align to 8 bytes, we know we are 4 byte aligned to start. |
|
2093 __ tbz(to, 2, L_skip_align4); |
|
2094 __ strw(value, Address(__ post(to, 4))); |
|
2095 __ subw(count, count, 4 >> shift); |
|
2096 __ bind(L_skip_align4); |
|
2097 break; |
|
2098 default: ShouldNotReachHere(); |
|
2099 } |
|
2100 } |
|
2101 |
|
2102 // |
|
2103 // Fill large chunks |
|
2104 // |
|
2105 __ lsrw(cnt_words, count, 3 - shift); // number of words |
|
2106 __ bfi(value, value, 32, 32); // 32 bit -> 64 bit |
|
2107 __ subw(count, count, cnt_words, Assembler::LSL, 3 - shift); |
|
2108 __ fill_words(to, cnt_words, value); |
|
2109 |
|
2110 // Remaining count is less than 8 bytes. Fill it by a single store. |
|
2111 // Note that the total length is no less than 8 bytes. |
|
2112 if (t == T_BYTE || t == T_SHORT) { |
|
2113 Label L_exit1; |
|
2114 __ cbzw(count, L_exit1); |
|
2115 __ add(to, to, count, Assembler::LSL, shift); // points to the end |
|
2116 __ str(value, Address(to, -8)); // overwrite some elements |
|
2117 __ bind(L_exit1); |
|
2118 __ leave(); |
|
2119 __ ret(lr); |
|
2120 } |
|
2121 |
|
2122 // Handle copies less than 8 bytes. |
|
2123 Label L_fill_2, L_fill_4, L_exit2; |
|
2124 __ bind(L_fill_elements); |
|
2125 switch (t) { |
|
2126 case T_BYTE: |
|
2127 __ tbz(count, 0, L_fill_2); |
|
2128 __ strb(value, Address(__ post(to, 1))); |
|
2129 __ bind(L_fill_2); |
|
2130 __ tbz(count, 1, L_fill_4); |
|
2131 __ strh(value, Address(__ post(to, 2))); |
|
2132 __ bind(L_fill_4); |
|
2133 __ tbz(count, 2, L_exit2); |
|
2134 __ strw(value, Address(to)); |
|
2135 break; |
|
2136 case T_SHORT: |
|
2137 __ tbz(count, 0, L_fill_4); |
|
2138 __ strh(value, Address(__ post(to, 2))); |
|
2139 __ bind(L_fill_4); |
|
2140 __ tbz(count, 1, L_exit2); |
|
2141 __ strw(value, Address(to)); |
|
2142 break; |
|
2143 case T_INT: |
|
2144 __ cbzw(count, L_exit2); |
|
2145 __ strw(value, Address(to)); |
|
2146 break; |
|
2147 default: ShouldNotReachHere(); |
|
2148 } |
|
2149 __ bind(L_exit2); |
|
2150 __ leave(); |
|
2151 __ ret(lr); |
|
2152 return start; |
|
2153 } |
|
2154 |
2025 void generate_arraycopy_stubs() { |
2155 void generate_arraycopy_stubs() { |
2026 address entry; |
2156 address entry; |
2027 address entry_jbyte_arraycopy; |
2157 address entry_jbyte_arraycopy; |
2028 address entry_jshort_arraycopy; |
2158 address entry_jshort_arraycopy; |
2029 address entry_jint_arraycopy; |
2159 address entry_jint_arraycopy; |
2123 entry_jint_arraycopy, |
2253 entry_jint_arraycopy, |
2124 entry_oop_arraycopy, |
2254 entry_oop_arraycopy, |
2125 entry_jlong_arraycopy, |
2255 entry_jlong_arraycopy, |
2126 entry_checkcast_arraycopy); |
2256 entry_checkcast_arraycopy); |
2127 |
2257 |
|
2258 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); |
|
2259 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); |
|
2260 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); |
|
2261 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); |
|
2262 StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); |
|
2263 StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); |
2128 } |
2264 } |
2129 |
2265 |
2130 void generate_math_stubs() { Unimplemented(); } |
2266 void generate_math_stubs() { Unimplemented(); } |
2131 |
2267 |
2132 // Arguments: |
2268 // Arguments: |