summaryrefslogtreecommitdiffstats
path: root/js/src/jit/mips-shared/MacroAssembler-mips-shared.h
blob: 88238accbb2a587644e4b04b71edac4728c2225a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef jit_mips_shared_MacroAssembler_mips_shared_h
#define jit_mips_shared_MacroAssembler_mips_shared_h

#if defined(JS_CODEGEN_MIPS32)
#  include "jit/mips32/Assembler-mips32.h"
#elif defined(JS_CODEGEN_MIPS64)
#  include "jit/mips64/Assembler-mips64.h"
#endif

#include "jit/AtomicOp.h"

namespace js {
namespace jit {

enum LoadStoreSize {
  SizeByte = 8,
  SizeHalfWord = 16,
  SizeWord = 32,
  SizeDouble = 64
};

enum LoadStoreExtension { ZeroExtend = 0, SignExtend = 1 };

enum JumpKind { LongJump = 0, ShortJump = 1 };

enum DelaySlotFill { DontFillDelaySlot = 0, FillDelaySlot = 1 };

static Register CallReg = t9;

class MacroAssemblerMIPSShared : public Assembler {
 protected:
  // Perform a downcast. Should be removed by Bug 996602.
  MacroAssembler& asMasm();
  const MacroAssembler& asMasm() const;

  Condition ma_cmp(Register rd, Register lhs, Register rhs, Condition c);
  Condition ma_cmp(Register rd, Register lhs, Imm32 imm, Condition c);

  void compareFloatingPoint(FloatFormat fmt, FloatRegister lhs,
                            FloatRegister rhs, DoubleCondition c,
                            FloatTestKind* testKind, FPConditionBit fcc = FCC0);

 public:
  void ma_move(Register rd, Register rs);

  void ma_li(Register dest, ImmGCPtr ptr);

  void ma_li(Register dest, Imm32 imm);
  void ma_liPatchable(Register dest, Imm32 imm);

  // Shift operations
  void ma_sll(Register rd, Register rt, Imm32 shift);
  void ma_srl(Register rd, Register rt, Imm32 shift);
  void ma_sra(Register rd, Register rt, Imm32 shift);
  void ma_ror(Register rd, Register rt, Imm32 shift);
  void ma_rol(Register rd, Register rt, Imm32 shift);

  void ma_sll(Register rd, Register rt, Register shift);
  void ma_srl(Register rd, Register rt, Register shift);
  void ma_sra(Register rd, Register rt, Register shift);
  void ma_ror(Register rd, Register rt, Register shift);
  void ma_rol(Register rd, Register rt, Register shift);

  // Negate
  void ma_negu(Register rd, Register rs);

  void ma_not(Register rd, Register rs);

  // Bit extract/insert
  void ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size);
  void ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size);

  // Sign extend
  void ma_seb(Register rd, Register rt);
  void ma_seh(Register rd, Register rt);

  // and
  void ma_and(Register rd, Register rs);
  void ma_and(Register rd, Imm32 imm);
  void ma_and(Register rd, Register rs, Imm32 imm);

  // or
  void ma_or(Register rd, Register rs);
  void ma_or(Register rd, Imm32 imm);
  void ma_or(Register rd, Register rs, Imm32 imm);

  // xor
  void ma_xor(Register rd, Register rs);
  void ma_xor(Register rd, Imm32 imm);
  void ma_xor(Register rd, Register rs, Imm32 imm);

  // word swap byte within halfwords
  void ma_wsbh(Register rd, Register rt);

  void ma_ctz(Register rd, Register rs);

  // load
  void ma_load(Register dest, const BaseIndex& src,
               LoadStoreSize size = SizeWord,
               LoadStoreExtension extension = SignExtend);
  void ma_load_unaligned(Register dest, const BaseIndex& src,
                         LoadStoreSize size = SizeWord,
                         LoadStoreExtension extension = SignExtend);
  void ma_load_unaligned(Register dest, const Address& address,
                         LoadStoreSize size = SizeWord,
                         LoadStoreExtension extension = SignExtend);
  void ma_load_unaligned(const wasm::MemoryAccessDesc& access, Register dest,
                         const BaseIndex& src, Register temp,
                         LoadStoreSize size, LoadStoreExtension extension);

  // store
  void ma_store(Register data, const BaseIndex& dest,
                LoadStoreSize size = SizeWord,
                LoadStoreExtension extension = SignExtend);
  void ma_store(Imm32 imm, const BaseIndex& dest, LoadStoreSize size = SizeWord,
                LoadStoreExtension extension = SignExtend);
  void ma_store_unaligned(Register data, const Address& dest,
                          LoadStoreSize size = SizeWord);
  void ma_store_unaligned(Register data, const BaseIndex& dest,
                          LoadStoreSize size = SizeWord);
  void ma_store_unaligned(const wasm::MemoryAccessDesc& access, Register data,
                          const BaseIndex& dest, Register temp,
                          LoadStoreSize size, LoadStoreExtension extension);

  // arithmetic based ops
  // add
  void ma_addu(Register rd, Register rs, Imm32 imm);
  void ma_addu(Register rd, Register rs);
  void ma_addu(Register rd, Imm32 imm);
  void ma_add32TestCarry(Condition cond, Register rd, Register rs, Register rt,
                         Label* overflow);
  void ma_add32TestCarry(Condition cond, Register rd, Register rs, Imm32 imm,
                         Label* overflow);

