Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: src/mips/macro-assembler-mips.cc

Issue 1396133002: MIPS: r6 compact branch optimization. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebased, gcc build fixed, ra alignment failure fixed. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698