Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c
9913 views
1
/*
2
* Stack-less Just-In-Time compiler
3
*
4
* Copyright Zoltan Herczeg ([email protected]). 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
/* Latest MIPS architecture. */
28
29
#ifdef HAVE_PRCTL
30
#include <sys/prctl.h>
31
#endif
32
33
#if !defined(__mips_hard_float) || defined(__mips_single_float)
34
/* Disable automatic detection, covers both -msoft-float and -mno-float */
35
#define SLJIT_IS_FPU_AVAILABLE 0
36
#endif
37
38
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
39
{
40
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
41
42
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
43
return "MIPS32-R6" SLJIT_CPUINFO;
44
#else /* !SLJIT_CONFIG_MIPS_32 */
45
return "MIPS64-R6" SLJIT_CPUINFO;
46
#endif /* SLJIT_CONFIG_MIPS_32 */
47
48
#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 5)
49
50
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
51
return "MIPS32-R5" SLJIT_CPUINFO;
52
#else /* !SLJIT_CONFIG_MIPS_32 */
53
return "MIPS64-R5" SLJIT_CPUINFO;
54
#endif /* SLJIT_CONFIG_MIPS_32 */
55
56
#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
57
58
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
59
return "MIPS32-R2" SLJIT_CPUINFO;
60
#else /* !SLJIT_CONFIG_MIPS_32 */
61
return "MIPS64-R2" SLJIT_CPUINFO;
62
#endif /* SLJIT_CONFIG_MIPS_32 */
63
64
#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
65
66
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
67
return "MIPS32-R1" SLJIT_CPUINFO;
68
#else /* !SLJIT_CONFIG_MIPS_32 */
69
return "MIPS64-R1" SLJIT_CPUINFO;
70
#endif /* SLJIT_CONFIG_MIPS_32 */
71
72
#else /* SLJIT_MIPS_REV < 1 */
73
return "MIPS III" SLJIT_CPUINFO;
74
#endif /* SLJIT_MIPS_REV >= 6 */
75
}
76
77
/* Length of an instruction word
78
Both for mips-32 and mips-64 */
79
typedef sljit_u32 sljit_ins;
80
81
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
82
#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
83
#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
84
85
/* For position independent code, t9 must contain the function address. */
86
#define PIC_ADDR_REG TMP_REG1
87
88
/* Floating point status register. */
89
#define FCSR_REG 31
90
/* Return address register. */
91
#define RETURN_ADDR_REG 31
92
93
/* Flags are kept in volatile registers. */
94
#define EQUAL_FLAG 3
95
#define OTHER_FLAG 1
96
97
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
98
0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 25, 4, 31, 3, 1
99
};
100
101
#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
102
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
103
#define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)
104
105
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
106
107
static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3) << 1) + 1] = {
108
0,
109
0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20,
110
12, 10, 16,
111
1, 15, 3, 5, 7, 9, 19, 31, 29, 27, 25, 23, 21,
112
13, 11, 17
113
};
114
115
#else /* !SLJIT_CONFIG_MIPS_32 */
116
117
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
118
0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10
119
};
120
121
#endif /* SLJIT_CONFIG_MIPS_32 */
122
123
/* --------------------------------------------------------------------- */
124
/* Instrucion forms */
125
/* --------------------------------------------------------------------- */
126
127
#define S(s) ((sljit_ins)reg_map[s] << 21)
128
#define T(t) ((sljit_ins)reg_map[t] << 16)
129
#define D(d) ((sljit_ins)reg_map[d] << 11)
130
#define FT(t) ((sljit_ins)freg_map[t] << 16)
131
#define FS(s) ((sljit_ins)freg_map[s] << 11)
132
#define FD(d) ((sljit_ins)freg_map[d] << 6)
133
/* Absolute registers. */
134
#define SA(s) ((sljit_ins)(s) << 21)
135
#define TA(t) ((sljit_ins)(t) << 16)
136
#define DA(d) ((sljit_ins)(d) << 11)
137
#define IMM(imm) ((sljit_ins)(imm) & 0xffff)
138
#define SH_IMM(imm) ((sljit_ins)(imm) << 6)
139
140
#define DR(dr) (reg_map[dr])
141
#define FR(dr) (freg_map[dr])
142
#define HI(opcode) ((sljit_ins)(opcode) << 26)
143
#define LO(opcode) ((sljit_ins)(opcode))
144
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
145
/* CMP.cond.fmt */
146
/* S = (20 << 21) D = (21 << 21) */
147
#define CMP_FMT_S (20 << 21)
148
#endif /* SLJIT_MIPS_REV >= 6 */
149
/* S = (16 << 21) D = (17 << 21) */
150
#define FMT_S (16 << 21)
151
#define FMT_D (17 << 21)
152
153
#define ABS_S (HI(17) | FMT_S | LO(5))
154
#define ADD_S (HI(17) | FMT_S | LO(0))
155
#define ADDIU (HI(9))
156
#define ADDU (HI(0) | LO(33))
157
#define AND (HI(0) | LO(36))
158
#define ANDI (HI(12))
159
#define B (HI(4))
160
#define BAL (HI(1) | (17 << 16))
161
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
162
#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))
163
#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))
164
#else /* SLJIT_MIPS_REV < 6 */
165
#define BC1F (HI(17) | (8 << 21))
166
#define BC1T (HI(17) | (8 << 21) | (1 << 16))
167
#endif /* SLJIT_MIPS_REV >= 6 */
168
#define BEQ (HI(4))
169
#define BGEZ (HI(1) | (1 << 16))
170
#define BGTZ (HI(7))
171
#define BLEZ (HI(6))
172
#define BLTZ (HI(1) | (0 << 16))
173
#define BNE (HI(5))
174
#define BREAK (HI(0) | LO(13))
175
#define CFC1 (HI(17) | (2 << 21))
176
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
177
#define C_EQ_S (HI(17) | CMP_FMT_S | LO(2))
178
#define C_OLE_S (HI(17) | CMP_FMT_S | LO(6))
179
#define C_OLT_S (HI(17) | CMP_FMT_S | LO(4))
180
#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))
181
#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))
182
#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))
183
#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))
184
#define C_FD (FD(TMP_FREG3))
185
#else /* SLJIT_MIPS_REV < 6 */
186
#define C_EQ_S (HI(17) | FMT_S | LO(50))
187
#define C_OLE_S (HI(17) | FMT_S | LO(54))
188
#define C_OLT_S (HI(17) | FMT_S | LO(52))
189
#define C_UEQ_S (HI(17) | FMT_S | LO(51))
190
#define C_ULE_S (HI(17) | FMT_S | LO(55))
191
#define C_ULT_S (HI(17) | FMT_S | LO(53))
192
#define C_UN_S (HI(17) | FMT_S | LO(49))
193
#define C_FD (0)
194
#endif /* SLJIT_MIPS_REV >= 6 */
195
#define CVT_S_S (HI(17) | FMT_S | LO(32))
196
#define DADDIU (HI(25))
197
#define DADDU (HI(0) | LO(45))
198
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
199
#define DDIV (HI(0) | (2 << 6) | LO(30))
200
#define DDIVU (HI(0) | (2 << 6) | LO(31))
201
#define DMOD (HI(0) | (3 << 6) | LO(30))
202
#define DMODU (HI(0) | (3 << 6) | LO(31))
203
#define DIV (HI(0) | (2 << 6) | LO(26))
204
#define DIVU (HI(0) | (2 << 6) | LO(27))
205
#define DMUH (HI(0) | (3 << 6) | LO(28))
206
#define DMUHU (HI(0) | (3 << 6) | LO(29))
207
#define DMUL (HI(0) | (2 << 6) | LO(28))
208
#define DMULU (HI(0) | (2 << 6) | LO(29))
209
#else /* SLJIT_MIPS_REV < 6 */
210
#define DDIV (HI(0) | LO(30))
211
#define DDIVU (HI(0) | LO(31))
212
#define DIV (HI(0) | LO(26))
213
#define DIVU (HI(0) | LO(27))
214
#define DMULT (HI(0) | LO(28))
215
#define DMULTU (HI(0) | LO(29))
216
#endif /* SLJIT_MIPS_REV >= 6 */
217
#define DIV_S (HI(17) | FMT_S | LO(3))
218
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
219
#define DINSU (HI(31) | LO(6))
220
#endif /* SLJIT_MIPS_REV >= 2 */
221
#define DMFC1 (HI(17) | (1 << 21))
222
#define DMTC1 (HI(17) | (5 << 21))
223
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
224
#define DROTR (HI(0) | (1 << 21) | LO(58))
225
#define DROTR32 (HI(0) | (1 << 21) | LO(62))
226
#define DROTRV (HI(0) | (1 << 6) | LO(22))
227
#define DSBH (HI(31) | (2 << 6) | LO(36))
228
#define DSHD (HI(31) | (5 << 6) | LO(36))
229
#endif /* SLJIT_MIPS_REV >= 2 */
230
#define DSLL (HI(0) | LO(56))
231
#define DSLL32 (HI(0) | LO(60))
232
#define DSLLV (HI(0) | LO(20))
233
#define DSRA (HI(0) | LO(59))
234
#define DSRA32 (HI(0) | LO(63))
235
#define DSRAV (HI(0) | LO(23))
236
#define DSRL (HI(0) | LO(58))
237
#define DSRL32 (HI(0) | LO(62))
238
#define DSRLV (HI(0) | LO(22))
239
#define DSUBU (HI(0) | LO(47))
240
#define J (HI(2))
241
#define JAL (HI(3))
242
#define JALR (HI(0) | LO(9))
243
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
244
#define JR (HI(0) | LO(9))
245
#else /* SLJIT_MIPS_REV < 6 */
246
#define JR (HI(0) | LO(8))
247
#endif /* SLJIT_MIPS_REV >= 6 */
248
#define LD (HI(55))
249
#define LDL (HI(26))
250
#define LDR (HI(27))
251
#define LDC1 (HI(53))
252
#define LL (HI(48))
253
#define LLD (HI(52))
254
#define LUI (HI(15))
255
#define LW (HI(35))
256
#define LWL (HI(34))
257
#define LWR (HI(38))
258
#define LWC1 (HI(49))
259
#define MFC1 (HI(17))
260
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
261
#define MFHC1 (HI(17) | (3 << 21))
262
#endif /* SLJIT_MIPS_REV >= 2 */
263
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
264
#define MOD (HI(0) | (3 << 6) | LO(26))
265
#define MODU (HI(0) | (3 << 6) | LO(27))
266
#else /* SLJIT_MIPS_REV < 6 */
267
#define MFHI (HI(0) | LO(16))
268
#define MFLO (HI(0) | LO(18))
269
#endif /* SLJIT_MIPS_REV >= 6 */
270
#define MTC1 (HI(17) | (4 << 21))
271
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
272
#define MTHC1 (HI(17) | (7 << 21))
273
#endif /* SLJIT_MIPS_REV >= 2 */
274
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
275
#define MUH (HI(0) | (3 << 6) | LO(24))
276
#define MUHU (HI(0) | (3 << 6) | LO(25))
277
#define MUL (HI(0) | (2 << 6) | LO(24))
278
#define MULU (HI(0) | (2 << 6) | LO(25))
279
#else /* SLJIT_MIPS_REV < 6 */
280
#define MULT (HI(0) | LO(24))
281
#define MULTU (HI(0) | LO(25))
282
#endif /* SLJIT_MIPS_REV >= 6 */
283
#define MUL_S (HI(17) | FMT_S | LO(2))
284
#define NEG_S (HI(17) | FMT_S | LO(7))
285
#define NOP (HI(0) | LO(0))
286
#define NOR (HI(0) | LO(39))
287
#define OR (HI(0) | LO(37))
288
#define ORI (HI(13))
289
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
290
#define ROTR (HI(0) | (1 << 21) | LO(2))
291
#define ROTRV (HI(0) | (1 << 6) | LO(6))
292
#endif /* SLJIT_MIPS_REV >= 2 */
293
#define SC (HI(56))
294
#define SCD (HI(60))
295
#define SD (HI(63))
296
#define SDL (HI(44))
297
#define SDR (HI(45))
298
#define SDC1 (HI(61))
299
#define SLT (HI(0) | LO(42))
300
#define SLTI (HI(10))
301
#define SLTIU (HI(11))
302
#define SLTU (HI(0) | LO(43))
303
#define SLL (HI(0) | LO(0))
304
#define SLLV (HI(0) | LO(4))
305
#define SRL (HI(0) | LO(2))
306
#define SRLV (HI(0) | LO(6))
307
#define SRA (HI(0) | LO(3))
308
#define SRAV (HI(0) | LO(7))
309
#define SUB_S (HI(17) | FMT_S | LO(1))
310
#define SUBU (HI(0) | LO(35))
311
#define SW (HI(43))
312
#define SWL (HI(42))
313
#define SWR (HI(46))
314
#define SWC1 (HI(57))
315
#define SYNC (HI(0) | LO(15))
316
#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
317
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
318
#define WSBH (HI(31) | (2 << 6) | LO(32))
319
#endif /* SLJIT_MIPS_REV >= 2 */
320
#define XOR (HI(0) | LO(38))
321
#define XORI (HI(14))
322
323
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
324
#define CLZ (HI(28) | LO(32))
325
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
326
#define DCLZ (LO(18))
327
#else /* SLJIT_MIPS_REV < 6 */
328
#define DCLZ (HI(28) | LO(36))
329
#define MOVF (HI(0) | (0 << 16) | LO(1))
330
#define MOVF_S (HI(17) | FMT_S | (0 << 16) | LO(17))
331
#define MOVN (HI(0) | LO(11))
332
#define MOVN_S (HI(17) | FMT_S | LO(19))
333
#define MOVT (HI(0) | (1 << 16) | LO(1))
334
#define MOVT_S (HI(17) | FMT_S | (1 << 16) | LO(17))
335
#define MOVZ (HI(0) | LO(10))
336
#define MOVZ_S (HI(17) | FMT_S | LO(18))
337
#define MUL (HI(28) | LO(2))
338
#endif /* SLJIT_MIPS_REV >= 6 */
339
#define PREF (HI(51))
340
#define PREFX (HI(19) | LO(15))
341
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
342
#define SEB (HI(31) | (16 << 6) | LO(32))
343
#define SEH (HI(31) | (24 << 6) | LO(32))
344
#endif /* SLJIT_MIPS_REV >= 2 */
345
#endif /* SLJIT_MIPS_REV >= 1 */
346
347
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
348
#define ADDU_W ADDU
349
#define ADDIU_W ADDIU
350
#define SLL_W SLL
351
#define SRA_W SRA
352
#define SUBU_W SUBU
353
#define STORE_W SW
354
#define LOAD_W LW
355
#else
356
#define ADDU_W DADDU
357
#define ADDIU_W DADDIU
358
#define SLL_W DSLL
359
#define SRA_W DSRA
360
#define SUBU_W DSUBU
361
#define STORE_W SD
362
#define LOAD_W LD
363
#endif
364
365
#define MOV_fmt(f) (HI(17) | f | LO(6))
366
367
#define SIMM_MAX (0x7fff)
368
#define SIMM_MIN (-0x8000)
369
#define UIMM_MAX (0xffff)
370
371
#define CPU_FEATURE_DETECTED (1 << 0)
372
#define CPU_FEATURE_FPU (1 << 1)
373
#define CPU_FEATURE_FP64 (1 << 2)
374
#define CPU_FEATURE_FR (1 << 3)
375
376
static sljit_u32 cpu_feature_list = 0;
377
378
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
379
&& (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
380
381
static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)
382
{
383
if (compiler->scratches == -1)
384
return 0;
385
386
if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))
387
fr -= SLJIT_F64_SECOND(0);
388
389
return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches))
390
|| (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)
391
|| (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
392
}
393
394
static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)
395
{
396
SLJIT_UNUSED_ARG(compiler);
397
SLJIT_UNUSED_ARG(vr);
398
SLJIT_UNUSED_ARG(type);
399
400
/* SIMD is not supported. */
401
return 0;
402
}
403
404
#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */
405
406
static void get_cpu_features(void)
407
{
408
#if !defined(SLJIT_IS_FPU_AVAILABLE) && defined(__GNUC__)
409
sljit_u32 fir = 0;
410
#endif /* !SLJIT_IS_FPU_AVAILABLE && __GNUC__ */
411
sljit_u32 feature_list = CPU_FEATURE_DETECTED;
412
413
#if defined(SLJIT_IS_FPU_AVAILABLE)
414
#if SLJIT_IS_FPU_AVAILABLE
415
feature_list |= CPU_FEATURE_FPU;
416
#if SLJIT_IS_FPU_AVAILABLE == 64
417
feature_list |= CPU_FEATURE_FP64;
418
#endif /* SLJIT_IS_FPU_AVAILABLE == 64 */
419
#endif /* SLJIT_IS_FPU_AVAILABLE */
420
#elif defined(__GNUC__)
421
__asm__ ("cfc1 %0, $0" : "=r"(fir));
422
if ((fir & (0x3 << 16)) == (0x3 << 16))
423
feature_list |= CPU_FEATURE_FPU;
424
425
#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64) \
426
&& (!defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV < 2)
427
if ((feature_list & CPU_FEATURE_FPU))
428
feature_list |= CPU_FEATURE_FP64;
429
#else /* SLJIT_CONFIG_MIPS32 || SLJIT_MIPS_REV >= 2 */
430
if ((fir & (1 << 22)))
431
feature_list |= CPU_FEATURE_FP64;
432
#endif /* SLJIT_CONFIG_MIPS_64 && SLJIT_MIPS_REV < 2 */
433
#endif /* SLJIT_IS_FPU_AVAILABLE */
434
435
if ((feature_list & CPU_FEATURE_FPU) && (feature_list & CPU_FEATURE_FP64)) {
436
#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
437
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 6
438
feature_list |= CPU_FEATURE_FR;
439
#elif defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 0
440
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 5
441
feature_list |= CPU_FEATURE_FR;
442
#endif /* SLJIT_MIPS_REV >= 5 */
443
#else
444
sljit_s32 flag = -1;
445
#ifndef FR_GET_FP_MODE
446
sljit_f64 zero = 0.0;
447
#else /* PR_GET_FP_MODE */
448
flag = prctl(PR_GET_FP_MODE);
449
450
if (flag > 0)
451
feature_list |= CPU_FEATURE_FR;
452
#endif /* FP_GET_PR_MODE */
453
#if ((defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 2) \
454
|| (!defined(PR_GET_FP_MODE) && (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1))) \
455
&& (defined(__GNUC__) && (defined(__mips) && __mips >= 2))
456
if (flag < 0) {
457
__asm__ (".set oddspreg\n"
458
"lwc1 $f17, %0\n"
459
"ldc1 $f16, %1\n"
460
"swc1 $f17, %0\n"
461
: "+m" (flag) : "m" (zero) : "$f16", "$f17");
462
if (flag)
463
feature_list |= CPU_FEATURE_FR;
464
}
465
#endif /* (!PR_GET_FP_MODE || (PR_GET_FP_MODE && SLJIT_DETECT_FR == 2)) && __GNUC__ */
466
#endif /* SLJIT_MIPS_REV >= 6 */
467
#else /* !SLJIT_CONFIG_MIPS_32 */
468
/* StatusFR=1 is the only mode supported by the code in MIPS64 */
469
feature_list |= CPU_FEATURE_FR;
470
#endif /* SLJIT_CONFIG_MIPS_32 */
471
}
472
473
cpu_feature_list = feature_list;
474
}
475
476
/* dest_reg is the absolute name of the register
477
Useful for reordering instructions in the delay slot. */
478
static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
479
{
480
sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
481
SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
482
|| (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)
483
|| (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));
484
FAIL_IF(!ptr);
485
*ptr = ins;
486
compiler->size++;
487
compiler->delay_slot = delay_slot;
488
return SLJIT_SUCCESS;
489
}
490
491
static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)
492
{
493
if (flags & IS_BIT26_COND)
494
return (1 << 26);
495
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
496
if (flags & IS_BIT23_COND)
497
return (1 << 23);
498
#endif /* SLJIT_MIPS_REV >= 6 */
499
return (1 << 16);
500
}
501
502
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
503
{
504
sljit_sw diff;
505
sljit_uw target_addr;
506
sljit_ins *inst;
507
sljit_ins saved_inst;
508
509
inst = (sljit_ins *)jump->addr;
510
511
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
512
if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
513
goto exit;
514
#else
515
if (jump->flags & SLJIT_REWRITABLE_JUMP)
516
goto exit;
517
#endif
518
519
if (jump->flags & JUMP_ADDR)
520
target_addr = jump->u.target;
521
else {
522
SLJIT_ASSERT(jump->u.label != NULL);
523
target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
524
}
525
526
if (jump->flags & IS_COND)
527
inst--;
528
529
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
530
if (jump->flags & IS_CALL)
531
goto preserve_addr;
532
#endif
533
534
/* B instructions. */
535
if (jump->flags & IS_MOVABLE) {
536
diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
537
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
538
jump->flags |= PATCH_B;
539
540
if (!(jump->flags & IS_COND)) {
541
inst[0] = inst[-1];
542
inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
543
jump->addr -= sizeof(sljit_ins);
544
return inst;
545
}
546
saved_inst = inst[0];
547
inst[0] = inst[-1];
548
inst[-1] = saved_inst ^ invert_branch(jump->flags);
549
jump->addr -= 2 * sizeof(sljit_ins);
550
return inst;
551
}
552
} else {
553
diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
554
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
555
jump->flags |= PATCH_B;
556
557
if (!(jump->flags & IS_COND)) {
558
inst[0] = (jump->flags & IS_JAL) ? BAL : B;
559
/* Keep inst[1] */
560
return inst + 1;
561
}
562
inst[0] ^= invert_branch(jump->flags);
563
inst[1] = NOP;
564
jump->addr -= sizeof(sljit_ins);
565
return inst + 1;
566
}
567
}
568
569
if (jump->flags & IS_COND) {
570
if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
571
jump->flags |= PATCH_J;
572
saved_inst = inst[0];
573
inst[0] = inst[-1];
574
inst[-1] = (saved_inst & 0xffff0000) | 3;
575
inst[1] = J;
576
inst[2] = NOP;
577
return inst + 2;
578
}
579
else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
580
jump->flags |= PATCH_J;
581
inst[0] = (inst[0] & 0xffff0000) | 3;
582
inst[1] = NOP;
583
inst[2] = J;
584
inst[3] = NOP;
585
jump->addr += sizeof(sljit_ins);
586
return inst + 3;
587
}
588
}
589
else {
590
/* J instuctions. */
591
if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {
592
jump->flags |= PATCH_J;
593
inst[0] = inst[-1];
594
inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
595
jump->addr -= sizeof(sljit_ins);
596
return inst;
597
}
598
599
if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
600
jump->flags |= PATCH_J;
601
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
602
/* Keep inst[1] */
603
return inst + 1;
604
}
605
}
606
607
if (jump->flags & IS_COND)
608
inst++;
609
610
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
611
preserve_addr:
612
if (target_addr <= 0x7fffffff) {
613
jump->flags |= PATCH_ABS32;
614
if (jump->flags & IS_COND)
615
inst[-1] -= 4;
616
617
inst[2] = inst[0];
618
inst[3] = inst[1];
619
return inst + 3;
620
}
621
if (target_addr <= 0x7fffffffffffl) {
622
jump->flags |= PATCH_ABS48;
623
if (jump->flags & IS_COND)
624
inst[-1] -= 2;
625
626
inst[4] = inst[0];
627
inst[5] = inst[1];
628
return inst + 5;
629
}
630
#endif
631
632
exit:
633
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
634
inst[2] = inst[0];
635
inst[3] = inst[1];
636
return inst + 3;
637
#else
638
inst[6] = inst[0];
639
inst[7] = inst[1];
640
return inst + 7;
641
#endif
642
}
643
644
#ifdef __GNUC__
645
static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
646
{
647
SLJIT_CACHE_FLUSH(code, code_ptr);
648
}
649
#endif
650
651
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
652
653
static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
654
{
655
sljit_uw addr;
656
SLJIT_UNUSED_ARG(executable_offset);
657
658
if (jump->flags & JUMP_ADDR)
659
addr = jump->u.target;
660
else
661
addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
662
663
if (addr < 0x80000000l) {
664
jump->flags |= PATCH_ABS32;
665
return 1;
666
}
667
668
if (addr < 0x800000000000l) {
669
jump->flags |= PATCH_ABS48;
670
return 3;
671
}
672
673
return 5;
674
}
675
676
#endif /* SLJIT_CONFIG_MIPS_64 */
677
678
static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump)
679
{
680
sljit_uw flags = jump->flags;
681
sljit_ins *ins = (sljit_ins*)jump->addr;
682
sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
683
sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : PIC_ADDR_REG;
684
685
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
686
ins[0] = LUI | T(reg) | IMM(addr >> 16);
687
#else /* !SLJIT_CONFIG_MIPS_32 */
688
if (flags & PATCH_ABS32) {
689
SLJIT_ASSERT(addr < 0x80000000l);
690
ins[0] = LUI | T(reg) | IMM(addr >> 16);
691
}
692
else if (flags & PATCH_ABS48) {
693
SLJIT_ASSERT(addr < 0x800000000000l);
694
ins[0] = LUI | T(reg) | IMM(addr >> 32);
695
ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
696
ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
697
ins += 2;
698
}
699
else {
700
ins[0] = LUI | T(reg) | IMM(addr >> 48);
701
ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
702
ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
703
ins[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
704
ins[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
705
ins += 4;
706
}
707
#endif /* SLJIT_CONFIG_MIPS_32 */
708
709
ins[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
710
}
711
712
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
713
{
714
struct sljit_memory_fragment *buf;
715
sljit_ins *code;
716
sljit_ins *code_ptr;
717
sljit_ins *buf_ptr;
718
sljit_ins *buf_end;
719
sljit_uw word_count;
720
SLJIT_NEXT_DEFINE_TYPES;
721
sljit_sw executable_offset;
722
sljit_uw addr;
723
struct sljit_label *label;
724
struct sljit_jump *jump;
725
struct sljit_const *const_;
726
727
CHECK_ERROR_PTR();
728
CHECK_PTR(check_sljit_generate_code(compiler));
729
reverse_buf(compiler);
730
731
code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
732
PTR_FAIL_WITH_EXEC_IF(code);
733
buf = compiler->buf;
734
735
code_ptr = code;
736
word_count = 0;
737
label = compiler->labels;
738
jump = compiler->jumps;
739
const_ = compiler->consts;
740
SLJIT_NEXT_INIT_TYPES();
741
SLJIT_GET_NEXT_MIN();
742
743
do {
744
buf_ptr = (sljit_ins*)buf->memory;
745
buf_end = buf_ptr + (buf->used_size >> 2);
746
do {
747
*code_ptr = *buf_ptr++;
748
if (next_min_addr == word_count) {
749
SLJIT_ASSERT(!label || label->size >= word_count);
750
SLJIT_ASSERT(!jump || jump->addr >= word_count);
751
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
752
753
/* These structures are ordered by their address. */
754
if (next_min_addr == next_label_size) {
755
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
756
label->size = (sljit_uw)(code_ptr - code);
757
label = label->next;
758
next_label_size = SLJIT_GET_NEXT_SIZE(label);
759
}
760
761
if (next_min_addr == next_jump_addr) {
762
if (!(jump->flags & JUMP_MOV_ADDR)) {
763
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
764
word_count += 2;
765
#else /* !SLJIT_CONFIG_MIPS_32 */
766
word_count += 6;
767
#endif /* SLJIT_CONFIG_MIPS_32 */
768
jump->addr = (sljit_uw)(code_ptr - 1);
769
code_ptr = detect_jump_type(jump, code, executable_offset);
770
} else {
771
jump->addr = (sljit_uw)code_ptr;
772
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
773
code_ptr += 1;
774
word_count += 1;
775
#else /* !SLJIT_CONFIG_MIPS_32 */
776
code_ptr += mov_addr_get_length(jump, code, executable_offset);
777
word_count += 5;
778
#endif /* SLJIT_CONFIG_MIPS_32 */
779
}
780
781
jump = jump->next;
782
next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
783
} else if (next_min_addr == next_const_addr) {
784
const_->addr = (sljit_uw)code_ptr;
785
const_ = const_->next;
786
next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
787
}
788
789
SLJIT_GET_NEXT_MIN();
790
}
791
code_ptr++;
792
word_count++;
793
} while (buf_ptr < buf_end);
794
795
buf = buf->next;
796
} while (buf);
797
798
if (label && label->size == word_count) {
799
label->u.addr = (sljit_uw)code_ptr;
800
label->size = (sljit_uw)(code_ptr - code);
801
label = label->next;
802
}
803
804
SLJIT_ASSERT(!label);
805
SLJIT_ASSERT(!jump);
806
SLJIT_ASSERT(!const_);
807
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
808
809
jump = compiler->jumps;
810
while (jump) {
811
do {
812
addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
813
buf_ptr = (sljit_ins *)jump->addr;
814
815
if (jump->flags & PATCH_B) {
816
addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);
817
SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
818
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);
819
break;
820
}
821
if (jump->flags & PATCH_J) {
822
SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)
823
== (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));
824
buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;
825
break;
826
}
827
828
load_addr_to_reg(jump);
829
} while (0);
830
831
jump = jump->next;
832
}
833
834
compiler->error = SLJIT_ERR_COMPILED;
835
compiler->executable_offset = executable_offset;
836
compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
837
838
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
839
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
840
841
#ifndef __GNUC__
842
SLJIT_CACHE_FLUSH(code, code_ptr);
843
#else
844
/* GCC workaround for invalid code generation with -O2. */
845
sljit_cache_flush(code, code_ptr);
846
#endif
847
SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
848
return code;
849
}
850
851
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
852
{
853
switch (feature_type) {
854
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
855
&& (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE)
856
case SLJIT_HAS_F64_AS_F32_PAIR:
857
if (!cpu_feature_list)
858
get_cpu_features();
859
860
return (cpu_feature_list & CPU_FEATURE_FR) != 0;
861
#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */
862
case SLJIT_HAS_FPU:
863
if (!cpu_feature_list)
864
get_cpu_features();
865
866
return (cpu_feature_list & CPU_FEATURE_FPU) != 0;
867
case SLJIT_HAS_ZERO_REGISTER:
868
case SLJIT_HAS_COPY_F32:
869
case SLJIT_HAS_COPY_F64:
870
return 1;
871
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
872
case SLJIT_HAS_CLZ:
873
case SLJIT_HAS_CMOV:
874
case SLJIT_HAS_PREFETCH:
875
case SLJIT_HAS_ATOMIC:
876
case SLJIT_HAS_MEMORY_BARRIER:
877
return 1;
878
879
case SLJIT_HAS_CTZ:
880
return 2;
881
#endif /* SLJIT_MIPS_REV >= 1 */
882
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
883
case SLJIT_HAS_REV:
884
case SLJIT_HAS_ROT:
885
return 1;
886
#endif /* SLJIT_MIPS_REV >= 2 */
887
default:
888
return 0;
889
}
890
}
891
892
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
893
{
894
SLJIT_UNUSED_ARG(type);
895
return 0;
896
}
897
898
/* --------------------------------------------------------------------- */
899
/* Entry, exit */
900
/* --------------------------------------------------------------------- */
901
902
/* Creates an index in data_transfer_insts array. */
903
#define LOAD_DATA 0x01
904
#define WORD_DATA 0x00
905
#define BYTE_DATA 0x02
906
#define HALF_DATA 0x04
907
#define INT_DATA 0x06
908
#define SIGNED_DATA 0x08
909
/* Separates integer and floating point registers */
910
#define GPR_REG 0x0f
911
#define DOUBLE_DATA 0x10
912
#define SINGLE_DATA 0x12
913
914
#define MEM_MASK 0x1f
915
916
#define ARG_TEST 0x00020
917
#define ALT_KEEP_CACHE 0x00040
918
#define CUMULATIVE_OP 0x00080
919
#define LOGICAL_OP 0x00100
920
#define IMM_OP 0x00200
921
#define MOVE_OP 0x00400
922
#define SRC2_IMM 0x00800
923
924
#define UNUSED_DEST 0x01000
925
#define REG_DEST 0x02000
926
#define REG1_SOURCE 0x04000
927
#define REG2_SOURCE 0x08000
928
#define SLOW_SRC1 0x10000
929
#define SLOW_SRC2 0x20000
930
#define SLOW_DEST 0x40000
931
932
static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
933
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);
934
935
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
936
#define SELECT_OP(d, w) (w)
937
#else
938
#define SELECT_OP(d, w) (!(op & SLJIT_32) ? (d) : (w))
939
#endif
940
941
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
942
#include "sljitNativeMIPS_32.c"
943
#else
944
#include "sljitNativeMIPS_64.c"
945
#endif
946
947
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
948
sljit_s32 options, sljit_s32 arg_types,
949
sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
950
{
951
sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
952
sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
953
sljit_ins base;
954
sljit_s32 i, tmp, offset;
955
sljit_s32 arg_count, word_arg_count, float_arg_count;
956
sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
957
958
CHECK_ERROR();
959
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
960
set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
961
962
scratches = ENTER_GET_REGS(scratches);
963
saveds = ENTER_GET_REGS(saveds);
964
965
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
966
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
967
if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
968
if ((local_size & SSIZE_OF(sw)) != 0)
969
local_size += SSIZE_OF(sw);
970
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
971
}
972
973
local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
974
#else
975
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
976
local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
977
#endif
978
compiler->local_size = local_size;
979
980
offset = 0;
981
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
982
if (!(options & SLJIT_ENTER_REG_ARG)) {
983
tmp = arg_types >> SLJIT_ARG_SHIFT;
984
arg_count = 0;
985
986
while (tmp) {
987
offset = arg_count;
988
if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
989
if ((arg_count & 0x1) != 0)
990
arg_count++;
991
arg_count++;
992
}
993
994
arg_count++;
995
tmp >>= SLJIT_ARG_SHIFT;
996
}
997
998
compiler->args_size = (sljit_uw)arg_count << 2;
999
offset = (offset >= 4) ? (offset << 2) : 0;
1000
}
1001
#endif /* SLJIT_CONFIG_MIPS_32 */
1002
1003
if (local_size + offset <= -SIMM_MIN) {
1004
/* Frequent case. */
1005
FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
1006
base = S(SLJIT_SP);
1007
offset = local_size - SSIZE_OF(sw);
1008
} else {
1009
FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));
1010
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
1011
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
1012
base = S(TMP_REG1);
1013
offset = -SSIZE_OF(sw);
1014
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1015
local_size = 0;
1016
#endif
1017
}
1018
1019
FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS));
1020
1021
tmp = SLJIT_S0 - saveds;
1022
for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
1023
offset -= SSIZE_OF(sw);
1024
FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));
1025
}
1026
1027
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
1028
offset -= SSIZE_OF(sw);
1029
FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));
1030
}
1031
1032
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1033
/* This alignment is valid because offset is not used after storing FPU regs. */
1034
if ((offset & SSIZE_OF(sw)) != 0)
1035
offset -= SSIZE_OF(sw);
1036
#endif
1037
1038
tmp = SLJIT_FS0 - fsaveds;
1039
for (i = SLJIT_FS0; i > tmp; i--) {
1040
offset -= SSIZE_OF(f64);
1041
FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
1042
}
1043
1044
for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
1045
offset -= SSIZE_OF(f64);
1046
FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
1047
}
1048
1049
if (options & SLJIT_ENTER_REG_ARG)
1050
return SLJIT_SUCCESS;
1051
1052
arg_types >>= SLJIT_ARG_SHIFT;
1053
arg_count = 0;
1054
word_arg_count = 0;
1055
float_arg_count = 0;
1056
1057
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1058
/* The first maximum two floating point arguments are passed in floating point
1059
registers if no integer argument precedes them. The first 16 byte data is
1060
passed in four integer registers, the rest is placed onto the stack.
1061
The floating point registers are also part of the first 16 byte data, so
1062
their corresponding integer registers are not used when they are present. */
1063
1064
while (arg_types) {
1065
switch (arg_types & SLJIT_ARG_MASK) {
1066
case SLJIT_ARG_TYPE_F64:
1067
float_arg_count++;
1068
if ((arg_count & 0x1) != 0)
1069
arg_count++;
1070
1071
if (word_arg_count == 0 && float_arg_count <= 2) {
1072
if (float_arg_count == 1)
1073
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1074
} else if (arg_count < 4) {
1075
FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
1076
switch (cpu_feature_list & CPU_FEATURE_FR) {
1077
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
1078
case CPU_FEATURE_FR:
1079
FAIL_IF(push_inst(compiler, MTHC1 | TA(5 + arg_count) | FS(float_arg_count), MOVABLE_INS));
1080
break;
1081
#endif /* SLJIT_MIPS_REV >= 2 */
1082
default:
1083
FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
1084
break;
1085
}
1086
} else
1087
FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
1088
arg_count++;
1089
break;
1090
case SLJIT_ARG_TYPE_F32:
1091
float_arg_count++;
1092
1093
if (word_arg_count == 0 && float_arg_count <= 2) {
1094
if (float_arg_count == 1)
1095
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1096
} else if (arg_count < 4)
1097
FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
1098
else
1099
FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
1100
break;
1101
default:
1102
word_arg_count++;
1103
1104
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1105
tmp = SLJIT_S0 - saved_arg_count;
1106
saved_arg_count++;
1107
} else if (word_arg_count != arg_count + 1 || arg_count == 0)
1108
tmp = word_arg_count;
1109
else
1110
break;
1111
1112
if (arg_count < 4)
1113
FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));
1114
else
1115
FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));
1116
break;
1117
}
1118
arg_count++;
1119
arg_types >>= SLJIT_ARG_SHIFT;
1120
}
1121
1122
SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);
1123
#else /* !SLJIT_CONFIG_MIPS_32 */
1124
while (arg_types) {
1125
arg_count++;
1126
switch (arg_types & SLJIT_ARG_MASK) {
1127
case SLJIT_ARG_TYPE_F64:
1128
float_arg_count++;
1129
if (arg_count != float_arg_count)
1130
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
1131
else if (arg_count == 1)
1132
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1133
break;
1134
case SLJIT_ARG_TYPE_F32:
1135
float_arg_count++;
1136
if (arg_count != float_arg_count)
1137
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
1138
else if (arg_count == 1)
1139
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
1140
break;
1141
default:
1142
word_arg_count++;
1143
1144
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1145
tmp = SLJIT_S0 - saved_arg_count;
1146
saved_arg_count++;
1147
} else if (word_arg_count != arg_count || word_arg_count <= 1)
1148
tmp = word_arg_count;
1149
else
1150
break;
1151
1152
FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));
1153
break;
1154
}
1155
arg_types >>= SLJIT_ARG_SHIFT;
1156
}
1157
#endif /* SLJIT_CONFIG_MIPS_32 */
1158
1159
return SLJIT_SUCCESS;
1160
}
1161
1162
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
1163
sljit_s32 options, sljit_s32 arg_types,
1164
sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
1165
{
1166
sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
1167
sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
1168
1169
CHECK_ERROR();
1170
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
1171
set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
1172
1173
scratches = ENTER_GET_REGS(scratches);
1174
saveds = ENTER_GET_REGS(saveds);
1175
1176
local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
1177
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1178
if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1179
if ((local_size & SSIZE_OF(sw)) != 0)
1180
local_size += SSIZE_OF(sw);
1181
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1182
}
1183
1184
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
1185
#else
1186
local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1187
compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
1188
#endif
1189
return SLJIT_SUCCESS;
1190
}
1191
1192
static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)
1193
{
1194
sljit_s32 local_size, i, tmp, offset;
1195
sljit_s32 load_return_addr = (frame_size == 0);
1196
sljit_s32 scratches = compiler->scratches;
1197
sljit_s32 saveds = compiler->saveds;
1198
sljit_s32 fsaveds = compiler->fsaveds;
1199
sljit_s32 fscratches = compiler->fscratches;
1200
sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
1201
1202
SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0);
1203
frame_size &= ~0xf;
1204
1205
local_size = compiler->local_size;
1206
1207
tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1);
1208
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1209
if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1210
if ((tmp & SSIZE_OF(sw)) != 0)
1211
tmp += SSIZE_OF(sw);
1212
tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1213
}
1214
#else
1215
tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
1216
#endif
1217
1218
if (local_size <= SIMM_MAX) {
1219
if (local_size < frame_size) {
1220
FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));
1221
local_size = frame_size;
1222
}
1223
} else {
1224
if (tmp < frame_size)
1225
tmp = frame_size;
1226
1227
FAIL_IF(load_immediate(compiler, DR(TMP_REG2), local_size - tmp));
1228
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG2) | D(SLJIT_SP), DR(SLJIT_SP)));
1229
local_size = tmp;
1230
}
1231
1232
SLJIT_ASSERT(local_size >= frame_size);
1233
1234
offset = local_size - SSIZE_OF(sw);
1235
if (load_return_addr)
1236
FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));
1237
1238
tmp = SLJIT_S0 - saveds;
1239
for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) {
1240
offset -= SSIZE_OF(sw);
1241
FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1242
}
1243
1244
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
1245
offset -= SSIZE_OF(sw);
1246
FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
1247
}
1248
1249
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1250
/* This alignment is valid because offset is not used after storing FPU regs. */
1251
if ((offset & SSIZE_OF(sw)) != 0)
1252
offset -= SSIZE_OF(sw);
1253
#endif
1254
1255
tmp = SLJIT_FS0 - fsaveds;
1256
for (i = SLJIT_FS0; i > tmp; i--) {
1257
offset -= SSIZE_OF(f64);
1258
FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1259
}
1260
1261
for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
1262
offset -= SSIZE_OF(f64);
1263
FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
1264
}
1265
1266
if (local_size > frame_size)
1267
*ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);
1268
else
1269
*ins_ptr = NOP;
1270
1271
return SLJIT_SUCCESS;
1272
}
1273
1274
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
1275
{
1276
sljit_ins ins;
1277
1278
CHECK_ERROR();
1279
CHECK(check_sljit_emit_return_void(compiler));
1280
1281
emit_stack_frame_release(compiler, 0, &ins);
1282
1283
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
1284
return push_inst(compiler, ins, UNMOVABLE_INS);
1285
}
1286
1287
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
1288
sljit_s32 src, sljit_sw srcw)
1289
{
1290
sljit_ins ins;
1291
1292
CHECK_ERROR();
1293
CHECK(check_sljit_emit_return_to(compiler, src, srcw));
1294
1295
if (src & SLJIT_MEM) {
1296
ADJUST_LOCAL_OFFSET(src, srcw);
1297
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
1298
src = PIC_ADDR_REG;
1299
srcw = 0;
1300
} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
1301
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
1302
src = PIC_ADDR_REG;
1303
srcw = 0;
1304
}
1305
1306
FAIL_IF(emit_stack_frame_release(compiler, 1, &ins));
1307
1308
if (src != SLJIT_IMM) {
1309
FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
1310
return push_inst(compiler, ins, UNMOVABLE_INS);
1311
}
1312
1313
if (ins != NOP)
1314
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
1315
1316
SLJIT_SKIP_CHECKS(compiler);
1317
return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
1318
}
1319
1320
/* --------------------------------------------------------------------- */
1321
/* Operators */
1322
/* --------------------------------------------------------------------- */
1323
1324
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1325
#define ARCH_32_64(a, b) a
1326
#else
1327
#define ARCH_32_64(a, b) b
1328
#endif
1329
1330
static const sljit_ins data_transfer_insts[16 + 4] = {
1331
/* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1332
/* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1333
/* u b s */ HI(40) /* sb */,
1334
/* u b l */ HI(36) /* lbu */,
1335
/* u h s */ HI(41) /* sh */,
1336
/* u h l */ HI(37) /* lhu */,
1337
/* u i s */ HI(43) /* sw */,
1338
/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
1339
1340
/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1341
/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1342
/* s b s */ HI(40) /* sb */,
1343
/* s b l */ HI(32) /* lb */,
1344
/* s h s */ HI(41) /* sh */,
1345
/* s h l */ HI(33) /* lh */,
1346
/* s i s */ HI(43) /* sw */,
1347
/* s i l */ HI(35) /* lw */,
1348
1349
/* d s */ HI(61) /* sdc1 */,
1350
/* d l */ HI(53) /* ldc1 */,
1351
/* s s */ HI(57) /* swc1 */,
1352
/* s l */ HI(49) /* lwc1 */,
1353
};
1354
1355
#undef ARCH_32_64
1356
1357
/* reg_ar is an absoulute register! */
1358
1359
/* Can perform an operation using at most 1 instruction. */
1360
static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1361
{
1362
SLJIT_ASSERT(arg & SLJIT_MEM);
1363
1364
if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
1365
/* Works for both absoulte and relative addresses. */
1366
if (SLJIT_UNLIKELY(flags & ARG_TEST))
1367
return 1;
1368
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
1369
| TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
1370
return -1;
1371
}
1372
return 0;
1373
}
1374
1375
#define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0))
1376
1377
/* See getput_arg below.
1378
Note: can_cache is called only for binary operators. */
1379
static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1380
{
1381
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
1382
1383
/* Simple operation except for updates. */
1384
if (arg & OFFS_REG_MASK) {
1385
argw &= 0x3;
1386
next_argw &= 0x3;
1387
if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
1388
return 1;
1389
return 0;
1390
}
1391
1392
if (arg == next_arg) {
1393
if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)
1394
|| TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
1395
return 1;
1396
return 0;
1397
}
1398
1399
return 0;
1400
}
1401
1402
/* Emit the necessary instructions. See can_cache above. */
1403
static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1404
{
1405
sljit_s32 tmp_ar, base, delay_slot;
1406
sljit_sw offset, argw_hi;
1407
1408
SLJIT_ASSERT(arg & SLJIT_MEM);
1409
if (!(next_arg & SLJIT_MEM)) {
1410
next_arg = 0;
1411
next_argw = 0;
1412
}
1413
1414
/* Since tmp can be the same as base or offset registers,
1415
* these might be unavailable after modifying tmp. */
1416
if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1417
tmp_ar = reg_ar;
1418
delay_slot = reg_ar;
1419
}
1420
else {
1421
tmp_ar = DR(TMP_REG1);
1422
delay_slot = MOVABLE_INS;
1423
}
1424
base = arg & REG_MASK;
1425
1426
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1427
argw &= 0x3;
1428
1429
/* Using the cache. */
1430
if (argw == compiler->cache_argw) {
1431
if (arg == compiler->cache_arg)
1432
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1433
1434
if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
1435
if (arg == next_arg && argw == (next_argw & 0x3)) {
1436
compiler->cache_arg = arg;
1437
compiler->cache_argw = argw;
1438
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1439
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1440
}
1441
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
1442
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1443
}
1444
}
1445
1446
if (SLJIT_UNLIKELY(argw)) {
1447
compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1448
compiler->cache_argw = argw;
1449
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
1450
}
1451
1452
if (arg == next_arg && argw == (next_argw & 0x3)) {
1453
compiler->cache_arg = arg;
1454
compiler->cache_argw = argw;
1455
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1456
tmp_ar = DR(TMP_REG3);
1457
}
1458
else
1459
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
1460
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1461
}
1462
1463
if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
1464
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot);
1465
1466
if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {
1467
offset = argw - compiler->cache_argw;
1468
} else {
1469
compiler->cache_arg = SLJIT_MEM;
1470
1471
argw_hi = TO_ARGW_HI(argw);
1472
1473
if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
1474
FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
1475
compiler->cache_argw = argw;
1476
offset = 0;
1477
} else {
1478
FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi));
1479
compiler->cache_argw = argw_hi;
1480
offset = argw & 0xffff;
1481
argw = argw_hi;
1482
}
1483
}
1484
1485
if (!base)
1486
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
1487
1488
if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
1489
compiler->cache_arg = arg;
1490
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
1491
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
1492
}
1493
1494
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
1495
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot);
1496
}
1497
1498
static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1499
{
1500
sljit_s32 tmp_ar, base, delay_slot;
1501
1502
if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
1503
return compiler->error;
1504
1505
if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1506
tmp_ar = reg_ar;
1507
delay_slot = reg_ar;
1508
}
1509
else {
1510
tmp_ar = DR(TMP_REG1);
1511
delay_slot = MOVABLE_INS;
1512
}
1513
base = arg & REG_MASK;
1514
1515
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1516
argw &= 0x3;
1517
1518
if (SLJIT_UNLIKELY(argw)) {
1519
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
1520
FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));
1521
}
1522
else
1523
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
1524
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1525
}
1526
1527
FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw)));
1528
1529
if (base != 0)
1530
FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));
1531
1532
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);
1533
}
1534
1535
static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
1536
{
1537
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1538
return compiler->error;
1539
return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1540
}
1541
1542
#define EMIT_LOGICAL(op_imm, op_reg) \
1543
if (flags & SRC2_IMM) { \
1544
if (op & SLJIT_SET_Z) \
1545
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
1546
if (!(flags & UNUSED_DEST)) \
1547
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
1548
} \
1549
else { \
1550
if (op & SLJIT_SET_Z) \
1551
FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
1552
if (!(flags & UNUSED_DEST)) \
1553
FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \
1554
}
1555
1556
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1557
1558
#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \
1559
op_imm = (imm); \
1560
op_v = (v);
1561
1562
#else /* !SLJIT_CONFIG_MIPS_32 */
1563
1564
1565
#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \
1566
op_dimm = (dimm); \
1567
op_dimm32 = (dimm32); \
1568
op_imm = (imm); \
1569
op_dv = (dv); \
1570
op_v = (v);
1571
1572
#endif /* SLJIT_CONFIG_MIPS_32 */
1573
1574
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1)
1575
1576
static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1577
{
1578
sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);
1579
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1580
sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
1581
#else /* !SLJIT_CONFIG_MIPS_64 */
1582
sljit_ins word_size = 32;
1583
#endif /* SLJIT_CONFIG_MIPS_64 */
1584
1585
/* The TMP_REG2 is the next value. */
1586
if (src != TMP_REG2)
1587
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
1588
1589
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS));
1590
/* The OTHER_FLAG is the counter. Delay slot. */
1591
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(word_size), OTHER_FLAG));
1592
1593
if (!is_clz) {
1594
FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1)));
1595
FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS));
1596
} else
1597
FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS));
1598
1599
/* Delay slot. */
1600
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG));
1601
1602
/* The TMP_REG1 is the next shift. */
1603
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(word_size), DR(TMP_REG1)));
1604
1605
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1606
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
1607
1608
FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG1) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));
1609
FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS));
1610
/* Delay slot. */
1611
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1612
1613
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2)));
1614
FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG2) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));
1615
1616
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS));
1617
/* Delay slot. */
1618
FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG));
1619
1620
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst));
1621
}
1622
1623
#endif /* SLJIT_MIPS_REV < 1 */
1624
1625
static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1626
{
1627
#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
1628
int is_32 = (op & SLJIT_32);
1629
#endif /* SLJIT_CONFIG_MIPS_64 */
1630
1631
op = GET_OPCODE(op);
1632
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
1633
#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
1634
if (!is_32 && (op == SLJIT_REV)) {
1635
FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));
1636
return push_inst(compiler, DSHD | T(dst) | D(dst), DR(dst));
1637
}
1638
if (op != SLJIT_REV && src != TMP_REG2) {
1639
FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG1), DR(TMP_REG1)));
1640
src = TMP_REG1;
1641
}
1642
#endif /* SLJIT_CONFIG_MIPS_64 */
1643
FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));
1644
FAIL_IF(push_inst(compiler, ROTR | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
1645
#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
1646
if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3)
1647
FAIL_IF(push_inst(compiler, DINSU | T(dst) | SA(0) | (31 << 11), DR(dst)));
1648
#endif /* SLJIT_CONFIG_MIPS_64 */
1649
#else /* SLJIT_MIPS_REV < 2 */
1650
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1651
if (!is_32) {
1652
FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
1653
FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));
1654
FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst)));
1655
FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG));
1656
FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1657
1658
FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));
1659
FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));
1660
FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1661
FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1662
FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG));
1663
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
1664
FAIL_IF(push_inst(compiler, XOR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
1665
FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1666
1667
FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
1668
FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1669
FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1670
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));
1671
return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
1672
}
1673
1674
if (op != SLJIT_REV && src != TMP_REG2) {
1675
FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(0), DR(TMP_REG2)));
1676
src = TMP_REG2;
1677
}
1678
#endif /* SLJIT_CONFIG_MIPS_64 */
1679
1680
FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));
1681
FAIL_IF(push_inst(compiler, LUI | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));
1682
FAIL_IF(push_inst(compiler, SLL | T(src) | D(dst) | SH_IMM(16), DR(dst)));
1683
FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));
1684
FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1685
1686
FAIL_IF(push_inst(compiler, SRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
1687
FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1688
FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1689
FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));
1690
FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
1691
1692
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1693
if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) {
1694
FAIL_IF(push_inst(compiler, DSLL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));
1695
FAIL_IF(push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));
1696
}
1697
#endif /* SLJIT_CONFIG_MIPS_64 */
1698
#endif /* SLJIT_MIPR_REV >= 2 */
1699
return SLJIT_SUCCESS;
1700
}
1701
1702
static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1703
{
1704
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
1705
#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
1706
FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));
1707
#else /* !SLJIT_CONFIG_MIPS_32 */
1708
FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));
1709
#endif /* SLJIT_CONFIG_MIPS_32 */
1710
if (GET_OPCODE(op) == SLJIT_REV_U16)
1711
return push_inst(compiler, ANDI | S(dst) | T(dst) | 0xffff, DR(dst));
1712
else
1713
return push_inst(compiler, SEH | T(dst) | D(dst), DR(dst));
1714
#else /* SLJIT_MIPS_REV < 2 */
1715
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(src) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
1716
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(src) | D(dst) | SH_IMM(24), DR(dst)));
1717
FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG1) | T(TMP_REG1) | 0xff, DR(TMP_REG1)));
1718
FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SELECT_OP(DSRL32, SRL) : SELECT_OP(DSRA32, SRA)) | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
1719
return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
1720
#endif /* SLJIT_MIPS_REV >= 2 */
1721
}
1722
1723
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1724
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
1725
{
1726
sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled, reg;
1727
sljit_ins op_imm, op_v;
1728
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1729
sljit_ins ins, op_dimm, op_dimm32, op_dv;
1730
#endif
1731
1732
switch (GET_OPCODE(op)) {
1733
case SLJIT_MOV:
1734
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1735
if (dst != src2)
1736
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
1737
return SLJIT_SUCCESS;
1738
1739
case SLJIT_MOV_U8:
1740
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1741
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1742
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
1743
SLJIT_ASSERT(dst == src2);
1744
return SLJIT_SUCCESS;
1745
1746
case SLJIT_MOV_S8:
1747
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1748
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1749
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1750
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1751
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
1752
#else /* SLJIT_MIPS_REV < 2 */
1753
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
1754
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
1755
#endif /* SLJIT_MIPS_REV >= 2 */
1756
#else /* !SLJIT_CONFIG_MIPS_32 */
1757
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1758
if (op & SLJIT_32)
1759
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
1760
#endif /* SLJIT_MIPS_REV >= 2 */
1761
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
1762
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
1763
#endif /* SLJIT_CONFIG_MIPS_32 */
1764
}
1765
SLJIT_ASSERT(dst == src2);
1766
return SLJIT_SUCCESS;
1767
1768
case SLJIT_MOV_U16:
1769
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1770
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1771
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
1772
SLJIT_ASSERT(dst == src2);
1773
return SLJIT_SUCCESS;
1774
1775
case SLJIT_MOV_S16:
1776
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1777
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1778
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1779
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1780
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
1781
#else /* SLJIT_MIPS_REV < 2 */
1782
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
1783
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
1784
#endif /* SLJIT_MIPS_REV >= 2 */
1785
#else /* !SLJIT_CONFIG_MIPS_32 */
1786
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1787
if (op & SLJIT_32)
1788
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
1789
#endif /* SLJIT_MIPS_REV >= 2 */
1790
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
1791
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
1792
#endif /* SLJIT_CONFIG_MIPS_32 */
1793
}
1794
SLJIT_ASSERT(dst == src2);
1795
return SLJIT_SUCCESS;
1796
1797
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1798
case SLJIT_MOV_U32:
1799
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
1800
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1801
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
1802
if (dst == src2)
1803
return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11), DR(dst));
1804
#endif /* SLJIT_MIPS_REV >= 2 */
1805
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
1806
return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
1807
}
1808
SLJIT_ASSERT(dst == src2);
1809
return SLJIT_SUCCESS;
1810
1811
case SLJIT_MOV_S32:
1812
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
1813
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1814
return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
1815
}
1816
SLJIT_ASSERT(dst == src2);
1817
return SLJIT_SUCCESS;
1818
#endif /* SLJIT_CONFIG_MIPS_64 */
1819
1820
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1821
case SLJIT_CLZ:
1822
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1823
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1824
return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst));
1825
#else /* SLJIT_MIPS_REV < 6 */
1826
return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst));
1827
#endif /* SLJIT_MIPS_REV >= 6 */
1828
case SLJIT_CTZ:
1829
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1830
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
1831
FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst)));
1832
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1833
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst)));
1834
#else /* SLJIT_MIPS_REV < 6 */
1835
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst)));
1836
#endif /* SLJIT_MIPS_REV >= 6 */
1837
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1)));
1838
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1)));
1839
return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
1840
#else /* SLJIT_MIPS_REV < 1 */
1841
case SLJIT_CLZ:
1842
case SLJIT_CTZ:
1843
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1844
return emit_clz_ctz(compiler, op, dst, src2);
1845
#endif /* SLJIT_MIPS_REV >= 1 */
1846
1847
case SLJIT_REV:
1848
case SLJIT_REV_U32:
1849
case SLJIT_REV_S32:
1850
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && src2 != TMP_REG1 && dst != TMP_REG1);
1851
return emit_rev(compiler, op, dst, src2);
1852
1853
case SLJIT_REV_U16:
1854
case SLJIT_REV_S16:
1855
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1856
return emit_rev16(compiler, op, dst, src2);
1857
1858
case SLJIT_ADD:
1859
/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
1860
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
1861
carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1862
1863
if (flags & SRC2_IMM) {
1864
if (is_overflow) {
1865
if (src2 >= 0)
1866
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1867
else
1868
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
1869
}
1870
else if (op & SLJIT_SET_Z)
1871
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
1872
1873
/* Only the zero flag is needed. */
1874
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1875
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
1876
}
1877
else {
1878
if (is_overflow)
1879
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1880
else if (op & SLJIT_SET_Z)
1881
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
1882
1883
if (is_overflow || carry_src_ar != 0) {
1884
if (src1 != dst)
1885
carry_src_ar = DR(src1);
1886
else if (src2 != dst)
1887
carry_src_ar = DR(src2);
1888
else {
1889
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));
1890
carry_src_ar = OTHER_FLAG;
1891
}
1892
}
1893
1894
/* Only the zero flag is needed. */
1895
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1896
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
1897
}
1898
1899
/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1900
if (is_overflow || carry_src_ar != 0) {
1901
if (flags & SRC2_IMM)
1902
FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1903
else
1904
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG));
1905
}
1906
1907
if (!is_overflow)
1908
return SLJIT_SUCCESS;
1909
1910
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
1911
if (op & SLJIT_SET_Z)
1912
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1913
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
1914
return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1915
1916
case SLJIT_ADDC:
1917
carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1918
1919
if (flags & SRC2_IMM) {
1920
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
1921
} else {
1922
if (carry_src_ar != 0) {
1923
if (src1 != dst)
1924
carry_src_ar = DR(src1);
1925
else if (src2 != dst)
1926
carry_src_ar = DR(src2);
1927
else {
1928
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
1929
carry_src_ar = EQUAL_FLAG;
1930
}
1931
}
1932
1933
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
1934
}
1935
1936
/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1937
if (carry_src_ar != 0) {
1938
if (flags & SRC2_IMM)
1939
FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
1940
else
1941
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG));
1942
}
1943
1944
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
1945
1946
if (carry_src_ar == 0)
1947
return SLJIT_SUCCESS;
1948
1949
/* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
1950
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
1951
/* Set carry flag. */
1952
return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
1953
1954
case SLJIT_SUB:
1955
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1956
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
1957
src2 = TMP_REG2;
1958
flags &= ~SRC2_IMM;
1959
}
1960
1961
is_handled = 0;
1962
1963
if (flags & SRC2_IMM) {
1964
if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
1965
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1966
is_handled = 1;
1967
}
1968
else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
1969
FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
1970
is_handled = 1;
1971
}
1972
}
1973
1974
if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1975
is_handled = 1;
1976
1977
if (flags & SRC2_IMM) {
1978
reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
1979
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(reg) | IMM(src2), DR(reg)));
1980
src2 = reg;
1981
flags &= ~SRC2_IMM;
1982
}
1983
1984
switch (GET_FLAG_TYPE(op)) {
1985
case SLJIT_LESS:
1986
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
1987
break;
1988
case SLJIT_GREATER:
1989
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
1990
break;
1991
case SLJIT_SIG_LESS:
1992
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
1993
break;
1994
case SLJIT_SIG_GREATER:
1995
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
1996
break;
1997
}
1998
}
1999
2000
if (is_handled) {
2001
if (flags & SRC2_IMM) {
2002
if (op & SLJIT_SET_Z)
2003
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
2004
if (!(flags & UNUSED_DEST))
2005
return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
2006
}
2007
else {
2008
if (op & SLJIT_SET_Z)
2009
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2010
if (!(flags & UNUSED_DEST))
2011
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
2012
}
2013
return SLJIT_SUCCESS;
2014
}
2015
2016
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
2017
is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
2018
2019
if (flags & SRC2_IMM) {
2020
if (is_overflow) {
2021
if (src2 >= 0)
2022
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2023
else
2024
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2025
}
2026
else if (op & SLJIT_SET_Z)
2027
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
2028
2029
if (is_overflow || is_carry)
2030
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
2031
2032
/* Only the zero flag is needed. */
2033
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
2034
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
2035
}
2036
else {
2037
if (is_overflow)
2038
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2039
else if (op & SLJIT_SET_Z)
2040
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2041
2042
if (is_overflow || is_carry)
2043
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
2044
2045
/* Only the zero flag is needed. */
2046
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
2047
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
2048
}
2049
2050
if (!is_overflow)
2051
return SLJIT_SUCCESS;
2052
2053
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
2054
if (op & SLJIT_SET_Z)
2055
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
2056
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
2057
return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
2058
2059
case SLJIT_SUBC:
2060
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
2061
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
2062
src2 = TMP_REG2;
2063
flags &= ~SRC2_IMM;
2064
}
2065
2066
is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
2067
2068
if (flags & SRC2_IMM) {
2069
if (is_carry)
2070
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
2071
2072
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
2073
}
2074
else {
2075
if (is_carry)
2076
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2077
2078
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
2079
}
2080
2081
if (is_carry)
2082
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
2083
2084
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
2085
2086
if (!is_carry)
2087
return SLJIT_SUCCESS;
2088
2089
return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG);
2090
2091
case SLJIT_MUL:
2092
SLJIT_ASSERT(!(flags & SRC2_IMM));
2093
2094
if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {
2095
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2096
return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
2097
#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2098
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2099
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
2100
#else /* !SLJIT_CONFIG_MIPS_32 */
2101
if (op & SLJIT_32)
2102
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
2103
FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
2104
return push_inst(compiler, MFLO | D(dst), DR(dst));
2105
#endif /* SLJIT_CONFIG_MIPS_32 */
2106
#else /* SLJIT_MIPS_REV < 1 */
2107
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
2108
return push_inst(compiler, MFLO | D(dst), DR(dst));
2109
#endif /* SLJIT_MIPS_REV >= 6 */
2110
}
2111
2112
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2113
FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));
2114
FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2115
#else /* SLJIT_MIPS_REV < 6 */
2116
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
2117
FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
2118
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
2119
#endif /* SLJIT_MIPS_REV >= 6 */
2120
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
2121
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
2122
2123
case SLJIT_AND:
2124
EMIT_LOGICAL(ANDI, AND);
2125
return SLJIT_SUCCESS;
2126
2127
case SLJIT_OR:
2128
EMIT_LOGICAL(ORI, OR);
2129
return SLJIT_SUCCESS;
2130
2131
case SLJIT_XOR:
2132
if (!(flags & LOGICAL_OP)) {
2133
SLJIT_ASSERT((flags & SRC2_IMM) && src2 == -1);
2134
if (op & SLJIT_SET_Z)
2135
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2136
if (!(flags & UNUSED_DEST))
2137
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | D(dst), DR(dst)));
2138
return SLJIT_SUCCESS;
2139
}
2140
EMIT_LOGICAL(XORI, XOR);
2141
return SLJIT_SUCCESS;
2142
2143
case SLJIT_SHL:
2144
case SLJIT_MSHL:
2145
EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
2146
break;
2147
2148
case SLJIT_LSHR:
2149
case SLJIT_MLSHR:
2150
EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
2151
break;
2152
2153
case SLJIT_ASHR:
2154
case SLJIT_MASHR:
2155
EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
2156
break;
2157
2158
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
2159
case SLJIT_ROTL:
2160
if ((flags & SRC2_IMM) || src2 == 0) {
2161
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2162
src2 = -src2 & 0x1f;
2163
#else /* !SLJIT_CONFIG_MIPS_32 */
2164
src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f);
2165
#endif /* SLJIT_CONFIG_MIPS_32 */
2166
} else {
2167
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2)));
2168
src2 = TMP_REG2;
2169
}
2170
/* fallthrough */
2171
2172
case SLJIT_ROTR:
2173
EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV);
2174
break;
2175
#else /* SLJIT_MIPS_REV < 1 */
2176
case SLJIT_ROTL:
2177
case SLJIT_ROTR:
2178
if (flags & SRC2_IMM) {
2179
SLJIT_ASSERT(src2 != 0);
2180
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2181
if (!(op & SLJIT_32)) {
2182
if (GET_OPCODE(op) == SLJIT_ROTL)
2183
op_imm = ((src2 < 32) ? DSLL : DSLL32);
2184
else
2185
op_imm = ((src2 < 32) ? DSRL : DSRL32);
2186
2187
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG));
2188
2189
src2 = 64 - src2;
2190
if (GET_OPCODE(op) == SLJIT_ROTL)
2191
op_imm = ((src2 < 32) ? DSRL : DSRL32);
2192
else
2193
op_imm = ((src2 < 32) ? DSLL : DSLL32);
2194
2195
FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));
2196
return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2197
}
2198
#endif /* SLJIT_CONFIG_MIPS_64 */
2199
2200
op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;
2201
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG));
2202
2203
src2 = 32 - src2;
2204
op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;
2205
FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));
2206
return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2207
}
2208
2209
if (src2 == 0) {
2210
if (dst != src1)
2211
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst));
2212
return SLJIT_SUCCESS;
2213
}
2214
2215
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
2216
2217
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2218
if (!(op & SLJIT_32)) {
2219
op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV;
2220
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
2221
op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV;
2222
FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));
2223
return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2224
}
2225
#endif /* SLJIT_CONFIG_MIPS_64 */
2226
2227
op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV;
2228
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
2229
op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV;
2230
FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));
2231
return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
2232
#endif /* SLJIT_MIPS_REV >= 2 */
2233
2234
default:
2235
SLJIT_UNREACHABLE();
2236
return SLJIT_SUCCESS;
2237
}
2238
2239
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2240
if ((flags & SRC2_IMM) || src2 == 0) {
2241
if (op & SLJIT_SET_Z)
2242
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));
2243
2244
if (flags & UNUSED_DEST)
2245
return SLJIT_SUCCESS;
2246
return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst));
2247
}
2248
2249
if (op & SLJIT_SET_Z)
2250
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2251
2252
if (flags & UNUSED_DEST)
2253
return SLJIT_SUCCESS;
2254
return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst));
2255
#else /* !SLJIT_CONFIG_MIPS_32 */
2256
if ((flags & SRC2_IMM) || src2 == 0) {
2257
if (src2 >= 32) {
2258
SLJIT_ASSERT(!(op & SLJIT_32));
2259
ins = op_dimm32;
2260
src2 -= 32;
2261
}
2262
else
2263
ins = (op & SLJIT_32) ? op_imm : op_dimm;
2264
2265
if (op & SLJIT_SET_Z)
2266
FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));
2267
2268
if (flags & UNUSED_DEST)
2269
return SLJIT_SUCCESS;
2270
return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst));
2271
}
2272
2273
ins = (op & SLJIT_32) ? op_v : op_dv;
2274
if (op & SLJIT_SET_Z)
2275
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
2276
2277
if (flags & UNUSED_DEST)
2278
return SLJIT_SUCCESS;
2279
return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst));
2280
#endif /* SLJIT_CONFIG_MIPS_32 */
2281
}
2282
2283
#define CHECK_IMM(flags, srcw) \
2284
((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \
2285
|| (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX)))
2286
2287
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
2288
sljit_s32 dst, sljit_sw dstw,
2289
sljit_s32 src1, sljit_sw src1w,
2290
sljit_s32 src2, sljit_sw src2w)
2291
{
2292
/* arg1 goes to TMP_REG1 or src reg
2293
arg2 goes to TMP_REG2, imm or src reg
2294
TMP_REG3 can be used for caching
2295
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
2296
sljit_s32 dst_r = TMP_REG2;
2297
sljit_s32 src1_r;
2298
sljit_sw src2_r = 0;
2299
sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
2300
2301
if (!(flags & ALT_KEEP_CACHE)) {
2302
compiler->cache_arg = 0;
2303
compiler->cache_argw = 0;
2304
}
2305
2306
if (dst == 0) {
2307
SLJIT_ASSERT(HAS_FLAGS(op));
2308
flags |= UNUSED_DEST;
2309
dst = TMP_REG2;
2310
}
2311
else if (FAST_IS_REG(dst)) {
2312
dst_r = dst;
2313
flags |= REG_DEST;
2314
if (flags & MOVE_OP)
2315
src2_tmp_reg = dst_r;
2316
}
2317
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
2318
flags |= SLOW_DEST;
2319
2320
if (flags & IMM_OP) {
2321
if (src2 == SLJIT_IMM && src2w != 0 && CHECK_IMM(flags, src2w)) {
2322
flags |= SRC2_IMM;
2323
src2_r = src2w;
2324
} else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && CHECK_IMM(flags, src1w)) {
2325
flags |= SRC2_IMM;
2326
src2_r = src1w;
2327
2328
/* And swap arguments. */
2329
src1 = src2;
2330
src1w = src2w;
2331
src2 = SLJIT_IMM;
2332
/* src2w = src2_r unneeded. */
2333
}
2334
}
2335
2336
/* Source 1. */
2337
if (FAST_IS_REG(src1)) {
2338
src1_r = src1;
2339
flags |= REG1_SOURCE;
2340
}
2341
else if (src1 == SLJIT_IMM) {
2342
if (src1w) {
2343
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
2344
src1_r = TMP_REG1;
2345
}
2346
else
2347
src1_r = 0;
2348
}
2349
else {
2350
if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
2351
FAIL_IF(compiler->error);
2352
else
2353
flags |= SLOW_SRC1;
2354
src1_r = TMP_REG1;
2355
}
2356
2357
/* Source 2. */
2358
if (FAST_IS_REG(src2)) {
2359
src2_r = src2;
2360
flags |= REG2_SOURCE;
2361
if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
2362
dst_r = (sljit_s32)src2_r;
2363
}
2364
else if (src2 == SLJIT_IMM) {
2365
if (!(flags & SRC2_IMM)) {
2366
if (src2w) {
2367
FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w));
2368
src2_r = src2_tmp_reg;
2369
}
2370
else {
2371
src2_r = 0;
2372
if (flags & MOVE_OP) {
2373
if (dst & SLJIT_MEM)
2374
dst_r = 0;
2375
else
2376
op = SLJIT_MOV;
2377
}
2378
}
2379
}
2380
}
2381
else {
2382
if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w))
2383
FAIL_IF(compiler->error);
2384
else
2385
flags |= SLOW_SRC2;
2386
src2_r = src2_tmp_reg;
2387
}
2388
2389
if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
2390
SLJIT_ASSERT(src2_r == TMP_REG2);
2391
if ((flags & SLOW_DEST) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
2392
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
2393
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
2394
}
2395
else {
2396
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
2397
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
2398
}
2399
}
2400
else if (flags & SLOW_SRC1)
2401
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
2402
else if (flags & SLOW_SRC2)
2403
FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w, dst, dstw));
2404
2405
FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
2406
2407
if (dst & SLJIT_MEM) {
2408
if (!(flags & SLOW_DEST)) {
2409
getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
2410
return compiler->error;
2411
}
2412
return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
2413
}
2414
2415
return SLJIT_SUCCESS;
2416
}
2417
2418
#undef CHECK_IMM
2419
2420
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
2421
{
2422
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2423
sljit_s32 int_op = op & SLJIT_32;
2424
#endif
2425
2426
CHECK_ERROR();
2427
CHECK(check_sljit_emit_op0(compiler, op));
2428
2429
op = GET_OPCODE(op);
2430
switch (op) {
2431
case SLJIT_BREAKPOINT:
2432
return push_inst(compiler, BREAK, UNMOVABLE_INS);
2433
case SLJIT_NOP:
2434
return push_inst(compiler, NOP, UNMOVABLE_INS);
2435
case SLJIT_LMUL_UW:
2436
case SLJIT_LMUL_SW:
2437
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2438
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2439
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2440
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2441
#else /* !SLJIT_CONFIG_MIPS_64 */
2442
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2443
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2444
#endif /* SLJIT_CONFIG_MIPS_64 */
2445
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
2446
return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
2447
#else /* SLJIT_MIPS_REV < 6 */
2448
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2449
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2450
#else /* !SLJIT_CONFIG_MIPS_64 */
2451
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2452
#endif /* SLJIT_CONFIG_MIPS_64 */
2453
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
2454
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
2455
#endif /* SLJIT_MIPS_REV >= 6 */
2456
case SLJIT_DIVMOD_UW:
2457
case SLJIT_DIVMOD_SW:
2458
case SLJIT_DIV_UW:
2459
case SLJIT_DIV_SW:
2460
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
2461
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2462
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2463
if (int_op) {
2464
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2465
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2466
}
2467
else {
2468
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2469
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2470
}
2471
#else /* !SLJIT_CONFIG_MIPS_64 */
2472
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
2473
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
2474
#endif /* SLJIT_CONFIG_MIPS_64 */
2475
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
2476
return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
2477
#else /* SLJIT_MIPS_REV < 6 */
2478
#if !(defined SLJIT_MIPS_REV)
2479
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2480
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2481
#endif /* !SLJIT_MIPS_REV */
2482
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2483
if (int_op)
2484
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2485
else
2486
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2487
#else /* !SLJIT_CONFIG_MIPS_64 */
2488
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
2489
#endif /* SLJIT_CONFIG_MIPS_64 */
2490
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
2491
return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
2492
#endif /* SLJIT_MIPS_REV >= 6 */
2493
case SLJIT_MEMORY_BARRIER:
2494
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2495
return push_inst(compiler, SYNC, UNMOVABLE_INS);
2496
#else /* SLJIT_MIPS_REV < 1 */
2497
return SLJIT_ERR_UNSUPPORTED;
2498
#endif /* SLJIT_MIPS_REV >= 1 */
2499
case SLJIT_ENDBR:
2500
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
2501
return SLJIT_SUCCESS;
2502
}
2503
2504
return SLJIT_SUCCESS;
2505
}
2506
2507
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2508
static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
2509
sljit_s32 src, sljit_sw srcw)
2510
{
2511
if (!(src & OFFS_REG_MASK)) {
2512
if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
2513
return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
2514
2515
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2516
return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
2517
}
2518
2519
srcw &= 0x3;
2520
2521
if (SLJIT_UNLIKELY(srcw != 0)) {
2522
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
2523
return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
2524
}
2525
2526
return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
2527
}
2528
#endif /* SLJIT_MIPS_REV >= 1 */
2529
2530
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
2531
sljit_s32 dst, sljit_sw dstw,
2532
sljit_s32 src, sljit_sw srcw)
2533
{
2534
sljit_s32 flags = 0;
2535
2536
CHECK_ERROR();
2537
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
2538
ADJUST_LOCAL_OFFSET(dst, dstw);
2539
ADJUST_LOCAL_OFFSET(src, srcw);
2540
2541
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2542
if (op & SLJIT_32)
2543
flags = INT_DATA | SIGNED_DATA;
2544
#endif
2545
2546
switch (GET_OPCODE(op)) {
2547
case SLJIT_MOV:
2548
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2549
case SLJIT_MOV_U32:
2550
case SLJIT_MOV_S32:
2551
case SLJIT_MOV32:
2552
#endif
2553
case SLJIT_MOV_P:
2554
return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
2555
2556
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2557
case SLJIT_MOV_U32:
2558
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);
2559
2560
case SLJIT_MOV_S32:
2561
case SLJIT_MOV32:
2562
return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);
2563
#endif
2564
2565
case SLJIT_MOV_U8:
2566
return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
2567
2568
case SLJIT_MOV_S8:
2569
return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
2570
2571
case SLJIT_MOV_U16:
2572
return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
2573
2574
case SLJIT_MOV_S16:
2575
return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
2576
2577
case SLJIT_CLZ:
2578
case SLJIT_CTZ:
2579
case SLJIT_REV:
2580
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
2581
2582
case SLJIT_REV_U16:
2583
case SLJIT_REV_S16:
2584
return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
2585
2586
case SLJIT_REV_U32:
2587
case SLJIT_REV_S32:
2588
return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
2589
}
2590
2591
SLJIT_UNREACHABLE();
2592
return SLJIT_SUCCESS;
2593
}
2594
2595
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
2596
sljit_s32 dst, sljit_sw dstw,
2597
sljit_s32 src1, sljit_sw src1w,
2598
sljit_s32 src2, sljit_sw src2w)
2599
{
2600
sljit_s32 flags = 0;
2601
2602
CHECK_ERROR();
2603
CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
2604
ADJUST_LOCAL_OFFSET(dst, dstw);
2605
ADJUST_LOCAL_OFFSET(src1, src1w);
2606
ADJUST_LOCAL_OFFSET(src2, src2w);
2607
2608
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2609
if (op & SLJIT_32) {
2610
flags |= INT_DATA | SIGNED_DATA;
2611
if (src1 == SLJIT_IMM)
2612
src1w = (sljit_s32)src1w;
2613
if (src2 == SLJIT_IMM)
2614
src2w = (sljit_s32)src2w;
2615
}
2616
#endif
2617
2618
switch (GET_OPCODE(op)) {
2619
case SLJIT_ADD:
2620
case SLJIT_ADDC:
2621
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
2622
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2623
2624
case SLJIT_SUB:
2625
case SLJIT_SUBC:
2626
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
2627
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2628
2629
case SLJIT_MUL:
2630
compiler->status_flags_state = 0;
2631
return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
2632
2633
case SLJIT_XOR:
2634
if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {
2635
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2636
}
2637
/* fallthrough */
2638
case SLJIT_AND:
2639
case SLJIT_OR:
2640
return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2641
2642
case SLJIT_SHL:
2643
case SLJIT_MSHL:
2644
case SLJIT_LSHR:
2645
case SLJIT_MLSHR:
2646
case SLJIT_ASHR:
2647
case SLJIT_MASHR:
2648
case SLJIT_ROTL:
2649
case SLJIT_ROTR:
2650
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2651
if (src2 == SLJIT_IMM)
2652
src2w &= 0x1f;
2653
#else
2654
if (src2 == SLJIT_IMM) {
2655
if (op & SLJIT_32)
2656
src2w &= 0x1f;
2657
else
2658
src2w &= 0x3f;
2659
}
2660
#endif
2661
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2662
}
2663
2664
SLJIT_UNREACHABLE();
2665
return SLJIT_SUCCESS;
2666
}
2667
2668
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
2669
sljit_s32 src1, sljit_sw src1w,
2670
sljit_s32 src2, sljit_sw src2w)
2671
{
2672
CHECK_ERROR();
2673
CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
2674
2675
SLJIT_SKIP_CHECKS(compiler);
2676
return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);
2677
}
2678
2679
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2680
#define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6))
2681
#else /* !SLJIT_CONFIG_MIPS_64 */
2682
#define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6))
2683
#endif /* SLJIT_CONFIG_MIPS_64 */
2684
2685
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
2686
sljit_s32 dst_reg,
2687
sljit_s32 src1, sljit_sw src1w,
2688
sljit_s32 src2, sljit_sw src2w)
2689
{
2690
CHECK_ERROR();
2691
CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
2692
2693
switch (GET_OPCODE(op)) {
2694
case SLJIT_MULADD:
2695
SLJIT_SKIP_CHECKS(compiler);
2696
FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
2697
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst_reg) | T(TMP_REG2) | D(dst_reg), DR(dst_reg));
2698
}
2699
2700
return SLJIT_SUCCESS;
2701
}
2702
2703
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
2704
sljit_s32 dst_reg,
2705
sljit_s32 src1_reg,
2706
sljit_s32 src2_reg,
2707
sljit_s32 src3, sljit_sw src3w)
2708
{
2709
sljit_s32 is_left;
2710
sljit_ins ins1, ins2, ins3;
2711
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2712
sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2713
sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
2714
#else /* !SLJIT_CONFIG_MIPS_64 */
2715
sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
2716
sljit_sw bit_length = 32;
2717
#endif /* SLJIT_CONFIG_MIPS_64 */
2718
2719
CHECK_ERROR();
2720
CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
2721
2722
is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
2723
2724
if (src1_reg == src2_reg) {
2725
SLJIT_SKIP_CHECKS(compiler);
2726
return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
2727
}
2728
2729
ADJUST_LOCAL_OFFSET(src3, src3w);
2730
2731
if (src3 == SLJIT_IMM) {
2732
src3w &= bit_length - 1;
2733
2734
if (src3w == 0)
2735
return SLJIT_SUCCESS;
2736
2737
if (is_left) {
2738
ins1 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);
2739
src3w = bit_length - src3w;
2740
ins2 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);
2741
} else {
2742
ins1 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);
2743
src3w = bit_length - src3w;
2744
ins2 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);
2745
}
2746
2747
FAIL_IF(push_inst(compiler, ins1 | T(src1_reg) | D(dst_reg), DR(dst_reg)));
2748
FAIL_IF(push_inst(compiler, ins2 | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));
2749
return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));
2750
}
2751
2752
if (src3 & SLJIT_MEM) {
2753
FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src3, src3w));
2754
src3 = TMP_REG2;
2755
} else if (dst_reg == src3) {
2756
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src3) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
2757
src3 = TMP_REG2;
2758
}
2759
2760
if (is_left) {
2761
ins1 = SELECT_OP(DSRL, SRL);
2762
ins2 = SELECT_OP(DSLLV, SLLV);
2763
ins3 = SELECT_OP(DSRLV, SRLV);
2764
} else {
2765
ins1 = SELECT_OP(DSLL, SLL);
2766
ins2 = SELECT_OP(DSRLV, SRLV);
2767
ins3 = SELECT_OP(DSLLV, SLLV);
2768
}
2769
2770
FAIL_IF(push_inst(compiler, ins2 | S(src3) | T(src1_reg) | D(dst_reg), DR(dst_reg)));
2771
2772
if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
2773
FAIL_IF(push_inst(compiler, ins1 | T(src2_reg) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1)));
2774
FAIL_IF(push_inst(compiler, XORI | S(src3) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2)));
2775
src2_reg = TMP_REG1;
2776
} else
2777
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src3) | D(TMP_REG2), DR(TMP_REG2)));
2778
2779
FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));
2780
return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));
2781
}
2782
2783
#undef SELECT_OP3
2784
2785
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
2786
sljit_s32 src, sljit_sw srcw)
2787
{
2788
CHECK_ERROR();
2789
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
2790
ADJUST_LOCAL_OFFSET(src, srcw);
2791
2792
switch (op) {
2793
case SLJIT_FAST_RETURN:
2794
if (FAST_IS_REG(src))
2795
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
2796
else
2797
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
2798
2799
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
2800
return push_inst(compiler, NOP, UNMOVABLE_INS);
2801
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
2802
return SLJIT_SUCCESS;
2803
case SLJIT_PREFETCH_L1:
2804
case SLJIT_PREFETCH_L2:
2805
case SLJIT_PREFETCH_L3:
2806
case SLJIT_PREFETCH_ONCE:
2807
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
2808
return emit_prefetch(compiler, src, srcw);
2809
#else /* SLJIT_MIPS_REV < 1 */
2810
return SLJIT_SUCCESS;
2811
#endif /* SLJIT_MIPS_REV >= 1 */
2812
}
2813
2814
return SLJIT_SUCCESS;
2815
}
2816
2817
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
2818
sljit_s32 dst, sljit_sw dstw)
2819
{
2820
sljit_s32 dst_ar = RETURN_ADDR_REG;
2821
2822
CHECK_ERROR();
2823
CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
2824
ADJUST_LOCAL_OFFSET(dst, dstw);
2825
2826
switch (op) {
2827
case SLJIT_FAST_ENTER:
2828
if (FAST_IS_REG(dst))
2829
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
2830
break;
2831
case SLJIT_GET_RETURN_ADDRESS:
2832
dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2);
2833
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_ar, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));
2834
break;
2835
}
2836
2837
if (dst & SLJIT_MEM) {
2838
FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw));
2839
2840
if (op == SLJIT_FAST_ENTER)
2841
compiler->delay_slot = UNMOVABLE_INS;
2842
}
2843
2844
return SLJIT_SUCCESS;
2845
}
2846
2847
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
2848
{
2849
CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
2850
2851
if (type == SLJIT_GP_REGISTER)
2852
return reg_map[reg];
2853
2854
if (type != SLJIT_FLOAT_REGISTER)
2855
return -1;
2856
2857
return FR(reg);
2858
}
2859
2860
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
2861
void *instruction, sljit_u32 size)
2862
{
2863
SLJIT_UNUSED_ARG(size);
2864
2865
CHECK_ERROR();
2866
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
2867
2868
return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
2869
}
2870
2871
/* --------------------------------------------------------------------- */
2872
/* Floating point operators */
2873
/* --------------------------------------------------------------------- */
2874
2875
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
2876
#define FMT(op) (FMT_S | (~(sljit_ins)op & SLJIT_32) << (21 - (5 + 3)))
2877
2878
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
2879
sljit_s32 dst, sljit_sw dstw,
2880
sljit_s32 src, sljit_sw srcw)
2881
{
2882
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2883
sljit_u32 flags = 0;
2884
#else
2885
sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
2886
#endif
2887
2888
if (src & SLJIT_MEM) {
2889
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
2890
src = TMP_FREG1;
2891
}
2892
2893
FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
2894
2895
if (FAST_IS_REG(dst)) {
2896
FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));
2897
#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
2898
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2899
#endif /* MIPS III */
2900
return SLJIT_SUCCESS;
2901
}
2902
2903
return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
2904
}
2905
2906
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
2907
sljit_s32 dst, sljit_sw dstw,
2908
sljit_s32 src, sljit_sw srcw)
2909
{
2910
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2911
sljit_u32 flags = 0;
2912
#else
2913
sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;
2914
#endif
2915
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2916
2917
if (src & SLJIT_MEM)
2918
FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
2919
else {
2920
if (src == SLJIT_IMM) {
2921
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2922
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
2923
srcw = (sljit_s32)srcw;
2924
#endif
2925
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2926
src = TMP_REG1;
2927
}
2928
2929
FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
2930
#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
2931
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2932
#endif /* MIPS III */
2933
}
2934
2935
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
2936
2937
if (dst & SLJIT_MEM)
2938
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
2939
return SLJIT_SUCCESS;
2940
}
2941
2942
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
2943
sljit_s32 dst, sljit_sw dstw,
2944
sljit_s32 src, sljit_sw srcw)
2945
{
2946
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2947
sljit_u32 flags = 0;
2948
#else
2949
sljit_u32 flags = 1 << 21;
2950
#endif
2951
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2952
2953
if (src & SLJIT_MEM) {
2954
FAIL_IF(emit_op_mem2(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW ? WORD_DATA : INT_DATA) | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
2955
src = TMP_REG1;
2956
} else if (src == SLJIT_IMM) {
2957
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2958
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)
2959
srcw = (sljit_u32)srcw;
2960
#endif
2961
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2962
src = TMP_REG1;
2963
}
2964
2965
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2966
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
2967
if (src != TMP_REG1) {
2968
FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
2969
FAIL_IF(push_inst(compiler, DSRL32 | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
2970
}
2971
2972
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
2973
#if !defined(SLJIT_MIPS_REV)
2974
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2975
#endif /* MIPS III */
2976
2977
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
2978
2979
if (dst & SLJIT_MEM)
2980
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
2981
return SLJIT_SUCCESS;
2982
}
2983
#else /* !SLJIT_CONFIG_MIPS_64 */
2984
if (!(op & SLJIT_32)) {
2985
FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));
2986
FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));
2987
2988
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG2) | FS(TMP_FREG1), MOVABLE_INS));
2989
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
2990
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2991
#endif /* MIPS III */
2992
2993
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | 1 | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
2994
2995
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
2996
FAIL_IF(push_inst(compiler, BGEZ | S(src) | 5, UNMOVABLE_INS));
2997
#else /* SLJIT_MIPS_REV >= 1 */
2998
FAIL_IF(push_inst(compiler, BGEZ | S(src) | 4, UNMOVABLE_INS));
2999
#endif /* SLJIT_MIPS_REV < 1 */
3000
3001
FAIL_IF(push_inst(compiler, LUI | T(TMP_REG2) | IMM(0x41e0), UNMOVABLE_INS));
3002
FAIL_IF(push_inst(compiler, MTC1 | TA(0) | FS(TMP_FREG2), UNMOVABLE_INS));
3003
switch (cpu_feature_list & CPU_FEATURE_FR) {
3004
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
3005
case CPU_FEATURE_FR:
3006
FAIL_IF(push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(TMP_FREG2), UNMOVABLE_INS));
3007
break;
3008
#endif /* SLJIT_MIPS_REV >= 2 */
3009
default:
3010
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(TMP_FREG2) | (1 << 11), UNMOVABLE_INS));
3011
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
3012
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3013
#endif /* MIPS III */
3014
break;
3015
}
3016
FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(TMP_FREG2) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));
3017
3018
if (dst & SLJIT_MEM)
3019
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
3020
return SLJIT_SUCCESS;
3021
}
3022
#endif /* SLJIT_CONFIG_MIPS_64 */
3023
3024
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
3025
FAIL_IF(push_inst(compiler, BLTZ | S(src) | 5, UNMOVABLE_INS));
3026
#else /* SLJIT_MIPS_REV >= 1 */
3027
FAIL_IF(push_inst(compiler, BLTZ | S(src) | 4, UNMOVABLE_INS));
3028
#endif /* SLJIT_MIPS_REV < 1 */
3029
FAIL_IF(push_inst(compiler, ANDI | S(src) | T(TMP_REG2) | IMM(1), DR(TMP_REG2)));
3030
3031
FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
3032
#if !defined(SLJIT_MIPS_REV)
3033
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3034
#endif /* !SLJIT_MIPS_REV */
3035
3036
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
3037
3038
#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
3039
FAIL_IF(push_inst(compiler, BEQ | 6, UNMOVABLE_INS));
3040
#else /* SLJIT_MIPS_REV >= 1 */
3041
FAIL_IF(push_inst(compiler, BEQ | 5, UNMOVABLE_INS));
3042
#endif /* SLJIT_MIPS_REV < 1 */
3043
3044
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3045
FAIL_IF(push_inst(compiler, DSRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
3046
#else /* !SLJIT_CONFIG_MIPS_64 */
3047
FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
3048
#endif /* SLJIT_CONFIG_MIPS_64 */
3049
3050
FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));
3051
3052
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
3053
#if !defined(SLJIT_MIPS_REV)
3054
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3055
#endif /* !SLJIT_MIPS_REV */
3056
3057
FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
3058
FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(dst_r) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));
3059
3060
if (dst & SLJIT_MEM)
3061
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
3062
return SLJIT_SUCCESS;
3063
}
3064
3065
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
3066
sljit_s32 src1, sljit_sw src1w,
3067
sljit_s32 src2, sljit_sw src2w)
3068
{
3069
sljit_ins inst;
3070
3071
if (src1 & SLJIT_MEM) {
3072
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
3073
src1 = TMP_FREG1;
3074
}
3075
3076
if (src2 & SLJIT_MEM) {
3077
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
3078
src2 = TMP_FREG2;
3079
}
3080
3081
switch (GET_FLAG_TYPE(op)) {
3082
case SLJIT_F_EQUAL:
3083
case SLJIT_ORDERED_EQUAL:
3084
inst = C_EQ_S;
3085
break;
3086
case SLJIT_F_NOT_EQUAL:
3087
case SLJIT_UNORDERED_OR_EQUAL:
3088
inst = C_UEQ_S;
3089
break;
3090
case SLJIT_F_LESS:
3091
case SLJIT_ORDERED_LESS:
3092
inst = C_OLT_S;
3093
break;
3094
case SLJIT_F_GREATER_EQUAL:
3095
case SLJIT_UNORDERED_OR_LESS:
3096
inst = C_ULT_S;
3097
break;
3098
case SLJIT_F_GREATER:
3099
case SLJIT_ORDERED_GREATER:
3100
inst = C_ULE_S;
3101
break;
3102
case SLJIT_F_LESS_EQUAL:
3103
case SLJIT_UNORDERED_OR_GREATER:
3104
inst = C_OLE_S;
3105
break;
3106
default:
3107
SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED);
3108
inst = C_UN_S;
3109
break;
3110
}
3111
return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
3112
}
3113
3114
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
3115
sljit_s32 dst, sljit_sw dstw,
3116
sljit_s32 src, sljit_sw srcw)
3117
{
3118
sljit_s32 dst_r;
3119
3120
CHECK_ERROR();
3121
compiler->cache_arg = 0;
3122
compiler->cache_argw = 0;
3123
3124
SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
3125
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
3126
3127
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
3128
op ^= SLJIT_32;
3129
3130
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
3131
3132
if (src & SLJIT_MEM) {
3133
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
3134
src = dst_r;
3135
}
3136
3137
switch (GET_OPCODE(op)) {
3138
case SLJIT_MOV_F64:
3139
if (src != dst_r) {
3140
if (!(dst & SLJIT_MEM))
3141
FAIL_IF(push_inst(compiler, MOV_fmt(FMT(op)) | FS(src) | FD(dst_r), MOVABLE_INS));
3142
else
3143
dst_r = src;
3144
}
3145
break;
3146
case SLJIT_NEG_F64:
3147
FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
3148
break;
3149
case SLJIT_ABS_F64:
3150
FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
3151
break;
3152
case SLJIT_CONV_F64_FROM_F32:
3153
/* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
3154
FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
3155
op ^= SLJIT_32;
3156
break;
3157
}
3158
3159
if (dst & SLJIT_MEM)
3160
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
3161
return SLJIT_SUCCESS;
3162
}
3163
3164
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
3165
sljit_s32 dst, sljit_sw dstw,
3166
sljit_s32 src1, sljit_sw src1w,
3167
sljit_s32 src2, sljit_sw src2w)
3168
{
3169
sljit_s32 dst_r, flags = 0;
3170
3171
CHECK_ERROR();
3172
CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
3173
ADJUST_LOCAL_OFFSET(dst, dstw);
3174
ADJUST_LOCAL_OFFSET(src1, src1w);
3175
ADJUST_LOCAL_OFFSET(src2, src2w);
3176
3177
compiler->cache_arg = 0;
3178
compiler->cache_argw = 0;
3179
3180
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
3181
3182
if (src1 & SLJIT_MEM) {
3183
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
3184
FAIL_IF(compiler->error);
3185
src1 = TMP_FREG1;
3186
} else
3187
flags |= SLOW_SRC1;
3188
}
3189
3190
if (src2 & SLJIT_MEM) {
3191
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
3192
FAIL_IF(compiler->error);
3193
src2 = TMP_FREG2;
3194
} else
3195
flags |= SLOW_SRC2;
3196
}
3197
3198
if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
3199
if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
3200
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
3201
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
3202
} else {
3203
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
3204
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
3205
}
3206
}
3207
else if (flags & SLOW_SRC1)
3208
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
3209
else if (flags & SLOW_SRC2)
3210
FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
3211
3212
if (flags & SLOW_SRC1)
3213
src1 = TMP_FREG1;
3214
if (flags & SLOW_SRC2)
3215
src2 = TMP_FREG2;
3216
3217
switch (GET_OPCODE(op)) {
3218
case SLJIT_ADD_F64:
3219
FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3220
break;
3221
case SLJIT_SUB_F64:
3222
FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3223
break;
3224
case SLJIT_MUL_F64:
3225
FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3226
break;
3227
case SLJIT_DIV_F64:
3228
FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
3229
break;
3230
case SLJIT_COPYSIGN_F64:
3231
return emit_copysign(compiler, op, src1, src2, dst_r);
3232
}
3233
3234
if (dst_r == TMP_FREG2)
3235
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
3236
3237
return SLJIT_SUCCESS;
3238
}
3239
3240
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
3241
sljit_s32 freg, sljit_f32 value)
3242
{
3243
union {
3244
sljit_s32 imm;
3245
sljit_f32 value;
3246
} u;
3247
3248
CHECK_ERROR();
3249
CHECK(check_sljit_emit_fset32(compiler, freg, value));
3250
3251
u.value = value;
3252
3253
if (u.imm == 0)
3254
return push_inst(compiler, MTC1 | TA(0) | FS(freg), MOVABLE_INS);
3255
3256
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));
3257
return push_inst(compiler, MTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS);
3258
}
3259
3260
/* --------------------------------------------------------------------- */
3261
/* Conditional instructions */
3262
/* --------------------------------------------------------------------- */
3263
3264
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
3265
{
3266
struct sljit_label *label;
3267
3268
CHECK_ERROR_PTR();
3269
CHECK_PTR(check_sljit_emit_label(compiler));
3270
3271
if (compiler->last_label && compiler->last_label->size == compiler->size)
3272
return compiler->last_label;
3273
3274
label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
3275
PTR_FAIL_IF(!label);
3276
set_label(label, compiler);
3277
compiler->delay_slot = UNMOVABLE_INS;
3278
return label;
3279
}
3280
3281
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3282
#define BRANCH_LENGTH 4
3283
#else
3284
#define BRANCH_LENGTH 8
3285
#endif
3286
3287
#define BR_Z(src) \
3288
inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \
3289
flags = IS_BIT26_COND; \
3290
delay_check = src;
3291
3292
#define BR_NZ(src) \
3293
inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \
3294
flags = IS_BIT26_COND; \
3295
delay_check = src;
3296
3297
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3298
3299
#define BR_T() \
3300
inst = BC1NEZ; \
3301
flags = IS_BIT23_COND; \
3302
delay_check = FCSR_FCC;
3303
#define BR_F() \
3304
inst = BC1EQZ; \
3305
flags = IS_BIT23_COND; \
3306
delay_check = FCSR_FCC;
3307
3308
#else /* SLJIT_MIPS_REV < 6 */
3309
3310
#define BR_T() \
3311
inst = BC1T | BRANCH_LENGTH; \
3312
flags = IS_BIT16_COND; \
3313
delay_check = FCSR_FCC;
3314
#define BR_F() \
3315
inst = BC1F | BRANCH_LENGTH; \
3316
flags = IS_BIT16_COND; \
3317
delay_check = FCSR_FCC;
3318
3319
#endif /* SLJIT_MIPS_REV >= 6 */
3320
3321
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
3322
{
3323
struct sljit_jump *jump;
3324
sljit_ins inst;
3325
sljit_u32 flags = 0;
3326
sljit_s32 delay_check = UNMOVABLE_INS;
3327
3328
CHECK_ERROR_PTR();
3329
CHECK_PTR(check_sljit_emit_jump(compiler, type));
3330
3331
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3332
PTR_FAIL_IF(!jump);
3333
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
3334
type &= 0xff;
3335
3336
switch (type) {
3337
case SLJIT_EQUAL:
3338
BR_NZ(EQUAL_FLAG);
3339
break;
3340
case SLJIT_NOT_EQUAL:
3341
BR_Z(EQUAL_FLAG);
3342
break;
3343
case SLJIT_LESS:
3344
case SLJIT_GREATER:
3345
case SLJIT_SIG_LESS:
3346
case SLJIT_SIG_GREATER:
3347
case SLJIT_OVERFLOW:
3348
case SLJIT_CARRY:
3349
case SLJIT_ATOMIC_STORED:
3350
BR_Z(OTHER_FLAG);
3351
break;
3352
case SLJIT_GREATER_EQUAL:
3353
case SLJIT_LESS_EQUAL:
3354
case SLJIT_SIG_GREATER_EQUAL:
3355
case SLJIT_SIG_LESS_EQUAL:
3356
case SLJIT_NOT_OVERFLOW:
3357
case SLJIT_NOT_CARRY:
3358
case SLJIT_ATOMIC_NOT_STORED:
3359
BR_NZ(OTHER_FLAG);
3360
break;
3361
case SLJIT_F_NOT_EQUAL:
3362
case SLJIT_F_GREATER_EQUAL:
3363
case SLJIT_F_GREATER:
3364
case SLJIT_UNORDERED_OR_NOT_EQUAL:
3365
case SLJIT_ORDERED_NOT_EQUAL:
3366
case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3367
case SLJIT_ORDERED_GREATER_EQUAL:
3368
case SLJIT_ORDERED_GREATER:
3369
case SLJIT_UNORDERED_OR_GREATER:
3370
case SLJIT_ORDERED:
3371
BR_T();
3372
break;
3373
case SLJIT_F_EQUAL:
3374
case SLJIT_F_LESS:
3375
case SLJIT_F_LESS_EQUAL:
3376
case SLJIT_ORDERED_EQUAL:
3377
case SLJIT_UNORDERED_OR_EQUAL:
3378
case SLJIT_ORDERED_LESS:
3379
case SLJIT_UNORDERED_OR_LESS:
3380
case SLJIT_UNORDERED_OR_LESS_EQUAL:
3381
case SLJIT_ORDERED_LESS_EQUAL:
3382
case SLJIT_UNORDERED:
3383
BR_F();
3384
break;
3385
default:
3386
/* Not conditional branch. */
3387
inst = 0;
3388
break;
3389
}
3390
3391
jump->flags |= flags;
3392
if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
3393
jump->flags |= IS_MOVABLE;
3394
3395
if (inst)
3396
PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
3397
3398
if (type <= SLJIT_JUMP)
3399
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
3400
else {
3401
jump->flags |= IS_JAL;
3402
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
3403
}
3404
3405
jump->addr = compiler->size;
3406
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3407
3408
/* Maximum number of instructions required for generating a constant. */
3409
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3410
compiler->size += 2;
3411
#else
3412
compiler->size += 6;
3413
#endif
3414
return jump;
3415
}
3416
3417
#define RESOLVE_IMM1() \
3418
if (src1 == SLJIT_IMM) { \
3419
if (src1w) { \
3420
PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
3421
src1 = TMP_REG1; \
3422
} \
3423
else \
3424
src1 = 0; \
3425
}
3426
3427
#define RESOLVE_IMM2() \
3428
if (src2 == SLJIT_IMM) { \
3429
if (src2w) { \
3430
PTR_FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w)); \
3431
src2 = src2_tmp_reg; \
3432
} \
3433
else \
3434
src2 = 0; \
3435
}
3436
3437
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
3438
sljit_s32 src1, sljit_sw src1w,
3439
sljit_s32 src2, sljit_sw src2w)
3440
{
3441
struct sljit_jump *jump;
3442
sljit_s32 flags;
3443
sljit_ins inst;
3444
sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
3445
3446
CHECK_ERROR_PTR();
3447
CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
3448
ADJUST_LOCAL_OFFSET(src1, src1w);
3449
ADJUST_LOCAL_OFFSET(src2, src2w);
3450
3451
compiler->cache_arg = 0;
3452
compiler->cache_argw = 0;
3453
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3454
flags = WORD_DATA | LOAD_DATA;
3455
#else /* !SLJIT_CONFIG_MIPS_32 */
3456
flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
3457
#endif /* SLJIT_CONFIG_MIPS_32 */
3458
3459
if (src1 & SLJIT_MEM) {
3460
PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
3461
src1 = TMP_REG1;
3462
}
3463
3464
if (src2 & SLJIT_MEM) {
3465
PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(src2_tmp_reg), src2, src2w, 0, 0));
3466
src2 = src2_tmp_reg;
3467
}
3468
3469
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3470
PTR_FAIL_IF(!jump);
3471
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
3472
type &= 0xff;
3473
3474
if (type <= SLJIT_NOT_EQUAL) {
3475
RESOLVE_IMM1();
3476
RESOLVE_IMM2();
3477
jump->flags |= IS_BIT26_COND;
3478
if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
3479
jump->flags |= IS_MOVABLE;
3480
PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS));
3481
} else if (type >= SLJIT_SIG_LESS && ((src1 == SLJIT_IMM && src1w == 0) || (src2 == SLJIT_IMM && src2w == 0))) {
3482
inst = NOP;
3483
if (src1 == SLJIT_IMM && src1w == 0) {
3484
RESOLVE_IMM2();
3485
switch (type) {
3486
case SLJIT_SIG_LESS:
3487
inst = BLEZ;
3488
jump->flags |= IS_BIT26_COND;
3489
break;
3490
case SLJIT_SIG_GREATER_EQUAL:
3491
inst = BGTZ;
3492
jump->flags |= IS_BIT26_COND;
3493
break;
3494
case SLJIT_SIG_GREATER:
3495
inst = BGEZ;
3496
jump->flags |= IS_BIT16_COND;
3497
break;
3498
case SLJIT_SIG_LESS_EQUAL:
3499
inst = BLTZ;
3500
jump->flags |= IS_BIT16_COND;
3501
break;
3502
}
3503
src1 = src2;
3504
}
3505
else {
3506
RESOLVE_IMM1();
3507
switch (type) {
3508
case SLJIT_SIG_LESS:
3509
inst = BGEZ;
3510
jump->flags |= IS_BIT16_COND;
3511
break;
3512
case SLJIT_SIG_GREATER_EQUAL:
3513
inst = BLTZ;
3514
jump->flags |= IS_BIT16_COND;
3515
break;
3516
case SLJIT_SIG_GREATER:
3517
inst = BLEZ;
3518
jump->flags |= IS_BIT26_COND;
3519
break;
3520
case SLJIT_SIG_LESS_EQUAL:
3521
inst = BGTZ;
3522
jump->flags |= IS_BIT26_COND;
3523
break;
3524
}
3525
}
3526
PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS));
3527
}
3528
else {
3529
if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {
3530
RESOLVE_IMM1();
3531
if (src2 == SLJIT_IMM && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
3532
PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
3533
else {
3534
RESOLVE_IMM2();
3535
PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
3536
}
3537
type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
3538
}
3539
else {
3540
RESOLVE_IMM2();
3541
if (src1 == SLJIT_IMM && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
3542
PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
3543
else {
3544
RESOLVE_IMM1();
3545
PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
3546
}
3547
type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
3548
}
3549
3550
jump->flags |= IS_BIT26_COND;
3551
PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS));
3552
}
3553
3554
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
3555
jump->addr = compiler->size;
3556
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
3557
3558
/* Maximum number of instructions required for generating a constant. */
3559
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3560
compiler->size += 2;
3561
#else
3562
compiler->size += 6;
3563
#endif
3564
return jump;
3565
}
3566
3567
#undef RESOLVE_IMM1
3568
#undef RESOLVE_IMM2
3569
3570
#undef BRANCH_LENGTH
3571
#undef BR_Z
3572
#undef BR_NZ
3573
#undef BR_T
3574
#undef BR_F
3575
3576
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
3577
{
3578
struct sljit_jump *jump = NULL;
3579
3580
CHECK_ERROR();
3581
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
3582
3583
if (src == SLJIT_IMM) {
3584
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3585
FAIL_IF(!jump);
3586
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
3587
jump->u.target = (sljit_uw)srcw;
3588
3589
if (compiler->delay_slot != UNMOVABLE_INS)
3590
jump->flags |= IS_MOVABLE;
3591
3592
src = PIC_ADDR_REG;
3593
} else if (src & SLJIT_MEM) {
3594
ADJUST_LOCAL_OFFSET(src, srcw);
3595
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
3596
src = PIC_ADDR_REG;
3597
}
3598
3599
if (type <= SLJIT_JUMP)
3600
FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
3601
else
3602
FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
3603
3604
if (jump != NULL) {
3605
jump->addr = compiler->size;
3606
3607
/* Maximum number of instructions required for generating a constant. */
3608
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3609
compiler->size += 2;
3610
#else
3611
compiler->size += 6;
3612
#endif
3613
}
3614
3615
return push_inst(compiler, NOP, UNMOVABLE_INS);
3616
}
3617
3618
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
3619
sljit_s32 dst, sljit_sw dstw,
3620
sljit_s32 type)
3621
{
3622
sljit_s32 src_ar, dst_ar, invert;
3623
sljit_s32 saved_op = op;
3624
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3625
sljit_s32 mem_type = WORD_DATA;
3626
#else
3627
sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
3628
#endif
3629
3630
CHECK_ERROR();
3631
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
3632
ADJUST_LOCAL_OFFSET(dst, dstw);
3633
3634
op = GET_OPCODE(op);
3635
dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
3636
3637
compiler->cache_arg = 0;
3638
compiler->cache_argw = 0;
3639
3640
if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
3641
FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
3642
3643
if (type < SLJIT_F_EQUAL) {
3644
src_ar = OTHER_FLAG;
3645
invert = type & 0x1;
3646
3647
switch (type) {
3648
case SLJIT_EQUAL:
3649
case SLJIT_NOT_EQUAL:
3650
FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
3651
src_ar = dst_ar;
3652
break;
3653
case SLJIT_OVERFLOW:
3654
case SLJIT_NOT_OVERFLOW:
3655
if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
3656
src_ar = OTHER_FLAG;
3657
break;
3658
}
3659
FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
3660
src_ar = dst_ar;
3661
invert ^= 0x1;
3662
break;
3663
}
3664
} else {
3665
invert = 0;
3666
3667
switch (type) {
3668
case SLJIT_F_NOT_EQUAL:
3669
case SLJIT_F_GREATER_EQUAL:
3670
case SLJIT_F_GREATER:
3671
case SLJIT_UNORDERED_OR_NOT_EQUAL:
3672
case SLJIT_ORDERED_NOT_EQUAL:
3673
case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3674
case SLJIT_ORDERED_GREATER_EQUAL:
3675
case SLJIT_ORDERED_GREATER:
3676
case SLJIT_UNORDERED_OR_GREATER:
3677
case SLJIT_ORDERED:
3678
invert = 1;
3679
break;
3680
}
3681
3682
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3683
FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
3684
#else /* SLJIT_MIPS_REV < 6 */
3685
FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
3686
#endif /* SLJIT_MIPS_REV >= 6 */
3687
FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
3688
FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
3689
src_ar = dst_ar;
3690
}
3691
3692
if (invert) {
3693
FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
3694
src_ar = dst_ar;
3695
}
3696
3697
if (op < SLJIT_ADD) {
3698
if (dst & SLJIT_MEM)
3699
return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
3700
3701
if (src_ar != dst_ar)
3702
return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
3703
return SLJIT_SUCCESS;
3704
}
3705
3706
/* OTHER_FLAG cannot be specified as src2 argument at the moment. */
3707
if (DR(TMP_REG2) != src_ar)
3708
FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
3709
3710
mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
3711
3712
if (dst & SLJIT_MEM)
3713
return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
3714
return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
3715
}
3716
3717
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3718
3719
static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float)
3720
{
3721
switch (type & ~SLJIT_32) {
3722
case SLJIT_EQUAL:
3723
return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG);
3724
case SLJIT_NOT_EQUAL:
3725
return (is_float ? MOVN_S : MOVN) | TA(EQUAL_FLAG);
3726
case SLJIT_LESS:
3727
case SLJIT_GREATER:
3728
case SLJIT_SIG_LESS:
3729
case SLJIT_SIG_GREATER:
3730
case SLJIT_OVERFLOW:
3731
case SLJIT_CARRY:
3732
return (is_float ? MOVN_S : MOVN) | TA(OTHER_FLAG);
3733
case SLJIT_GREATER_EQUAL:
3734
case SLJIT_LESS_EQUAL:
3735
case SLJIT_SIG_GREATER_EQUAL:
3736
case SLJIT_SIG_LESS_EQUAL:
3737
case SLJIT_NOT_OVERFLOW:
3738
case SLJIT_NOT_CARRY:
3739
return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);
3740
case SLJIT_F_EQUAL:
3741
case SLJIT_F_LESS:
3742
case SLJIT_F_LESS_EQUAL:
3743
case SLJIT_ORDERED_EQUAL:
3744
case SLJIT_UNORDERED_OR_EQUAL:
3745
case SLJIT_ORDERED_LESS:
3746
case SLJIT_UNORDERED_OR_LESS:
3747
case SLJIT_UNORDERED_OR_LESS_EQUAL:
3748
case SLJIT_ORDERED_LESS_EQUAL:
3749
case SLJIT_UNORDERED:
3750
return is_float ? MOVT_S : MOVT;
3751
case SLJIT_F_NOT_EQUAL:
3752
case SLJIT_F_GREATER_EQUAL:
3753
case SLJIT_F_GREATER:
3754
case SLJIT_UNORDERED_OR_NOT_EQUAL:
3755
case SLJIT_ORDERED_NOT_EQUAL:
3756
case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3757
case SLJIT_ORDERED_GREATER_EQUAL:
3758
case SLJIT_ORDERED_GREATER:
3759
case SLJIT_UNORDERED_OR_GREATER:
3760
case SLJIT_ORDERED:
3761
return is_float ? MOVF_S : MOVF;
3762
default:
3763
SLJIT_UNREACHABLE();
3764
return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);
3765
}
3766
}
3767
3768
#endif /* SLJIT_MIPS_REV >= 1 */
3769
3770
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
3771
sljit_s32 dst_reg,
3772
sljit_s32 src1, sljit_sw src1w,
3773
sljit_s32 src2_reg)
3774
{
3775
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3776
sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
3777
sljit_ins mov_ins = (type & SLJIT_32) ? ADDU : DADDU;
3778
#else /* !SLJIT_CONFIG_MIPS_64 */
3779
sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
3780
sljit_ins mov_ins = ADDU;
3781
#endif /* SLJIT_CONFIG_MIPS_64 */
3782
3783
#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3784
struct sljit_label *label;
3785
struct sljit_jump *jump;
3786
#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */
3787
3788
CHECK_ERROR();
3789
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
3790
ADJUST_LOCAL_OFFSET(src1, src1w);
3791
3792
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3793
if (src1 & SLJIT_MEM) {
3794
FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));
3795
src1 = TMP_REG1;
3796
} else if (src1 == SLJIT_IMM) {
3797
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3798
if (type & SLJIT_32)
3799
src1w = (sljit_s32)src1w;
3800
#endif
3801
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
3802
src1 = TMP_REG1;
3803
}
3804
3805
if (dst_reg != src2_reg) {
3806
if (dst_reg == src1) {
3807
src1 = src2_reg;
3808
type ^= 0x1;
3809
} else
3810
FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));
3811
}
3812
3813
return push_inst(compiler, get_select_cc(type, 0) | S(src1) | D(dst_reg), DR(dst_reg));
3814
3815
#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
3816
if (dst_reg != src2_reg) {
3817
if (dst_reg == src1) {
3818
src1 = src2_reg;
3819
src1w = 0;
3820
type ^= 0x1;
3821
} else {
3822
if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
3823
FAIL_IF(push_inst(compiler, ADDU_W | S(dst_reg) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
3824
3825
if ((src1 & REG_MASK) == dst_reg)
3826
src1 = (src1 & ~REG_MASK) | TMP_REG1;
3827
3828
if (OFFS_REG(src1) == dst_reg)
3829
src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
3830
}
3831
3832
FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));
3833
}
3834
}
3835
3836
SLJIT_SKIP_CHECKS(compiler);
3837
jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);
3838
FAIL_IF(!jump);
3839
3840
if (src1 & SLJIT_MEM) {
3841
FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w));
3842
} else if (src1 == SLJIT_IMM) {
3843
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
3844
if (type & SLJIT_32)
3845
src1w = (sljit_s32)src1w;
3846
#endif /* SLJIT_CONFIG_MIPS_64 */
3847
FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w));
3848
} else
3849
FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg)));
3850
3851
SLJIT_SKIP_CHECKS(compiler);
3852
label = sljit_emit_label(compiler);
3853
FAIL_IF(!label);
3854
3855
sljit_set_label(jump, label);
3856
return SLJIT_SUCCESS;
3857
#endif /* SLJIT_MIPS_REV >= 1 */
3858
}
3859
3860
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
3861
sljit_s32 dst_freg,
3862
sljit_s32 src1, sljit_sw src1w,
3863
sljit_s32 src2_freg)
3864
{
3865
#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3866
struct sljit_label *label;
3867
struct sljit_jump *jump;
3868
#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */
3869
3870
CHECK_ERROR();
3871
CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
3872
3873
ADJUST_LOCAL_OFFSET(src1, src1w);
3874
3875
if (dst_freg != src2_freg) {
3876
if (dst_freg == src1) {
3877
src1 = src2_freg;
3878
src1w = 0;
3879
type ^= 0x1;
3880
} else
3881
FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src2_freg) | FD(dst_freg), MOVABLE_INS));
3882
}
3883
3884
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
3885
if (src1 & SLJIT_MEM) {
3886
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(TMP_FREG2), src1, src1w));
3887
src1 = TMP_FREG2;
3888
}
3889
3890
return push_inst(compiler, get_select_cc(type, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);
3891
3892
#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
3893
SLJIT_SKIP_CHECKS(compiler);
3894
jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);
3895
FAIL_IF(!jump);
3896
3897
if (src1 & SLJIT_MEM)
3898
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(dst_freg), src1, src1w));
3899
else
3900
FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src1) | FD(dst_freg), MOVABLE_INS));
3901
3902
SLJIT_SKIP_CHECKS(compiler);
3903
label = sljit_emit_label(compiler);
3904
FAIL_IF(!label);
3905
3906
sljit_set_label(jump, label);
3907
return SLJIT_SUCCESS;
3908
#endif /* SLJIT_MIPS_REV >= 1 */
3909
}
3910
3911
#undef FLOAT_DATA
3912
#undef FMT
3913
3914
static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)
3915
{
3916
sljit_s32 arg = *mem;
3917
sljit_sw argw = *memw;
3918
3919
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
3920
argw &= 0x3;
3921
3922
if (SLJIT_UNLIKELY(argw)) {
3923
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
3924
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)));
3925
} else
3926
FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));
3927
3928
*mem = TMP_REG1;
3929
*memw = 0;
3930
3931
return SLJIT_SUCCESS;
3932
}
3933
3934
if (argw <= max_offset && argw >= SIMM_MIN) {
3935
*mem = arg & REG_MASK;
3936
return SLJIT_SUCCESS;
3937
}
3938
3939
*mem = TMP_REG1;
3940
3941
if ((sljit_s16)argw > max_offset) {
3942
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));
3943
*memw = 0;
3944
} else {
3945
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));
3946
*memw = (sljit_s16)argw;
3947
}
3948
3949
if ((arg & REG_MASK) == 0)
3950
return SLJIT_SUCCESS;
3951
3952
return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1));
3953
}
3954
3955
#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
3956
#define IMM_LEFT(memw) IMM((memw) + SSIZE_OF(sw) - 1)
3957
#define IMM_RIGHT(memw) IMM(memw)
3958
#define IMM_32_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
3959
#define IMM_32_RIGHT(memw) IMM(memw)
3960
#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
3961
#define IMM_F64_FIRST_RIGHT(memw) IMM(memw)
3962
#define IMM_F64_SECOND_LEFT(memw) IMM((memw) + SSIZE_OF(f64) - 1)
3963
#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32))
3964
#define IMM_16_FIRST(memw) IMM((memw) + 1)
3965
#define IMM_16_SECOND(memw) IMM(memw)
3966
#else /* !SLJIT_LITTLE_ENDIAN */
3967
#define IMM_LEFT(memw) IMM(memw)
3968
#define IMM_RIGHT(memw) IMM((memw) + SSIZE_OF(sw) - 1)
3969
#define IMM_32_LEFT(memw) IMM(memw)
3970
#define IMM_32_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
3971
#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32))
3972
#define IMM_F64_FIRST_RIGHT(memw) IMM((memw) + SSIZE_OF(f64) - 1)
3973
#define IMM_F64_SECOND_LEFT(memw) IMM(memw)
3974
#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
3975
#define IMM_16_FIRST(memw) IMM(memw)
3976
#define IMM_16_SECOND(memw) IMM((memw) + 1)
3977
#endif /* SLJIT_LITTLE_ENDIAN */
3978
3979
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
3980
#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16))
3981
#else /* !SLJIT_CONFIG_MIPS_32 */
3982
#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))
3983
#endif /* SLJIT_CONFIG_MIPS_32 */
3984
3985
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
3986
sljit_s32 reg,
3987
sljit_s32 mem, sljit_sw memw)
3988
{
3989
sljit_s32 op = type & 0xff;
3990
sljit_s32 flags = 0;
3991
sljit_ins ins;
3992
#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
3993
sljit_ins ins_right;
3994
#endif /* !(SLJIT_MIPS_REV >= 6) */
3995
3996
CHECK_ERROR();
3997
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
3998
3999
if (reg & REG_PAIR_MASK) {
4000
ADJUST_LOCAL_OFFSET(mem, memw);
4001
4002
#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
4003
if (MEM_CHECK_UNALIGNED(type)) {
4004
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1)));
4005
4006
if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) {
4007
FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
4008
mem = TMP_REG1;
4009
}
4010
4011
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4012
ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem);
4013
ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem);
4014
#else /* !SLJIT_CONFIG_MIPS_32 */
4015
ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem);
4016
ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem);
4017
#endif /* SLJIT_CONFIG_MIPS_32 */
4018
4019
FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM_LEFT(memw), DR(REG_PAIR_FIRST(reg))));
4020
FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM_RIGHT(memw), DR(REG_PAIR_FIRST(reg))));
4021
FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM_LEFT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));
4022
return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM_RIGHT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));
4023
}
4024
#endif /* !(SLJIT_MIPS_REV >= 6) */
4025
4026
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw)));
4027
4028
ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem);
4029
4030
if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
4031
FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));
4032
return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)));
4033
}
4034
4035
FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))));
4036
return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));
4037
}
4038
4039
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
4040
return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
4041
#else /* !(SLJIT_MIPS_REV >= 6) */
4042
ADJUST_LOCAL_OFFSET(mem, memw);
4043
4044
switch (op) {
4045
case SLJIT_MOV_U8:
4046
case SLJIT_MOV_S8:
4047
flags = BYTE_DATA;
4048
if (!(type & SLJIT_MEM_STORE))
4049
flags |= LOAD_DATA;
4050
4051
if (op == SLJIT_MOV_S8)
4052
flags |= SIGNED_DATA;
4053
4054
return emit_op_mem(compiler, flags, DR(reg), mem, memw);
4055
4056
case SLJIT_MOV_U16:
4057
case SLJIT_MOV_S16:
4058
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));
4059
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4060
4061
if (type & SLJIT_MEM_STORE) {
4062
FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
4063
FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), MOVABLE_INS));
4064
return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), MOVABLE_INS);
4065
}
4066
4067
flags = BYTE_DATA | LOAD_DATA;
4068
4069
if (op == SLJIT_MOV_S16)
4070
flags |= SIGNED_DATA;
4071
4072
FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), DR(TMP_REG2)));
4073
FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), DR(reg)));
4074
FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
4075
return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));
4076
4077
case SLJIT_MOV:
4078
case SLJIT_MOV_P:
4079
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4080
if (type & SLJIT_MEM_ALIGNED_32) {
4081
flags = WORD_DATA;
4082
if (!(type & SLJIT_MEM_STORE))
4083
flags |= LOAD_DATA;
4084
4085
return emit_op_mem(compiler, flags, DR(reg), mem, memw);
4086
}
4087
#else /* !SLJIT_CONFIG_MIPS_32 */
4088
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));
4089
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4090
4091
if (type & SLJIT_MEM_STORE) {
4092
FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM_LEFT(memw), MOVABLE_INS));
4093
return push_inst(compiler, SDR | S(mem) | T(reg) | IMM_RIGHT(memw), MOVABLE_INS);
4094
}
4095
4096
if (mem == reg) {
4097
FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
4098
mem = TMP_REG1;
4099
}
4100
4101
FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM_LEFT(memw), DR(reg)));
4102
return push_inst(compiler, LDR | S(mem) | T(reg) | IMM_RIGHT(memw), DR(reg));
4103
#endif /* SLJIT_CONFIG_MIPS_32 */
4104
}
4105
4106
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));
4107
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4108
4109
if (type & SLJIT_MEM_STORE) {
4110
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM_32_LEFT(memw), MOVABLE_INS));
4111
return push_inst(compiler, SWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), MOVABLE_INS);
4112
}
4113
4114
if (mem == reg) {
4115
FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
4116
mem = TMP_REG1;
4117
}
4118
4119
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM_32_LEFT(memw), DR(reg)));
4120
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4121
return push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg));
4122
#else /* !SLJIT_CONFIG_MIPS_32 */
4123
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg)));
4124
4125
if (op != SLJIT_MOV_U32)
4126
return SLJIT_SUCCESS;
4127
4128
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
4129
return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11), DR(reg));
4130
#else /* SLJIT_MIPS_REV < 2 */
4131
FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));
4132
return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));
4133
#endif /* SLJIT_MIPS_REV >= 2 */
4134
#endif /* SLJIT_CONFIG_MIPS_32 */
4135
#endif /* SLJIT_MIPS_REV >= 6 */
4136
}
4137
4138
#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
4139
4140
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
4141
sljit_s32 freg,
4142
sljit_s32 mem, sljit_sw memw)
4143
{
4144
CHECK_ERROR();
4145
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
4146
4147
FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));
4148
SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
4149
4150
if (type & SLJIT_MEM_STORE) {
4151
if (type & SLJIT_32) {
4152
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4153
#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
4154
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4155
#endif /* MIPS III */
4156
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), MOVABLE_INS));
4157
return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), MOVABLE_INS);
4158
}
4159
4160
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4161
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4162
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4163
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4164
#endif /* MIPS III */
4165
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), MOVABLE_INS));
4166
FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), MOVABLE_INS));
4167
switch (cpu_feature_list & CPU_FEATURE_FR) {
4168
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
4169
case CPU_FEATURE_FR:
4170
FAIL_IF(push_inst(compiler, MFHC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4171
break;
4172
#endif /* SLJIT_MIPS_REV >= 2 */
4173
default:
4174
FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg) | (1 << 11), DR(TMP_REG2)));
4175
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4176
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4177
#endif
4178
break;
4179
}
4180
4181
FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), MOVABLE_INS));
4182
return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), MOVABLE_INS);
4183
#else /* !SLJIT_CONFIG_MIPS_32 */
4184
FAIL_IF(push_inst(compiler, DMFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
4185
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4186
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4187
#endif /* MIPS III */
4188
FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), MOVABLE_INS));
4189
return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), MOVABLE_INS);
4190
#endif /* SLJIT_CONFIG_MIPS_32 */
4191
}
4192
4193
if (type & SLJIT_32) {
4194
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), DR(TMP_REG2)));
4195
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), DR(TMP_REG2)));
4196
4197
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
4198
#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
4199
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4200
#endif /* MIPS III */
4201
return SLJIT_SUCCESS;
4202
}
4203
4204
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4205
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), DR(TMP_REG2)));
4206
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), DR(TMP_REG2)));
4207
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
4208
4209
FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), DR(TMP_REG2)));
4210
FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), DR(TMP_REG2)));
4211
switch (cpu_feature_list & CPU_FEATURE_FR) {
4212
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
4213
case CPU_FEATURE_FR:
4214
return push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS);
4215
#endif /* SLJIT_MIPS_REV >= 2 */
4216
default:
4217
FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg) | (1 << 11), MOVABLE_INS));
4218
break;
4219
}
4220
#else /* !SLJIT_CONFIG_MIPS_32 */
4221
FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), DR(TMP_REG2)));
4222
FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), DR(TMP_REG2)));
4223
4224
FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
4225
#endif /* SLJIT_CONFIG_MIPS_32 */
4226
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
4227
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
4228
#endif /* MIPS III */
4229
return SLJIT_SUCCESS;
4230
}
4231
4232
#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */
4233
4234
#undef IMM_16_SECOND
4235
#undef IMM_16_FIRST
4236
#undef IMM_F64_SECOND_RIGHT
4237
#undef IMM_F64_SECOND_LEFT
4238
#undef IMM_F64_FIRST_RIGHT
4239
#undef IMM_F64_FIRST_LEFT
4240
#undef IMM_32_RIGHT
4241
#undef IMM_32_LEFT
4242
#undef IMM_RIGHT
4243
#undef IMM_LEFT
4244
#undef MEM_CHECK_UNALIGNED
4245
4246
#undef TO_ARGW_HI
4247
4248
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
4249
sljit_s32 dst_reg,
4250
sljit_s32 mem_reg)
4251
{
4252
sljit_ins ins;
4253
4254
CHECK_ERROR();
4255
CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
4256
4257
if (op & SLJIT_ATOMIC_USE_CAS)
4258
return SLJIT_ERR_UNSUPPORTED;
4259
4260
switch (GET_OPCODE(op)) {
4261
case SLJIT_MOV:
4262
case SLJIT_MOV_P:
4263
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
4264
ins = LLD;
4265
break;
4266
#endif /* SLJIT_CONFIG_MIPS_64 */
4267
case SLJIT_MOV_S32:
4268
case SLJIT_MOV32:
4269
ins = LL;
4270
break;
4271
4272
default:
4273
return SLJIT_ERR_UNSUPPORTED;
4274
}
4275
4276
if (op & SLJIT_ATOMIC_TEST)
4277
return SLJIT_SUCCESS;
4278
4279
return push_inst(compiler, ins | T(dst_reg) | S(mem_reg), DR(dst_reg));
4280
}
4281
4282
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
4283
sljit_s32 src_reg,
4284
sljit_s32 mem_reg,
4285
sljit_s32 temp_reg)
4286
{
4287
sljit_ins ins;
4288
4289
/* temp_reg == mem_reg is undefined so use another temp register */
4290
SLJIT_UNUSED_ARG(temp_reg);
4291
4292
CHECK_ERROR();
4293
CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
4294
4295
if (op & SLJIT_ATOMIC_USE_CAS)
4296
return SLJIT_ERR_UNSUPPORTED;
4297
4298
switch (GET_OPCODE(op)) {
4299
case SLJIT_MOV:
4300
case SLJIT_MOV_P:
4301
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
4302
ins = SCD;
4303
break;
4304
#endif /* SLJIT_CONFIG_RISCV_64 */
4305
case SLJIT_MOV_S32:
4306
case SLJIT_MOV32:
4307
op |= SLJIT_32;
4308
ins = SC;
4309
break;
4310
4311
default:
4312
return SLJIT_ERR_UNSUPPORTED;
4313
}
4314
4315
if (op & SLJIT_ATOMIC_TEST)
4316
return SLJIT_SUCCESS;
4317
4318
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src_reg) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));
4319
return push_inst(compiler, ins | TA(OTHER_FLAG) | S(mem_reg), OTHER_FLAG);
4320
}
4321
4322
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
4323
{
4324
struct sljit_const *const_;
4325
sljit_s32 dst_r;
4326
4327
CHECK_ERROR_PTR();
4328
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
4329
ADJUST_LOCAL_OFFSET(dst, dstw);
4330
4331
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
4332
PTR_FAIL_IF(!const_);
4333
set_const(const_, compiler);
4334
4335
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
4336
PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
4337
4338
if (dst & SLJIT_MEM)
4339
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
4340
4341
return const_;
4342
}
4343
4344
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
4345
{
4346
struct sljit_jump *jump;
4347
sljit_s32 dst_r;
4348
4349
CHECK_ERROR_PTR();
4350
CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
4351
ADJUST_LOCAL_OFFSET(dst, dstw);
4352
4353
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
4354
PTR_FAIL_IF(!jump);
4355
set_mov_addr(jump, compiler, 0);
4356
4357
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
4358
PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));
4359
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
4360
compiler->size += 1;
4361
#else
4362
compiler->size += 5;
4363
#endif
4364
4365
if (dst & SLJIT_MEM)
4366
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
4367
4368
return jump;
4369
}
4370
4371