  // subtract
  void ma_subu(Register rd, Register rs, Imm32 imm);
  void ma_subu(Register rd, Register rs);
  void ma_subu(Register rd, Imm32 imm);
  void ma_sub32TestOverflow(Register rd, Register rs, Imm32 imm,
                            Label* overflow);

  // multiplies.  For now, there are only few that we care about.
  void ma_mul(Register rd, Register rs, Imm32 imm);
  void ma_mul32TestOverflow(Register rd, Register rs, Register rt,
                            Label* overflow);
  void ma_mul32TestOverflow(Register rd, Register rs, Imm32 imm,
                            Label* overflow);

  // divisions
  void ma_div_branch_overflow(Register rd, Register rs, Register rt,
                              Label* overflow);
  void ma_div_branch_overflow(Register rd, Register rs, Imm32 imm,
                              Label* overflow);

  // fast mod, uses scratch registers, and thus needs to be in the assembler
  // implicitly assumes that we can overwrite dest at the beginning of the
  // sequence
  void ma_mod_mask(Register src, Register dest, Register hold, Register remain,
                   int32_t shift, Label* negZero = nullptr);

  // branches when done from within mips-specific code
  void ma_b(Register lhs, Register rhs, Label* l, Condition c,
            JumpKind jumpKind = LongJump);
  void ma_b(Register lhs, Imm32 imm, Label* l, Condition c,
            JumpKind jumpKind = LongJump);
  void ma_b(Register lhs, ImmPtr imm, Label* l, Condition c,
            JumpKind jumpKind = LongJump);
  void ma_b(Register lhs, ImmGCPtr imm, Label* l, Condition c,
            JumpKind jumpKind = LongJump) {
    MOZ_ASSERT(lhs != ScratchRegister);
    ma_li(ScratchRegister, imm);
    ma_b(lhs, ScratchRegister, l, c, jumpKind);
  }

  void ma_b(Label* l, JumpKind jumpKind = LongJump);

  // fp instructions
  void ma_lis(FloatRegister dest, float value);

  void ma_sd(FloatRegister src, BaseIndex address);
  void ma_ss(FloatRegister src, BaseIndex address);

  void ma_ld(FloatRegister dest, const BaseIndex& src);
  void ma_ls(FloatRegister dest, const BaseIndex& src);

  // FP branches
  void ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label* label,
               DoubleCondition c, JumpKind jumpKind = LongJump,
               FPConditionBit fcc = FCC0);
  void ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label* label,
               DoubleCondition c, JumpKind jumpKind = LongJump,
               FPConditionBit fcc = FCC0);

  void ma_call(ImmPtr dest);

  void ma_jump(ImmPtr dest);

  void ma_cmp_set(Register dst, Register lhs, Register rhs, Condition c);
  void ma_cmp_set(Register dst, Register lhs, Imm32 imm, Condition c);
  // void ma_cmp_set(Register dst, Address address, Imm32 imm, Condition c);
  void ma_cmp_set_double(Register dst, FloatRegister lhs, FloatRegister rhs,
                         DoubleCondition c);
  void ma_cmp_set_float32(Register dst, FloatRegister lhs, FloatRegister rhs,
                          DoubleCondition c);

  void moveToDoubleLo(Register src, FloatRegister dest) { as_mtc1(src, dest); }
  void moveFromDoubleLo(FloatRegister src, Register dest) {
    as_mfc1(dest, src);
  }

  void moveToFloat32(Register src, FloatRegister dest) { as_mtc1(src, dest); }
  void moveFromFloat32(FloatRegister src, Register dest) { as_mfc1(dest, src); }

  // Evaluate srcDest = minmax<isMax>{Float32,Double}(srcDest, other).
  // Handle NaN specially if handleNaN is true.
  void minMaxDouble(FloatRegister srcDest, FloatRegister other, bool handleNaN,
                    bool isMax);
  void minMaxFloat32(FloatRegister srcDest, FloatRegister other, bool handleNaN,
                     bool isMax);

  void loadDouble(const Address& addr, FloatRegister dest);
  void loadDouble(const BaseIndex& src, FloatRegister dest);

  // Load a float value into a register, then expand it to a double.
  void loadFloatAsDouble(const Address& addr, FloatRegister dest);
  void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest);

  void loadFloat32(const Address& addr, FloatRegister dest);
  void loadFloat32(const BaseIndex& src, FloatRegister dest);

  void outOfLineWasmTruncateToInt32Check(FloatRegister input, Register output,
                                         MIRType fromType, TruncFlags flags,
                                         Label* rejoin,
                                         wasm::BytecodeOffset trapOffset);
  void outOfLineWasmTruncateToInt64Check(FloatRegister input, Register64 output,
                                         MIRType fromType, TruncFlags flags,
                                         Label* rejoin,
                                         wasm::BytecodeOffset trapOffset);

 protected:
  void wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase,
                    Register ptr, Register ptrScratch, AnyRegister output,
                    Register tmp);
  void wasmStoreImpl(const wasm::MemoryAccessDesc& access, AnyRegister value,
                     Register memoryBase, Register ptr, Register ptrScratch,
                     Register tmp);
};

}  // namespace jit
}  // namespace js

#endif /* jit_mips_shared_MacroAssembler_mips_shared_h */