OLD | NEW |
---|---|
1 | 1 |
2 // Copyright 2012 the V8 project authors. All rights reserved. | 2 // Copyright 2012 the V8 project authors. All rights reserved. |
3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
5 | 5 |
6 #include <limits.h> // For LONG_MIN, LONG_MAX. | 6 #include <limits.h> // For LONG_MIN, LONG_MAX. |
7 | 7 |
8 #if V8_TARGET_ARCH_MIPS | 8 #if V8_TARGET_ARCH_MIPS |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1931 | 1931 |
1932 | 1932 |
1933 // Emulated condtional branches do not emit a nop in the branch delay slot. | 1933 // Emulated condtional branches do not emit a nop in the branch delay slot. |
1934 // | 1934 // |
1935 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. | 1935 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. |
1936 #define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK( \ | 1936 #define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK( \ |
1937 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ | 1937 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ |
1938 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) | 1938 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) |
1939 | 1939 |
1940 | 1940 |
1941 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { | 1941 void MacroAssembler::Branch(int32_t offset, BranchDelaySlot bdslot) { |
1942 BranchShort(offset, bdslot); | 1942 BranchShort(offset, bdslot); |
1943 } | 1943 } |
1944 | 1944 |
1945 | 1945 |
1946 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, | 1946 void MacroAssembler::Branch(int32_t offset, Condition cond, Register rs, |
1947 const Operand& rt, | 1947 const Operand& rt, BranchDelaySlot bdslot) { |
1948 BranchDelaySlot bdslot) { | |
1949 BranchShort(offset, cond, rs, rt, bdslot); | 1948 BranchShort(offset, cond, rs, rt, bdslot); |
1950 } | 1949 } |
1951 | 1950 |
1952 | 1951 |
1953 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { | 1952 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { |
1954 if (L->is_bound()) { | 1953 if (L->is_bound()) { |
1955 if (is_near(L)) { | 1954 if (is_near(L)) { |
1956 BranchShort(L, bdslot); | 1955 BranchShort(L, bdslot); |
1957 } else { | 1956 } else { |
1958 Jr(L, bdslot); | 1957 Jr(L, bdslot); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2005 void MacroAssembler::Branch(Label* L, | 2004 void MacroAssembler::Branch(Label* L, |
2006 Condition cond, | 2005 Condition cond, |
2007 Register rs, | 2006 Register rs, |
2008 Heap::RootListIndex index, | 2007 Heap::RootListIndex index, |
2009 BranchDelaySlot bdslot) { | 2008 BranchDelaySlot bdslot) { |
2010 LoadRoot(at, index); | 2009 LoadRoot(at, index); |
2011 Branch(L, cond, rs, Operand(at), bdslot); | 2010 Branch(L, cond, rs, Operand(at), bdslot); |
2012 } | 2011 } |
2013 | 2012 |
2014 | 2013 |
2015 void MacroAssembler::BranchShort(int16_t offset, BranchDelaySlot bdslot) { | 2014 void MacroAssembler::BranchShortHelper(int16_t offset, Label* L, |
2015 BranchDelaySlot bdslot) { | |
2016 offset = GetOffset(offset, L, 16); | |
2016 b(offset); | 2017 b(offset); |
2017 | 2018 |
2018 // Emit a nop in the branch delay slot if required. | 2019 // Emit a nop in the branch delay slot if required. |
2019 if (bdslot == PROTECT) | 2020 if (bdslot == PROTECT) |
2020 nop(); | 2021 nop(); |
2021 } | 2022 } |
2022 | 2023 |
2023 | 2024 |
2024 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, | 2025 void MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L) { |
2025 const Operand& rt, | 2026 offset = GetOffset(offset, L, 26); |
2026 BranchDelaySlot bdslot) { | 2027 bc(offset); |
2027 BRANCH_ARGS_CHECK(cond, rs, rt); | 2028 } |
2028 DCHECK(!rs.is(zero_reg)); | 2029 |
2029 Register r2 = no_reg; | 2030 |
2031 void MacroAssembler::BranchShort(int32_t offset, BranchDelaySlot bdslot) { | |
2032 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { | |
2033 DCHECK(is_int26(offset)); | |
2034 BranchShortHelperR6(offset, nullptr); | |
2035 } else { | |
2036 DCHECK(is_int16(offset)); | |
2037 BranchShortHelper(offset, nullptr, bdslot); | |
2038 } | |
2039 } | |
2040 | |
2041 | |
2042 void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) { | |
2043 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { | |
2044 BranchShortHelperR6(0, L); | |
2045 } else { | |
2046 BranchShortHelper(0, L, bdslot); | |
2047 } | |
2048 } | |
2049 | |
2050 | |
2051 static inline bool IsZero(const Operand& rt) { | |
2052 if (rt.is_reg()) { | |
2053 return rt.rm().is(zero_reg); | |
2054 } else { | |
2055 return rt.immediate() == 0; | |
2056 } | |
2057 } | |
2058 | |
2059 | |
2060 int32_t MacroAssembler::GetOffset(int32_t offset, Label* L, int bits) { | |
2061 if (L) { | |
2062 return branch_offset_helper(L, false, bits) >> 2; | |
2063 } else { | |
2064 DCHECK(is_intn(offset, bits)); | |
2065 } | |
2066 return offset; | |
2067 } | |
2068 | |
2069 | |
2070 void MacroAssembler::BranchShortHelperR6(int32_t offset, Label* L, | |
2071 Condition cond, Register rs, | |
2072 const Operand& rt) { | |
2073 Register scratch = rs.is(at) ? t8 : at; | |
2074 | |
2075 // Be careful to always use shifted_branch_offset only just before the | |
2076 // branch instruction, as the location will be remember for patching the | |
2077 // target. | |
2078 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2079 switch (cond) { | |
2080 case cc_always: | |
2081 offset = GetOffset(offset, L, 26); | |
2082 bc(offset); | |
2083 break; | |
2084 case eq: | |
2085 if (rs.code() == rt.rm_.reg_code) { | |
2086 // Pre R6 beq is used here to make the code patchable. Otherwise bc | |
2087 // should be used which has no condition field so is not patchable. | |
2088 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2089 offset = GetOffset(offset, L, 26); | |
2090 beq(rs, scratch, offset); | |
2091 nop(); | |
2092 } else if (IsZero(rt)) { | |
2093 offset = GetOffset(offset, L, 21); | |
2094 beqzc(rs, offset); | |
2095 } else { | |
2096 // We don't want any other register but scratch clobbered. | |
2097 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2098 offset = GetOffset(offset, L, 16); | |
2099 beqc(rs, scratch, offset); | |
2100 } | |
2101 break; | |
2102 case ne: | |
2103 if (rs.code() == rt.rm_.reg_code) { | |
2104 // Pre R6 bne is used here to make the code patchable. Otherwise we | |
2105 // should not generate any instruction. | |
2106 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2107 offset = GetOffset(offset, L, 26); | |
2108 bne(rs, scratch, offset); | |
2109 nop(); | |
2110 } else if (IsZero(rt)) { | |
2111 offset = GetOffset(offset, L, 21); | |
2112 bnezc(rs, offset); | |
2113 } else { | |
2114 // We don't want any other register but scratch clobbered. | |
2115 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2116 offset = GetOffset(offset, L, 16); | |
2117 bnec(rs, scratch, offset); | |
2118 } | |
2119 break; | |
2120 | |
2121 // Signed comparison. | |
2122 case greater: | |
2123 // rs > rt | |
2124 if (rs.code() == rt.rm_.reg_code) { | |
2125 break; // No code needs to be emitted. | |
2126 } else if (rs.is(zero_reg)) { | |
2127 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2128 offset = GetOffset(offset, L, 16); | |
2129 bltzc(scratch, offset); | |
2130 } else if (IsZero(rt)) { | |
2131 offset = GetOffset(offset, L, 16); | |
2132 bgtzc(rs, offset); | |
2133 } else { | |
2134 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2135 DCHECK(!rs.is(scratch)); | |
2136 offset = GetOffset(offset, L, 16); | |
2137 bltc(scratch, rs, offset); | |
2138 } | |
2139 break; | |
2140 case greater_equal: | |
2141 // rs >= rt | |
2142 if (rs.code() == rt.rm_.reg_code) { | |
2143 offset = GetOffset(offset, L, 26); | |
2144 bc(offset); | |
2145 } else if (rs.is(zero_reg)) { | |
2146 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2147 offset = GetOffset(offset, L, 16); | |
2148 blezc(scratch, offset); | |
2149 } else if (IsZero(rt)) { | |
2150 offset = GetOffset(offset, L, 16); | |
2151 bgezc(rs, offset); | |
2152 } else { | |
2153 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2154 DCHECK(!rs.is(scratch)); | |
2155 offset = GetOffset(offset, L, 16); | |
2156 bgec(rs, scratch, offset); | |
2157 } | |
2158 break; | |
2159 case less: | |
2160 // rs < rt | |
2161 if (rs.code() == rt.rm_.reg_code) { | |
2162 break; // No code needs to be emitted. | |
2163 } else if (rs.is(zero_reg)) { | |
2164 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2165 offset = GetOffset(offset, L, 16); | |
2166 bgtzc(scratch, offset); | |
2167 } else if (IsZero(rt)) { | |
2168 offset = GetOffset(offset, L, 16); | |
2169 bltzc(rs, offset); | |
2170 } else { | |
2171 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2172 DCHECK(!rs.is(scratch)); | |
2173 offset = GetOffset(offset, L, 16); | |
2174 bltc(rs, scratch, offset); | |
2175 } | |
2176 break; | |
2177 case less_equal: | |
2178 // rs <= rt | |
2179 if (rs.code() == rt.rm_.reg_code) { | |
2180 offset = GetOffset(offset, L, 26); | |
2181 bc(offset); | |
2182 } else if (rs.is(zero_reg)) { | |
2183 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2184 offset = GetOffset(offset, L, 16); | |
2185 bgezc(scratch, offset); | |
2186 } else if (IsZero(rt)) { | |
2187 offset = GetOffset(offset, L, 16); | |
2188 blezc(rs, offset); | |
2189 } else { | |
2190 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2191 DCHECK(!rs.is(scratch)); | |
2192 offset = GetOffset(offset, L, 21); | |
2193 bgec(scratch, rs, offset); | |
2194 } | |
2195 break; | |
2196 | |
2197 // Unsigned comparison. | |
2198 case Ugreater: | |
2199 // rs > rt | |
2200 if (rs.code() == rt.rm_.reg_code) { | |
2201 break; // No code needs to be emitted. | |
2202 } else if (rs.is(zero_reg)) { | |
2203 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2204 offset = GetOffset(offset, L, 16); | |
2205 bnezc(scratch, offset); | |
2206 } else if (IsZero(rt)) { | |
2207 offset = GetOffset(offset, L, 21); | |
2208 bnezc(rs, offset); | |
2209 } else { | |
2210 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2211 DCHECK(!rs.is(scratch)); | |
2212 offset = GetOffset(offset, L, 16); | |
2213 bltuc(scratch, rs, offset); | |
2214 } | |
2215 break; | |
2216 case Ugreater_equal: | |
2217 // rs >= rt | |
2218 if (rs.code() == rt.rm_.reg_code) { | |
2219 offset = GetOffset(offset, L, 26); | |
2220 bc(offset); | |
2221 } else if (rs.is(zero_reg)) { | |
2222 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2223 offset = GetOffset(offset, L, 21); | |
2224 beqzc(scratch, offset); | |
2225 } else if (IsZero(rt)) { | |
2226 offset = GetOffset(offset, L, 26); | |
2227 bc(offset); | |
2228 } else { | |
2229 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2230 DCHECK(!rs.is(scratch)); | |
2231 offset = GetOffset(offset, L, 16); | |
2232 bgeuc(rs, scratch, offset); | |
2233 } | |
2234 break; | |
2235 case Uless: | |
2236 // rs < rt | |
2237 if (rs.code() == rt.rm_.reg_code) { | |
2238 break; // No code needs to be emitted. | |
2239 } else if (rs.is(zero_reg)) { | |
2240 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2241 offset = GetOffset(offset, L, 21); | |
2242 bnezc(scratch, offset); | |
2243 } else if (IsZero(rt)) { | |
2244 break; // No code needs to be emitted. | |
2245 } else { | |
2246 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2247 DCHECK(!rs.is(scratch)); | |
2248 offset = GetOffset(offset, L, 16); | |
2249 bltuc(rs, scratch, offset); | |
2250 } | |
2251 break; | |
2252 case Uless_equal: | |
2253 // rs <= rt | |
2254 if (rs.code() == rt.rm_.reg_code) { | |
2255 offset = GetOffset(offset, L, 26); | |
2256 bc(offset); | |
2257 } else if (rs.is(zero_reg)) { | |
2258 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2259 offset = GetOffset(offset, L, 26); | |
2260 bc(offset); | |
2261 } else if (IsZero(rt)) { | |
2262 offset = GetOffset(offset, L, 21); | |
2263 beqzc(rs, offset); | |
2264 } else { | |
2265 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2266 DCHECK(!rs.is(scratch)); | |
2267 offset = GetOffset(offset, L, 16); | |
2268 bgeuc(scratch, rs, offset); | |
2269 } | |
2270 break; | |
2271 default: | |
2272 UNREACHABLE(); | |
2273 } | |
2274 } | |
2275 | |
2276 | |
2277 void MacroAssembler::BranchShortHelper(int16_t offset, Label* L, Condition cond, | |
2278 Register rs, const Operand& rt, | |
2279 BranchDelaySlot bdslot) { | |
2030 Register scratch = at; | 2280 Register scratch = at; |
2031 | 2281 |
2032 if (rt.is_reg()) { | 2282 // Be careful to always use shifted_branch_offset only just before the |
2033 // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or | 2283 // branch instruction, as the location will be remember for patching the |
2034 // rt. | 2284 // target. |
2035 BlockTrampolinePoolScope block_trampoline_pool(this); | 2285 BlockTrampolinePoolScope block_trampoline_pool(this); |
2036 r2 = rt.rm_; | 2286 switch (cond) { |
2037 switch (cond) { | 2287 case cc_always: |
2038 case cc_always: | 2288 offset = GetOffset(offset, L, 16); |
2289 b(offset); | |
2290 break; | |
2291 case eq: | |
2292 if (IsZero(rt)) { | |
2293 offset = GetOffset(offset, L, 16); | |
2294 beq(rs, zero_reg, offset); | |
2295 } else { | |
2296 // We don't want any other register but scratch clobbered. | |
2297 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2298 offset = GetOffset(offset, L, 16); | |
2299 beq(rs, scratch, offset); | |
2300 } | |
2301 break; | |
2302 case ne: | |
2303 if (IsZero(rt)) { | |
2304 offset = GetOffset(offset, L, 16); | |
2305 bne(rs, zero_reg, offset); | |
2306 } else { | |
2307 // We don't want any other register but scratch clobbered. | |
2308 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2309 offset = GetOffset(offset, L, 16); | |
2310 bne(rs, scratch, offset); | |
2311 } | |
2312 break; | |
2313 | |
2314 // Signed comparison. | |
2315 case greater: | |
2316 if (IsZero(rt)) { | |
2317 offset = GetOffset(offset, L, 16); | |
2318 bgtz(rs, offset); | |
2319 } else { | |
2320 Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2321 offset = GetOffset(offset, L, 16); | |
2322 bne(scratch, zero_reg, offset); | |
2323 } | |
2324 break; | |
2325 case greater_equal: | |
2326 if (IsZero(rt)) { | |
2327 offset = GetOffset(offset, L, 16); | |
2328 bgez(rs, offset); | |
2329 } else { | |
2330 Slt(scratch, rs, rt); | |
2331 offset = GetOffset(offset, L, 16); | |
2332 beq(scratch, zero_reg, offset); | |
2333 } | |
2334 break; | |
2335 case less: | |
2336 if (IsZero(rt)) { | |
2337 offset = GetOffset(offset, L, 16); | |
2338 bltz(rs, offset); | |
2339 } else { | |
2340 Slt(scratch, rs, rt); | |
2341 offset = GetOffset(offset, L, 16); | |
2342 bne(scratch, zero_reg, offset); | |
2343 } | |
2344 break; | |
2345 case less_equal: | |
2346 if (IsZero(rt)) { | |
2347 offset = GetOffset(offset, L, 16); | |
2348 blez(rs, offset); | |
2349 } else { | |
2350 Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2351 offset = GetOffset(offset, L, 16); | |
2352 beq(scratch, zero_reg, offset); | |
2353 } | |
2354 break; | |
2355 | |
2356 // Unsigned comparison. | |
2357 case Ugreater: | |
2358 if (IsZero(rt)) { | |
2359 offset = GetOffset(offset, L, 16); | |
2360 bne(rs, zero_reg, offset); | |
2361 } else { | |
2362 Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2363 offset = GetOffset(offset, L, 16); | |
2364 bne(scratch, zero_reg, offset); | |
2365 } | |
2366 break; | |
2367 case Ugreater_equal: | |
2368 if (IsZero(rt)) { | |
2369 offset = GetOffset(offset, L, 16); | |
2039 b(offset); | 2370 b(offset); |
2040 break; | 2371 } else { |
2041 case eq: | 2372 Sltu(scratch, rs, rt); |
2042 beq(rs, r2, offset); | 2373 offset = GetOffset(offset, L, 16); |
2043 break; | 2374 beq(scratch, zero_reg, offset); |
2044 case ne: | 2375 } |
2045 bne(rs, r2, offset); | 2376 break; |
2046 break; | 2377 case Uless: |
2047 // Signed comparison. | 2378 if (IsZero(rt)) { |
2048 case greater: | 2379 return; // No code needs to be emitted. |
2049 if (r2.is(zero_reg)) { | 2380 } else { |
2050 bgtz(rs, offset); | 2381 Sltu(scratch, rs, rt); |
2051 } else { | 2382 offset = GetOffset(offset, L, 16); |
2052 slt(scratch, r2, rs); | 2383 bne(scratch, zero_reg, offset); |
2053 bne(scratch, zero_reg, offset); | 2384 } |
2054 } | 2385 break; |
2055 break; | 2386 case Uless_equal: |
2056 case greater_equal: | 2387 if (IsZero(rt)) { |
2057 if (r2.is(zero_reg)) { | 2388 offset = GetOffset(offset, L, 16); |
2058 bgez(rs, offset); | 2389 beq(rs, zero_reg, offset); |
2059 } else { | 2390 } else { |
2060 slt(scratch, rs, r2); | 2391 Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); |
2061 beq(scratch, zero_reg, offset); | 2392 offset = GetOffset(offset, L, 16); |
2062 } | 2393 beq(scratch, zero_reg, offset); |
2063 break; | 2394 } |
2064 case less: | 2395 break; |
2065 if (r2.is(zero_reg)) { | 2396 default: |
2066 bltz(rs, offset); | 2397 UNREACHABLE(); |
2067 } else { | 2398 } |
2068 slt(scratch, rs, r2); | 2399 |
2069 bne(scratch, zero_reg, offset); | |
2070 } | |
2071 break; | |
2072 case less_equal: | |
2073 if (r2.is(zero_reg)) { | |
2074 blez(rs, offset); | |
2075 } else { | |
2076 slt(scratch, r2, rs); | |
2077 beq(scratch, zero_reg, offset); | |
2078 } | |
2079 break; | |
2080 // Unsigned comparison. | |
2081 case Ugreater: | |
2082 if (r2.is(zero_reg)) { | |
2083 bne(rs, zero_reg, offset); | |
2084 } else { | |
2085 sltu(scratch, r2, rs); | |
2086 bne(scratch, zero_reg, offset); | |
2087 } | |
2088 break; | |
2089 case Ugreater_equal: | |
2090 if (r2.is(zero_reg)) { | |
2091 b(offset); | |
2092 } else { | |
2093 sltu(scratch, rs, r2); | |
2094 beq(scratch, zero_reg, offset); | |
2095 } | |
2096 break; | |
2097 case Uless: | |
2098 if (r2.is(zero_reg)) { | |
2099 // No code needs to be emitted. | |
2100 return; | |
2101 } else { | |
2102 sltu(scratch, rs, r2); | |
2103 bne(scratch, zero_reg, offset); | |
2104 } | |
2105 break; | |
2106 case Uless_equal: | |
2107 if (r2.is(zero_reg)) { | |
2108 beq(rs, zero_reg, offset); | |
2109 } else { | |
2110 sltu(scratch, r2, rs); | |
2111 beq(scratch, zero_reg, offset); | |
2112 } | |
2113 break; | |
2114 default: | |
2115 UNREACHABLE(); | |
2116 } | |
2117 } else { | |
2118 // Be careful to always use shifted_branch_offset only just before the | |
2119 // branch instruction, as the location will be remember for patching the | |
2120 // target. | |
2121 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2122 switch (cond) { | |
2123 case cc_always: | |
2124 b(offset); | |
2125 break; | |
2126 case eq: | |
2127 if (rt.imm32_ == 0) { | |
2128 beq(rs, zero_reg, offset); | |
2129 } else { | |
2130 // We don't want any other register but scratch clobbered. | |
2131 DCHECK(!scratch.is(rs)); | |
2132 r2 = scratch; | |
2133 li(r2, rt); | |
2134 beq(rs, r2, offset); | |
2135 } | |
2136 break; | |
2137 case ne: | |
2138 if (rt.imm32_ == 0) { | |
2139 bne(rs, zero_reg, offset); | |
2140 } else { | |
2141 // We don't want any other register but scratch clobbered. | |
2142 DCHECK(!scratch.is(rs)); | |
2143 r2 = scratch; | |
2144 li(r2, rt); | |
2145 bne(rs, r2, offset); | |
2146 } | |
2147 break; | |
2148 // Signed comparison. | |
2149 case greater: | |
2150 if (rt.imm32_ == 0) { | |
2151 bgtz(rs, offset); | |
2152 } else { | |
2153 r2 = scratch; | |
2154 li(r2, rt); | |
2155 slt(scratch, r2, rs); | |
2156 bne(scratch, zero_reg, offset); | |
2157 } | |
2158 break; | |
2159 case greater_equal: | |
2160 if (rt.imm32_ == 0) { | |
2161 bgez(rs, offset); | |
2162 } else if (is_int16(rt.imm32_)) { | |
2163 slti(scratch, rs, rt.imm32_); | |
2164 beq(scratch, zero_reg, offset); | |
2165 } else { | |
2166 r2 = scratch; | |
2167 li(r2, rt); | |
2168 slt(scratch, rs, r2); | |
2169 beq(scratch, zero_reg, offset); | |
2170 } | |
2171 break; | |
2172 case less: | |
2173 if (rt.imm32_ == 0) { | |
2174 bltz(rs, offset); | |
2175 } else if (is_int16(rt.imm32_)) { | |
2176 slti(scratch, rs, rt.imm32_); | |
2177 bne(scratch, zero_reg, offset); | |
2178 } else { | |
2179 r2 = scratch; | |
2180 li(r2, rt); | |
2181 slt(scratch, rs, r2); | |
2182 bne(scratch, zero_reg, offset); | |
2183 } | |
2184 break; | |
2185 case less_equal: | |
2186 if (rt.imm32_ == 0) { | |
2187 blez(rs, offset); | |
2188 } else { | |
2189 r2 = scratch; | |
2190 li(r2, rt); | |
2191 slt(scratch, r2, rs); | |
2192 beq(scratch, zero_reg, offset); | |
2193 } | |
2194 break; | |
2195 // Unsigned comparison. | |
2196 case Ugreater: | |
2197 if (rt.imm32_ == 0) { | |
2198 bne(rs, zero_reg, offset); | |
2199 } else { | |
2200 r2 = scratch; | |
2201 li(r2, rt); | |
2202 sltu(scratch, r2, rs); | |
2203 bne(scratch, zero_reg, offset); | |
2204 } | |
2205 break; | |
2206 case Ugreater_equal: | |
2207 if (rt.imm32_ == 0) { | |
2208 b(offset); | |
2209 } else if (is_int16(rt.imm32_)) { | |
2210 sltiu(scratch, rs, rt.imm32_); | |
2211 beq(scratch, zero_reg, offset); | |
2212 } else { | |
2213 r2 = scratch; | |
2214 li(r2, rt); | |
2215 sltu(scratch, rs, r2); | |
2216 beq(scratch, zero_reg, offset); | |
2217 } | |
2218 break; | |
2219 case Uless: | |
2220 if (rt.imm32_ == 0) { | |
2221 // No code needs to be emitted. | |
2222 return; | |
2223 } else if (is_int16(rt.imm32_)) { | |
2224 sltiu(scratch, rs, rt.imm32_); | |
2225 bne(scratch, zero_reg, offset); | |
2226 } else { | |
2227 r2 = scratch; | |
2228 li(r2, rt); | |
2229 sltu(scratch, rs, r2); | |
2230 bne(scratch, zero_reg, offset); | |
2231 } | |
2232 break; | |
2233 case Uless_equal: | |
2234 if (rt.imm32_ == 0) { | |
2235 beq(rs, zero_reg, offset); | |
2236 } else { | |
2237 r2 = scratch; | |
2238 li(r2, rt); | |
2239 sltu(scratch, r2, rs); | |
2240 beq(scratch, zero_reg, offset); | |
2241 } | |
2242 break; | |
2243 default: | |
2244 UNREACHABLE(); | |
2245 } | |
2246 } | |
2247 // Emit a nop in the branch delay slot if required. | 2400 // Emit a nop in the branch delay slot if required. |
2248 if (bdslot == PROTECT) | 2401 if (bdslot == PROTECT) |
2249 nop(); | |
2250 } | |
2251 | |
2252 | |
2253 void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) { | |
2254 // We use branch_offset as an argument for the branch instructions to be sure | |
2255 // it is called just before generating the branch instruction, as needed. | |
2256 | |
2257 b(shifted_branch_offset(L, false)); | |
2258 | |
2259 // Emit a nop in the branch delay slot if required. | |
2260 if (bdslot == PROTECT) | |
2261 nop(); | 2402 nop(); |
2262 } | 2403 } |
2263 | 2404 |
2264 | 2405 |
2406 void MacroAssembler::BranchShort(int32_t offset, Condition cond, Register rs, | |
2407 const Operand& rt, BranchDelaySlot bdslot) { | |
2408 BRANCH_ARGS_CHECK(cond, rs, rt); | |
2409 | |
2410 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { | |
2411 DCHECK(is_int26(offset)); | |
2412 BranchShortHelperR6(offset, nullptr, cond, rs, rt); | |
2413 } else { | |
2414 DCHECK(is_int16(offset)); | |
2415 BranchShortHelper(offset, nullptr, cond, rs, rt, bdslot); | |
2416 } | |
2417 } | |
2418 | |
2419 | |
2265 void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs, | 2420 void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs, |
2266 const Operand& rt, | 2421 const Operand& rt, |
2267 BranchDelaySlot bdslot) { | 2422 BranchDelaySlot bdslot) { |
2268 BRANCH_ARGS_CHECK(cond, rs, rt); | 2423 BRANCH_ARGS_CHECK(cond, rs, rt); |
2269 | 2424 |
2270 int32_t offset = 0; | 2425 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { |
2271 Register r2 = no_reg; | 2426 BranchShortHelperR6(0, L, cond, rs, rt); |
2272 Register scratch = at; | |
2273 if (rt.is_reg()) { | |
2274 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2275 r2 = rt.rm_; | |
2276 // Be careful to always use shifted_branch_offset only just before the | |
2277 // branch instruction, as the location will be remember for patching the | |
2278 // target. | |
2279 switch (cond) { | |
2280 case cc_always: | |
2281 offset = shifted_branch_offset(L, false); | |
2282 b(offset); | |
2283 break; | |
2284 case eq: | |
2285 offset = shifted_branch_offset(L, false); | |
2286 beq(rs, r2, offset); | |
2287 break; | |
2288 case ne: | |
2289 offset = shifted_branch_offset(L, false); | |
2290 bne(rs, r2, offset); | |
2291 break; | |
2292 // Signed comparison. | |
2293 case greater: | |
2294 if (r2.is(zero_reg)) { | |
2295 offset = shifted_branch_offset(L, false); | |
2296 bgtz(rs, offset); | |
2297 } else { | |
2298 slt(scratch, r2, rs); | |
2299 offset = shifted_branch_offset(L, false); | |
2300 bne(scratch, zero_reg, offset); | |
2301 } | |
2302 break; | |
2303 case greater_equal: | |
2304 if (r2.is(zero_reg)) { | |
2305 offset = shifted_branch_offset(L, false); | |
2306 bgez(rs, offset); | |
2307 } else { | |
2308 slt(scratch, rs, r2); | |
2309 offset = shifted_branch_offset(L, false); | |
2310 beq(scratch, zero_reg, offset); | |
2311 } | |
2312 break; | |
2313 case less: | |
2314 if (r2.is(zero_reg)) { | |
2315 offset = shifted_branch_offset(L, false); | |
2316 bltz(rs, offset); | |
2317 } else { | |
2318 slt(scratch, rs, r2); | |
2319 offset = shifted_branch_offset(L, false); | |
2320 bne(scratch, zero_reg, offset); | |
2321 } | |
2322 break; | |
2323 case less_equal: | |
2324 if (r2.is(zero_reg)) { | |
2325 offset = shifted_branch_offset(L, false); | |
2326 blez(rs, offset); | |
2327 } else { | |
2328 slt(scratch, r2, rs); | |
2329 offset = shifted_branch_offset(L, false); | |
2330 beq(scratch, zero_reg, offset); | |
2331 } | |
2332 break; | |
2333 // Unsigned comparison. | |
2334 case Ugreater: | |
2335 if (r2.is(zero_reg)) { | |
2336 offset = shifted_branch_offset(L, false); | |
2337 bne(rs, zero_reg, offset); | |
2338 } else { | |
2339 sltu(scratch, r2, rs); | |
2340 offset = shifted_branch_offset(L, false); | |
2341 bne(scratch, zero_reg, offset); | |
2342 } | |
2343 break; | |
2344 case Ugreater_equal: | |
2345 if (r2.is(zero_reg)) { | |
2346 offset = shifted_branch_offset(L, false); | |
2347 b(offset); | |
2348 } else { | |
2349 sltu(scratch, rs, r2); | |
2350 offset = shifted_branch_offset(L, false); | |
2351 beq(scratch, zero_reg, offset); | |
2352 } | |
2353 break; | |
2354 case Uless: | |
2355 if (r2.is(zero_reg)) { | |
2356 // No code needs to be emitted. | |
2357 return; | |
2358 } else { | |
2359 sltu(scratch, rs, r2); | |
2360 offset = shifted_branch_offset(L, false); | |
2361 bne(scratch, zero_reg, offset); | |
2362 } | |
2363 break; | |
2364 case Uless_equal: | |
2365 if (r2.is(zero_reg)) { | |
2366 offset = shifted_branch_offset(L, false); | |
2367 beq(rs, zero_reg, offset); | |
2368 } else { | |
2369 sltu(scratch, r2, rs); | |
2370 offset = shifted_branch_offset(L, false); | |
2371 beq(scratch, zero_reg, offset); | |
2372 } | |
2373 break; | |
2374 default: | |
2375 UNREACHABLE(); | |
2376 } | |
2377 } else { | 2427 } else { |
2378 // Be careful to always use shifted_branch_offset only just before the | 2428 BranchShortHelper(0, L, cond, rs, rt, bdslot); |
2379 // branch instruction, as the location will be remember for patching the | |
2380 // target. | |
2381 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2382 switch (cond) { | |
2383 case cc_always: | |
2384 offset = shifted_branch_offset(L, false); | |
2385 b(offset); | |
2386 break; | |
2387 case eq: | |
2388 if (rt.imm32_ == 0) { | |
2389 offset = shifted_branch_offset(L, false); | |
2390 beq(rs, zero_reg, offset); | |
2391 } else { | |
2392 DCHECK(!scratch.is(rs)); | |
2393 r2 = scratch; | |
2394 li(r2, rt); | |
2395 offset = shifted_branch_offset(L, false); | |
2396 beq(rs, r2, offset); | |
2397 } | |
2398 break; | |
2399 case ne: | |
2400 if (rt.imm32_ == 0) { | |
2401 offset = shifted_branch_offset(L, false); | |
2402 bne(rs, zero_reg, offset); | |
2403 } else { | |
2404 DCHECK(!scratch.is(rs)); | |
2405 r2 = scratch; | |
2406 li(r2, rt); | |
2407 offset = shifted_branch_offset(L, false); | |
2408 bne(rs, r2, offset); | |
2409 } | |
2410 break; | |
2411 // Signed comparison. | |
2412 case greater: | |
2413 if (rt.imm32_ == 0) { | |
2414 offset = shifted_branch_offset(L, false); | |
2415 bgtz(rs, offset); | |
2416 } else { | |
2417 DCHECK(!scratch.is(rs)); | |
2418 r2 = scratch; | |
2419 li(r2, rt); | |
2420 slt(scratch, r2, rs); | |
2421 offset = shifted_branch_offset(L, false); | |
2422 bne(scratch, zero_reg, offset); | |
2423 } | |
2424 break; | |
2425 case greater_equal: | |
2426 if (rt.imm32_ == 0) { | |
2427 offset = shifted_branch_offset(L, false); | |
2428 bgez(rs, offset); | |
2429 } else if (is_int16(rt.imm32_)) { | |
2430 slti(scratch, rs, rt.imm32_); | |
2431 offset = shifted_branch_offset(L, false); | |
2432 beq(scratch, zero_reg, offset); | |
2433 } else { | |
2434 DCHECK(!scratch.is(rs)); | |
2435 r2 = scratch; | |
2436 li(r2, rt); | |
2437 slt(scratch, rs, r2); | |
2438 offset = shifted_branch_offset(L, false); | |
2439 beq(scratch, zero_reg, offset); | |
2440 } | |
2441 break; | |
2442 case less: | |
2443 if (rt.imm32_ == 0) { | |
2444 offset = shifted_branch_offset(L, false); | |
2445 bltz(rs, offset); | |
2446 } else if (is_int16(rt.imm32_)) { | |
2447 slti(scratch, rs, rt.imm32_); | |
2448 offset = shifted_branch_offset(L, false); | |
2449 bne(scratch, zero_reg, offset); | |
2450 } else { | |
2451 DCHECK(!scratch.is(rs)); | |
2452 r2 = scratch; | |
2453 li(r2, rt); | |
2454 slt(scratch, rs, r2); | |
2455 offset = shifted_branch_offset(L, false); | |
2456 bne(scratch, zero_reg, offset); | |
2457 } | |
2458 break; | |
2459 case less_equal: | |
2460 if (rt.imm32_ == 0) { | |
2461 offset = shifted_branch_offset(L, false); | |
2462 blez(rs, offset); | |
2463 } else { | |
2464 DCHECK(!scratch.is(rs)); | |
2465 r2 = scratch; | |
2466 li(r2, rt); | |
2467 slt(scratch, r2, rs); | |
2468 offset = shifted_branch_offset(L, false); | |
2469 beq(scratch, zero_reg, offset); | |
2470 } | |
2471 break; | |
2472 // Unsigned comparison. | |
2473 case Ugreater: | |
2474 if (rt.imm32_ == 0) { | |
2475 offset = shifted_branch_offset(L, false); | |
2476 bne(rs, zero_reg, offset); | |
2477 } else { | |
2478 DCHECK(!scratch.is(rs)); | |
2479 r2 = scratch; | |
2480 li(r2, rt); | |
2481 sltu(scratch, r2, rs); | |
2482 offset = shifted_branch_offset(L, false); | |
2483 bne(scratch, zero_reg, offset); | |
2484 } | |
2485 break; | |
2486 case Ugreater_equal: | |
2487 if (rt.imm32_ == 0) { | |
2488 offset = shifted_branch_offset(L, false); | |
2489 b(offset); | |
2490 } else if (is_int16(rt.imm32_)) { | |
2491 sltiu(scratch, rs, rt.imm32_); | |
2492 offset = shifted_branch_offset(L, false); | |
2493 beq(scratch, zero_reg, offset); | |
2494 } else { | |
2495 DCHECK(!scratch.is(rs)); | |
2496 r2 = scratch; | |
2497 li(r2, rt); | |
2498 sltu(scratch, rs, r2); | |
2499 offset = shifted_branch_offset(L, false); | |
2500 beq(scratch, zero_reg, offset); | |
2501 } | |
2502 break; | |
2503 case Uless: | |
2504 if (rt.imm32_ == 0) { | |
2505 // No code needs to be emitted. | |
2506 return; | |
2507 } else if (is_int16(rt.imm32_)) { | |
2508 sltiu(scratch, rs, rt.imm32_); | |
2509 offset = shifted_branch_offset(L, false); | |
2510 bne(scratch, zero_reg, offset); | |
2511 } else { | |
2512 DCHECK(!scratch.is(rs)); | |
2513 r2 = scratch; | |
2514 li(r2, rt); | |
2515 sltu(scratch, rs, r2); | |
2516 offset = shifted_branch_offset(L, false); | |
2517 bne(scratch, zero_reg, offset); | |
2518 } | |
2519 break; | |
2520 case Uless_equal: | |
2521 if (rt.imm32_ == 0) { | |
2522 offset = shifted_branch_offset(L, false); | |
2523 beq(rs, zero_reg, offset); | |
2524 } else { | |
2525 DCHECK(!scratch.is(rs)); | |
2526 r2 = scratch; | |
2527 li(r2, rt); | |
2528 sltu(scratch, r2, rs); | |
2529 offset = shifted_branch_offset(L, false); | |
2530 beq(scratch, zero_reg, offset); | |
2531 } | |
2532 break; | |
2533 default: | |
2534 UNREACHABLE(); | |
2535 } | |
2536 } | 2429 } |
2537 // Check that offset could actually hold on an int16_t. | |
2538 DCHECK(is_int16(offset)); | |
2539 // Emit a nop in the branch delay slot if required. | |
2540 if (bdslot == PROTECT) | |
2541 nop(); | |
2542 } | 2430 } |
2543 | 2431 |
2544 | 2432 |
2545 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) { | 2433 void MacroAssembler::BranchAndLink(int32_t offset, BranchDelaySlot bdslot) { |
2546 BranchAndLinkShort(offset, bdslot); | 2434 BranchAndLinkShort(offset, bdslot); |
2547 } | 2435 } |
2548 | 2436 |
2549 | 2437 |
2550 void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs, | 2438 void MacroAssembler::BranchAndLink(int32_t offset, Condition cond, Register rs, |
2551 const Operand& rt, | 2439 const Operand& rt, BranchDelaySlot bdslot) { |
2552 BranchDelaySlot bdslot) { | |
2553 BranchAndLinkShort(offset, cond, rs, rt, bdslot); | 2440 BranchAndLinkShort(offset, cond, rs, rt, bdslot); |
2554 } | 2441 } |
2555 | 2442 |
2556 | 2443 |
2557 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { | 2444 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { |
2558 if (L->is_bound()) { | 2445 if (L->is_bound()) { |
2559 if (is_near(L)) { | 2446 if (is_near(L)) { |
2560 BranchAndLinkShort(L, bdslot); | 2447 BranchAndLinkShort(L, bdslot); |
2561 } else { | 2448 } else { |
2562 Jalr(L, bdslot); | 2449 Jalr(L, bdslot); |
(...skipping 28 matching lines...) Expand all Loading... | |
2591 BranchShort(&skip, neg_cond, rs, rt); | 2478 BranchShort(&skip, neg_cond, rs, rt); |
2592 Jalr(L, bdslot); | 2479 Jalr(L, bdslot); |
2593 bind(&skip); | 2480 bind(&skip); |
2594 } else { | 2481 } else { |
2595 BranchAndLinkShort(L, cond, rs, rt, bdslot); | 2482 BranchAndLinkShort(L, cond, rs, rt, bdslot); |
2596 } | 2483 } |
2597 } | 2484 } |
2598 } | 2485 } |
2599 | 2486 |
2600 | 2487 |
2601 // We need to use a bgezal or bltzal, but they can't be used directly with the | 2488 Register MacroAssembler::GetRtAsRegisterHelper(const Operand& rt, |
2602 // slt instructions. We could use sub or add instead but we would miss overflow | 2489 Register scratch) { |
2603 // cases, so we keep slt and add an intermediate third instruction. | 2490 Register r2 = no_reg; |
2604 void MacroAssembler::BranchAndLinkShort(int16_t offset, | 2491 if (rt.is_reg()) { |
2605 BranchDelaySlot bdslot) { | 2492 r2 = rt.rm_; |
2493 } else { | |
2494 r2 = scratch; | |
2495 li(r2, rt); | |
2496 } | |
2497 | |
2498 return r2; | |
2499 } | |
2500 | |
2501 | |
2502 void MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L, | |
2503 BranchDelaySlot bdslot) { | |
2504 offset = GetOffset(offset, L, 16); | |
ivica.bogosavljevic
2015/10/15 11:49:08
16 -> constant. it applies elsewhere as well
balazs.kilvady
2015/10/30 21:11:14
Done.
| |
2606 bal(offset); | 2505 bal(offset); |
2607 | 2506 |
2608 // Emit a nop in the branch delay slot if required. | 2507 // Emit a nop in the branch delay slot if required. |
2609 if (bdslot == PROTECT) | 2508 if (bdslot == PROTECT) |
2610 nop(); | 2509 nop(); |
2611 } | 2510 } |
2612 | 2511 |
2613 | 2512 |
2614 void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond, | 2513 void MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L) { |
2615 Register rs, const Operand& rt, | 2514 offset = GetOffset(offset, L, 26); |
2515 balc(offset); | |
2516 } | |
2517 | |
2518 | |
2519 void MacroAssembler::BranchAndLinkShort(int32_t offset, | |
2616 BranchDelaySlot bdslot) { | 2520 BranchDelaySlot bdslot) { |
2617 BRANCH_ARGS_CHECK(cond, rs, rt); | 2521 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { |
2618 Register r2 = no_reg; | 2522 DCHECK(is_int26(offset)); |
2619 Register scratch = at; | 2523 BranchAndLinkShortHelperR6(offset, nullptr); |
2620 | |
2621 if (rt.is_reg()) { | |
2622 r2 = rt.rm_; | |
2623 } else if (cond != cc_always) { | |
2624 r2 = scratch; | |
2625 li(r2, rt); | |
2626 } | |
2627 | |
2628 if (!IsMipsArchVariant(kMips32r6)) { | |
2629 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2630 switch (cond) { | |
2631 case cc_always: | |
2632 bal(offset); | |
2633 break; | |
2634 case eq: | |
2635 bne(rs, r2, 2); | |
2636 nop(); | |
2637 bal(offset); | |
2638 break; | |
2639 case ne: | |
2640 beq(rs, r2, 2); | |
2641 nop(); | |
2642 bal(offset); | |
2643 break; | |
2644 | |
2645 // Signed comparison. | |
2646 case greater: | |
2647 slt(scratch, r2, rs); | |
2648 addiu(scratch, scratch, -1); | |
2649 bgezal(scratch, offset); | |
2650 break; | |
2651 case greater_equal: | |
2652 slt(scratch, rs, r2); | |
2653 addiu(scratch, scratch, -1); | |
2654 bltzal(scratch, offset); | |
2655 break; | |
2656 case less: | |
2657 slt(scratch, rs, r2); | |
2658 addiu(scratch, scratch, -1); | |
2659 bgezal(scratch, offset); | |
2660 break; | |
2661 case less_equal: | |
2662 slt(scratch, r2, rs); | |
2663 addiu(scratch, scratch, -1); | |
2664 bltzal(scratch, offset); | |
2665 break; | |
2666 | |
2667 // Unsigned comparison. | |
2668 case Ugreater: | |
2669 sltu(scratch, r2, rs); | |
2670 addiu(scratch, scratch, -1); | |
2671 bgezal(scratch, offset); | |
2672 break; | |
2673 case Ugreater_equal: | |
2674 sltu(scratch, rs, r2); | |
2675 addiu(scratch, scratch, -1); | |
2676 bltzal(scratch, offset); | |
2677 break; | |
2678 case Uless: | |
2679 sltu(scratch, rs, r2); | |
2680 addiu(scratch, scratch, -1); | |
2681 bgezal(scratch, offset); | |
2682 break; | |
2683 case Uless_equal: | |
2684 sltu(scratch, r2, rs); | |
2685 addiu(scratch, scratch, -1); | |
2686 bltzal(scratch, offset); | |
2687 break; | |
2688 | |
2689 default: | |
2690 UNREACHABLE(); | |
2691 } | |
2692 } else { | 2524 } else { |
2693 BlockTrampolinePoolScope block_trampoline_pool(this); | 2525 DCHECK(is_int16(offset)); |
2694 switch (cond) { | 2526 BranchAndLinkShortHelper(offset, nullptr, bdslot); |
2695 case cc_always: | 2527 } |
2696 bal(offset); | 2528 } |
2697 break; | 2529 |
2698 case eq: | 2530 |
2699 bne(rs, r2, 2); | 2531 void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) { |
2700 nop(); | 2532 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { |
2701 bal(offset); | 2533 BranchAndLinkShortHelperR6(0, L); |
2702 break; | 2534 } else { |
2703 case ne: | 2535 BranchAndLinkShortHelper(0, L, bdslot); |
2704 beq(rs, r2, 2); | 2536 } |
2705 nop(); | 2537 } |
2706 bal(offset); | 2538 |
2707 break; | 2539 |
2708 | 2540 void MacroAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L, |
2709 // Signed comparison. | 2541 Condition cond, Register rs, |
2710 case greater: | 2542 const Operand& rt) { |
2711 // rs > rt | 2543 Register scratch = rs.is(at) ? t8 : at; |
2712 slt(scratch, r2, rs); | 2544 |
2713 beq(scratch, zero_reg, 2); | 2545 BlockTrampolinePoolScope block_trampoline_pool(this); |
2714 nop(); | 2546 DCHECK((cond == cc_always && is_int26(offset)) || is_int16(offset)); |
2715 bal(offset); | 2547 switch (cond) { |
2716 break; | 2548 case cc_always: |
2717 case greater_equal: | 2549 offset = GetOffset(offset, L, 26); |
2718 // rs >= rt | 2550 balc(offset); |
2719 slt(scratch, rs, r2); | 2551 break; |
2720 bne(scratch, zero_reg, 2); | 2552 case eq: |
2721 nop(); | 2553 Subu(scratch, rs, rt); |
2722 bal(offset); | 2554 offset = GetOffset(offset, L, 16); |
2723 break; | 2555 beqzalc(scratch, offset); |
2724 case less: | 2556 break; |
2725 // rs < r2 | 2557 case ne: |
2726 slt(scratch, rs, r2); | 2558 Subu(scratch, rs, rt); |
2727 bne(scratch, zero_reg, 2); | 2559 offset = GetOffset(offset, L, 16); |
2728 nop(); | 2560 bnezalc(scratch, offset); |
2729 bal(offset); | 2561 break; |
2730 break; | 2562 |
2731 case less_equal: | 2563 // Signed comparison. |
2732 // rs <= r2 | 2564 case greater: |
2733 slt(scratch, r2, rs); | 2565 // rs > rt |
2734 bne(scratch, zero_reg, 2); | 2566 if (rs.code() == rt.rm_.reg_code) { |
2735 nop(); | 2567 break; // No code needs to be emitted. |
2736 bal(offset); | 2568 } else if (rs.is(zero_reg)) { |
2737 break; | 2569 scratch = GetRtAsRegisterHelper(rt, scratch); |
2738 | 2570 offset = GetOffset(offset, L, 16); |
2739 | 2571 bltzalc(scratch, offset); |
2740 // Unsigned comparison. | 2572 } else if (IsZero(rt)) { |
2741 case Ugreater: | 2573 offset = GetOffset(offset, L, 16); |
2742 // rs > rt | 2574 bgtzalc(rs, offset); |
2743 sltu(scratch, r2, rs); | 2575 } else { |
2744 beq(scratch, zero_reg, 2); | 2576 Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); |
2745 nop(); | 2577 offset = GetOffset(offset, L, 16); |
2746 bal(offset); | 2578 bnezalc(scratch, offset); |
2747 break; | 2579 } |
2748 case Ugreater_equal: | 2580 break; |
2749 // rs >= rt | 2581 case greater_equal: |
2750 sltu(scratch, rs, r2); | 2582 // rs >= rt |
2751 bne(scratch, zero_reg, 2); | 2583 if (rs.code() == rt.rm_.reg_code) { |
2752 nop(); | 2584 offset = GetOffset(offset, L, 26); |
2753 bal(offset); | 2585 balc(offset); |
2754 break; | 2586 } else if (rs.is(zero_reg)) { |
2755 case Uless: | 2587 scratch = GetRtAsRegisterHelper(rt, scratch); |
2756 // rs < r2 | 2588 offset = GetOffset(offset, L, 16); |
2757 sltu(scratch, rs, r2); | 2589 blezalc(scratch, offset); |
2758 bne(scratch, zero_reg, 2); | 2590 } else if (IsZero(rt)) { |
2759 nop(); | 2591 offset = GetOffset(offset, L, 16); |
2760 bal(offset); | 2592 bgezalc(rs, offset); |
2761 break; | 2593 } else { |
2762 case Uless_equal: | 2594 Slt(scratch, rs, rt); |
2763 // rs <= r2 | 2595 offset = GetOffset(offset, L, 16); |
2764 sltu(scratch, r2, rs); | 2596 beqzalc(scratch, offset); |
2765 bne(scratch, zero_reg, 2); | 2597 } |
2766 nop(); | 2598 break; |
2767 bal(offset); | 2599 case less: |
2768 break; | 2600 // rs < rt |
2769 default: | 2601 if (rs.code() == rt.rm_.reg_code) { |
2770 UNREACHABLE(); | 2602 break; // No code needs to be emitted. |
2771 } | 2603 } else if (rs.is(zero_reg)) { |
2604 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2605 offset = GetOffset(offset, L, 16); | |
2606 bgtzalc(scratch, offset); | |
2607 } else if (IsZero(rt)) { | |
2608 offset = GetOffset(offset, L, 16); | |
2609 bltzalc(rs, offset); | |
2610 } else { | |
2611 Slt(scratch, rs, rt); | |
2612 offset = GetOffset(offset, L, 16); | |
2613 bnezalc(scratch, offset); | |
2614 } | |
2615 break; | |
2616 case less_equal: | |
2617 // rs <= r2 | |
2618 if (rs.code() == rt.rm_.reg_code) { | |
2619 offset = GetOffset(offset, L, 26); | |
2620 balc(offset); | |
2621 } else if (rs.is(zero_reg)) { | |
2622 scratch = GetRtAsRegisterHelper(rt, scratch); | |
2623 offset = GetOffset(offset, L, 16); | |
2624 bgezalc(scratch, offset); | |
2625 } else if (IsZero(rt)) { | |
2626 offset = GetOffset(offset, L, 16); | |
2627 blezalc(rs, offset); | |
2628 } else { | |
2629 Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2630 offset = GetOffset(offset, L, 16); | |
2631 beqzalc(scratch, offset); | |
2632 } | |
2633 break; | |
2634 | |
2635 | |
2636 // Unsigned comparison. | |
2637 case Ugreater: | |
2638 // rs > r2 | |
2639 Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2640 offset = GetOffset(offset, L, 16); | |
2641 bnezalc(scratch, offset); | |
2642 break; | |
2643 case Ugreater_equal: | |
2644 // rs >= r2 | |
2645 Sltu(scratch, rs, rt); | |
2646 offset = GetOffset(offset, L, 16); | |
2647 beqzalc(scratch, offset); | |
2648 break; | |
2649 case Uless: | |
2650 // rs < r2 | |
2651 Sltu(scratch, rs, rt); | |
2652 offset = GetOffset(offset, L, 16); | |
2653 bnezalc(scratch, offset); | |
2654 break; | |
2655 case Uless_equal: | |
2656 // rs <= r2 | |
2657 Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2658 offset = GetOffset(offset, L, 16); | |
2659 beqzalc(scratch, offset); | |
2660 break; | |
2661 default: | |
2662 UNREACHABLE(); | |
2663 } | |
2664 } | |
2665 | |
2666 | |
2667 // Pre r6 we need to use a bgezal or bltzal, but they can't be used directly | |
2668 // with the slt instructions. We could use sub or add instead but we would miss | |
2669 // overflow cases, so we keep slt and add an intermediate third instruction. | |
2670 void MacroAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L, | |
2671 Condition cond, Register rs, | |
2672 const Operand& rt, | |
2673 BranchDelaySlot bdslot) { | |
2674 Register scratch = t8; | |
2675 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2676 switch (cond) { | |
2677 case cc_always: | |
2678 offset = GetOffset(offset, L, 16); | |
2679 bal(offset); | |
2680 break; | |
2681 case eq: | |
2682 bne(rs, GetRtAsRegisterHelper(rt, scratch), 2); | |
2683 nop(); | |
2684 offset = GetOffset(offset, L, 16); | |
2685 bal(offset); | |
2686 break; | |
2687 case ne: | |
2688 beq(rs, GetRtAsRegisterHelper(rt, scratch), 2); | |
2689 nop(); | |
2690 offset = GetOffset(offset, L, 16); | |
2691 bal(offset); | |
2692 break; | |
2693 | |
2694 // Signed comparison. | |
2695 case greater: | |
2696 Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2697 addiu(scratch, scratch, -1); | |
2698 offset = GetOffset(offset, L, 16); | |
2699 bgezal(scratch, offset); | |
2700 break; | |
2701 case greater_equal: | |
2702 Slt(scratch, rs, rt); | |
2703 addiu(scratch, scratch, -1); | |
2704 offset = GetOffset(offset, L, 16); | |
2705 bltzal(scratch, offset); | |
2706 break; | |
2707 case less: | |
2708 Slt(scratch, rs, rt); | |
2709 addiu(scratch, scratch, -1); | |
2710 offset = GetOffset(offset, L, 16); | |
2711 bgezal(scratch, offset); | |
2712 break; | |
2713 case less_equal: | |
2714 Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2715 addiu(scratch, scratch, -1); | |
2716 offset = GetOffset(offset, L, 16); | |
2717 bltzal(scratch, offset); | |
2718 break; | |
2719 | |
2720 // Unsigned comparison. | |
2721 case Ugreater: | |
2722 Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2723 addiu(scratch, scratch, -1); | |
2724 offset = GetOffset(offset, L, 16); | |
2725 bgezal(scratch, offset); | |
2726 break; | |
2727 case Ugreater_equal: | |
2728 Sltu(scratch, rs, rt); | |
2729 addiu(scratch, scratch, -1); | |
2730 offset = GetOffset(offset, L, 16); | |
2731 bltzal(scratch, offset); | |
2732 break; | |
2733 case Uless: | |
2734 Sltu(scratch, rs, rt); | |
2735 addiu(scratch, scratch, -1); | |
2736 offset = GetOffset(offset, L, 16); | |
2737 bgezal(scratch, offset); | |
2738 break; | |
2739 case Uless_equal: | |
2740 Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); | |
2741 addiu(scratch, scratch, -1); | |
2742 offset = GetOffset(offset, L, 16); | |
2743 bltzal(scratch, offset); | |
2744 break; | |
2745 | |
2746 default: | |
2747 UNREACHABLE(); | |
2772 } | 2748 } |
2773 | 2749 |
2774 // Emit a nop in the branch delay slot if required. | 2750 // Emit a nop in the branch delay slot if required. |
2775 if (bdslot == PROTECT) | 2751 if (bdslot == PROTECT) |
2776 nop(); | |
2777 } | |
2778 | |
2779 | |
2780 void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) { | |
2781 bal(shifted_branch_offset(L, false)); | |
2782 | |
2783 // Emit a nop in the branch delay slot if required. | |
2784 if (bdslot == PROTECT) | |
2785 nop(); | 2752 nop(); |
2786 } | 2753 } |
2787 | 2754 |
2788 | 2755 |
2756 void MacroAssembler::BranchAndLinkShort(int32_t offset, Condition cond, | |
2757 Register rs, const Operand& rt, | |
2758 BranchDelaySlot bdslot) { | |
2759 BRANCH_ARGS_CHECK(cond, rs, rt); | |
2760 | |
2761 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { | |
2762 DCHECK(is_int26(offset)); | |
2763 BranchAndLinkShortHelperR6(offset, nullptr, cond, rs, rt); | |
2764 } else { | |
2765 DCHECK(is_int16(offset)); | |
2766 BranchAndLinkShortHelper(offset, nullptr, cond, rs, rt, bdslot); | |
2767 } | |
2768 } | |
2769 | |
2770 | |
2789 void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs, | 2771 void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs, |
2790 const Operand& rt, | 2772 const Operand& rt, |
2791 BranchDelaySlot bdslot) { | 2773 BranchDelaySlot bdslot) { |
2792 BRANCH_ARGS_CHECK(cond, rs, rt); | 2774 BRANCH_ARGS_CHECK(cond, rs, rt); |
2793 | 2775 |
2794 int32_t offset = 0; | 2776 if (IsMipsArchVariant(kMips32r6) && bdslot == PROTECT) { |
2795 Register r2 = no_reg; | 2777 BranchAndLinkShortHelperR6(0, L, cond, rs, rt); |
2796 Register scratch = at; | 2778 } else { |
2797 if (rt.is_reg()) { | 2779 BranchAndLinkShortHelper(0, L, cond, rs, rt, bdslot); |
2798 r2 = rt.rm_; | |
2799 } else if (cond != cc_always) { | |
2800 r2 = scratch; | |
2801 li(r2, rt); | |
2802 } | 2780 } |
2803 | |
2804 if (!IsMipsArchVariant(kMips32r6)) { | |
2805 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2806 switch (cond) { | |
2807 case cc_always: | |
2808 offset = shifted_branch_offset(L, false); | |
2809 bal(offset); | |
2810 break; | |
2811 case eq: | |
2812 bne(rs, r2, 2); | |
2813 nop(); | |
2814 offset = shifted_branch_offset(L, false); | |
2815 bal(offset); | |
2816 break; | |
2817 case ne: | |
2818 beq(rs, r2, 2); | |
2819 nop(); | |
2820 offset = shifted_branch_offset(L, false); | |
2821 bal(offset); | |
2822 break; | |
2823 | |
2824 // Signed comparison. | |
2825 case greater: | |
2826 slt(scratch, r2, rs); | |
2827 addiu(scratch, scratch, -1); | |
2828 offset = shifted_branch_offset(L, false); | |
2829 bgezal(scratch, offset); | |
2830 break; | |
2831 case greater_equal: | |
2832 slt(scratch, rs, r2); | |
2833 addiu(scratch, scratch, -1); | |
2834 offset = shifted_branch_offset(L, false); | |
2835 bltzal(scratch, offset); | |
2836 break; | |
2837 case less: | |
2838 slt(scratch, rs, r2); | |
2839 addiu(scratch, scratch, -1); | |
2840 offset = shifted_branch_offset(L, false); | |
2841 bgezal(scratch, offset); | |
2842 break; | |
2843 case less_equal: | |
2844 slt(scratch, r2, rs); | |
2845 addiu(scratch, scratch, -1); | |
2846 offset = shifted_branch_offset(L, false); | |
2847 bltzal(scratch, offset); | |
2848 break; | |
2849 | |
2850 // Unsigned comparison. | |
2851 case Ugreater: | |
2852 sltu(scratch, r2, rs); | |
2853 addiu(scratch, scratch, -1); | |
2854 offset = shifted_branch_offset(L, false); | |
2855 bgezal(scratch, offset); | |
2856 break; | |
2857 case Ugreater_equal: | |
2858 sltu(scratch, rs, r2); | |
2859 addiu(scratch, scratch, -1); | |
2860 offset = shifted_branch_offset(L, false); | |
2861 bltzal(scratch, offset); | |
2862 break; | |
2863 case Uless: | |
2864 sltu(scratch, rs, r2); | |
2865 addiu(scratch, scratch, -1); | |
2866 offset = shifted_branch_offset(L, false); | |
2867 bgezal(scratch, offset); | |
2868 break; | |
2869 case Uless_equal: | |
2870 sltu(scratch, r2, rs); | |
2871 addiu(scratch, scratch, -1); | |
2872 offset = shifted_branch_offset(L, false); | |
2873 bltzal(scratch, offset); | |
2874 break; | |
2875 | |
2876 default: | |
2877 UNREACHABLE(); | |
2878 } | |
2879 } else { | |
2880 BlockTrampolinePoolScope block_trampoline_pool(this); | |
2881 switch (cond) { | |
2882 case cc_always: | |
2883 offset = shifted_branch_offset(L, false); | |
2884 bal(offset); | |
2885 break; | |
2886 case eq: | |
2887 bne(rs, r2, 2); | |
2888 nop(); | |
2889 offset = shifted_branch_offset(L, false); | |
2890 bal(offset); | |
2891 break; | |
2892 case ne: | |
2893 beq(rs, r2, 2); | |
2894 nop(); | |
2895 offset = shifted_branch_offset(L, false); | |
2896 bal(offset); | |
2897 break; | |
2898 | |
2899 // Signed comparison. | |
2900 case greater: | |
2901 // rs > rt | |
2902 slt(scratch, r2, rs); | |
2903 beq(scratch, zero_reg, 2); | |
2904 nop(); | |
2905 offset = shifted_branch_offset(L, false); | |
2906 bal(offset); | |
2907 break; | |
2908 case greater_equal: | |
2909 // rs >= rt | |
2910 slt(scratch, rs, r2); | |
2911 bne(scratch, zero_reg, 2); | |
2912 nop(); | |
2913 offset = shifted_branch_offset(L, false); | |
2914 bal(offset); | |
2915 break; | |
2916 case less: | |
2917 // rs < r2 | |
2918 slt(scratch, rs, r2); | |
2919 bne(scratch, zero_reg, 2); | |
2920 nop(); | |
2921 offset = shifted_branch_offset(L, false); | |
2922 bal(offset); | |
2923 break; | |
2924 case less_equal: | |
2925 // rs <= r2 | |
2926 slt(scratch, r2, rs); | |
2927 bne(scratch, zero_reg, 2); | |
2928 nop(); | |
2929 offset = shifted_branch_offset(L, false); | |
2930 bal(offset); | |
2931 break; | |
2932 | |
2933 | |
2934 // Unsigned comparison. | |
2935 case Ugreater: | |
2936 // rs > rt | |
2937 sltu(scratch, r2, rs); | |
2938 beq(scratch, zero_reg, 2); | |
2939 nop(); | |
2940 offset = shifted_branch_offset(L, false); | |
2941 bal(offset); | |
2942 break; | |
2943 case Ugreater_equal: | |
2944 // rs >= rt | |
2945 sltu(scratch, rs, r2); | |
2946 bne(scratch, zero_reg, 2); | |
2947 nop(); | |
2948 offset = shifted_branch_offset(L, false); | |
2949 bal(offset); | |
2950 break; | |
2951 case Uless: | |
2952 // rs < r2 | |
2953 sltu(scratch, rs, r2); | |
2954 bne(scratch, zero_reg, 2); | |
2955 nop(); | |
2956 offset = shifted_branch_offset(L, false); | |
2957 bal(offset); | |
2958 break; | |
2959 case Uless_equal: | |
2960 // rs <= r2 | |
2961 sltu(scratch, r2, rs); | |
2962 bne(scratch, zero_reg, 2); | |
2963 nop(); | |
2964 offset = shifted_branch_offset(L, false); | |
2965 bal(offset); | |
2966 break; | |
2967 | |
2968 default: | |
2969 UNREACHABLE(); | |
2970 } | |
2971 } | |
2972 | |
2973 // Check that offset could actually hold on an int16_t. | |
2974 DCHECK(is_int16(offset)); | |
2975 | |
2976 // Emit a nop in the branch delay slot if required. | |
2977 if (bdslot == PROTECT) | |
2978 nop(); | |
2979 } | 2781 } |
2980 | 2782 |
2981 | 2783 |
2982 void MacroAssembler::Jump(Register target, | 2784 void MacroAssembler::Jump(Register target, |
2983 Condition cond, | 2785 Condition cond, |
2984 Register rs, | 2786 Register rs, |
2985 const Operand& rt, | 2787 const Operand& rt, |
2986 BranchDelaySlot bd) { | 2788 BranchDelaySlot bd) { |
2987 BlockTrampolinePoolScope block_trampoline_pool(this); | 2789 BlockTrampolinePoolScope block_trampoline_pool(this); |
2988 if (cond == cc_always) { | 2790 if (cond == cc_always) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3058 return size * kInstrSize; | 2860 return size * kInstrSize; |
3059 } | 2861 } |
3060 | 2862 |
3061 | 2863 |
3062 // Note: To call gcc-compiled C code on mips, you must call thru t9. | 2864 // Note: To call gcc-compiled C code on mips, you must call thru t9. |
3063 void MacroAssembler::Call(Register target, | 2865 void MacroAssembler::Call(Register target, |
3064 Condition cond, | 2866 Condition cond, |
3065 Register rs, | 2867 Register rs, |
3066 const Operand& rt, | 2868 const Operand& rt, |
3067 BranchDelaySlot bd) { | 2869 BranchDelaySlot bd) { |
2870 #ifdef DEBUG | |
2871 int size = IsPrevInstrCompactBranch() ? kInstrSize : 0; | |
2872 #endif | |
2873 | |
3068 BlockTrampolinePoolScope block_trampoline_pool(this); | 2874 BlockTrampolinePoolScope block_trampoline_pool(this); |
3069 Label start; | 2875 Label start; |
3070 bind(&start); | 2876 bind(&start); |
3071 if (cond == cc_always) { | 2877 if (cond == cc_always) { |
3072 jalr(target); | 2878 jalr(target); |
3073 } else { | 2879 } else { |
3074 BRANCH_ARGS_CHECK(cond, rs, rt); | 2880 BRANCH_ARGS_CHECK(cond, rs, rt); |
3075 Branch(2, NegateCondition(cond), rs, rt); | 2881 Branch(2, NegateCondition(cond), rs, rt); |
3076 jalr(target); | 2882 jalr(target); |
3077 } | 2883 } |
3078 // Emit a nop in the branch delay slot if required. | 2884 // Emit a nop in the branch delay slot if required. |
3079 if (bd == PROTECT) | 2885 if (bd == PROTECT) |
3080 nop(); | 2886 nop(); |
3081 | 2887 |
3082 DCHECK_EQ(CallSize(target, cond, rs, rt, bd), | 2888 #ifdef DEBUG |
3083 SizeOfCodeGeneratedSince(&start)); | 2889 CHECK_EQ(size + CallSize(target, cond, rs, rt, bd), |
2890 SizeOfCodeGeneratedSince(&start)); | |
2891 #endif | |
3084 } | 2892 } |
3085 | 2893 |
3086 | 2894 |
3087 int MacroAssembler::CallSize(Address target, | 2895 int MacroAssembler::CallSize(Address target, |
3088 RelocInfo::Mode rmode, | 2896 RelocInfo::Mode rmode, |
3089 Condition cond, | 2897 Condition cond, |
3090 Register rs, | 2898 Register rs, |
3091 const Operand& rt, | 2899 const Operand& rt, |
3092 BranchDelaySlot bd) { | 2900 BranchDelaySlot bd) { |
3093 int size = CallSize(t9, cond, rs, rt, bd); | 2901 int size = CallSize(t9, cond, rs, rt, bd); |
(...skipping 2786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5880 void CodePatcher::Emit(Instr instr) { | 5688 void CodePatcher::Emit(Instr instr) { |
5881 masm()->emit(instr); | 5689 masm()->emit(instr); |
5882 } | 5690 } |
5883 | 5691 |
5884 | 5692 |
5885 void CodePatcher::Emit(Address addr) { | 5693 void CodePatcher::Emit(Address addr) { |
5886 masm()->emit(reinterpret_cast<Instr>(addr)); | 5694 masm()->emit(reinterpret_cast<Instr>(addr)); |
5887 } | 5695 } |
5888 | 5696 |
5889 | 5697 |
5890 void CodePatcher::ChangeBranchCondition(Condition cond) { | 5698 void CodePatcher::ChangeBranchCondition() { |
5891 Instr instr = Assembler::instr_at(masm_.pc_); | 5699 Instr instr = Assembler::instr_at(masm_.pc_); |
5892 DCHECK(Assembler::IsBranch(instr)); | 5700 DCHECK(Assembler::IsBranch(instr)); |
5893 uint32_t opcode = Assembler::GetOpcodeField(instr); | 5701 uint32_t opcode = Assembler::GetOpcodeField(instr); |
5894 // Currently only the 'eq' and 'ne' cond values are supported and the simple | 5702 // Currently only the 'eq' and 'ne' cond values are supported and the simple |
5895 // branch instructions (with opcode being the branch type). | 5703 // branch instructions (with opcode being the branch type). |
5896 // There are some special cases (see Assembler::IsBranch()) so extending this | 5704 // There are some special cases (see Assembler::IsBranch()) so extending this |
5897 // would be tricky. | 5705 // would be tricky. |
paul.l...
2015/10/15 01:51:24
This comment block is a little out of date. Same b
balazs.kilvady
2015/10/30 21:11:14
Done.
| |
5898 DCHECK(opcode == BEQ || | 5706 DCHECK(opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ || |
5899 opcode == BNE || | 5707 opcode == BEQL || opcode == BNEL || opcode == BLEZL || |
5900 opcode == BLEZ || | 5708 opcode == BGTZL || opcode == POP10 || // BEQC |
5901 opcode == BGTZ || | 5709 opcode == POP30 || // BNEC |
5902 opcode == BEQL || | 5710 opcode == POP66 || // BEQZC |
5903 opcode == BNEL || | 5711 opcode == POP76); // BNEZC; |
5904 opcode == BLEZL || | 5712 switch (opcode) { |
5905 opcode == BGTZL); | 5713 case BEQ: |
5906 opcode = (cond == eq) ? BEQ : BNE; | 5714 opcode = BNE; |
5715 break; | |
5716 case POP10: | |
5717 opcode = POP30; | |
paul.l...
2015/10/15 01:51:24
Even with the comments above, I really don't like
balazs.kilvady
2015/10/30 21:11:14
Done.
| |
5718 break; | |
5719 case POP66: | |
5720 opcode = POP76; | |
5721 break; | |
5722 case BNE: | |
5723 opcode = BEQ; | |
5724 break; | |
5725 case POP30: | |
5726 opcode = POP10; | |
5727 break; | |
5728 case POP76: | |
5729 opcode = POP66; | |
5730 break; | |
5731 default: | |
5732 UNIMPLEMENTED(); | |
5733 } | |
5907 instr = (instr & ~kOpcodeMask) | opcode; | 5734 instr = (instr & ~kOpcodeMask) | opcode; |
5908 masm_.emit(instr); | 5735 masm_.emit(instr); |
5909 } | 5736 } |
5910 | 5737 |
5911 | 5738 |
5912 void MacroAssembler::TruncatingDiv(Register result, | 5739 void MacroAssembler::TruncatingDiv(Register result, |
5913 Register dividend, | 5740 Register dividend, |
5914 int32_t divisor) { | 5741 int32_t divisor) { |
5915 DCHECK(!dividend.is(result)); | 5742 DCHECK(!dividend.is(result)); |
5916 DCHECK(!dividend.is(at)); | 5743 DCHECK(!dividend.is(at)); |
(...skipping 12 matching lines...) Expand all Loading... | |
5929 if (mag.shift > 0) sra(result, result, mag.shift); | 5756 if (mag.shift > 0) sra(result, result, mag.shift); |
5930 srl(at, dividend, 31); | 5757 srl(at, dividend, 31); |
5931 Addu(result, result, Operand(at)); | 5758 Addu(result, result, Operand(at)); |
5932 } | 5759 } |
5933 | 5760 |
5934 | 5761 |
5935 } // namespace internal | 5762 } // namespace internal |
5936 } // namespace v8 | 5763 } // namespace v8 |
5937 | 5764 |
5938 #endif // V8_TARGET_ARCH_MIPS | 5765 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |