Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.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
/* ppc 64-bit arch dependent functions. */
28
29
#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
30
#define ASM_SLJIT_CLZ(src, dst) \
31
__asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
32
#elif defined(__xlc__)
33
#error "Please enable GCC syntax for inline assembly statements"
34
#else
35
#error "Must implement count leading zeroes"
36
#endif
37
38
/* Computes SLDI(63 - shift). */
39
#define PUSH_SLDI_NEG(reg, shift) \
40
push_inst(compiler, RLDICR | S(reg) | A(reg) | RLDI_SH(63 - shift) | RLDI_ME(shift))
41
42
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
43
{
44
sljit_uw tmp;
45
sljit_uw shift;
46
sljit_uw tmp2;
47
sljit_uw shift2;
48
49
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
50
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
51
52
if (((sljit_uw)imm >> 16) == 0)
53
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
54
55
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
56
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
57
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
58
}
59
60
if (((sljit_uw)imm >> 32) == 0) {
61
FAIL_IF(push_inst(compiler, ORIS | S(TMP_ZERO) | A(reg) | IMM(imm >> 16)));
62
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
63
}
64
65
/* Count leading zeroes. */
66
tmp = (sljit_uw)((imm >= 0) ? imm : ~imm);
67
ASM_SLJIT_CLZ(tmp, shift);
68
SLJIT_ASSERT(shift > 0);
69
shift--;
70
tmp = ((sljit_uw)imm << shift);
71
72
if ((tmp & ~0xffff000000000000ul) == 0) {
73
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
74
shift += 15;
75
return PUSH_SLDI_NEG(reg, shift);
76
}
77
78
if ((tmp & ~0xffffffff00000000ul) == 0) {
79
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
80
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
81
shift += 31;
82
return PUSH_SLDI_NEG(reg, shift);
83
}
84
85
/* Cut out the 16 bit from immediate. */
86
shift += 15;
87
tmp2 = (sljit_uw)imm & (((sljit_uw)1 << (63 - shift)) - 1);
88
89
if (tmp2 <= 0xffff) {
90
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
91
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
92
return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2);
93
}
94
95
if (tmp2 <= 0xffffffff) {
96
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
97
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
98
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16)));
99
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
100
}
101
102
ASM_SLJIT_CLZ(tmp2, shift2);
103
tmp2 <<= shift2;
104
105
if ((tmp2 & ~0xffff000000000000ul) == 0) {
106
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
107
shift2 += 15;
108
shift += (63 - shift2);
109
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
110
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));
111
return PUSH_SLDI_NEG(reg, shift2);
112
}
113
114
/* The general version. */
115
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48)));
116
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
117
FAIL_IF(PUSH_SLDI_NEG(reg, 31));
118
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
119
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
120
}
121
122
#undef PUSH_SLDI_NEG
123
124
#define CLRLDI(dst, src, n) \
125
(RLDICL | S(src) | A(dst) | RLDI_SH(0) | RLDI_MB(n))
126
127
/* Sign extension for integer operations. */
128
#define UN_EXTS() \
129
if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
130
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
131
src2 = TMP_REG2; \
132
}
133
134
#define BIN_EXTS() \
135
if (flags & ALT_SIGN_EXT) { \
136
if (flags & REG1_SOURCE) { \
137
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
138
src1 = TMP_REG1; \
139
} \
140
if (flags & REG2_SOURCE) { \
141
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
142
src2 = TMP_REG2; \
143
} \
144
}
145
146
#define BIN_IMM_EXTS() \
147
if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
148
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
149
src1 = TMP_REG1; \
150
}
151
152
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
153
sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
154
{
155
sljit_u32 imm;
156
157
switch (op) {
158
case SLJIT_MOV:
159
case SLJIT_MOV_P:
160
SLJIT_ASSERT(src1 == TMP_REG1);
161
if (dst != src2)
162
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
163
return SLJIT_SUCCESS;
164
165
case SLJIT_MOV_U32:
166
case SLJIT_MOV_S32:
167
SLJIT_ASSERT(src1 == TMP_REG1);
168
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
169
if (op == SLJIT_MOV_S32)
170
return push_inst(compiler, EXTSW | S(src2) | A(dst));
171
return push_inst(compiler, CLRLDI(dst, src2, 32));
172
}
173
else {
174
SLJIT_ASSERT(dst == src2);
175
}
176
return SLJIT_SUCCESS;
177
178
case SLJIT_MOV_U8:
179
case SLJIT_MOV_S8:
180
SLJIT_ASSERT(src1 == TMP_REG1);
181
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
182
if (op == SLJIT_MOV_S8)
183
return push_inst(compiler, EXTSB | S(src2) | A(dst));
184
return push_inst(compiler, CLRLDI(dst, src2, 56));
185
}
186
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
187
return push_inst(compiler, EXTSB | S(src2) | A(dst));
188
else {
189
SLJIT_ASSERT(dst == src2);
190
}
191
return SLJIT_SUCCESS;
192
193
case SLJIT_MOV_U16:
194
case SLJIT_MOV_S16:
195
SLJIT_ASSERT(src1 == TMP_REG1);
196
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
197
if (op == SLJIT_MOV_S16)
198
return push_inst(compiler, EXTSH | S(src2) | A(dst));
199
return push_inst(compiler, CLRLDI(dst, src2, 48));
200
}
201
else {
202
SLJIT_ASSERT(dst == src2);
203
}
204
return SLJIT_SUCCESS;
205
206
case SLJIT_CLZ:
207
SLJIT_ASSERT(src1 == TMP_REG1);
208
return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst));
209
210
case SLJIT_CTZ:
211
SLJIT_ASSERT(src1 == TMP_REG1);
212
FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
213
FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
214
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(dst) | A(dst)));
215
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM((flags & ALT_FORM1) ? -32 : -64)));
216
/* The highest bits are set, if dst < bit width, zero otherwise. */
217
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? SRWI(27) : SRDI(58)) | S(TMP_REG1) | A(TMP_REG1)));
218
return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
219
220
case SLJIT_ADD:
221
if (flags & ALT_FORM1) {
222
if (flags & ALT_SIGN_EXT) {
223
FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
224
src1 = TMP_REG1;
225
FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
226
src2 = TMP_REG2;
227
}
228
/* Setting XER SO is not enough, CR SO is also needed. */
229
FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
230
if (flags & ALT_SIGN_EXT)
231
return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
232
return SLJIT_SUCCESS;
233
}
234
235
if (flags & ALT_FORM2) {
236
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
237
SLJIT_ASSERT(src2 == TMP_REG2);
238
239
if (flags & ALT_FORM3)
240
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
241
242
imm = compiler->imm;
243
244
if (flags & ALT_FORM4) {
245
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
246
src1 = dst;
247
}
248
249
return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
250
}
251
if (flags & ALT_FORM3) {
252
SLJIT_ASSERT(src2 == TMP_REG2);
253
BIN_IMM_EXTS();
254
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
255
}
256
if (flags & ALT_FORM4) {
257
if (flags & ALT_FORM5)
258
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm));
259
else
260
FAIL_IF(push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)));
261
return push_inst(compiler, CMPI | A(dst) | 0);
262
}
263
if (!(flags & ALT_SET_FLAGS))
264
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
265
BIN_EXTS();
266
if (flags & ALT_FORM5)
267
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
268
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
269
270
case SLJIT_ADDC:
271
BIN_EXTS();
272
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
273
274
case SLJIT_SUB:
275
if (flags & ALT_FORM1) {
276
if (flags & ALT_FORM2) {
277
FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
278
if (!(flags & ALT_FORM3))
279
return SLJIT_SUCCESS;
280
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
281
}
282
FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
283
if (!(flags & ALT_FORM3))
284
return SLJIT_SUCCESS;
285
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
286
}
287
288
if (flags & ALT_FORM2) {
289
if (flags & ALT_FORM3) {
290
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
291
if (!(flags & ALT_FORM4))
292
return SLJIT_SUCCESS;
293
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
294
}
295
FAIL_IF(push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
296
if (!(flags & ALT_FORM4))
297
return SLJIT_SUCCESS;
298
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
299
}
300
301
if (flags & ALT_FORM3) {
302
if (flags & ALT_SIGN_EXT) {
303
if (src1 != TMP_ZERO) {
304
FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
305
src1 = TMP_REG1;
306
}
307
if (src2 != TMP_ZERO) {
308
FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
309
src2 = TMP_REG2;
310
}
311
}
312
313
/* Setting XER SO is not enough, CR SO is also needed. */
314
if (src1 != TMP_ZERO)
315
FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
316
else
317
FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2)));
318
319
if (flags & ALT_SIGN_EXT)
320
return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
321
return SLJIT_SUCCESS;
322
}
323
324
if (flags & ALT_FORM4) {
325
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
326
SLJIT_ASSERT(src2 == TMP_REG2);
327
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
328
}
329
330
if (!(flags & ALT_SET_FLAGS)) {
331
SLJIT_ASSERT(src1 != TMP_ZERO);
332
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
333
}
334
335
BIN_EXTS();
336
if (flags & ALT_FORM5)
337
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
338
339
if (src1 != TMP_ZERO)
340
return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
341
return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
342
343
case SLJIT_SUBC:
344
BIN_EXTS();
345
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
346
347
case SLJIT_MUL:
348
if (flags & ALT_FORM1) {
349
SLJIT_ASSERT(src2 == TMP_REG2);
350
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
351
}
352
BIN_EXTS();
353
if (flags & ALT_FORM2)
354
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
355
return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
356
357
case SLJIT_AND:
358
if (flags & ALT_FORM1) {
359
SLJIT_ASSERT(src2 == TMP_REG2);
360
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
361
}
362
if (flags & ALT_FORM2) {
363
SLJIT_ASSERT(src2 == TMP_REG2);
364
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
365
}
366
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
367
368
case SLJIT_OR:
369
if (flags & ALT_FORM1) {
370
SLJIT_ASSERT(src2 == TMP_REG2);
371
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
372
}
373
if (flags & ALT_FORM2) {
374
SLJIT_ASSERT(src2 == TMP_REG2);
375
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
376
}
377
if (flags & ALT_FORM3) {
378
SLJIT_ASSERT(src2 == TMP_REG2);
379
imm = compiler->imm;
380
381
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
382
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
383
}
384
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
385
386
case SLJIT_XOR:
387
if (flags & ALT_FORM1) {
388
SLJIT_ASSERT(src2 == TMP_REG2);
389
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
390
}
391
if (flags & ALT_FORM2) {
392
SLJIT_ASSERT(src2 == TMP_REG2);
393
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
394
}
395
if (flags & ALT_FORM3) {
396
SLJIT_ASSERT(src2 == TMP_REG2);
397
imm = compiler->imm;
398
399
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
400
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
401
}
402
if (flags & ALT_FORM4) {
403
SLJIT_ASSERT(src1 == TMP_REG1);
404
UN_EXTS();
405
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
406
}
407
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
408
409
case SLJIT_SHL:
410
case SLJIT_MSHL:
411
if (flags & ALT_FORM1) {
412
SLJIT_ASSERT(src2 == TMP_REG2);
413
imm = compiler->imm;
414
415
if (flags & ALT_FORM2) {
416
imm &= 0x1f;
417
return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
418
}
419
420
imm &= 0x3f;
421
return push_inst(compiler, SLDI(imm) | RC(flags) | S(src1) | A(dst));
422
}
423
424
if (op == SLJIT_MSHL) {
425
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
426
src2 = TMP_REG2;
427
}
428
429
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
430
431
case SLJIT_LSHR:
432
case SLJIT_MLSHR:
433
if (flags & ALT_FORM1) {
434
SLJIT_ASSERT(src2 == TMP_REG2);
435
imm = compiler->imm;
436
437
if (flags & ALT_FORM2) {
438
imm &= 0x1f;
439
/* Since imm can be 0, SRWI() cannot be used. */
440
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
441
}
442
443
imm &= 0x3f;
444
/* Since imm can be 0, SRDI() cannot be used. */
445
return push_inst(compiler, RLDICL | RC(flags) | S(src1) | A(dst) | RLDI_SH((64 - imm) & 0x3f) | RLDI_MB(imm));
446
}
447
448
if (op == SLJIT_MLSHR) {
449
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
450
src2 = TMP_REG2;
451
}
452
453
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
454
455
case SLJIT_ASHR:
456
case SLJIT_MASHR:
457
if (flags & ALT_FORM1) {
458
SLJIT_ASSERT(src2 == TMP_REG2);
459
imm = compiler->imm;
460
461
if (flags & ALT_FORM2) {
462
imm &= 0x1f;
463
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
464
}
465
466
imm &= 0x3f;
467
return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | RLDI_SH(imm));
468
}
469
470
if (op == SLJIT_MASHR) {
471
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
472
src2 = TMP_REG2;
473
}
474
475
return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
476
477
case SLJIT_ROTL:
478
case SLJIT_ROTR:
479
if (flags & ALT_FORM1) {
480
SLJIT_ASSERT(src2 == TMP_REG2);
481
imm = compiler->imm;
482
483
if (op == SLJIT_ROTR)
484
imm = (sljit_u32)(-(sljit_s32)imm);
485
486
if (flags & ALT_FORM2) {
487
imm &= 0x1f;
488
return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
489
}
490
491
imm &= 0x3f;
492
return push_inst(compiler, RLDICL | S(src1) | A(dst) | RLDI_SH(imm));
493
}
494
495
if (op == SLJIT_ROTR) {
496
FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
497
src2 = TMP_REG2;
498
}
499
500
return push_inst(compiler, ((flags & ALT_FORM2) ? (RLWNM | RLWI_MBE(0, 31)) : (RLDCL | RLDI_MB(0))) | S(src1) | A(dst) | B(src2));
501
}
502
503
SLJIT_UNREACHABLE();
504
return SLJIT_SUCCESS;
505
}
506
507
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
508
{
509
sljit_s32 arg_count = 0;
510
sljit_s32 word_arg_count = 0;
511
sljit_s32 types = 0;
512
sljit_s32 reg = 0;
513
514
if (src)
515
reg = *src & REG_MASK;
516
517
arg_types >>= SLJIT_ARG_SHIFT;
518
519
while (arg_types) {
520
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
521
522
switch (arg_types & SLJIT_ARG_MASK) {
523
case SLJIT_ARG_TYPE_F64:
524
case SLJIT_ARG_TYPE_F32:
525
arg_count++;
526
break;
527
default:
528
arg_count++;
529
word_arg_count++;
530
531
if (arg_count != word_arg_count && arg_count == reg) {
532
FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));
533
*src = TMP_CALL_REG;
534
}
535
break;
536
}
537
538
arg_types >>= SLJIT_ARG_SHIFT;
539
}
540
541
while (types) {
542
switch (types & SLJIT_ARG_MASK) {
543
case SLJIT_ARG_TYPE_F64:
544
case SLJIT_ARG_TYPE_F32:
545
arg_count--;
546
break;
547
default:
548
if (arg_count != word_arg_count)
549
FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));
550
551
arg_count--;
552
word_arg_count--;
553
break;
554
}
555
556
types >>= SLJIT_ARG_SHIFT;
557
}
558
559
return SLJIT_SUCCESS;
560
}
561
562
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
563
{
564
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
565
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
566
FAIL_IF(push_inst(compiler, SLDI(32) | S(reg) | A(reg)));
567
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));
568
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
569
}
570
571
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
572
sljit_s32 dst, sljit_sw dstw,
573
sljit_s32 src, sljit_sw srcw)
574
{
575
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
576
577
if (src == SLJIT_IMM) {
578
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
579
srcw = (sljit_s32)srcw;
580
581
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
582
src = TMP_REG1;
583
} else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
584
if (FAST_IS_REG(src))
585
FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
586
else
587
FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
588
src = TMP_REG1;
589
}
590
591
if (FAST_IS_REG(src)) {
592
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
593
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
594
} else
595
FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
596
597
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
598
599
if (op & SLJIT_32)
600
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
601
602
if (dst & SLJIT_MEM)
603
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
604
return SLJIT_SUCCESS;
605
}
606
607
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
608
sljit_s32 dst, sljit_sw dstw,
609
sljit_s32 src, sljit_sw srcw)
610
{
611
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
612
613
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
614
if (src == SLJIT_IMM) {
615
FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_u32)srcw));
616
src = TMP_REG1;
617
} else {
618
if (FAST_IS_REG(src))
619
FAIL_IF(push_inst(compiler, CLRLDI(TMP_REG1, src, 32)));
620
else
621
FAIL_IF(emit_op_mem(compiler, INT_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
622
src = TMP_REG1;
623
}
624
625
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
626
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
627
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
628
} else {
629
if (src == SLJIT_IMM) {
630
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
631
src = TMP_REG1;
632
} else if (src & SLJIT_MEM) {
633
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
634
src = TMP_REG1;
635
}
636
637
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | 1) | A(src) | 0));
638
FAIL_IF(push_inst(compiler, BCx | (12 << 21) | (0 << 16) | 20));
639
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
640
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
641
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
642
FAIL_IF(push_inst(compiler, Bx | ((op & SLJIT_32) ? 36 : 32)));
643
644
if (op & SLJIT_32)
645
FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(TMP_REG2) | RLWI_SH(10) | RLWI_MBE(10, 21)));
646
else
647
FAIL_IF(push_inst(compiler, ANDI | S(src) | A(TMP_REG2) | 0x1));
648
649
/* Shift right. */
650
FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(63) | RLDI_MB(1)));
651
652
if (op & SLJIT_32)
653
FAIL_IF(push_inst(compiler, RLDICR | S(TMP_REG1) | A(TMP_REG1) | RLDI_SH(0) | RLDI_ME(53)));
654
655
FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
656
657
FAIL_IF(push_inst(compiler, STD | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
658
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
659
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
660
FAIL_IF(push_inst(compiler, FADD | FD(dst_r) | FA(dst_r) | FB(dst_r)));
661
}
662
663
if (op & SLJIT_32)
664
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
665
666
if (dst & SLJIT_MEM)
667
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
668
return SLJIT_SUCCESS;
669
}
670
671
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
672
sljit_s32 freg, sljit_f64 value)
673
{
674
union {
675
sljit_sw imm;
676
sljit_f64 value;
677
} u;
678
679
CHECK_ERROR();
680
CHECK(check_sljit_emit_fset64(compiler, freg, value));
681
682
u.value = value;
683
684
if (u.imm != 0)
685
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
686
687
FAIL_IF(push_inst(compiler, STD | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
688
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
689
}
690
691
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
692
sljit_s32 freg, sljit_s32 reg)
693
{
694
CHECK_ERROR();
695
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
696
697
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {
698
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STW : STD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
699
return push_inst(compiler, ((op & SLJIT_32) ? LFS : LFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
700
}
701
702
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
703
return push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
704
}
705
706
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
707
{
708
sljit_ins *inst = (sljit_ins*)addr;
709
SLJIT_UNUSED_ARG(executable_offset);
710
711
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
712
inst[0] = (inst[0] & 0xffff0000u) | ((sljit_ins)(new_target >> 48) & 0xffff);
713
inst[1] = (inst[1] & 0xffff0000u) | ((sljit_ins)(new_target >> 32) & 0xffff);
714
inst[3] = (inst[3] & 0xffff0000u) | ((sljit_ins)(new_target >> 16) & 0xffff);
715
inst[4] = (inst[4] & 0xffff0000u) | ((sljit_ins)new_target & 0xffff);
716
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
717
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
718
SLJIT_CACHE_FLUSH(inst, inst + 5);
719
}
720
721