new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / external / pcre2-10.32 / src / sljit / sljitNativeMIPS_64.c
1 /*
2  *    Stack-less Just-In-Time compiler
3  *
4  *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without modification, are
7  * permitted provided that the following conditions are met:
8  *
9  *   1. Redistributions of source code must retain the above copyright notice, this list of
10  *      conditions and the following disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
13  *      of conditions and the following disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 /* mips 64-bit arch dependent functions. */
28
29 static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
30 {
31         sljit_s32 shift = 32;
32         sljit_s32 shift2;
33         sljit_s32 inv = 0;
34         sljit_ins ins;
35         sljit_uw uimm;
36
37         if (!(imm & ~0xffff))
38                 return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
39
40         if (imm < 0 && imm >= SIMM_MIN)
41                 return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
42
43         if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
44                 FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
45                 return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
46         }
47
48         /* Zero extended number. */
49         uimm = imm;
50         if (imm < 0) {
51                 uimm = ~imm;
52                 inv = 1;
53         }
54
55         while (!(uimm & 0xff00000000000000l)) {
56                 shift -= 8;
57                 uimm <<= 8;
58         }
59
60         if (!(uimm & 0xf000000000000000l)) {
61                 shift -= 4;
62                 uimm <<= 4;
63         }
64
65         if (!(uimm & 0xc000000000000000l)) {
66                 shift -= 2;
67                 uimm <<= 2;
68         }
69
70         if ((sljit_sw)uimm < 0) {
71                 uimm >>= 1;
72                 shift += 1;
73         }
74         SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
75
76         if (inv)
77                 uimm = ~uimm;
78
79         FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
80         if (uimm & 0x0000ffff00000000l)
81                 FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
82
83         imm &= (1l << shift) - 1;
84         if (!(imm & ~0xffff)) {
85                 ins = (shift == 32) ? DSLL32 : DSLL;
86                 if (shift < 32)
87                         ins |= SH_IMM(shift);
88                 FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
89                 return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
90         }
91
92         /* Double shifts needs to be performed. */
93         uimm <<= 32;
94         shift2 = shift - 16;
95
96         while (!(uimm & 0xf000000000000000l)) {
97                 shift2 -= 4;
98                 uimm <<= 4;
99         }
100
101         if (!(uimm & 0xc000000000000000l)) {
102                 shift2 -= 2;
103                 uimm <<= 2;
104         }
105
106         if (!(uimm & 0x8000000000000000l)) {
107                 shift2--;
108                 uimm <<= 1;
109         }
110
111         SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
112
113         FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
114         FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
115         FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
116
117         imm &= (1l << shift2) - 1;
118         return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
119 }
120
121 #define SELECT_OP(a, b) \
122         (!(op & SLJIT_I32_OP) ? a : b)
123
124 #define EMIT_LOGICAL(op_imm, op_norm) \
125         if (flags & SRC2_IMM) { \
126                 if (op & SLJIT_SET_Z) \
127                         FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
128                 if (!(flags & UNUSED_DEST)) \
129                         FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
130         } \
131         else { \
132                 if (op & SLJIT_SET_Z) \
133                         FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
134                 if (!(flags & UNUSED_DEST)) \
135                         FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
136         }
137
138 #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
139         if (flags & SRC2_IMM) { \
140                 if (src2 >= 32) { \
141                         SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \
142                         ins = op_dimm32; \
143                         src2 -= 32; \
144                 } \
145                 else \
146                         ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
147                 if (op & SLJIT_SET_Z) \
148                         FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
149                 if (!(flags & UNUSED_DEST)) \
150                         FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
151         } \
152         else { \
153                 ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
154                 if (op & SLJIT_SET_Z) \
155                         FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
156                 if (!(flags & UNUSED_DEST)) \
157                         FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
158         }
159
160 static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
161         sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
162 {
163         sljit_ins ins;
164         sljit_s32 is_overflow, is_carry, is_handled;
165
166         switch (GET_OPCODE(op)) {
167         case SLJIT_MOV:
168         case SLJIT_MOV_P:
169                 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
170                 if (dst != src2)
171                         return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
172                 return SLJIT_SUCCESS;
173
174         case SLJIT_MOV_U8:
175         case SLJIT_MOV_S8:
176                 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
177                 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
178                         if (op == SLJIT_MOV_S8) {
179                                 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
180                                 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
181                         }
182                         return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
183                 }
184                 else {
185                         SLJIT_ASSERT(dst == src2);
186                 }
187                 return SLJIT_SUCCESS;
188
189         case SLJIT_MOV_U16:
190         case SLJIT_MOV_S16:
191                 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
192                 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
193                         if (op == SLJIT_MOV_S16) {
194                                 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
195                                 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
196                         }
197                         return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
198                 }
199                 else {
200                         SLJIT_ASSERT(dst == src2);
201                 }
202                 return SLJIT_SUCCESS;
203
204         case SLJIT_MOV_U32:
205                 SLJIT_ASSERT(!(op & SLJIT_I32_OP));
206                 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
207                 return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
208
209         case SLJIT_MOV_S32:
210                 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
211                 return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
212
213         case SLJIT_NOT:
214                 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
215                 if (op & SLJIT_SET_Z)
216                         FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
217                 if (!(flags & UNUSED_DEST))
218                         FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
219                 return SLJIT_SUCCESS;
220
221         case SLJIT_CLZ:
222                 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
223 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
224                 if (op & SLJIT_SET_Z)
225                         FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
226                 if (!(flags & UNUSED_DEST))
227                         FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
228 #else
229                 if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
230                         FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
231                         return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
232                 }
233                 /* Nearly all instructions are unmovable in the following sequence. */
234                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
235                 /* Check zero. */
236                 FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
237                 FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));
238                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
239                 /* Loop for searching the highest bit. */
240                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
241                 FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
242                 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
243 #endif
244                 return SLJIT_SUCCESS;
245
246         case SLJIT_ADD:
247                 is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
248                 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
249
250                 if (flags & SRC2_IMM) {
251                         if (is_overflow) {
252                                 if (src2 >= 0)
253                                         FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
254                                 else
255                                         FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
256                         }
257                         else if (op & SLJIT_SET_Z)
258                                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
259
260                         if (is_overflow || is_carry) {
261                                 if (src2 >= 0)
262                                         FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
263                                 else {
264                                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
265                                         FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
266                                 }
267                         }
268                         /* dst may be the same as src1 or src2. */
269                         if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
270                                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
271                 }
272                 else {
273                         if (is_overflow)
274                                 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
275                         else if (op & SLJIT_SET_Z)
276                                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
277
278                         if (is_overflow || is_carry)
279                                 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
280                         /* dst may be the same as src1 or src2. */
281                         if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
282                                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
283                 }
284
285                 /* a + b >= a | b (otherwise, the carry should be set to 1). */
286                 if (is_overflow || is_carry)
287                         FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
288                 if (!is_overflow)
289                         return SLJIT_SUCCESS;
290                 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
291                 FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
292                 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
293                 if (op & SLJIT_SET_Z)
294                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
295                 return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
296
297         case SLJIT_ADDC:
298                 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
299
300                 if (flags & SRC2_IMM) {
301                         if (is_carry) {
302                                 if (src2 >= 0)
303                                         FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
304                                 else {
305                                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
306                                         FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
307                                 }
308                         }
309                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
310                 } else {
311                         if (is_carry)
312                                 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
313                         /* dst may be the same as src1 or src2. */
314                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
315                 }
316                 if (is_carry)
317                         FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
318
319                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
320                 if (!is_carry)
321                         return SLJIT_SUCCESS;
322
323                 /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
324                 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
325                 /* Set carry flag. */
326                 return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
327
328         case SLJIT_SUB:
329                 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
330                         FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
331                         src2 = TMP_REG2;
332                         flags &= ~SRC2_IMM;
333                 }
334
335                 is_handled = 0;
336
337                 if (flags & SRC2_IMM) {
338                         if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
339                                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
340                                 is_handled = 1;
341                         }
342                         else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
343                                 FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
344                                 is_handled = 1;
345                         }
346                 }
347
348                 if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
349                         is_handled = 1;
350
351                         if (flags & SRC2_IMM) {
352                                 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
353                                 src2 = TMP_REG2;
354                                 flags &= ~SRC2_IMM;
355                         }
356
357                         if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
358                                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
359                         }
360                         else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
361                         {
362                                 FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
363                         }
364                         else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
365                                 FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
366                         }
367                         else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
368                         {
369                                 FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
370                         }
371                 }
372
373                 if (is_handled) {
374                         if (flags & SRC2_IMM) {
375                                 if (op & SLJIT_SET_Z)
376                                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
377                                 if (!(flags & UNUSED_DEST))
378                                         return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
379                         }
380                         else {
381                                 if (op & SLJIT_SET_Z)
382                                         FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
383                                 if (!(flags & UNUSED_DEST))
384                                         return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
385                         }
386                         return SLJIT_SUCCESS;
387                 }
388
389                 is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
390                 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
391
392                 if (flags & SRC2_IMM) {
393                         if (is_overflow) {
394                                 if (src2 >= 0)
395                                         FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
396                                 else
397                                         FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
398                         }
399                         else if (op & SLJIT_SET_Z)
400                                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
401
402                         if (is_overflow || is_carry)
403                                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
404                         /* dst may be the same as src1 or src2. */
405                         if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
406                                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
407                 }
408                 else {
409                         if (is_overflow)
410                                 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
411                         else if (op & SLJIT_SET_Z)
412                                 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
413
414                         if (is_overflow || is_carry)
415                                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
416                         /* dst may be the same as src1 or src2. */
417                         if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
418                                 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
419                 }
420
421                 if (!is_overflow)
422                         return SLJIT_SUCCESS;
423                 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
424                 FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
425                 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
426                 if (op & SLJIT_SET_Z)
427                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
428                 return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
429
430         case SLJIT_SUBC:
431                 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
432                         FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
433                         src2 = TMP_REG2;
434                         flags &= ~SRC2_IMM;
435                 }
436
437                 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
438
439                 if (flags & SRC2_IMM) {
440                         if (is_carry)
441                                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
442                         /* dst may be the same as src1 or src2. */
443                         FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
444                 }
445                 else {
446                         if (is_carry)
447                                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
448                         /* dst may be the same as src1 or src2. */
449                         FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
450                 }
451
452                 if (is_carry)
453                         FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
454
455                 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
456                 return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
457
458         case SLJIT_MUL:
459                 SLJIT_ASSERT(!(flags & SRC2_IMM));
460
461                 if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
462 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
463                         if (op & SLJIT_I32_OP)
464                                 return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
465                         FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
466                         return push_inst(compiler, MFLO | D(dst), DR(dst));
467 #else
468                         FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
469                         return push_inst(compiler, MFLO | D(dst), DR(dst));
470 #endif
471                 }
472                 FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
473                 FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
474                 FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
475                 FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
476                 return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
477
478         case SLJIT_AND:
479                 EMIT_LOGICAL(ANDI, AND);
480                 return SLJIT_SUCCESS;
481
482         case SLJIT_OR:
483                 EMIT_LOGICAL(ORI, OR);
484                 return SLJIT_SUCCESS;
485
486         case SLJIT_XOR:
487                 EMIT_LOGICAL(XORI, XOR);
488                 return SLJIT_SUCCESS;
489
490         case SLJIT_SHL:
491                 EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
492                 return SLJIT_SUCCESS;
493
494         case SLJIT_LSHR:
495                 EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
496                 return SLJIT_SUCCESS;
497
498         case SLJIT_ASHR:
499                 EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
500                 return SLJIT_SUCCESS;
501         }
502
503         SLJIT_UNREACHABLE();
504         return SLJIT_SUCCESS;
505 }
506
507 static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
508 {
509         FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
510         FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
511         FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
512         FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
513         FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
514         return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
515 }
516
517 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
518 {
519         sljit_ins *inst = (sljit_ins *)addr;
520
521         inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
522         inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
523         inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
524         inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);
525         inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
526         SLJIT_CACHE_FLUSH(inst, inst + 6);
527 }
528
529 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
530 {
531         sljit_ins *inst = (sljit_ins *)addr;
532
533         inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
534         inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
535         inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
536         inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
537         inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
538         SLJIT_CACHE_FLUSH(inst, inst + 6);
539 }
540
541 static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
542 {
543         sljit_s32 arg_count = 0;
544         sljit_s32 word_arg_count = 0;
545         sljit_s32 float_arg_count = 0;
546         sljit_s32 types = 0;
547         sljit_ins prev_ins = NOP;
548         sljit_ins ins = NOP;
549
550         SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
551
552         arg_types >>= SLJIT_DEF_SHIFT;
553
554         while (arg_types) {
555                 types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
556
557                 switch (arg_types & SLJIT_DEF_MASK) {
558                 case SLJIT_ARG_TYPE_F32:
559                 case SLJIT_ARG_TYPE_F64:
560                         arg_count++;
561                         float_arg_count++;
562                         break;
563                 default:
564                         arg_count++;
565                         word_arg_count++;
566                         break;
567                 }
568
569                 arg_types >>= SLJIT_DEF_SHIFT;
570         }
571
572         while (types) {
573                 switch (types & SLJIT_DEF_MASK) {
574                 case SLJIT_ARG_TYPE_F32:
575                         if (arg_count != float_arg_count)
576                                 ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);
577                         else if (arg_count == 1)
578                                 ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
579                         arg_count--;
580                         float_arg_count--;
581                         break;
582                 case SLJIT_ARG_TYPE_F64:
583                         if (arg_count != float_arg_count)
584                                 ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);
585                         else if (arg_count == 1)
586                                 ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
587                         arg_count--;
588                         float_arg_count--;
589                         break;
590                 default:
591                         if (arg_count != word_arg_count)
592                                 ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
593                         else if (arg_count == 1)
594                                 ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);
595                         arg_count--;
596                         word_arg_count--;
597                         break;
598                 }
599
600                 if (ins != NOP) {
601                         if (prev_ins != NOP)
602                                 FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
603                         prev_ins = ins;
604                         ins = NOP;
605                 }
606
607                 types >>= SLJIT_DEF_SHIFT;
608         }
609
610         *ins_ptr = prev_ins;
611
612         return SLJIT_SUCCESS;
613 }
614
615 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
616         sljit_s32 arg_types)
617 {
618         struct sljit_jump *jump;
619         sljit_ins ins;
620
621         CHECK_ERROR_PTR();
622         CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
623
624         jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
625         PTR_FAIL_IF(!jump);
626         set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
627         type &= 0xff;
628
629         PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
630
631         SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
632
633         PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
634
635         jump->flags |= IS_JAL | IS_CALL;
636         PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
637         jump->addr = compiler->size;
638         PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
639
640         return jump;
641 }
642
643 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
644         sljit_s32 arg_types,
645         sljit_s32 src, sljit_sw srcw)
646 {
647         sljit_ins ins;
648
649         CHECK_ERROR();
650         CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
651
652         SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
653
654         if (src & SLJIT_IMM)
655                 FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
656         else if (FAST_IS_REG(src))
657                 FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
658         else if (src & SLJIT_MEM) {
659                 ADJUST_LOCAL_OFFSET(src, srcw);
660                 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
661         }
662
663         FAIL_IF(call_with_args(compiler, arg_types, &ins));
664
665         /* Register input. */
666         FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
667         return push_inst(compiler, ins, UNMOVABLE_INS);
668 }