1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/mips/MacroAssembler-mips.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1156 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_mips_MacroAssembler_mips_h 1.11 +#define jit_mips_MacroAssembler_mips_h 1.12 + 1.13 +#include "jsopcode.h" 1.14 + 1.15 +#include "jit/IonCaches.h" 1.16 +#include "jit/IonFrames.h" 1.17 +#include "jit/mips/Assembler-mips.h" 1.18 +#include "jit/MoveResolver.h" 1.19 + 1.20 +namespace js { 1.21 +namespace jit { 1.22 + 1.23 +enum LoadStoreSize 1.24 +{ 1.25 + SizeByte = 8, 1.26 + SizeHalfWord = 16, 1.27 + SizeWord = 32, 1.28 + SizeDouble = 64 1.29 +}; 1.30 + 1.31 +enum LoadStoreExtension 1.32 +{ 1.33 + ZeroExtend = 0, 1.34 + SignExtend = 1 1.35 +}; 1.36 + 1.37 +enum JumpKind 1.38 +{ 1.39 + LongJump = 0, 1.40 + ShortJump = 1 1.41 +}; 1.42 + 1.43 +struct ImmTag : public Imm32 1.44 +{ 1.45 + ImmTag(JSValueTag mask) 1.46 + : Imm32(int32_t(mask)) 1.47 + { } 1.48 +}; 1.49 + 1.50 +struct ImmType : public ImmTag 1.51 +{ 1.52 + ImmType(JSValueType type) 1.53 + : ImmTag(JSVAL_TYPE_TO_TAG(type)) 1.54 + { } 1.55 +}; 1.56 + 1.57 +static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg_Type, JSReturnReg_Data); 1.58 +static const ValueOperand softfpReturnOperand = ValueOperand(v1, v0); 1.59 + 1.60 +static Register CallReg = t9; 1.61 +static const int defaultShift = 3; 1.62 +static_assert(1 << defaultShift == sizeof(jsval), "The defaultShift is wrong"); 1.63 + 1.64 +class MacroAssemblerMIPS : public Assembler 1.65 +{ 1.66 + public: 1.67 + 1.68 + void convertBoolToInt32(Register source, Register dest); 1.69 + void convertInt32ToDouble(const Register &src, const FloatRegister &dest); 1.70 + void convertInt32ToDouble(const Address &src, FloatRegister dest); 1.71 + void convertUInt32ToDouble(const Register &src, const FloatRegister &dest); 1.72 + void convertUInt32ToFloat32(const Register &src, const FloatRegister &dest); 1.73 + void convertDoubleToFloat32(const FloatRegister &src, const FloatRegister &dest); 1.74 + void branchTruncateDouble(const FloatRegister &src, const Register &dest, Label *fail); 1.75 + void convertDoubleToInt32(const FloatRegister &src, const Register &dest, Label *fail, 1.76 + bool negativeZeroCheck = true); 1.77 + void convertFloat32ToInt32(const FloatRegister &src, const Register &dest, Label *fail, 1.78 + bool negativeZeroCheck = true); 1.79 + 1.80 + void convertFloat32ToDouble(const FloatRegister &src, const FloatRegister &dest); 1.81 + void branchTruncateFloat32(const FloatRegister &src, const Register &dest, Label *fail); 1.82 + void convertInt32ToFloat32(const Register &src, const FloatRegister &dest); 1.83 + void convertInt32ToFloat32(const Address &src, FloatRegister dest); 1.84 + 1.85 + 1.86 + void addDouble(FloatRegister src, FloatRegister dest); 1.87 + void subDouble(FloatRegister src, FloatRegister dest); 1.88 + void mulDouble(FloatRegister src, FloatRegister dest); 1.89 + void divDouble(FloatRegister src, FloatRegister dest); 1.90 + 1.91 + void negateDouble(FloatRegister reg); 1.92 + void inc64(AbsoluteAddress dest); 1.93 + 1.94 + public: 1.95 + 1.96 + void ma_move(Register rd, Register rs); 1.97 + 1.98 + void ma_li(Register dest, const ImmGCPtr &ptr); 1.99 + 1.100 + void ma_li(const Register &dest, AbsoluteLabel *label); 1.101 + 1.102 + void ma_li(Register dest, Imm32 imm); 1.103 + void ma_liPatchable(Register dest, Imm32 imm); 1.104 + void ma_liPatchable(Register dest, ImmPtr imm); 1.105 + 1.106 + // Shift operations 1.107 + void ma_sll(Register rd, Register rt, Imm32 shift); 1.108 + void ma_srl(Register rd, Register rt, Imm32 shift); 1.109 + void ma_sra(Register rd, Register rt, Imm32 shift); 1.110 + void ma_ror(Register rd, Register rt, Imm32 shift); 1.111 + void ma_rol(Register rd, Register rt, Imm32 shift); 1.112 + 1.113 + void ma_sll(Register rd, Register rt, Register shift); 1.114 + void ma_srl(Register rd, Register rt, Register shift); 1.115 + void ma_sra(Register rd, Register rt, Register shift); 1.116 + void ma_ror(Register rd, Register rt, Register shift); 1.117 + void ma_rol(Register rd, Register rt, Register shift); 1.118 + 1.119 + // Negate 1.120 + void ma_negu(Register rd, Register rs); 1.121 + 1.122 + void ma_not(Register rd, Register rs); 1.123 + 1.124 + // and 1.125 + void ma_and(Register rd, Register rs); 1.126 + void ma_and(Register rd, Register rs, Register rt); 1.127 + void ma_and(Register rd, Imm32 imm); 1.128 + void ma_and(Register rd, Register rs, Imm32 imm); 1.129 + 1.130 + // or 1.131 + void ma_or(Register rd, Register rs); 1.132 + void ma_or(Register rd, Register rs, Register rt); 1.133 + void ma_or(Register rd, Imm32 imm); 1.134 + void ma_or(Register rd, Register rs, Imm32 imm); 1.135 + 1.136 + // xor 1.137 + void ma_xor(Register rd, Register rs); 1.138 + void ma_xor(Register rd, Register rs, Register rt); 1.139 + void ma_xor(Register rd, Imm32 imm); 1.140 + void ma_xor(Register rd, Register rs, Imm32 imm); 1.141 + 1.142 + // load 1.143 + void ma_load(const Register &dest, Address address, LoadStoreSize size = SizeWord, 1.144 + LoadStoreExtension extension = SignExtend); 1.145 + void ma_load(const Register &dest, const BaseIndex &src, LoadStoreSize size = SizeWord, 1.146 + LoadStoreExtension extension = SignExtend); 1.147 + 1.148 + // store 1.149 + void ma_store(const Register &data, Address address, LoadStoreSize size = SizeWord, 1.150 + LoadStoreExtension extension = SignExtend); 1.151 + void ma_store(const Register &data, const BaseIndex &dest, LoadStoreSize size = SizeWord, 1.152 + LoadStoreExtension extension = SignExtend); 1.153 + void ma_store(const Imm32 &imm, const BaseIndex &dest, LoadStoreSize size = SizeWord, 1.154 + LoadStoreExtension extension = SignExtend); 1.155 + 1.156 + void computeScaledAddress(const BaseIndex &address, Register dest); 1.157 + 1.158 + void computeEffectiveAddress(const Address &address, Register dest) { 1.159 + ma_addu(dest, address.base, Imm32(address.offset)); 1.160 + } 1.161 + 1.162 + void computeEffectiveAddress(const BaseIndex &address, Register dest) { 1.163 + computeScaledAddress(address, dest); 1.164 + if (address.offset) { 1.165 + ma_addu(dest, dest, Imm32(address.offset)); 1.166 + } 1.167 + } 1.168 + 1.169 + // arithmetic based ops 1.170 + // add 1.171 + void ma_addu(Register rd, Register rs, Imm32 imm); 1.172 + void ma_addu(Register rd, Register rs); 1.173 + void ma_addu(Register rd, Imm32 imm); 1.174 + void ma_addTestOverflow(Register rd, Register rs, Register rt, Label *overflow); 1.175 + void ma_addTestOverflow(Register rd, Register rs, Imm32 imm, Label *overflow); 1.176 + 1.177 + // subtract 1.178 + void ma_subu(Register rd, Register rs, Register rt); 1.179 + void ma_subu(Register rd, Register rs, Imm32 imm); 1.180 + void ma_subu(Register rd, Imm32 imm); 1.181 + void ma_subTestOverflow(Register rd, Register rs, Register rt, Label *overflow); 1.182 + void ma_subTestOverflow(Register rd, Register rs, Imm32 imm, Label *overflow); 1.183 + 1.184 + // multiplies. For now, there are only few that we care about. 1.185 + void ma_mult(Register rs, Imm32 imm); 1.186 + void ma_mul_branch_overflow(Register rd, Register rs, Register rt, Label *overflow); 1.187 + void ma_mul_branch_overflow(Register rd, Register rs, Imm32 imm, Label *overflow); 1.188 + 1.189 + // divisions 1.190 + void ma_div_branch_overflow(Register rd, Register rs, Register rt, Label *overflow); 1.191 + void ma_div_branch_overflow(Register rd, Register rs, Imm32 imm, Label *overflow); 1.192 + 1.193 + // fast mod, uses scratch registers, and thus needs to be in the assembler 1.194 + // implicitly assumes that we can overwrite dest at the beginning of the sequence 1.195 + void ma_mod_mask(Register src, Register dest, Register hold, int32_t shift, 1.196 + Label *negZero = nullptr); 1.197 + 1.198 + // memory 1.199 + // shortcut for when we know we're transferring 32 bits of data 1.200 + void ma_lw(Register data, Address address); 1.201 + 1.202 + void ma_sw(Register data, Address address); 1.203 + void ma_sw(Imm32 imm, Address address); 1.204 + 1.205 + void ma_pop(Register r); 1.206 + void ma_push(Register r); 1.207 + 1.208 + // branches when done from within mips-specific code 1.209 + void ma_b(Register lhs, Register rhs, Label *l, Condition c, JumpKind jumpKind = LongJump); 1.210 + void ma_b(Register lhs, Imm32 imm, Label *l, Condition c, JumpKind jumpKind = LongJump); 1.211 + void ma_b(Register lhs, Address addr, Label *l, Condition c, JumpKind jumpKind = LongJump); 1.212 + void ma_b(Address addr, Imm32 imm, Label *l, Condition c, JumpKind jumpKind = LongJump); 1.213 + void ma_b(Label *l, JumpKind jumpKind = LongJump); 1.214 + void ma_bal(Label *l, JumpKind jumpKind = LongJump); 1.215 + 1.216 + // fp instructions 1.217 + void ma_lis(FloatRegister dest, float value); 1.218 + void ma_lid(FloatRegister dest, double value); 1.219 + void ma_liNegZero(FloatRegister dest); 1.220 + 1.221 + void ma_mv(FloatRegister src, ValueOperand dest); 1.222 + void ma_mv(ValueOperand src, FloatRegister dest); 1.223 + 1.224 + void ma_ls(FloatRegister fd, Address address); 1.225 + void ma_ld(FloatRegister fd, Address address); 1.226 + void ma_sd(FloatRegister fd, Address address); 1.227 + void ma_sd(FloatRegister fd, BaseIndex address); 1.228 + void ma_ss(FloatRegister fd, Address address); 1.229 + void ma_ss(FloatRegister fd, BaseIndex address); 1.230 + 1.231 + void ma_pop(FloatRegister fs); 1.232 + void ma_push(FloatRegister fs); 1.233 + 1.234 + //FP branches 1.235 + void ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label *label, DoubleCondition c, 1.236 + JumpKind jumpKind = LongJump, FPConditionBit fcc = FCC0); 1.237 + void ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label *label, DoubleCondition c, 1.238 + JumpKind jumpKind = LongJump, FPConditionBit fcc = FCC0); 1.239 + 1.240 + 1.241 + // These fuctions abstract the access to high part of the double precision 1.242 + // float register. It is intended to work on both 32 bit and 64 bit 1.243 + // floating point coprocessor. 1.244 + // :TODO: (Bug 985881) Modify this for N32 ABI to use mthc1 and mfhc1 1.245 + void moveToDoubleHi(Register src, FloatRegister dest) { 1.246 + as_mtc1(src, getOddPair(dest)); 1.247 + } 1.248 + void moveFromDoubleHi(FloatRegister src, Register dest) { 1.249 + as_mfc1(dest, getOddPair(src)); 1.250 + } 1.251 + 1.252 + void moveToDoubleLo(Register src, FloatRegister dest) { 1.253 + as_mtc1(src, dest); 1.254 + } 1.255 + void moveFromDoubleLo(FloatRegister src, Register dest) { 1.256 + as_mfc1(dest, src); 1.257 + } 1.258 + 1.259 + void moveToFloat32(Register src, FloatRegister dest) { 1.260 + as_mtc1(src, dest); 1.261 + } 1.262 + void moveFromFloat32(FloatRegister src, Register dest) { 1.263 + as_mfc1(dest, src); 1.264 + } 1.265 + 1.266 + protected: 1.267 + void branchWithCode(InstImm code, Label *label, JumpKind jumpKind); 1.268 + Condition ma_cmp(Register rd, Register lhs, Register rhs, Condition c); 1.269 + 1.270 + void compareFloatingPoint(FloatFormat fmt, FloatRegister lhs, FloatRegister rhs, 1.271 + DoubleCondition c, FloatTestKind *testKind, 1.272 + FPConditionBit fcc = FCC0); 1.273 + 1.274 + public: 1.275 + // calls an Ion function, assumes that the stack is untouched (8 byte alinged) 1.276 + void ma_callIon(const Register reg); 1.277 + // callso an Ion function, assuming that sp has already been decremented 1.278 + void ma_callIonNoPush(const Register reg); 1.279 + // calls an ion function, assuming that the stack is currently not 8 byte aligned 1.280 + void ma_callIonHalfPush(const Register reg); 1.281 + 1.282 + void ma_call(ImmPtr dest); 1.283 + 1.284 + void ma_jump(ImmPtr dest); 1.285 + 1.286 + void ma_cmp_set(Register dst, Register lhs, Register rhs, Condition c); 1.287 + void ma_cmp_set(Register dst, Register lhs, Imm32 imm, Condition c); 1.288 + void ma_cmp_set(Register rd, Register rs, Address addr, Condition c); 1.289 + void ma_cmp_set(Register dst, Address lhs, Register imm, Condition c); 1.290 + void ma_cmp_set_double(Register dst, FloatRegister lhs, FloatRegister rhs, DoubleCondition c); 1.291 + void ma_cmp_set_float32(Register dst, FloatRegister lhs, FloatRegister rhs, DoubleCondition c); 1.292 +}; 1.293 + 1.294 +class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS 1.295 +{ 1.296 + // Number of bytes the stack is adjusted inside a call to C. Calls to C may 1.297 + // not be nested. 1.298 + bool inCall_; 1.299 + uint32_t args_; 1.300 + // The actual number of arguments that were passed, used to assert that 1.301 + // the initial number of arguments declared was correct. 1.302 + uint32_t passedArgs_; 1.303 + 1.304 + uint32_t usedArgSlots_; 1.305 + MoveOp::Type firstArgType; 1.306 + 1.307 + bool dynamicAlignment_; 1.308 + 1.309 + bool enoughMemory_; 1.310 + // Compute space needed for the function call and set the properties of the 1.311 + // callee. It returns the space which has to be allocated for calling the 1.312 + // function. 1.313 + // 1.314 + // arg Number of arguments of the function. 1.315 + void setupABICall(uint32_t arg); 1.316 + 1.317 + protected: 1.318 + MoveResolver moveResolver_; 1.319 + 1.320 + // Extra bytes currently pushed onto the frame beyond frameDepth_. This is 1.321 + // needed to compute offsets to stack slots while temporary space has been 1.322 + // reserved for unexpected spills or C++ function calls. It is maintained 1.323 + // by functions which track stack alignment, which for clear distinction 1.324 + // use StudlyCaps (for example, Push, Pop). 1.325 + uint32_t framePushed_; 1.326 + void adjustFrame(int value) { 1.327 + setFramePushed(framePushed_ + value); 1.328 + } 1.329 + public: 1.330 + MacroAssemblerMIPSCompat() 1.331 + : inCall_(false), 1.332 + enoughMemory_(true), 1.333 + framePushed_(0) 1.334 + { } 1.335 + bool oom() const { 1.336 + return Assembler::oom(); 1.337 + } 1.338 + 1.339 + public: 1.340 + using MacroAssemblerMIPS::call; 1.341 + 1.342 + void j(Label *dest) { 1.343 + ma_b(dest); 1.344 + } 1.345 + 1.346 + void mov(Register src, Register dest) { 1.347 + as_or(dest, src, zero); 1.348 + } 1.349 + void mov(ImmWord imm, Register dest) { 1.350 + ma_li(dest, Imm32(imm.value)); 1.351 + } 1.352 + void mov(ImmPtr imm, Register dest) { 1.353 + mov(ImmWord(uintptr_t(imm.value)), dest); 1.354 + } 1.355 + void mov(Register src, Address dest) { 1.356 + MOZ_ASSUME_UNREACHABLE("NYI-IC"); 1.357 + } 1.358 + void mov(Address src, Register dest) { 1.359 + MOZ_ASSUME_UNREACHABLE("NYI-IC"); 1.360 + } 1.361 + 1.362 + void call(const Register reg) { 1.363 + as_jalr(reg); 1.364 + as_nop(); 1.365 + } 1.366 + 1.367 + void call(Label *label) { 1.368 + // for now, assume that it'll be nearby? 1.369 + ma_bal(label); 1.370 + } 1.371 + 1.372 + void call(ImmWord imm) { 1.373 + call(ImmPtr((void*)imm.value)); 1.374 + } 1.375 + void call(ImmPtr imm) { 1.376 + BufferOffset bo = m_buffer.nextOffset(); 1.377 + addPendingJump(bo, imm, Relocation::HARDCODED); 1.378 + ma_call(imm); 1.379 + } 1.380 + void call(AsmJSImmPtr imm) { 1.381 + movePtr(imm, CallReg); 1.382 + call(CallReg); 1.383 + } 1.384 + void call(JitCode *c) { 1.385 + BufferOffset bo = m_buffer.nextOffset(); 1.386 + addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE); 1.387 + ma_liPatchable(ScratchRegister, Imm32((uint32_t)c->raw())); 1.388 + ma_callIonHalfPush(ScratchRegister); 1.389 + } 1.390 + void branch(JitCode *c) { 1.391 + BufferOffset bo = m_buffer.nextOffset(); 1.392 + addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE); 1.393 + ma_liPatchable(ScratchRegister, Imm32((uint32_t)c->raw())); 1.394 + as_jr(ScratchRegister); 1.395 + as_nop(); 1.396 + } 1.397 + void branch(const Register reg) { 1.398 + as_jr(reg); 1.399 + as_nop(); 1.400 + } 1.401 + void nop() { 1.402 + as_nop(); 1.403 + } 1.404 + void ret() { 1.405 + ma_pop(ra); 1.406 + as_jr(ra); 1.407 + as_nop(); 1.408 + } 1.409 + void retn(Imm32 n) { 1.410 + // pc <- [sp]; sp += n 1.411 + ma_lw(ra, Address(StackPointer, 0)); 1.412 + ma_addu(StackPointer, StackPointer, n); 1.413 + as_jr(ra); 1.414 + as_nop(); 1.415 + } 1.416 + void push(Imm32 imm) { 1.417 + ma_li(ScratchRegister, imm); 1.418 + ma_push(ScratchRegister); 1.419 + } 1.420 + void push(ImmWord imm) { 1.421 + ma_li(ScratchRegister, Imm32(imm.value)); 1.422 + ma_push(ScratchRegister); 1.423 + } 1.424 + void push(ImmGCPtr imm) { 1.425 + ma_li(ScratchRegister, imm); 1.426 + ma_push(ScratchRegister); 1.427 + } 1.428 + void push(const Address &address) { 1.429 + ma_lw(ScratchRegister, address); 1.430 + ma_push(ScratchRegister); 1.431 + } 1.432 + void push(const Register ®) { 1.433 + ma_push(reg); 1.434 + } 1.435 + void push(const FloatRegister ®) { 1.436 + ma_push(reg); 1.437 + } 1.438 + void pop(const Register ®) { 1.439 + ma_pop(reg); 1.440 + } 1.441 + void pop(const FloatRegister ®) { 1.442 + ma_pop(reg); 1.443 + } 1.444 + 1.445 + // Emit a branch that can be toggled to a non-operation. On MIPS we use 1.446 + // "andi" instruction to toggle the branch. 1.447 + // See ToggleToJmp(), ToggleToCmp(). 1.448 + CodeOffsetLabel toggledJump(Label *label); 1.449 + 1.450 + // Emit a "jalr" or "nop" instruction. ToggleCall can be used to patch 1.451 + // this instruction. 1.452 + CodeOffsetLabel toggledCall(JitCode *target, bool enabled); 1.453 + 1.454 + static size_t ToggledCallSize() { 1.455 + // Four instructions used in: MacroAssemblerMIPSCompat::toggledCall 1.456 + return 4 * sizeof(uint32_t); 1.457 + } 1.458 + 1.459 + CodeOffsetLabel pushWithPatch(ImmWord imm) { 1.460 + CodeOffsetLabel label = movWithPatch(imm, ScratchRegister); 1.461 + ma_push(ScratchRegister); 1.462 + return label; 1.463 + } 1.464 + 1.465 + CodeOffsetLabel movWithPatch(ImmWord imm, Register dest) { 1.466 + CodeOffsetLabel label = currentOffset(); 1.467 + ma_liPatchable(dest, Imm32(imm.value)); 1.468 + return label; 1.469 + } 1.470 + CodeOffsetLabel movWithPatch(ImmPtr imm, Register dest) { 1.471 + return movWithPatch(ImmWord(uintptr_t(imm.value)), dest); 1.472 + } 1.473 + 1.474 + void jump(Label *label) { 1.475 + ma_b(label); 1.476 + } 1.477 + void jump(Register reg) { 1.478 + as_jr(reg); 1.479 + as_nop(); 1.480 + } 1.481 + void jump(const Address &address) { 1.482 + ma_lw(ScratchRegister, address); 1.483 + as_jr(ScratchRegister); 1.484 + as_nop(); 1.485 + } 1.486 + 1.487 + void neg32(Register reg) { 1.488 + ma_negu(reg, reg); 1.489 + } 1.490 + void negl(Register reg) { 1.491 + ma_negu(reg, reg); 1.492 + } 1.493 + 1.494 + // Returns the register containing the type tag. 1.495 + Register splitTagForTest(const ValueOperand &value) { 1.496 + return value.typeReg(); 1.497 + } 1.498 + 1.499 + void branchTestGCThing(Condition cond, const Address &address, Label *label); 1.500 + void branchTestGCThing(Condition cond, const BaseIndex &src, Label *label); 1.501 + 1.502 + void branchTestPrimitive(Condition cond, const ValueOperand &value, Label *label); 1.503 + void branchTestPrimitive(Condition cond, const Register &tag, Label *label); 1.504 + 1.505 + void branchTestValue(Condition cond, const ValueOperand &value, const Value &v, Label *label); 1.506 + void branchTestValue(Condition cond, const Address &valaddr, const ValueOperand &value, 1.507 + Label *label); 1.508 + 1.509 + // unboxing code 1.510 + void unboxInt32(const ValueOperand &operand, const Register &dest); 1.511 + void unboxInt32(const Address &src, const Register &dest); 1.512 + void unboxBoolean(const ValueOperand &operand, const Register &dest); 1.513 + void unboxBoolean(const Address &src, const Register &dest); 1.514 + void unboxDouble(const ValueOperand &operand, const FloatRegister &dest); 1.515 + void unboxDouble(const Address &src, const FloatRegister &dest); 1.516 + void unboxString(const ValueOperand &operand, const Register &dest); 1.517 + void unboxString(const Address &src, const Register &dest); 1.518 + void unboxObject(const ValueOperand &src, const Register &dest); 1.519 + void unboxValue(const ValueOperand &src, AnyRegister dest); 1.520 + void unboxPrivate(const ValueOperand &src, Register dest); 1.521 + 1.522 + void notBoolean(const ValueOperand &val) { 1.523 + as_xori(val.payloadReg(), val.payloadReg(), 1); 1.524 + } 1.525 + 1.526 + // boxing code 1.527 + void boxDouble(const FloatRegister &src, const ValueOperand &dest); 1.528 + void boxNonDouble(JSValueType type, const Register &src, const ValueOperand &dest); 1.529 + 1.530 + // Extended unboxing API. If the payload is already in a register, returns 1.531 + // that register. Otherwise, provides a move to the given scratch register, 1.532 + // and returns that. 1.533 + Register extractObject(const Address &address, Register scratch); 1.534 + Register extractObject(const ValueOperand &value, Register scratch) { 1.535 + return value.payloadReg(); 1.536 + } 1.537 + Register extractInt32(const ValueOperand &value, Register scratch) { 1.538 + return value.payloadReg(); 1.539 + } 1.540 + Register extractBoolean(const ValueOperand &value, Register scratch) { 1.541 + return value.payloadReg(); 1.542 + } 1.543 + Register extractTag(const Address &address, Register scratch); 1.544 + Register extractTag(const BaseIndex &address, Register scratch); 1.545 + Register extractTag(const ValueOperand &value, Register scratch) { 1.546 + return value.typeReg(); 1.547 + } 1.548 + 1.549 + void boolValueToDouble(const ValueOperand &operand, const FloatRegister &dest); 1.550 + void int32ValueToDouble(const ValueOperand &operand, const FloatRegister &dest); 1.551 + void loadInt32OrDouble(const Address &address, const FloatRegister &dest); 1.552 + void loadInt32OrDouble(Register base, Register index, 1.553 + const FloatRegister &dest, int32_t shift = defaultShift); 1.554 + void loadConstantDouble(double dp, const FloatRegister &dest); 1.555 + 1.556 + void boolValueToFloat32(const ValueOperand &operand, const FloatRegister &dest); 1.557 + void int32ValueToFloat32(const ValueOperand &operand, const FloatRegister &dest); 1.558 + void loadConstantFloat32(float f, const FloatRegister &dest); 1.559 + 1.560 + void branchTestInt32(Condition cond, const ValueOperand &value, Label *label); 1.561 + void branchTestInt32(Condition cond, const Register &tag, Label *label); 1.562 + void branchTestInt32(Condition cond, const Address &address, Label *label); 1.563 + void branchTestInt32(Condition cond, const BaseIndex &src, Label *label); 1.564 + 1.565 + void branchTestBoolean(Condition cond, const ValueOperand &value, Label *label); 1.566 + void branchTestBoolean(Condition cond, const Register &tag, Label *label); 1.567 + void branchTestBoolean(Condition cond, const BaseIndex &src, Label *label); 1.568 + 1.569 + void branch32(Condition cond, Register lhs, Register rhs, Label *label) { 1.570 + ma_b(lhs, rhs, label, cond); 1.571 + } 1.572 + void branch32(Condition cond, Register lhs, Imm32 imm, Label *label) { 1.573 + ma_b(lhs, imm, label, cond); 1.574 + } 1.575 + void branch32(Condition cond, const Operand &lhs, Register rhs, Label *label) { 1.576 + if (lhs.getTag() == Operand::REG) { 1.577 + ma_b(lhs.toReg(), rhs, label, cond); 1.578 + } else { 1.579 + branch32(cond, lhs.toAddress(), rhs, label); 1.580 + } 1.581 + } 1.582 + void branch32(Condition cond, const Operand &lhs, Imm32 rhs, Label *label) { 1.583 + if (lhs.getTag() == Operand::REG) { 1.584 + ma_b(lhs.toReg(), rhs, label, cond); 1.585 + } else { 1.586 + branch32(cond, lhs.toAddress(), rhs, label); 1.587 + } 1.588 + } 1.589 + void branch32(Condition cond, const Address &lhs, Register rhs, Label *label) { 1.590 + ma_lw(ScratchRegister, lhs); 1.591 + ma_b(ScratchRegister, rhs, label, cond); 1.592 + } 1.593 + void branch32(Condition cond, const Address &lhs, Imm32 rhs, Label *label) { 1.594 + ma_lw(SecondScratchReg, lhs); 1.595 + ma_b(SecondScratchReg, rhs, label, cond); 1.596 + } 1.597 + void branchPtr(Condition cond, const Address &lhs, Register rhs, Label *label) { 1.598 + branch32(cond, lhs, rhs, label); 1.599 + } 1.600 + 1.601 + void branchPrivatePtr(Condition cond, const Address &lhs, ImmPtr ptr, Label *label) { 1.602 + branchPtr(cond, lhs, ptr, label); 1.603 + } 1.604 + 1.605 + void branchPrivatePtr(Condition cond, const Address &lhs, Register ptr, Label *label) { 1.606 + branchPtr(cond, lhs, ptr, label); 1.607 + } 1.608 + 1.609 + void branchPrivatePtr(Condition cond, Register lhs, ImmWord ptr, Label *label) { 1.610 + branchPtr(cond, lhs, ptr, label); 1.611 + } 1.612 + 1.613 + void branchTestDouble(Condition cond, const ValueOperand &value, Label *label); 1.614 + void branchTestDouble(Condition cond, const Register &tag, Label *label); 1.615 + void branchTestDouble(Condition cond, const Address &address, Label *label); 1.616 + void branchTestDouble(Condition cond, const BaseIndex &src, Label *label); 1.617 + 1.618 + void branchTestNull(Condition cond, const ValueOperand &value, Label *label); 1.619 + void branchTestNull(Condition cond, const Register &tag, Label *label); 1.620 + void branchTestNull(Condition cond, const BaseIndex &src, Label *label); 1.621 + 1.622 + void branchTestObject(Condition cond, const ValueOperand &value, Label *label); 1.623 + void branchTestObject(Condition cond, const Register &tag, Label *label); 1.624 + void branchTestObject(Condition cond, const BaseIndex &src, Label *label); 1.625 + 1.626 + void branchTestString(Condition cond, const ValueOperand &value, Label *label); 1.627 + void branchTestString(Condition cond, const Register &tag, Label *label); 1.628 + void branchTestString(Condition cond, const BaseIndex &src, Label *label); 1.629 + 1.630 + void branchTestUndefined(Condition cond, const ValueOperand &value, Label *label); 1.631 + void branchTestUndefined(Condition cond, const Register &tag, Label *label); 1.632 + void branchTestUndefined(Condition cond, const BaseIndex &src, Label *label); 1.633 + void branchTestUndefined(Condition cond, const Address &address, Label *label); 1.634 + 1.635 + void branchTestNumber(Condition cond, const ValueOperand &value, Label *label); 1.636 + void branchTestNumber(Condition cond, const Register &tag, Label *label); 1.637 + 1.638 + void branchTestMagic(Condition cond, const ValueOperand &value, Label *label); 1.639 + void branchTestMagic(Condition cond, const Register &tag, Label *label); 1.640 + void branchTestMagic(Condition cond, const Address &address, Label *label); 1.641 + void branchTestMagic(Condition cond, const BaseIndex &src, Label *label); 1.642 + 1.643 + void branchTestMagicValue(Condition cond, const ValueOperand &val, JSWhyMagic why, 1.644 + Label *label) { 1.645 + MOZ_ASSERT(cond == Equal || cond == NotEqual); 1.646 + // Test for magic 1.647 + Label notmagic; 1.648 + branchTestMagic(cond, val, ¬magic); 1.649 + // Test magic value 1.650 + branch32(cond, val.payloadReg(), Imm32(static_cast<int32_t>(why)), label); 1.651 + bind(¬magic); 1.652 + } 1.653 + 1.654 + void branchTestInt32Truthy(bool b, const ValueOperand &value, Label *label); 1.655 + 1.656 + void branchTestStringTruthy(bool b, const ValueOperand &value, Label *label); 1.657 + 1.658 + void branchTestDoubleTruthy(bool b, const FloatRegister &value, Label *label); 1.659 + 1.660 + void branchTestBooleanTruthy(bool b, const ValueOperand &operand, Label *label); 1.661 + 1.662 + void branchTest32(Condition cond, const Register &lhs, const Register &rhs, Label *label) { 1.663 + MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned); 1.664 + if (lhs == rhs) { 1.665 + ma_b(lhs, rhs, label, cond); 1.666 + } else { 1.667 + as_and(ScratchRegister, lhs, rhs); 1.668 + ma_b(ScratchRegister, ScratchRegister, label, cond); 1.669 + } 1.670 + } 1.671 + void branchTest32(Condition cond, const Register &lhs, Imm32 imm, Label *label) { 1.672 + ma_li(ScratchRegister, imm); 1.673 + branchTest32(cond, lhs, ScratchRegister, label); 1.674 + } 1.675 + void branchTest32(Condition cond, const Address &address, Imm32 imm, Label *label) { 1.676 + ma_lw(SecondScratchReg, address); 1.677 + branchTest32(cond, SecondScratchReg, imm, label); 1.678 + } 1.679 + void branchTestPtr(Condition cond, const Register &lhs, const Register &rhs, Label *label) { 1.680 + branchTest32(cond, lhs, rhs, label); 1.681 + } 1.682 + void branchTestPtr(Condition cond, const Register &lhs, const Imm32 rhs, Label *label) { 1.683 + branchTest32(cond, lhs, rhs, label); 1.684 + } 1.685 + void branchTestPtr(Condition cond, const Address &lhs, Imm32 imm, Label *label) { 1.686 + branchTest32(cond, lhs, imm, label); 1.687 + } 1.688 + void branchPtr(Condition cond, Register lhs, Register rhs, Label *label) { 1.689 + ma_b(lhs, rhs, label, cond); 1.690 + } 1.691 + void branchPtr(Condition cond, Register lhs, ImmGCPtr ptr, Label *label) { 1.692 + ma_li(ScratchRegister, ptr); 1.693 + ma_b(lhs, ScratchRegister, label, cond); 1.694 + } 1.695 + void branchPtr(Condition cond, Register lhs, ImmWord imm, Label *label) { 1.696 + ma_b(lhs, Imm32(imm.value), label, cond); 1.697 + } 1.698 + void branchPtr(Condition cond, Register lhs, ImmPtr imm, Label *label) { 1.699 + branchPtr(cond, lhs, ImmWord(uintptr_t(imm.value)), label); 1.700 + } 1.701 + void branchPtr(Condition cond, Register lhs, AsmJSImmPtr imm, Label *label) { 1.702 + movePtr(imm, ScratchRegister); 1.703 + branchPtr(cond, lhs, ScratchRegister, label); 1.704 + } 1.705 + void branchPtr(Condition cond, Register lhs, Imm32 imm, Label *label) { 1.706 + ma_b(lhs, imm, label, cond); 1.707 + } 1.708 + void decBranchPtr(Condition cond, const Register &lhs, Imm32 imm, Label *label) { 1.709 + subPtr(imm, lhs); 1.710 + branch32(cond, lhs, Imm32(0), label); 1.711 + } 1.712 + 1.713 +protected: 1.714 + uint32_t getType(const Value &val); 1.715 + void moveData(const Value &val, Register data); 1.716 +public: 1.717 + void moveValue(const Value &val, Register type, Register data); 1.718 + 1.719 + CodeOffsetJump jumpWithPatch(RepatchLabel *label); 1.720 + 1.721 + template <typename T> 1.722 + CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel *label) { 1.723 + movePtr(ptr, ScratchRegister); 1.724 + Label skipJump; 1.725 + ma_b(reg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump); 1.726 + CodeOffsetJump off = jumpWithPatch(label); 1.727 + bind(&skipJump); 1.728 + return off; 1.729 + } 1.730 + 1.731 + template <typename T> 1.732 + CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel *label) { 1.733 + loadPtr(addr, SecondScratchReg); 1.734 + movePtr(ptr, ScratchRegister); 1.735 + Label skipJump; 1.736 + ma_b(SecondScratchReg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump); 1.737 + CodeOffsetJump off = jumpWithPatch(label); 1.738 + bind(&skipJump); 1.739 + return off; 1.740 + } 1.741 + void branchPtr(Condition cond, Address addr, ImmGCPtr ptr, Label *label) { 1.742 + ma_lw(SecondScratchReg, addr); 1.743 + ma_li(ScratchRegister, ptr); 1.744 + ma_b(SecondScratchReg, ScratchRegister, label, cond); 1.745 + } 1.746 + void branchPtr(Condition cond, Address addr, ImmWord ptr, Label *label) { 1.747 + ma_lw(SecondScratchReg, addr); 1.748 + ma_b(SecondScratchReg, Imm32(ptr.value), label, cond); 1.749 + } 1.750 + void branchPtr(Condition cond, Address addr, ImmPtr ptr, Label *label) { 1.751 + branchPtr(cond, addr, ImmWord(uintptr_t(ptr.value)), label); 1.752 + } 1.753 + void branchPtr(Condition cond, const AbsoluteAddress &addr, const Register &ptr, Label *label) { 1.754 + loadPtr(addr, ScratchRegister); 1.755 + ma_b(ScratchRegister, ptr, label, cond); 1.756 + } 1.757 + void branchPtr(Condition cond, const AsmJSAbsoluteAddress &addr, const Register &ptr, 1.758 + Label *label) { 1.759 + loadPtr(addr, ScratchRegister); 1.760 + ma_b(ScratchRegister, ptr, label, cond); 1.761 + } 1.762 + void branch32(Condition cond, const AbsoluteAddress &lhs, Imm32 rhs, Label *label) { 1.763 + loadPtr(lhs, SecondScratchReg); // ma_b might use scratch 1.764 + ma_b(SecondScratchReg, rhs, label, cond); 1.765 + } 1.766 + void branch32(Condition cond, const AbsoluteAddress &lhs, const Register &rhs, Label *label) { 1.767 + loadPtr(lhs, ScratchRegister); 1.768 + ma_b(ScratchRegister, rhs, label, cond); 1.769 + } 1.770 + 1.771 + void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) { 1.772 + if (dest.isFloat()) 1.773 + loadInt32OrDouble(address, dest.fpu()); 1.774 + else 1.775 + ma_lw(dest.gpr(), address); 1.776 + } 1.777 + 1.778 + void loadUnboxedValue(BaseIndex address, MIRType type, AnyRegister dest) { 1.779 + if (dest.isFloat()) 1.780 + loadInt32OrDouble(address.base, address.index, dest.fpu(), address.scale); 1.781 + else 1.782 + load32(address, dest.gpr()); 1.783 + } 1.784 + 1.785 + void moveValue(const Value &val, const ValueOperand &dest); 1.786 + 1.787 + void moveValue(const ValueOperand &src, const ValueOperand &dest) { 1.788 + MOZ_ASSERT(src.typeReg() != dest.payloadReg()); 1.789 + MOZ_ASSERT(src.payloadReg() != dest.typeReg()); 1.790 + if (src.typeReg() != dest.typeReg()) 1.791 + ma_move(dest.typeReg(), src.typeReg()); 1.792 + if (src.payloadReg() != dest.payloadReg()) 1.793 + ma_move(dest.payloadReg(), src.payloadReg()); 1.794 + } 1.795 + 1.796 + void storeValue(ValueOperand val, Operand dst); 1.797 + void storeValue(ValueOperand val, const BaseIndex &dest); 1.798 + void storeValue(JSValueType type, Register reg, BaseIndex dest); 1.799 + void storeValue(ValueOperand val, const Address &dest); 1.800 + void storeValue(JSValueType type, Register reg, Address dest); 1.801 + void storeValue(const Value &val, Address dest); 1.802 + void storeValue(const Value &val, BaseIndex dest); 1.803 + 1.804 + void loadValue(Address src, ValueOperand val); 1.805 + void loadValue(Operand dest, ValueOperand val) { 1.806 + loadValue(dest.toAddress(), val); 1.807 + } 1.808 + void loadValue(const BaseIndex &addr, ValueOperand val); 1.809 + void tagValue(JSValueType type, Register payload, ValueOperand dest); 1.810 + 1.811 + void pushValue(ValueOperand val); 1.812 + void popValue(ValueOperand val); 1.813 + void pushValue(const Value &val) { 1.814 + jsval_layout jv = JSVAL_TO_IMPL(val); 1.815 + push(Imm32(jv.s.tag)); 1.816 + if (val.isMarkable()) 1.817 + push(ImmGCPtr(reinterpret_cast<gc::Cell *>(val.toGCThing()))); 1.818 + else 1.819 + push(Imm32(jv.s.payload.i32)); 1.820 + } 1.821 + void pushValue(JSValueType type, Register reg) { 1.822 + push(ImmTag(JSVAL_TYPE_TO_TAG(type))); 1.823 + ma_push(reg); 1.824 + } 1.825 + void pushValue(const Address &addr); 1.826 + void Push(const ValueOperand &val) { 1.827 + pushValue(val); 1.828 + framePushed_ += sizeof(Value); 1.829 + } 1.830 + void Pop(const ValueOperand &val) { 1.831 + popValue(val); 1.832 + framePushed_ -= sizeof(Value); 1.833 + } 1.834 + void storePayload(const Value &val, Address dest); 1.835 + void storePayload(Register src, Address dest); 1.836 + void storePayload(const Value &val, Register base, Register index, int32_t shift = defaultShift); 1.837 + void storePayload(Register src, Register base, Register index, int32_t shift = defaultShift); 1.838 + void storeTypeTag(ImmTag tag, Address dest); 1.839 + void storeTypeTag(ImmTag tag, Register base, Register index, int32_t shift = defaultShift); 1.840 + 1.841 + void makeFrameDescriptor(Register frameSizeReg, FrameType type) { 1.842 + ma_sll(frameSizeReg, frameSizeReg, Imm32(FRAMESIZE_SHIFT)); 1.843 + ma_or(frameSizeReg, frameSizeReg, Imm32(type)); 1.844 + } 1.845 + 1.846 + void linkExitFrame(); 1.847 + void linkParallelExitFrame(const Register &pt); 1.848 + void handleFailureWithHandler(void *handler); 1.849 + void handleFailureWithHandlerTail(); 1.850 + 1.851 + ///////////////////////////////////////////////////////////////// 1.852 + // Common interface. 1.853 + ///////////////////////////////////////////////////////////////// 1.854 + public: 1.855 + // The following functions are exposed for use in platform-shared code. 1.856 + void Push(const Register ®) { 1.857 + ma_push(reg); 1.858 + adjustFrame(sizeof(intptr_t)); 1.859 + } 1.860 + void Push(const Imm32 imm) { 1.861 + ma_li(ScratchRegister, imm); 1.862 + ma_push(ScratchRegister); 1.863 + adjustFrame(sizeof(intptr_t)); 1.864 + } 1.865 + void Push(const ImmWord imm) { 1.866 + ma_li(ScratchRegister, Imm32(imm.value)); 1.867 + ma_push(ScratchRegister); 1.868 + adjustFrame(sizeof(intptr_t)); 1.869 + } 1.870 + void Push(const ImmPtr imm) { 1.871 + Push(ImmWord(uintptr_t(imm.value))); 1.872 + } 1.873 + void Push(const ImmGCPtr ptr) { 1.874 + ma_li(ScratchRegister, ptr); 1.875 + ma_push(ScratchRegister); 1.876 + adjustFrame(sizeof(intptr_t)); 1.877 + } 1.878 + void Push(const FloatRegister &f) { 1.879 + ma_push(f); 1.880 + adjustFrame(sizeof(double)); 1.881 + } 1.882 + 1.883 + CodeOffsetLabel PushWithPatch(const ImmWord &word) { 1.884 + framePushed_ += sizeof(word.value); 1.885 + return pushWithPatch(word); 1.886 + } 1.887 + CodeOffsetLabel PushWithPatch(const ImmPtr &imm) { 1.888 + return PushWithPatch(ImmWord(uintptr_t(imm.value))); 1.889 + } 1.890 + 1.891 + void Pop(const Register ®) { 1.892 + ma_pop(reg); 1.893 + adjustFrame(-sizeof(intptr_t)); 1.894 + } 1.895 + void implicitPop(uint32_t args) { 1.896 + MOZ_ASSERT(args % sizeof(intptr_t) == 0); 1.897 + adjustFrame(-args); 1.898 + } 1.899 + uint32_t framePushed() const { 1.900 + return framePushed_; 1.901 + } 1.902 + void setFramePushed(uint32_t framePushed) { 1.903 + framePushed_ = framePushed; 1.904 + } 1.905 + 1.906 + // Builds an exit frame on the stack, with a return address to an internal 1.907 + // non-function. Returns offset to be passed to markSafepointAt(). 1.908 + bool buildFakeExitFrame(const Register &scratch, uint32_t *offset); 1.909 + 1.910 + void callWithExitFrame(JitCode *target); 1.911 + void callWithExitFrame(JitCode *target, Register dynStack); 1.912 + 1.913 + // Makes an Ion call using the only two methods that it is sane for 1.914 + // indep code to make a call 1.915 + void callIon(const Register &callee); 1.916 + 1.917 + void reserveStack(uint32_t amount); 1.918 + void freeStack(uint32_t amount); 1.919 + void freeStack(Register amount); 1.920 + 1.921 + void add32(Register src, Register dest); 1.922 + void add32(Imm32 imm, Register dest); 1.923 + void add32(Imm32 imm, const Address &dest); 1.924 + void sub32(Imm32 imm, Register dest); 1.925 + void sub32(Register src, Register dest); 1.926 + 1.927 + void and32(Imm32 imm, Register dest); 1.928 + void and32(Imm32 imm, const Address &dest); 1.929 + void or32(Imm32 imm, const Address &dest); 1.930 + void xor32(Imm32 imm, Register dest); 1.931 + void xorPtr(Imm32 imm, Register dest); 1.932 + void xorPtr(Register src, Register dest); 1.933 + void orPtr(Imm32 imm, Register dest); 1.934 + void orPtr(Register src, Register dest); 1.935 + void andPtr(Imm32 imm, Register dest); 1.936 + void andPtr(Register src, Register dest); 1.937 + void addPtr(Register src, Register dest); 1.938 + void subPtr(Register src, Register dest); 1.939 + void addPtr(const Address &src, Register dest); 1.940 + void not32(Register reg); 1.941 + 1.942 + void move32(const Imm32 &imm, const Register &dest); 1.943 + void move32(const Register &src, const Register &dest); 1.944 + 1.945 + void movePtr(const Register &src, const Register &dest); 1.946 + void movePtr(const ImmWord &imm, const Register &dest); 1.947 + void movePtr(const ImmPtr &imm, const Register &dest); 1.948 + void movePtr(const AsmJSImmPtr &imm, const Register &dest); 1.949 + void movePtr(const ImmGCPtr &imm, const Register &dest); 1.950 + 1.951 + void load8SignExtend(const Address &address, const Register &dest); 1.952 + void load8SignExtend(const BaseIndex &src, const Register &dest); 1.953 + 1.954 + void load8ZeroExtend(const Address &address, const Register &dest); 1.955 + void load8ZeroExtend(const BaseIndex &src, const Register &dest); 1.956 + 1.957 + void load16SignExtend(const Address &address, const Register &dest); 1.958 + void load16SignExtend(const BaseIndex &src, const Register &dest); 1.959 + 1.960 + void load16ZeroExtend(const Address &address, const Register &dest); 1.961 + void load16ZeroExtend(const BaseIndex &src, const Register &dest); 1.962 + 1.963 + void load32(const Address &address, const Register &dest); 1.964 + void load32(const BaseIndex &address, const Register &dest); 1.965 + void load32(const AbsoluteAddress &address, const Register &dest); 1.966 + 1.967 + void loadPtr(const Address &address, const Register &dest); 1.968 + void loadPtr(const BaseIndex &src, const Register &dest); 1.969 + void loadPtr(const AbsoluteAddress &address, const Register &dest); 1.970 + void loadPtr(const AsmJSAbsoluteAddress &address, const Register &dest); 1.971 + 1.972 + void loadPrivate(const Address &address, const Register &dest); 1.973 + 1.974 + void loadDouble(const Address &addr, const FloatRegister &dest); 1.975 + void loadDouble(const BaseIndex &src, const FloatRegister &dest); 1.976 + 1.977 + // Load a float value into a register, then expand it to a double. 1.978 + void loadFloatAsDouble(const Address &addr, const FloatRegister &dest); 1.979 + void loadFloatAsDouble(const BaseIndex &src, const FloatRegister &dest); 1.980 + 1.981 + void loadFloat32(const Address &addr, const FloatRegister &dest); 1.982 + void loadFloat32(const BaseIndex &src, const FloatRegister &dest); 1.983 + 1.984 + void store8(const Register &src, const Address &address); 1.985 + void store8(const Imm32 &imm, const Address &address); 1.986 + void store8(const Register &src, const BaseIndex &address); 1.987 + void store8(const Imm32 &imm, const BaseIndex &address); 1.988 + 1.989 + void store16(const Register &src, const Address &address); 1.990 + void store16(const Imm32 &imm, const Address &address); 1.991 + void store16(const Register &src, const BaseIndex &address); 1.992 + void store16(const Imm32 &imm, const BaseIndex &address); 1.993 + 1.994 + void store32(const Register &src, const AbsoluteAddress &address); 1.995 + void store32(const Register &src, const Address &address); 1.996 + void store32(const Register &src, const BaseIndex &address); 1.997 + void store32(const Imm32 &src, const Address &address); 1.998 + void store32(const Imm32 &src, const BaseIndex &address); 1.999 + 1.1000 + void storePtr(ImmWord imm, const Address &address); 1.1001 + void storePtr(ImmPtr imm, const Address &address); 1.1002 + void storePtr(ImmGCPtr imm, const Address &address); 1.1003 + void storePtr(Register src, const Address &address); 1.1004 + void storePtr(const Register &src, const AbsoluteAddress &dest); 1.1005 + void storeDouble(FloatRegister src, Address addr) { 1.1006 + ma_sd(src, addr); 1.1007 + } 1.1008 + void storeDouble(FloatRegister src, BaseIndex addr) { 1.1009 + MOZ_ASSERT(addr.offset == 0); 1.1010 + ma_sd(src, addr); 1.1011 + } 1.1012 + void moveDouble(FloatRegister src, FloatRegister dest) { 1.1013 + as_movd(dest, src); 1.1014 + } 1.1015 + 1.1016 + void storeFloat32(FloatRegister src, Address addr) { 1.1017 + ma_ss(src, addr); 1.1018 + } 1.1019 + void storeFloat32(FloatRegister src, BaseIndex addr) { 1.1020 + MOZ_ASSERT(addr.offset == 0); 1.1021 + ma_ss(src, addr); 1.1022 + } 1.1023 + 1.1024 + void zeroDouble(FloatRegister reg) { 1.1025 + moveToDoubleLo(zero, reg); 1.1026 + moveToDoubleHi(zero, reg); 1.1027 + } 1.1028 + 1.1029 + void clampIntToUint8(Register reg) { 1.1030 + // look at (reg >> 8) if it is 0, then src shouldn't be clamped 1.1031 + // if it is <0, then we want to clamp to 0, 1.1032 + // otherwise, we wish to clamp to 255 1.1033 + Label done; 1.1034 + ma_move(ScratchRegister, reg); 1.1035 + as_sra(ScratchRegister, ScratchRegister, 8); 1.1036 + ma_b(ScratchRegister, ScratchRegister, &done, Assembler::Zero, ShortJump); 1.1037 + { 1.1038 + Label negative; 1.1039 + ma_b(ScratchRegister, ScratchRegister, &negative, Assembler::Signed, ShortJump); 1.1040 + { 1.1041 + ma_li(reg, Imm32(255)); 1.1042 + ma_b(&done, ShortJump); 1.1043 + } 1.1044 + bind(&negative); 1.1045 + { 1.1046 + ma_move(reg, zero); 1.1047 + } 1.1048 + } 1.1049 + bind(&done); 1.1050 + } 1.1051 + 1.1052 + void subPtr(Imm32 imm, const Register dest); 1.1053 + void addPtr(Imm32 imm, const Register dest); 1.1054 + void addPtr(Imm32 imm, const Address &dest); 1.1055 + void addPtr(ImmWord imm, const Register dest) { 1.1056 + addPtr(Imm32(imm.value), dest); 1.1057 + } 1.1058 + void addPtr(ImmPtr imm, const Register dest) { 1.1059 + addPtr(ImmWord(uintptr_t(imm.value)), dest); 1.1060 + } 1.1061 + 1.1062 + void breakpoint(); 1.1063 + 1.1064 + void branchDouble(DoubleCondition cond, const FloatRegister &lhs, const FloatRegister &rhs, 1.1065 + Label *label); 1.1066 + 1.1067 + void branchFloat(DoubleCondition cond, const FloatRegister &lhs, const FloatRegister &rhs, 1.1068 + Label *label); 1.1069 + 1.1070 + void checkStackAlignment(); 1.1071 + 1.1072 + void alignPointerUp(Register src, Register dest, uint32_t alignment); 1.1073 + 1.1074 + void rshiftPtr(Imm32 imm, Register dest) { 1.1075 + ma_srl(dest, dest, imm); 1.1076 + } 1.1077 + void lshiftPtr(Imm32 imm, Register dest) { 1.1078 + ma_sll(dest, dest, imm); 1.1079 + } 1.1080 + 1.1081 + // If source is a double, load it into dest. If source is int32, 1.1082 + // convert it to double. Else, branch to failure. 1.1083 + void ensureDouble(const ValueOperand &source, FloatRegister dest, Label *failure); 1.1084 + 1.1085 + // Setup a call to C/C++ code, given the number of general arguments it 1.1086 + // takes. Note that this only supports cdecl. 1.1087 + // 1.1088 + // In order for alignment to work correctly, the MacroAssembler must have a 1.1089 + // consistent view of the stack displacement. It is okay to call "push" 1.1090 + // manually, however, if the stack alignment were to change, the macro 1.1091 + // assembler should be notified before starting a call. 1.1092 + void setupAlignedABICall(uint32_t args); 1.1093 + 1.1094 + // Sets up an ABI call for when the alignment is not known. This may need a 1.1095 + // scratch register. 1.1096 + void setupUnalignedABICall(uint32_t args, const Register &scratch); 1.1097 + 1.1098 + // Arguments must be assigned in a left-to-right order. This process may 1.1099 + // temporarily use more stack, in which case sp-relative addresses will be 1.1100 + // automatically adjusted. It is extremely important that sp-relative 1.1101 + // addresses are computed *after* setupABICall(). Furthermore, no 1.1102 + // operations should be emitted while setting arguments. 1.1103 + void passABIArg(const MoveOperand &from, MoveOp::Type type); 1.1104 + void passABIArg(const Register ®); 1.1105 + void passABIArg(const FloatRegister ®, MoveOp::Type type); 1.1106 + void passABIArg(const ValueOperand ®s); 1.1107 + 1.1108 + protected: 1.1109 + bool buildOOLFakeExitFrame(void *fakeReturnAddr); 1.1110 + 1.1111 + private: 1.1112 + void callWithABIPre(uint32_t *stackAdjust); 1.1113 + void callWithABIPost(uint32_t stackAdjust, MoveOp::Type result); 1.1114 + 1.1115 + public: 1.1116 + // Emits a call to a C/C++ function, resolving all argument moves. 1.1117 + void callWithABI(void *fun, MoveOp::Type result = MoveOp::GENERAL); 1.1118 + void callWithABI(AsmJSImmPtr imm, MoveOp::Type result = MoveOp::GENERAL); 1.1119 + void callWithABI(const Address &fun, MoveOp::Type result = MoveOp::GENERAL); 1.1120 + 1.1121 + CodeOffsetLabel labelForPatch() { 1.1122 + return CodeOffsetLabel(nextOffset().getOffset()); 1.1123 + } 1.1124 + 1.1125 + void memIntToValue(Address Source, Address Dest) { 1.1126 + MOZ_ASSUME_UNREACHABLE("NYI"); 1.1127 + } 1.1128 + 1.1129 + void lea(Operand addr, Register dest) { 1.1130 + MOZ_ASSUME_UNREACHABLE("NYI"); 1.1131 + } 1.1132 + 1.1133 + void abiret() { 1.1134 + MOZ_ASSUME_UNREACHABLE("NYI"); 1.1135 + } 1.1136 + 1.1137 + void ma_storeImm(Imm32 imm, const Address &addr) { 1.1138 + ma_sw(imm, addr); 1.1139 + } 1.1140 + 1.1141 + BufferOffset ma_BoundsCheck(Register bounded) { 1.1142 + BufferOffset bo = m_buffer.nextOffset(); 1.1143 + ma_liPatchable(bounded, Imm32(0)); 1.1144 + return bo; 1.1145 + } 1.1146 + 1.1147 + void moveFloat32(FloatRegister src, FloatRegister dest) { 1.1148 + as_movs(dest, src); 1.1149 + } 1.1150 + 1.1151 + void branchPtrInNurseryRange(Register ptr, Register temp, Label *label); 1.1152 +}; 1.1153 + 1.1154 +typedef MacroAssemblerMIPSCompat MacroAssemblerSpecific; 1.1155 + 1.1156 +} // namespace jit 1.1157 +} // namespace js 1.1158 + 1.1159 +#endif /* jit_mips_MacroAssembler_mips_h */