Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.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 32-bit arch dependent functions. */
28
29
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
30
{
31
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
32
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
33
34
if (!(imm & ~0xffff))
35
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
36
37
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
38
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
39
}
40
41
/* Simplified mnemonics: clrlwi. */
42
#define INS_CLEAR_LEFT(dst, src, from) \
43
(RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31))
44
45
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
46
sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
47
{
48
sljit_u32 imm;
49
50
switch (op) {
51
case SLJIT_MOV:
52
case SLJIT_MOV_U32:
53
case SLJIT_MOV_S32:
54
case SLJIT_MOV_P:
55
SLJIT_ASSERT(src1 == TMP_REG1);
56
if (dst != src2)
57
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
58
return SLJIT_SUCCESS;
59
60
case SLJIT_MOV_U8:
61
case SLJIT_MOV_S8:
62
SLJIT_ASSERT(src1 == TMP_REG1);
63
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
64
if (op == SLJIT_MOV_S8)
65
return push_inst(compiler, EXTSB | S(src2) | A(dst));
66
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
67
}
68
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
69
return push_inst(compiler, EXTSB | S(src2) | A(dst));
70
else {
71
SLJIT_ASSERT(dst == src2);
72
}
73
return SLJIT_SUCCESS;
74
75
case SLJIT_MOV_U16:
76
case SLJIT_MOV_S16:
77
SLJIT_ASSERT(src1 == TMP_REG1);
78
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
79
if (op == SLJIT_MOV_S16)
80
return push_inst(compiler, EXTSH | S(src2) | A(dst));
81
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
82
}
83
else {
84
SLJIT_ASSERT(dst == src2);
85
}
86
return SLJIT_SUCCESS;
87
88
case SLJIT_CLZ:
89
SLJIT_ASSERT(src1 == TMP_REG1);
90
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
91
92
case SLJIT_CTZ:
93
SLJIT_ASSERT(src1 == TMP_REG1);
94
FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
95
FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
96
FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst)));
97
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32)));
98
/* The highest bits are set, if dst < 32, zero otherwise. */
99
FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1)));
100
return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
101
102
case SLJIT_ADD:
103
if (flags & ALT_FORM1) {
104
/* Setting XER SO is not enough, CR SO is also needed. */
105
return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
106
}
107
108
if (flags & ALT_FORM2) {
109
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
110
SLJIT_ASSERT(src2 == TMP_REG2);
111
112
if (flags & ALT_FORM3)
113
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
114
115
imm = compiler->imm;
116
117
if (flags & ALT_FORM4) {
118
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
119
src1 = dst;
120
}
121
122
return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
123
}
124
if (flags & ALT_FORM3) {
125
SLJIT_ASSERT(src2 == TMP_REG2);
126
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
127
}
128
SLJIT_ASSERT(!(flags & ALT_FORM4));
129
if (!(flags & ALT_SET_FLAGS))
130
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
131
if (flags & ALT_FORM5)
132
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
133
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
134
135
case SLJIT_ADDC:
136
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
137
138
case SLJIT_SUB:
139
if (flags & ALT_FORM1) {
140
if (flags & ALT_FORM2) {
141
FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
142
if (!(flags & ALT_FORM3))
143
return SLJIT_SUCCESS;
144
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
145
}
146
FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
147
if (!(flags & ALT_FORM3))
148
return SLJIT_SUCCESS;
149
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
150
}
151
152
if (flags & ALT_FORM2) {
153
if (flags & ALT_FORM3) {
154
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
155
if (!(flags & ALT_FORM4))
156
return SLJIT_SUCCESS;
157
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
158
}
159
FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
160
if (!(flags & ALT_FORM4))
161
return SLJIT_SUCCESS;
162
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
163
}
164
165
if (flags & ALT_FORM3) {
166
/* Setting XER SO is not enough, CR SO is also needed. */
167
if (src1 != TMP_ZERO)
168
return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
169
return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
170
}
171
172
if (flags & ALT_FORM4) {
173
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
174
SLJIT_ASSERT(src2 == TMP_REG2);
175
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
176
}
177
178
if (!(flags & ALT_SET_FLAGS)) {
179
SLJIT_ASSERT(src1 != TMP_ZERO);
180
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
181
}
182
183
if (flags & ALT_FORM5)
184
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
185
186
if (src1 != TMP_ZERO)
187
return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
188
return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
189
190
case SLJIT_SUBC:
191
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
192
193
case SLJIT_MUL:
194
if (flags & ALT_FORM1) {
195
SLJIT_ASSERT(src2 == TMP_REG2);
196
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
197
}
198
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
199
200
case SLJIT_AND:
201
if (flags & ALT_FORM1) {
202
SLJIT_ASSERT(src2 == TMP_REG2);
203
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
204
}
205
if (flags & ALT_FORM2) {
206
SLJIT_ASSERT(src2 == TMP_REG2);
207
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
208
}
209
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
210
211
case SLJIT_OR:
212
if (flags & ALT_FORM1) {
213
SLJIT_ASSERT(src2 == TMP_REG2);
214
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
215
}
216
if (flags & ALT_FORM2) {
217
SLJIT_ASSERT(src2 == TMP_REG2);
218
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
219
}
220
if (flags & ALT_FORM3) {
221
SLJIT_ASSERT(src2 == TMP_REG2);
222
imm = compiler->imm;
223
224
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
225
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
226
}
227
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
228
229
case SLJIT_XOR:
230
if (flags & ALT_FORM1) {
231
SLJIT_ASSERT(src2 == TMP_REG2);
232
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
233
}
234
if (flags & ALT_FORM2) {
235
SLJIT_ASSERT(src2 == TMP_REG2);
236
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
237
}
238
if (flags & ALT_FORM3) {
239
SLJIT_ASSERT(src2 == TMP_REG2);
240
imm = compiler->imm;
241
242
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
243
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
244
}
245
if (flags & ALT_FORM4) {
246
SLJIT_ASSERT(src1 == TMP_REG1);
247
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
248
}
249
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
250
251
case SLJIT_SHL:
252
case SLJIT_MSHL:
253
if (flags & ALT_FORM1) {
254
SLJIT_ASSERT(src2 == TMP_REG2);
255
imm = compiler->imm & 0x1f;
256
return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
257
}
258
259
if (op == SLJIT_MSHL) {
260
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
261
src2 = TMP_REG2;
262
}
263
264
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
265
266
case SLJIT_LSHR:
267
case SLJIT_MLSHR:
268
if (flags & ALT_FORM1) {
269
SLJIT_ASSERT(src2 == TMP_REG2);
270
imm = compiler->imm & 0x1f;
271
/* Since imm can be 0, SRWI() cannot be used. */
272
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
273
}
274
275
if (op == SLJIT_MLSHR) {
276
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
277
src2 = TMP_REG2;
278
}
279
280
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
281
282
case SLJIT_ASHR:
283
case SLJIT_MASHR:
284
if (flags & ALT_FORM1) {
285
SLJIT_ASSERT(src2 == TMP_REG2);
286
imm = compiler->imm & 0x1f;
287
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
288
}
289
290
if (op == SLJIT_MASHR) {
291
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
292
src2 = TMP_REG2;
293
}
294
295
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
296
297
case SLJIT_ROTL:
298
case SLJIT_ROTR:
299
if (flags & ALT_FORM1) {
300
SLJIT_ASSERT(src2 == TMP_REG2);
301
imm = compiler->imm;
302
303
if (op == SLJIT_ROTR)
304
imm = (sljit_u32)(-(sljit_s32)imm);
305
306
imm &= 0x1f;
307
return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
308
}
309
310
if (op == SLJIT_ROTR) {
311
FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
312
src2 = TMP_REG2;
313
}
314
315
return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31));
316
}
317
318
SLJIT_UNREACHABLE();
319
return SLJIT_SUCCESS;
320
}
321
322
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
323
{
324
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
325
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
326
}
327
328
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
329
sljit_s32 dst, sljit_sw dstw,
330
sljit_s32 src, sljit_sw srcw)
331
{
332
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
333
sljit_s32 invert_sign = 1;
334
335
if (src == SLJIT_IMM) {
336
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
337
src = TMP_REG1;
338
invert_sign = 0;
339
} else if (!FAST_IS_REG(src)) {
340
FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
341
src = TMP_REG1;
342
}
343
344
/* First, a special double precision floating point value is constructed:
345
(2^53 + (src xor (2^31)))
346
The upper 32 bits of this number is a constant, and the lower 32 bits
347
is simply the value of the source argument. The xor 2^31 operation adds
348
0x80000000 to the source argument, which moves it into the 0 - 0xffffffff
349
range. Finally we substract 2^53 + 2^31 to get the converted value. */
350
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
351
if (invert_sign)
352
FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
353
FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
354
FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
355
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
356
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
357
FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
358
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
359
360
FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
361
362
if (op & SLJIT_32)
363
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
364
365
if (dst & SLJIT_MEM)
366
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
367
return SLJIT_SUCCESS;
368
}
369
370
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
371
sljit_s32 dst, sljit_sw dstw,
372
sljit_s32 src, sljit_sw srcw)
373
{
374
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
375
376
if (src == SLJIT_IMM) {
377
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
378
src = TMP_REG1;
379
} else if (!FAST_IS_REG(src)) {
380
FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
381
src = TMP_REG1;
382
}
383
384
/* First, a special double precision floating point value is constructed:
385
(2^53 + src)
386
The upper 32 bits of this number is a constant, and the lower 32 bits
387
is simply the value of the source argument. Finally we substract 2^53
388
to get the converted value. */
389
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
390
FAIL_IF(push_inst(compiler, STW | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
391
FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
392
393
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
394
FAIL_IF(push_inst(compiler, STW | S(TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
395
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
396
397
FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
398
399
if (op & SLJIT_32)
400
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
401
402
if (dst & SLJIT_MEM)
403
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
404
return SLJIT_SUCCESS;
405
}
406
407
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
408
sljit_s32 freg, sljit_f64 value)
409
{
410
union {
411
sljit_s32 imm[2];
412
sljit_f64 value;
413
} u;
414
415
CHECK_ERROR();
416
CHECK(check_sljit_emit_fset64(compiler, freg, value));
417
418
u.value = value;
419
420
if (u.imm[0] != 0)
421
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
422
if (u.imm[1] != 0)
423
FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
424
425
/* Saved in the same endianness. */
426
FAIL_IF(push_inst(compiler, STW | S(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
427
FAIL_IF(push_inst(compiler, STW | S(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | A(SLJIT_SP) | (TMP_MEM_OFFSET + sizeof(sljit_s32))));
428
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
429
}
430
431
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
432
sljit_s32 freg, sljit_s32 reg)
433
{
434
sljit_s32 reg2 = 0;
435
436
CHECK_ERROR();
437
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
438
439
if (op & SLJIT_32) {
440
if (op == SLJIT_COPY32_TO_F32) {
441
FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
442
return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
443
}
444
445
FAIL_IF(push_inst(compiler, STFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
446
return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
447
}
448
449
if (reg & REG_PAIR_MASK) {
450
reg2 = REG_PAIR_SECOND(reg);
451
reg = REG_PAIR_FIRST(reg);
452
}
453
454
if (op == SLJIT_COPY_TO_F64) {
455
FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
456
457
if (reg2 != 0)
458
FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
459
else
460
FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
461
462
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
463
}
464
465
FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
466
467
if (reg2 != 0)
468
FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
469
470
return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI);
471
}
472
473
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
474
{
475
sljit_ins *inst = (sljit_ins *)addr;
476
SLJIT_UNUSED_ARG(executable_offset);
477
478
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
479
SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
480
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
481
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
482
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
483
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
484
SLJIT_CACHE_FLUSH(inst, inst + 2);
485
}
486
487