Chromium Code Reviews| 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 |