1 /*
2 * Stack-less Just-In-Time compiler
3 *
4 * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 * of conditions and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
sljit_get_platform_name(void)27 SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
28 {
29 return "PowerPC" SLJIT_CPUINFO;
30 }
31
32 /* Length of an instruction word.
33 Both for ppc-32 and ppc-64. */
34 typedef sljit_u32 sljit_ins;
35
36 #if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \
37 || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
38 #define SLJIT_PPC_STACK_FRAME_V2 1
39 #endif
40
41 #ifdef _AIX
42 #include <sys/cache.h>
43 #endif
44
45 #if (defined _CALL_ELF && _CALL_ELF == 2)
46 #define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
47 #endif
48
49 #if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
50
ppc_cache_flush(sljit_ins * from,sljit_ins * to)51 static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
52 {
53 #ifdef _AIX
54 _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));
55 #elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
56 # if defined(_ARCH_PWR) || defined(_ARCH_PWR2)
57 /* Cache flush for POWER architecture. */
58 while (from < to) {
59 __asm__ volatile (
60 "clf 0, %0\n"
61 "dcs\n"
62 : : "r"(from)
63 );
64 from++;
65 }
66 __asm__ volatile ( "ics" );
67 # elif defined(_ARCH_COM) && !defined(_ARCH_PPC)
68 # error "Cache flush is not implemented for PowerPC/POWER common mode."
69 # else
70 /* Cache flush for PowerPC architecture. */
71 while (from < to) {
72 __asm__ volatile (
73 "dcbf 0, %0\n"
74 "sync\n"
75 "icbi 0, %0\n"
76 : : "r"(from)
77 );
78 from++;
79 }
80 __asm__ volatile ( "isync" );
81 # endif
82 # ifdef __xlc__
83 # warning "This file may fail to compile if -qfuncsect is used"
84 # endif
85 #elif defined(__xlc__)
86 #error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"
87 #else
88 #error "This platform requires a cache flush implementation."
89 #endif /* _AIX */
90 }
91
92 #endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
93
94 #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
95 #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
96 #define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)
97
98 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
99 #define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5)
100 #else
101 #define TMP_CALL_REG TMP_REG1
102 #endif
103
104 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
105 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
106
107 static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
108 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12
109 };
110
111 static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
112 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13
113 };
114
115 /* --------------------------------------------------------------------- */
116 /* Instrucion forms */
117 /* --------------------------------------------------------------------- */
118 #define D(d) ((sljit_ins)reg_map[d] << 21)
119 #define S(s) ((sljit_ins)reg_map[s] << 21)
120 #define A(a) ((sljit_ins)reg_map[a] << 16)
121 #define B(b) ((sljit_ins)reg_map[b] << 11)
122 #define C(c) ((sljit_ins)reg_map[c] << 6)
123 #define FD(fd) ((sljit_ins)freg_map[fd] << 21)
124 #define FS(fs) ((sljit_ins)freg_map[fs] << 21)
125 #define FA(fa) ((sljit_ins)freg_map[fa] << 16)
126 #define FB(fb) ((sljit_ins)freg_map[fb] << 11)
127 #define FC(fc) ((sljit_ins)freg_map[fc] << 6)
128 #define IMM(imm) ((sljit_ins)(imm) & 0xffff)
129 #define CRD(d) ((sljit_ins)(d) << 21)
130
131 /* Instruction bit sections.
132 OE and Rc flag (see ALT_SET_FLAGS). */
133 #define OE(flags) ((flags) & ALT_SET_FLAGS)
134 /* Rc flag (see ALT_SET_FLAGS). */
135 #define RC(flags) ((sljit_ins)((flags) & ALT_SET_FLAGS) >> 10)
136 #define HI(opcode) ((sljit_ins)(opcode) << 26)
137 #define LO(opcode) ((sljit_ins)(opcode) << 1)
138
139 #define ADD (HI(31) | LO(266))
140 #define ADDC (HI(31) | LO(10))
141 #define ADDE (HI(31) | LO(138))
142 #define ADDI (HI(14))
143 #define ADDIC (HI(13))
144 #define ADDIS (HI(15))
145 #define ADDME (HI(31) | LO(234))
146 #define AND (HI(31) | LO(28))
147 #define ANDI (HI(28))
148 #define ANDIS (HI(29))
149 #define Bx (HI(18))
150 #define BCx (HI(16))
151 #define BCCTR (HI(19) | LO(528) | (3 << 11))
152 #define BLR (HI(19) | LO(16) | (0x14 << 21))
153 #if defined(_ARCH_PWR10) && _ARCH_PWR10
154 #define BRD (HI(31) | LO(187))
155 #endif /* POWER10 */
156 #define CNTLZD (HI(31) | LO(58))
157 #define CNTLZW (HI(31) | LO(26))
158 #define CMP (HI(31) | LO(0))
159 #define CMPI (HI(11))
160 #define CMPL (HI(31) | LO(32))
161 #define CMPLI (HI(10))
162 #define CROR (HI(19) | LO(449))
163 #define DCBT (HI(31) | LO(278))
164 #define DIVD (HI(31) | LO(489))
165 #define DIVDU (HI(31) | LO(457))
166 #define DIVW (HI(31) | LO(491))
167 #define DIVWU (HI(31) | LO(459))
168 #define EXTSB (HI(31) | LO(954))
169 #define EXTSH (HI(31) | LO(922))
170 #define EXTSW (HI(31) | LO(986))
171 #define FABS (HI(63) | LO(264))
172 #define FADD (HI(63) | LO(21))
173 #define FADDS (HI(59) | LO(21))
174 #define FCFID (HI(63) | LO(846))
175 #define FCMPU (HI(63) | LO(0))
176 #define FCTIDZ (HI(63) | LO(815))
177 #define FCTIWZ (HI(63) | LO(15))
178 #define FDIV (HI(63) | LO(18))
179 #define FDIVS (HI(59) | LO(18))
180 #define FMR (HI(63) | LO(72))
181 #define FMUL (HI(63) | LO(25))
182 #define FMULS (HI(59) | LO(25))
183 #define FNEG (HI(63) | LO(40))
184 #define FRSP (HI(63) | LO(12))
185 #define FSUB (HI(63) | LO(20))
186 #define FSUBS (HI(59) | LO(20))
187 #define LD (HI(58) | 0)
188 #define LFD (HI(50))
189 #define LFS (HI(48))
190 #if defined(_ARCH_PWR7) && _ARCH_PWR7
191 #define LDBRX (HI(31) | LO(532))
192 #endif /* POWER7 */
193 #define LHBRX (HI(31) | LO(790))
194 #define LWBRX (HI(31) | LO(534))
195 #define LWZ (HI(32))
196 #define MFCR (HI(31) | LO(19))
197 #define MFLR (HI(31) | LO(339) | 0x80000)
198 #define MFXER (HI(31) | LO(339) | 0x10000)
199 #define MTCTR (HI(31) | LO(467) | 0x90000)
200 #define MTLR (HI(31) | LO(467) | 0x80000)
201 #define MTXER (HI(31) | LO(467) | 0x10000)
202 #define MULHD (HI(31) | LO(73))
203 #define MULHDU (HI(31) | LO(9))
204 #define MULHW (HI(31) | LO(75))
205 #define MULHWU (HI(31) | LO(11))
206 #define MULLD (HI(31) | LO(233))
207 #define MULLI (HI(7))
208 #define MULLW (HI(31) | LO(235))
209 #define NEG (HI(31) | LO(104))
210 #define NOP (HI(24))
211 #define NOR (HI(31) | LO(124))
212 #define OR (HI(31) | LO(444))
213 #define ORI (HI(24))
214 #define ORIS (HI(25))
215 #define RLDCL (HI(30) | LO(8))
216 #define RLDICL (HI(30) | LO(0 << 1))
217 #define RLDICR (HI(30) | LO(1 << 1))
218 #define RLDIMI (HI(30) | LO(3 << 1))
219 #define RLWIMI (HI(20))
220 #define RLWINM (HI(21))
221 #define RLWNM (HI(23))
222 #define SLD (HI(31) | LO(27))
223 #define SLW (HI(31) | LO(24))
224 #define SRAD (HI(31) | LO(794))
225 #define SRADI (HI(31) | LO(413 << 1))
226 #define SRAW (HI(31) | LO(792))
227 #define SRAWI (HI(31) | LO(824))
228 #define SRD (HI(31) | LO(539))
229 #define SRW (HI(31) | LO(536))
230 #define STD (HI(62) | 0)
231 #if defined(_ARCH_PWR7) && _ARCH_PWR7
232 #define STDBRX (HI(31) | LO(660))
233 #endif /* POWER7 */
234 #define STDU (HI(62) | 1)
235 #define STDUX (HI(31) | LO(181))
236 #define STFD (HI(54))
237 #define STFIWX (HI(31) | LO(983))
238 #define STFS (HI(52))
239 #define STHBRX (HI(31) | LO(918))
240 #define STW (HI(36))
241 #define STWBRX (HI(31) | LO(662))
242 #define STWU (HI(37))
243 #define STWUX (HI(31) | LO(183))
244 #define SUBF (HI(31) | LO(40))
245 #define SUBFC (HI(31) | LO(8))
246 #define SUBFE (HI(31) | LO(136))
247 #define SUBFIC (HI(8))
248 #define XOR (HI(31) | LO(316))
249 #define XORI (HI(26))
250 #define XORIS (HI(27))
251
252 #define SIMM_MAX (0x7fff)
253 #define SIMM_MIN (-0x8000)
254 #define UIMM_MAX (0xffff)
255
256 /* Shift helpers. */
257 #define RLWI_SH(sh) ((sljit_ins)(sh) << 11)
258 #define RLWI_MBE(mb, me) (((sljit_ins)(mb) << 6) | ((sljit_ins)(me) << 1))
259 #define RLDI_SH(sh) ((((sljit_ins)(sh) & 0x1f) << 11) | (((sljit_ins)(sh) & 0x20) >> 4))
260 #define RLDI_MB(mb) ((((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))
261 #define RLDI_ME(me) RLDI_MB(me)
262
263 #define SLWI(shift) (RLWINM | RLWI_SH(shift) | RLWI_MBE(0, 31 - (shift)))
264 #define SLDI(shift) (RLDICR | RLDI_SH(shift) | RLDI_ME(63 - (shift)))
265 /* shift > 0 */
266 #define SRWI(shift) (RLWINM | RLWI_SH(32 - (shift)) | RLWI_MBE((shift), 31))
267 #define SRDI(shift) (RLDICL | RLDI_SH(64 - (shift)) | RLDI_MB(shift))
268
269 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
270 #define SLWI_W(shift) SLWI(shift)
271 #define TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
272 #else /* !SLJIT_CONFIG_PPC_32 */
273 #define SLWI_W(shift) SLDI(shift)
274 #define TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
275 #endif /* SLJIT_CONFIG_PPC_32 */
276
277 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
278 #define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET)
279 #define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32))
280 #define LWBRX_FIRST_REG S(TMP_REG1)
281 #define LWBRX_SECOND_REG S(dst)
282 #else /* !SLJIT_LITTLE_ENDIAN */
283 #define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET + sizeof(sljit_s32))
284 #define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET)
285 #define LWBRX_FIRST_REG S(dst)
286 #define LWBRX_SECOND_REG S(TMP_REG1)
287 #endif /* SLJIT_LITTLE_ENDIAN */
288
289 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
sljit_set_function_context(void ** func_ptr,struct sljit_function_context * context,sljit_uw addr,void * func)290 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func)
291 {
292 sljit_uw* ptrs;
293
294 if (func_ptr)
295 *func_ptr = (void*)context;
296
297 ptrs = (sljit_uw*)func;
298 context->addr = addr ? addr : ptrs[0];
299 context->r2 = ptrs[1];
300 context->r11 = ptrs[2];
301 }
302 #endif
303
push_inst(struct sljit_compiler * compiler,sljit_ins ins)304 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
305 {
306 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
307 FAIL_IF(!ptr);
308 *ptr = ins;
309 compiler->size++;
310 return SLJIT_SUCCESS;
311 }
312
detect_jump_type(struct sljit_jump * jump,sljit_ins * code_ptr,sljit_ins * code,sljit_sw executable_offset)313 static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
314 {
315 sljit_sw diff;
316 sljit_uw target_addr;
317
318 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
319 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
320 goto exit;
321 #else
322 if (jump->flags & SLJIT_REWRITABLE_JUMP)
323 goto exit;
324 #endif
325
326 if (jump->flags & JUMP_ADDR)
327 target_addr = jump->u.target;
328 else {
329 SLJIT_ASSERT(jump->u.label != NULL);
330 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
331 }
332
333 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
334 if (jump->flags & IS_CALL)
335 goto keep_address;
336 #endif
337
338 diff = (sljit_sw)target_addr - (sljit_sw)code_ptr - executable_offset;
339
340 if (jump->flags & IS_COND) {
341 if (diff <= 0x7fff && diff >= -0x8000) {
342 jump->flags |= PATCH_B;
343 return code_ptr;
344 }
345 if (target_addr <= 0xffff) {
346 jump->flags |= PATCH_B | PATCH_ABS_B;
347 return code_ptr;
348 }
349
350 diff -= SSIZE_OF(ins);
351 }
352
353 if (diff <= 0x01ffffff && diff >= -0x02000000) {
354 jump->flags |= PATCH_B;
355 } else if (target_addr <= 0x01ffffff) {
356 jump->flags |= PATCH_B | PATCH_ABS_B;
357 }
358
359 if (jump->flags & PATCH_B) {
360 if (!(jump->flags & IS_COND))
361 return code_ptr;
362
363 code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
364 code_ptr[1] = Bx;
365 jump->addr += sizeof(sljit_ins);
366 jump->flags -= IS_COND;
367 return code_ptr + 1;
368 }
369
370 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
371 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
372 keep_address:
373 #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
374 if (target_addr < 0x80000000l) {
375 jump->flags |= PATCH_ABS32;
376 code_ptr[2] = MTCTR | S(TMP_CALL_REG);
377 code_ptr[3] = code_ptr[0];
378 return code_ptr + 3;
379 }
380
381 if (target_addr < 0x800000000000l) {
382 jump->flags |= PATCH_ABS48;
383 code_ptr[4] = MTCTR | S(TMP_CALL_REG);
384 code_ptr[5] = code_ptr[0];
385 return code_ptr + 5;
386 }
387 #endif /* SLJIT_CONFIG_PPC_64 */
388
389 exit:
390 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
391 code_ptr[2] = MTCTR | S(TMP_CALL_REG);
392 code_ptr[3] = code_ptr[0];
393 #else /* !SLJIT_CONFIG_PPC_32 */
394 code_ptr[5] = MTCTR | S(TMP_CALL_REG);
395 code_ptr[6] = code_ptr[0];
396 #endif /* SLJIT_CONFIG_PPC_32 */
397 return code_ptr + JUMP_MAX_SIZE - 1;
398 }
399
400 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
401
mov_addr_get_length(struct sljit_jump * jump,sljit_ins * code,sljit_sw executable_offset)402 static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
403 {
404 sljit_uw addr;
405 SLJIT_UNUSED_ARG(executable_offset);
406
407 SLJIT_ASSERT(jump->flags < ((sljit_uw)5 << JUMP_SIZE_SHIFT));
408 if (jump->flags & JUMP_ADDR)
409 addr = jump->u.target;
410 else
411 addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
412
413 if (addr < 0x80000000l) {
414 SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
415 jump->flags |= PATCH_ABS32;
416 return 1;
417 }
418
419 if (addr < 0x800000000000l) {
420 SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
421 jump->flags |= PATCH_ABS48;
422 return 3;
423 }
424
425 SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));
426 return 4;
427 }
428
429 #endif /* SLJIT_CONFIG_PPC_64 */
430
generate_jump_or_mov_addr(struct sljit_jump * jump,sljit_sw executable_offset)431 static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)
432 {
433 sljit_uw flags = jump->flags;
434 sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
435 sljit_ins *ins = (sljit_ins*)jump->addr;
436 sljit_s32 reg;
437 SLJIT_UNUSED_ARG(executable_offset);
438
439 if (flags & PATCH_B) {
440 if (flags & IS_COND) {
441 if (!(flags & PATCH_ABS_B)) {
442 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
443 SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
444 ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | (ins[0] & 0x03ff0001);
445 } else {
446 SLJIT_ASSERT(addr <= 0xffff);
447 ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*ins) & 0x03ff0001);
448 }
449 return;
450 }
451
452 if (!(flags & PATCH_ABS_B)) {
453 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
454 SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
455 ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | (ins[0] & 0x1);
456 } else {
457 SLJIT_ASSERT(addr <= 0x03ffffff);
458 ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | (ins[0] & 0x1);
459 }
460 return;
461 }
462
463 reg = (flags & JUMP_MOV_ADDR) ? (sljit_s32)ins[0] : TMP_CALL_REG;
464
465 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
466 ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);
467 ins[1] = ORI | S(reg) | A(reg) | IMM(addr);
468 #else /* !SLJIT_CONFIG_PPC_32 */
469
470 /* The TMP_ZERO cannot be used because it is restored for tail calls. */
471 if (flags & PATCH_ABS32) {
472 SLJIT_ASSERT(addr < 0x80000000l);
473 ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);
474 ins[1] = ORI | S(reg) | A(reg) | IMM(addr);
475 return;
476 }
477
478 if (flags & PATCH_ABS48) {
479 SLJIT_ASSERT(addr < 0x800000000000l);
480 ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 32);
481 ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 16);
482 ins[2] = SLDI(16) | S(reg) | A(reg);
483 ins[3] = ORI | S(reg) | A(reg) | IMM(addr);
484 return;
485 }
486
487 ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 48);
488 ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 32);
489 ins[2] = SLDI(32) | S(reg) | A(reg);
490 ins[3] = ORIS | S(reg) | A(reg) | IMM(addr >> 16);
491 ins[4] = ORI | S(reg) | A(reg) | IMM(addr);
492 #endif /* SLJIT_CONFIG_PPC_32 */
493 }
494
reduce_code_size(struct sljit_compiler * compiler)495 static void reduce_code_size(struct sljit_compiler *compiler)
496 {
497 struct sljit_label *label;
498 struct sljit_jump *jump;
499 struct sljit_const *const_;
500 SLJIT_NEXT_DEFINE_TYPES;
501 sljit_uw total_size;
502 sljit_uw size_reduce = 0;
503 sljit_sw diff;
504
505 label = compiler->labels;
506 jump = compiler->jumps;
507 const_ = compiler->consts;
508 SLJIT_NEXT_INIT_TYPES();
509
510 while (1) {
511 SLJIT_GET_NEXT_MIN();
512
513 if (next_min_addr == SLJIT_MAX_ADDRESS)
514 break;
515
516 if (next_min_addr == next_label_size) {
517 label->size -= size_reduce;
518
519 label = label->next;
520 next_label_size = SLJIT_GET_NEXT_SIZE(label);
521 }
522
523 if (next_min_addr == next_const_addr) {
524 const_->addr -= size_reduce;
525 const_ = const_->next;
526 next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
527 continue;
528 }
529
530 if (next_min_addr != next_jump_addr)
531 continue;
532
533 jump->addr -= size_reduce;
534 if (!(jump->flags & JUMP_MOV_ADDR)) {
535 total_size = JUMP_MAX_SIZE - 1;
536
537 if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
538 if (jump->flags & JUMP_ADDR) {
539 if (jump->u.target <= 0x01ffffff)
540 total_size = 1 - 1;
541 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
542 else if (jump->u.target < 0x80000000l)
543 total_size = 4 - 1;
544 else if (jump->u.target < 0x800000000000l)
545 total_size = 6 - 1;
546 #endif /* SLJIT_CONFIG_PPC_64 */
547 } else {
548 /* Unit size: instruction. */
549 diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
550
551 if (jump->flags & IS_COND) {
552 if (diff <= (0x7fff / SSIZE_OF(ins)) && diff >= (-0x8000 / SSIZE_OF(ins)))
553 total_size = 1 - 1;
554 else if ((diff - 1) <= (0x01ffffff / SSIZE_OF(ins)) && (diff - 1) >= (-0x02000000 / SSIZE_OF(ins)))
555 total_size = 2 - 1;
556 } else if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))
557 total_size = 1 - 1;
558 }
559 }
560
561 size_reduce += (JUMP_MAX_SIZE - 1) - total_size;
562 jump->flags |= total_size << JUMP_SIZE_SHIFT;
563 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
564 } else {
565 total_size = (sljit_uw)4 << JUMP_SIZE_SHIFT;
566
567 if (jump->flags & JUMP_ADDR) {
568 if (jump->u.target < 0x80000000l) {
569 total_size = (sljit_uw)1 << JUMP_SIZE_SHIFT;
570 size_reduce += 3;
571 } else if (jump->u.target < 0x800000000000l) {
572 total_size = (sljit_uw)3 << JUMP_SIZE_SHIFT;
573 size_reduce += 1;
574 }
575 }
576 jump->flags |= total_size;
577 #endif /* SLJIT_CONFIG_PPC_64 */
578 }
579
580 jump = jump->next;
581 next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
582 }
583
584 compiler->size -= size_reduce;
585 }
586
sljit_generate_code(struct sljit_compiler * compiler,sljit_s32 options,void * exec_allocator_data)587 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
588 {
589 struct sljit_memory_fragment *buf;
590 sljit_ins *code;
591 sljit_ins *code_ptr;
592 sljit_ins *buf_ptr;
593 sljit_ins *buf_end;
594 sljit_uw word_count;
595 SLJIT_NEXT_DEFINE_TYPES;
596 sljit_sw executable_offset;
597
598 struct sljit_label *label;
599 struct sljit_jump *jump;
600 struct sljit_const *const_;
601
602 CHECK_ERROR_PTR();
603 CHECK_PTR(check_sljit_generate_code(compiler));
604
605 reduce_code_size(compiler);
606
607 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
608 /* add to compiler->size additional instruction space to hold the trampoline and padding */
609 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
610 compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
611 #else
612 compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
613 #endif
614 #endif
615 code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
616 PTR_FAIL_WITH_EXEC_IF(code);
617
618 reverse_buf(compiler);
619 buf = compiler->buf;
620
621 code_ptr = code;
622 word_count = 0;
623 label = compiler->labels;
624 jump = compiler->jumps;
625 const_ = compiler->consts;
626 SLJIT_NEXT_INIT_TYPES();
627 SLJIT_GET_NEXT_MIN();
628
629 do {
630 buf_ptr = (sljit_ins*)buf->memory;
631 buf_end = buf_ptr + (buf->used_size >> 2);
632 do {
633 *code_ptr = *buf_ptr++;
634 if (next_min_addr == word_count) {
635 SLJIT_ASSERT(!label || label->size >= word_count);
636 SLJIT_ASSERT(!jump || jump->addr >= word_count);
637 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
638
639 /* These structures are ordered by their address. */
640 if (next_min_addr == next_label_size) {
641 /* Just recording the address. */
642 label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
643 label->size = (sljit_uw)(code_ptr - code);
644 label = label->next;
645 next_label_size = SLJIT_GET_NEXT_SIZE(label);
646 }
647
648 if (next_min_addr == next_jump_addr) {
649 if (!(jump->flags & JUMP_MOV_ADDR)) {
650 word_count += jump->flags >> JUMP_SIZE_SHIFT;
651 jump->addr = (sljit_uw)code_ptr;
652 code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
653 SLJIT_ASSERT(((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
654 } else {
655 jump->addr = (sljit_uw)code_ptr;
656 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
657 word_count += jump->flags >> JUMP_SIZE_SHIFT;
658 code_ptr += mov_addr_get_length(jump, code, executable_offset);
659 #else /* !SLJIT_CONFIG_PPC_64 */
660 word_count++;
661 code_ptr++;
662 #endif /* SLJIT_CONFIG_PPC_64 */
663 }
664 jump = jump->next;
665 next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
666 } else if (next_min_addr == next_const_addr) {
667 const_->addr = (sljit_uw)code_ptr;
668 const_ = const_->next;
669 next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
670 }
671
672 SLJIT_GET_NEXT_MIN();
673 }
674 code_ptr++;
675 word_count++;
676 } while (buf_ptr < buf_end);
677
678 buf = buf->next;
679 } while (buf);
680
681 if (label && label->size == word_count) {
682 label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
683 label->size = (sljit_uw)(code_ptr - code);
684 label = label->next;
685 }
686
687 SLJIT_ASSERT(!label);
688 SLJIT_ASSERT(!jump);
689 SLJIT_ASSERT(!const_);
690
691 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
692 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));
693 #else
694 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
695 #endif
696
697 jump = compiler->jumps;
698 while (jump) {
699 generate_jump_or_mov_addr(jump, executable_offset);
700 jump = jump->next;
701 }
702
703 compiler->error = SLJIT_ERR_COMPILED;
704 compiler->executable_offset = executable_offset;
705
706 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
707
708 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
709 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
710 if (((sljit_sw)code_ptr) & 0x4)
711 code_ptr++;
712 #endif
713 sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);
714 #endif
715
716 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
717
718 SLJIT_CACHE_FLUSH(code, code_ptr);
719 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
720
721 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
722 compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);
723 return code_ptr;
724 #else
725 compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
726 return code;
727 #endif
728 }
729
sljit_has_cpu_feature(sljit_s32 feature_type)730 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
731 {
732 switch (feature_type) {
733 case SLJIT_HAS_FPU:
734 #ifdef SLJIT_IS_FPU_AVAILABLE
735 return (SLJIT_IS_FPU_AVAILABLE) != 0;
736 #else
737 /* Available by default. */
738 return 1;
739 #endif
740 case SLJIT_HAS_REV:
741 #if defined(_ARCH_PWR10) && _ARCH_PWR10
742 return 1;
743 #else /* !POWER10 */
744 return 2;
745 #endif /* POWER10 */
746 /* A saved register is set to a zero value. */
747 case SLJIT_HAS_ZERO_REGISTER:
748 case SLJIT_HAS_CLZ:
749 case SLJIT_HAS_ROT:
750 case SLJIT_HAS_PREFETCH:
751 return 1;
752
753 case SLJIT_HAS_CTZ:
754 return 2;
755
756 default:
757 return 0;
758 }
759 }
760
sljit_cmp_info(sljit_s32 type)761 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
762 {
763 switch (type) {
764 case SLJIT_UNORDERED_OR_EQUAL:
765 case SLJIT_ORDERED_NOT_EQUAL:
766 case SLJIT_UNORDERED_OR_LESS:
767 case SLJIT_ORDERED_GREATER_EQUAL:
768 case SLJIT_UNORDERED_OR_GREATER:
769 case SLJIT_ORDERED_LESS_EQUAL:
770 return 1;
771 }
772
773 return 0;
774 }
775
776 /* --------------------------------------------------------------------- */
777 /* Entry, exit */
778 /* --------------------------------------------------------------------- */
779
780 /* inp_flags: */
781
782 /* Creates an index in data_transfer_insts array. */
783 #define LOAD_DATA 0x01
784 #define INDEXED 0x02
785 #define SIGNED_DATA 0x04
786
787 #define WORD_DATA 0x00
788 #define BYTE_DATA 0x08
789 #define HALF_DATA 0x10
790 #define INT_DATA 0x18
791 /* Separates integer and floating point registers */
792 #define GPR_REG 0x1f
793 #define DOUBLE_DATA 0x20
794
795 #define MEM_MASK 0x7f
796
797 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))
798
799 /* Other inp_flags. */
800
801 /* Integer opertion and set flags -> requires exts on 64 bit systems. */
802 #define ALT_SIGN_EXT 0x000100
803 /* This flag affects the RC() and OERC() macros. */
804 #define ALT_SET_FLAGS 0x000400
805 #define ALT_FORM1 0x001000
806 #define ALT_FORM2 0x002000
807 #define ALT_FORM3 0x004000
808 #define ALT_FORM4 0x008000
809 #define ALT_FORM5 0x010000
810
811 /* Source and destination is register. */
812 #define REG_DEST 0x000001
813 #define REG1_SOURCE 0x000002
814 #define REG2_SOURCE 0x000004
815 /*
816 ALT_SIGN_EXT 0x000100
817 ALT_SET_FLAGS 0x000200
818 ALT_FORM1 0x001000
819 ...
820 ALT_FORM5 0x010000 */
821
822 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
823 sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg);
824
825 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
826 #include "sljitNativePPC_32.c"
827 #else
828 #include "sljitNativePPC_64.c"
829 #endif
830
831 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
832 #define STACK_STORE STW
833 #define STACK_LOAD LWZ
834 #else
835 #define STACK_STORE STD
836 #define STACK_LOAD LD
837 #endif
838
839 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
840 #define LR_SAVE_OFFSET (2 * SSIZE_OF(sw))
841 #else
842 #define LR_SAVE_OFFSET SSIZE_OF(sw)
843 #endif
844
845 #define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)
846
sljit_emit_enter(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)847 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
848 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
849 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
850 {
851 sljit_s32 i, tmp, base, offset;
852 sljit_s32 word_arg_count = 0;
853 sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
854 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
855 sljit_s32 arg_count = 0;
856 #endif
857
858 CHECK_ERROR();
859 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
860 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
861
862 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)
863 + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
864
865 if (!(options & SLJIT_ENTER_REG_ARG))
866 local_size += SSIZE_OF(sw);
867
868 local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
869 compiler->local_size = local_size;
870
871 FAIL_IF(push_inst(compiler, MFLR | D(0)));
872
873 base = SLJIT_SP;
874 offset = local_size;
875
876 if (local_size <= STACK_MAX_DISTANCE) {
877 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
878 FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
879 #else
880 FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
881 #endif
882 } else {
883 base = TMP_REG1;
884 FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));
885 FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));
886 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
887 FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
888 #else
889 FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
890 #endif
891 local_size = 0;
892 offset = 0;
893 }
894
895 tmp = SLJIT_FS0 - fsaveds;
896 for (i = SLJIT_FS0; i > tmp; i--) {
897 offset -= SSIZE_OF(f64);
898 FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
899 }
900
901 for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
902 offset -= SSIZE_OF(f64);
903 FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
904 }
905
906 if (!(options & SLJIT_ENTER_REG_ARG)) {
907 offset -= SSIZE_OF(sw);
908 FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
909 }
910
911 tmp = SLJIT_S0 - saveds;
912 for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
913 offset -= SSIZE_OF(sw);
914 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
915 }
916
917 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
918 offset -= SSIZE_OF(sw);
919 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
920 }
921
922 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
923
924 if (options & SLJIT_ENTER_REG_ARG)
925 return SLJIT_SUCCESS;
926
927 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
928
929 arg_types >>= SLJIT_ARG_SHIFT;
930 saved_arg_count = 0;
931
932 while (arg_types > 0) {
933 if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
934 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
935 do {
936 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
937 tmp = SLJIT_S0 - saved_arg_count;
938 saved_arg_count++;
939 } else if (arg_count != word_arg_count)
940 tmp = SLJIT_R0 + word_arg_count;
941 else
942 break;
943
944 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));
945 } while (0);
946 #else
947 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
948 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));
949 saved_arg_count++;
950 }
951 #endif
952 word_arg_count++;
953 }
954
955 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
956 arg_count++;
957 #endif
958 arg_types >>= SLJIT_ARG_SHIFT;
959 }
960
961 return SLJIT_SUCCESS;
962 }
963
sljit_set_context(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)964 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
965 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
966 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
967 {
968 CHECK_ERROR();
969 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
970 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
971
972 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)
973 + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
974
975 if (!(options & SLJIT_ENTER_REG_ARG))
976 local_size += SSIZE_OF(sw);
977
978 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
979 return SLJIT_SUCCESS;
980 }
981
emit_stack_frame_release(struct sljit_compiler * compiler,sljit_s32 is_return_to)982 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
983 {
984 sljit_s32 i, tmp, base, offset;
985 sljit_s32 local_size = compiler->local_size;
986
987 SLJIT_ASSERT(TMP_CALL_REG != TMP_REG2);
988
989 base = SLJIT_SP;
990 if (local_size > STACK_MAX_DISTANCE) {
991 base = TMP_REG2;
992 if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {
993 FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));
994 local_size = 0;
995 } else {
996 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));
997 local_size = STACK_MAX_DISTANCE;
998 }
999 }
1000
1001 offset = local_size;
1002 if (!is_return_to)
1003 FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));
1004
1005 tmp = SLJIT_FS0 - compiler->fsaveds;
1006 for (i = SLJIT_FS0; i > tmp; i--) {
1007 offset -= SSIZE_OF(f64);
1008 FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
1009 }
1010
1011 for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
1012 offset -= SSIZE_OF(f64);
1013 FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
1014 }
1015
1016 if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {
1017 offset -= SSIZE_OF(sw);
1018 FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
1019 }
1020
1021 tmp = SLJIT_S0 - compiler->saveds;
1022 for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
1023 offset -= SSIZE_OF(sw);
1024 FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
1025 }
1026
1027 for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
1028 offset -= SSIZE_OF(sw);
1029 FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
1030 }
1031
1032 if (!is_return_to)
1033 push_inst(compiler, MTLR | S(0));
1034
1035 if (local_size > 0)
1036 return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));
1037
1038 SLJIT_ASSERT(base == TMP_REG2);
1039 return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));
1040 }
1041
1042 #undef STACK_STORE
1043 #undef STACK_LOAD
1044
sljit_emit_return_void(struct sljit_compiler * compiler)1045 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
1046 {
1047 CHECK_ERROR();
1048 CHECK(check_sljit_emit_return_void(compiler));
1049
1050 FAIL_IF(emit_stack_frame_release(compiler, 0));
1051 return push_inst(compiler, BLR);
1052 }
1053
sljit_emit_return_to(struct sljit_compiler * compiler,sljit_s32 src,sljit_sw srcw)1054 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
1055 sljit_s32 src, sljit_sw srcw)
1056 {
1057 CHECK_ERROR();
1058 CHECK(check_sljit_emit_return_to(compiler, src, srcw));
1059
1060 if (src & SLJIT_MEM) {
1061 ADJUST_LOCAL_OFFSET(src, srcw);
1062 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
1063 src = TMP_CALL_REG;
1064 srcw = 0;
1065 } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
1066 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
1067 src = TMP_CALL_REG;
1068 srcw = 0;
1069 }
1070
1071 FAIL_IF(emit_stack_frame_release(compiler, 1));
1072
1073 SLJIT_SKIP_CHECKS(compiler);
1074 return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
1075 }
1076
1077 /* --------------------------------------------------------------------- */
1078 /* Operators */
1079 /* --------------------------------------------------------------------- */
1080
1081 /* s/l - store/load (1 bit)
1082 i/x - immediate/indexed form
1083 u/s - signed/unsigned (1 bit)
1084 w/b/h/i - word/byte/half/int allowed (2 bit)
1085
1086 Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
1087
1088 /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
1089 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1090 #define INT_ALIGNED 0x10000
1091 #endif
1092
1093 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1094 #define ARCH_32_64(a, b) a
1095 #define INST_CODE_AND_DST(inst, flags, reg) \
1096 ((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
1097 #else
1098 #define ARCH_32_64(a, b) b
1099 #define INST_CODE_AND_DST(inst, flags, reg) \
1100 (((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
1101 #endif
1102
1103 static const sljit_ins data_transfer_insts[64 + 16] = {
1104
1105 /* -------- Integer -------- */
1106
1107 /* Word. */
1108
1109 /* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
1110 /* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
1111 /* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
1112 /* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
1113
1114 /* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
1115 /* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
1116 /* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
1117 /* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
1118
1119 /* Byte. */
1120
1121 /* b u i s */ HI(38) /* stb */,
1122 /* b u i l */ HI(34) /* lbz */,
1123 /* b u x s */ HI(31) | LO(215) /* stbx */,
1124 /* b u x l */ HI(31) | LO(87) /* lbzx */,
1125
1126 /* b s i s */ HI(38) /* stb */,
1127 /* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,
1128 /* b s x s */ HI(31) | LO(215) /* stbx */,
1129 /* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
1130
1131 /* Half. */
1132
1133 /* h u i s */ HI(44) /* sth */,
1134 /* h u i l */ HI(40) /* lhz */,
1135 /* h u x s */ HI(31) | LO(407) /* sthx */,
1136 /* h u x l */ HI(31) | LO(279) /* lhzx */,
1137
1138 /* h s i s */ HI(44) /* sth */,
1139 /* h s i l */ HI(42) /* lha */,
1140 /* h s x s */ HI(31) | LO(407) /* sthx */,
1141 /* h s x l */ HI(31) | LO(343) /* lhax */,
1142
1143 /* Int. */
1144
1145 /* i u i s */ HI(36) /* stw */,
1146 /* i u i l */ HI(32) /* lwz */,
1147 /* i u x s */ HI(31) | LO(151) /* stwx */,
1148 /* i u x l */ HI(31) | LO(23) /* lwzx */,
1149
1150 /* i s i s */ HI(36) /* stw */,
1151 /* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
1152 /* i s x s */ HI(31) | LO(151) /* stwx */,
1153 /* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
1154
1155 /* -------- Floating point -------- */
1156
1157 /* d i s */ HI(54) /* stfd */,
1158 /* d i l */ HI(50) /* lfd */,
1159 /* d x s */ HI(31) | LO(727) /* stfdx */,
1160 /* d x l */ HI(31) | LO(599) /* lfdx */,
1161
1162 /* s i s */ HI(52) /* stfs */,
1163 /* s i l */ HI(48) /* lfs */,
1164 /* s x s */ HI(31) | LO(663) /* stfsx */,
1165 /* s x l */ HI(31) | LO(535) /* lfsx */,
1166 };
1167
1168 static const sljit_ins updated_data_transfer_insts[64] = {
1169
1170 /* -------- Integer -------- */
1171
1172 /* Word. */
1173
1174 /* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
1175 /* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
1176 /* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
1177 /* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
1178
1179 /* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
1180 /* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
1181 /* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
1182 /* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
1183
1184 /* Byte. */
1185
1186 /* b u i s */ HI(39) /* stbu */,
1187 /* b u i l */ HI(35) /* lbzu */,
1188 /* b u x s */ HI(31) | LO(247) /* stbux */,
1189 /* b u x l */ HI(31) | LO(119) /* lbzux */,
1190
1191 /* b s i s */ HI(39) /* stbu */,
1192 /* b s i l */ 0 /* no such instruction */,
1193 /* b s x s */ HI(31) | LO(247) /* stbux */,
1194 /* b s x l */ 0 /* no such instruction */,
1195
1196 /* Half. */
1197
1198 /* h u i s */ HI(45) /* sthu */,
1199 /* h u i l */ HI(41) /* lhzu */,
1200 /* h u x s */ HI(31) | LO(439) /* sthux */,
1201 /* h u x l */ HI(31) | LO(311) /* lhzux */,
1202
1203 /* h s i s */ HI(45) /* sthu */,
1204 /* h s i l */ HI(43) /* lhau */,
1205 /* h s x s */ HI(31) | LO(439) /* sthux */,
1206 /* h s x l */ HI(31) | LO(375) /* lhaux */,
1207
1208 /* Int. */
1209
1210 /* i u i s */ HI(37) /* stwu */,
1211 /* i u i l */ HI(33) /* lwzu */,
1212 /* i u x s */ HI(31) | LO(183) /* stwux */,
1213 /* i u x l */ HI(31) | LO(55) /* lwzux */,
1214
1215 /* i s i s */ HI(37) /* stwu */,
1216 /* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),
1217 /* i s x s */ HI(31) | LO(183) /* stwux */,
1218 /* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
1219
1220 /* -------- Floating point -------- */
1221
1222 /* d i s */ HI(55) /* stfdu */,
1223 /* d i l */ HI(51) /* lfdu */,
1224 /* d x s */ HI(31) | LO(759) /* stfdux */,
1225 /* d x l */ HI(31) | LO(631) /* lfdux */,
1226
1227 /* s i s */ HI(53) /* stfsu */,
1228 /* s i l */ HI(49) /* lfsu */,
1229 /* s x s */ HI(31) | LO(695) /* stfsux */,
1230 /* s x l */ HI(31) | LO(567) /* lfsux */,
1231 };
1232
1233 #undef ARCH_32_64
1234
1235 /* Simple cases, (no caching is required). */
emit_op_mem(struct sljit_compiler * compiler,sljit_s32 inp_flags,sljit_s32 reg,sljit_s32 arg,sljit_sw argw,sljit_s32 tmp_reg)1236 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
1237 sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
1238 {
1239 sljit_ins inst;
1240 sljit_s32 offs_reg;
1241
1242 /* Should work when (arg & REG_MASK) == 0. */
1243 SLJIT_ASSERT(A(0) == 0);
1244 SLJIT_ASSERT(arg & SLJIT_MEM);
1245
1246 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1247 argw &= 0x3;
1248 offs_reg = OFFS_REG(arg);
1249
1250 if (argw != 0) {
1251 FAIL_IF(push_inst(compiler, SLWI_W(argw) | S(OFFS_REG(arg)) | A(tmp_reg)));
1252 offs_reg = tmp_reg;
1253 }
1254
1255 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1256
1257 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1258 SLJIT_ASSERT(!(inst & INT_ALIGNED));
1259 #endif /* SLJIT_CONFIG_PPC_64 */
1260
1261 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
1262 }
1263
1264 inst = data_transfer_insts[inp_flags & MEM_MASK];
1265 arg &= REG_MASK;
1266
1267 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1268 if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {
1269 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1270
1271 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1272 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1273 }
1274 #endif /* SLJIT_CONFIG_PPC_64 */
1275
1276 if (argw <= SIMM_MAX && argw >= SIMM_MIN)
1277 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));
1278
1279 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1280 if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
1281 #endif /* SLJIT_CONFIG_PPC_64 */
1282 FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM((argw + 0x8000) >> 16)));
1283 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));
1284 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1285 }
1286
1287 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1288
1289 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1290 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1291 #endif /* SLJIT_CONFIG_PPC_64 */
1292 }
1293
emit_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 input_flags,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1294 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
1295 sljit_s32 dst, sljit_sw dstw,
1296 sljit_s32 src1, sljit_sw src1w,
1297 sljit_s32 src2, sljit_sw src2w)
1298 {
1299 /* arg1 goes to TMP_REG1 or src reg
1300 arg2 goes to TMP_REG2, imm or src reg
1301 result goes to TMP_REG2, so put result can use TMP_REG1. */
1302 sljit_s32 dst_r = TMP_REG2;
1303 sljit_s32 src1_r;
1304 sljit_s32 src2_r;
1305 sljit_s32 src2_tmp_reg = (!(input_flags & ALT_SIGN_EXT) && GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
1306 sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
1307
1308 /* Destination check. */
1309 if (FAST_IS_REG(dst)) {
1310 dst_r = dst;
1311 /* The REG_DEST is only used by SLJIT_MOV operations, although
1312 * it is set for op2 operations with unset destination. */
1313 flags |= REG_DEST;
1314
1315 if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1316 src2_tmp_reg = dst_r;
1317 }
1318
1319 /* Source 2. */
1320 if (FAST_IS_REG(src2)) {
1321 src2_r = src2;
1322 flags |= REG2_SOURCE;
1323
1324 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1325 dst_r = src2_r;
1326 } else if (src2 == SLJIT_IMM) {
1327 src2_r = TMP_ZERO;
1328 if (src2w != 0) {
1329 FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));
1330 src2_r = src2_tmp_reg;
1331 }
1332 } else {
1333 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, src2_tmp_reg, src2, src2w, TMP_REG1));
1334 src2_r = src2_tmp_reg;
1335 }
1336
1337 /* Source 1. */
1338 if (FAST_IS_REG(src1)) {
1339 src1_r = src1;
1340 flags |= REG1_SOURCE;
1341 } else if (src1 == SLJIT_IMM) {
1342 src1_r = TMP_ZERO;
1343 if (src1w != 0) {
1344 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1345 src1_r = TMP_REG1;
1346 }
1347 } else {
1348 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
1349 src1_r = TMP_REG1;
1350 }
1351
1352 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1353
1354 if (!(dst & SLJIT_MEM))
1355 return SLJIT_SUCCESS;
1356
1357 return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
1358 }
1359
sljit_emit_op0(struct sljit_compiler * compiler,sljit_s32 op)1360 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1361 {
1362 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1363 sljit_s32 int_op = op & SLJIT_32;
1364 #endif
1365
1366 CHECK_ERROR();
1367 CHECK(check_sljit_emit_op0(compiler, op));
1368
1369 op = GET_OPCODE(op);
1370 switch (op) {
1371 case SLJIT_BREAKPOINT:
1372 case SLJIT_NOP:
1373 return push_inst(compiler, NOP);
1374 case SLJIT_LMUL_UW:
1375 case SLJIT_LMUL_SW:
1376 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1377 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1378 FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1379 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1380 #else
1381 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1382 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1383 #endif
1384 case SLJIT_DIVMOD_UW:
1385 case SLJIT_DIVMOD_SW:
1386 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1387 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1388 FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) : (op == SLJIT_DIVMOD_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1389 FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1390 #else
1391 FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1392 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1393 #endif
1394 return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
1395 case SLJIT_DIV_UW:
1396 case SLJIT_DIV_SW:
1397 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1398 return push_inst(compiler, (int_op ? (op == SLJIT_DIV_UW ? DIVWU : DIVW) : (op == SLJIT_DIV_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1399 #else
1400 return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1401 #endif
1402 case SLJIT_ENDBR:
1403 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1404 return SLJIT_SUCCESS;
1405 }
1406
1407 return SLJIT_SUCCESS;
1408 }
1409
emit_rev(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)1410 static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op,
1411 sljit_s32 dst, sljit_sw dstw,
1412 sljit_s32 src, sljit_sw srcw)
1413 {
1414 sljit_s32 mem, offs_reg, inp_flags;
1415 sljit_sw memw;
1416 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1417 sljit_s32 is_32 = op & SLJIT_32;
1418
1419 op = GET_OPCODE(op);
1420 #endif /* SLJIT_CONFIG_PPC_64 */
1421
1422 if (!((dst | src) & SLJIT_MEM)) {
1423 /* Both are registers. */
1424 if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
1425 if (src == dst) {
1426 FAIL_IF(push_inst(compiler, RLWIMI | S(dst) | A(dst) | RLWI_SH(16) | RLWI_MBE(8, 15)));
1427 FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | RLWI_SH(24) | RLWI_MBE(16, 31)));
1428 } else {
1429 FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(dst) | RLWI_SH(8) | RLWI_MBE(16, 23)));
1430 FAIL_IF(push_inst(compiler, RLWIMI | S(src) | A(dst) | RLWI_SH(24) | RLWI_MBE(24, 31)));
1431 }
1432
1433 if (op == SLJIT_REV_U16)
1434 return SLJIT_SUCCESS;
1435 return push_inst(compiler, EXTSH | S(dst) | A(dst));
1436 }
1437
1438 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1439 if (!is_32) {
1440 #if defined(_ARCH_PWR10) && _ARCH_PWR10
1441 return push_inst(compiler, BRD | S(src) | A(dst));
1442 #else /* !POWER10 */
1443 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_HI)));
1444 FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
1445 FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));
1446 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LO)));
1447 FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(SLJIT_SP) | B(TMP_REG2)));
1448 return push_inst(compiler, LD | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
1449 #endif /* POWER10 */
1450 }
1451 #endif /* SLJIT_CONFIG_PPC_64 */
1452
1453 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET)));
1454 FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));
1455 FAIL_IF(push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET));
1456
1457 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1458 if (op == SLJIT_REV_S32)
1459 return push_inst(compiler, EXTSW | S(dst) | A(dst));
1460 #endif /* SLJIT_CONFIG_PPC_64 */
1461 return SLJIT_SUCCESS;
1462 }
1463
1464 mem = src;
1465 memw = srcw;
1466
1467 if (dst & SLJIT_MEM) {
1468 mem = dst;
1469 memw = dstw;
1470
1471 if (src & SLJIT_MEM) {
1472 inp_flags = HALF_DATA | LOAD_DATA;
1473
1474 if (op != SLJIT_REV_U16 && op != SLJIT_REV_S16) {
1475 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1476 inp_flags = (is_32 ? INT_DATA : WORD_DATA) | LOAD_DATA;
1477 #else /* !SLJIT_CONFIG_PPC_64 */
1478 inp_flags = WORD_DATA | LOAD_DATA;
1479 #endif /* SLJIT_CONFIG_PPC_64 */
1480 }
1481
1482 FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src, srcw, TMP_REG2));
1483 src = TMP_REG1;
1484 }
1485 }
1486
1487 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
1488 offs_reg = OFFS_REG(mem);
1489 mem &= REG_MASK;
1490 memw &= 0x3;
1491
1492 if (memw != 0) {
1493 FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(offs_reg) | A(TMP_REG2)));
1494 offs_reg = TMP_REG2;
1495 }
1496 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1497 } else if (memw > 0x7fff7fffl || memw < -0x80000000l) {
1498 FAIL_IF(load_immediate(compiler, TMP_REG2, memw));
1499 offs_reg = TMP_REG2;
1500 mem &= REG_MASK;
1501 #endif /* SLJIT_CONFIG_PPC_64 */
1502 } else {
1503 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(mem & REG_MASK) | IMM(memw)));
1504 if (memw > SIMM_MAX || memw < SIMM_MIN)
1505 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(TMP_REG2) | IMM((memw + 0x8000) >> 16)));
1506
1507 mem = 0;
1508 offs_reg = TMP_REG2;
1509 }
1510
1511 if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
1512 if (dst & SLJIT_MEM)
1513 return push_inst(compiler, STHBRX | S(src) | A(mem) | B(offs_reg));
1514
1515 FAIL_IF(push_inst(compiler, LHBRX | S(dst) | A(mem) | B(offs_reg)));
1516
1517 if (op == SLJIT_REV_U16)
1518 return SLJIT_SUCCESS;
1519 return push_inst(compiler, EXTSH | S(dst) | A(dst));
1520 }
1521
1522 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1523 if (!is_32) {
1524 if (dst & SLJIT_MEM) {
1525 #if defined(_ARCH_PWR7) && _ARCH_PWR7
1526 return push_inst(compiler, STDBRX | S(src) | A(mem) | B(offs_reg));
1527 #else /* !POWER7 */
1528 #if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
1529 FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
1530 FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(offs_reg)));
1531 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
1532 return push_inst(compiler, STWBRX | S(src) | A(mem) | B(TMP_REG2));
1533 #else /* !SLJIT_LITTLE_ENDIAN */
1534 FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg)));
1535 FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
1536 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
1537 return push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2));
1538 #endif /* SLJIT_LITTLE_ENDIAN */
1539 #endif /* POWER7 */
1540 }
1541 #if defined(_ARCH_PWR7) && _ARCH_PWR7
1542 return push_inst(compiler, LDBRX | S(dst) | A(mem) | B(offs_reg));
1543 #else /* !POWER7 */
1544 FAIL_IF(push_inst(compiler, LWBRX | LWBRX_FIRST_REG | A(mem) | B(offs_reg)));
1545 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
1546 FAIL_IF(push_inst(compiler, LWBRX | LWBRX_SECOND_REG | A(mem) | B(TMP_REG2)));
1547 return push_inst(compiler, RLDIMI | S(TMP_REG1) | A(dst) | RLDI_SH(32) | RLDI_MB(0));
1548 #endif /* POWER7 */
1549 }
1550 #endif /* SLJIT_CONFIG_PPC_64 */
1551
1552 if (dst & SLJIT_MEM)
1553 return push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg));
1554
1555 FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg)));
1556 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1557 if (op == SLJIT_REV_S32)
1558 return push_inst(compiler, EXTSW | S(dst) | A(dst));
1559 #endif /* SLJIT_CONFIG_PPC_64 */
1560 return SLJIT_SUCCESS;
1561 }
1562
1563 #define EMIT_MOV(type, type_flags, type_cast) \
1564 emit_op(compiler, (src == SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? type_cast srcw : srcw)
1565
sljit_emit_op1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)1566 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1567 sljit_s32 dst, sljit_sw dstw,
1568 sljit_s32 src, sljit_sw srcw)
1569 {
1570 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1571 sljit_s32 op_flags = GET_ALL_FLAGS(op);
1572
1573 CHECK_ERROR();
1574 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1575 ADJUST_LOCAL_OFFSET(dst, dstw);
1576 ADJUST_LOCAL_OFFSET(src, srcw);
1577
1578 op = GET_OPCODE(op);
1579
1580 if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
1581 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1582
1583 if (op <= SLJIT_MOV_P && FAST_IS_REG(src) && src == dst) {
1584 if (!TYPE_CAST_NEEDED(op))
1585 return SLJIT_SUCCESS;
1586 }
1587
1588 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1589 if (op_flags & SLJIT_32) {
1590 if (op <= SLJIT_MOV_P) {
1591 if (src & SLJIT_MEM) {
1592 if (op == SLJIT_MOV_S32)
1593 op = SLJIT_MOV_U32;
1594 }
1595 else if (src == SLJIT_IMM) {
1596 if (op == SLJIT_MOV_U32)
1597 op = SLJIT_MOV_S32;
1598 }
1599 }
1600 else {
1601 /* Most operations expect sign extended arguments. */
1602 flags |= INT_DATA | SIGNED_DATA;
1603 if (HAS_FLAGS(op_flags))
1604 flags |= ALT_SIGN_EXT;
1605 }
1606 }
1607 #endif
1608
1609 switch (op) {
1610 case SLJIT_MOV:
1611 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1612 case SLJIT_MOV_U32:
1613 case SLJIT_MOV_S32:
1614 case SLJIT_MOV32:
1615 #endif
1616 case SLJIT_MOV_P:
1617 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
1618
1619 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1620 case SLJIT_MOV_U32:
1621 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
1622
1623 case SLJIT_MOV_S32:
1624 case SLJIT_MOV32:
1625 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1626 #endif
1627
1628 case SLJIT_MOV_U8:
1629 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1630
1631 case SLJIT_MOV_S8:
1632 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1633
1634 case SLJIT_MOV_U16:
1635 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1636
1637 case SLJIT_MOV_S16:
1638 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1639
1640 case SLJIT_CLZ:
1641 case SLJIT_CTZ:
1642 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1643 if (op_flags & SLJIT_32)
1644 flags |= ALT_FORM1;
1645 #endif /* SLJIT_CONFIG_PPC_64 */
1646 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1647 case SLJIT_REV_U32:
1648 case SLJIT_REV_S32:
1649 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1650 op |= SLJIT_32;
1651 #endif /* SLJIT_CONFIG_PPC_64 */
1652 /* fallthrough */
1653 case SLJIT_REV:
1654 case SLJIT_REV_U16:
1655 case SLJIT_REV_S16:
1656 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1657 op |= (op_flags & SLJIT_32);
1658 #endif /* SLJIT_CONFIG_PPC_64 */
1659 return emit_rev(compiler, op, dst, dstw, src, srcw);
1660 }
1661
1662 return SLJIT_SUCCESS;
1663 }
1664
1665 #undef EMIT_MOV
1666
1667 /* Macros for checking different operand types / values. */
1668 #define TEST_SL_IMM(src, srcw) \
1669 ((src) == SLJIT_IMM && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1670 #define TEST_UL_IMM(src, srcw) \
1671 ((src) == SLJIT_IMM && !((srcw) & ~0xffff))
1672 #define TEST_UH_IMM(src, srcw) \
1673 ((src) == SLJIT_IMM && !((srcw) & ~(sljit_sw)0xffff0000))
1674
1675 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1676 #define TEST_SH_IMM(src, srcw) \
1677 ((src) == SLJIT_IMM && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
1678 #define TEST_ADD_IMM(src, srcw) \
1679 ((src) == SLJIT_IMM && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
1680 #define TEST_UI_IMM(src, srcw) \
1681 ((src) == SLJIT_IMM && !((srcw) & ~0xffffffff))
1682
1683 #define TEST_ADD_FORM1(op) \
1684 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1685 || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))
1686 #define TEST_SUB_FORM2(op) \
1687 ((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
1688 || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))
1689 #define TEST_SUB_FORM3(op) \
1690 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1691 || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))
1692
1693 #else /* !SLJIT_CONFIG_PPC_64 */
1694 #define TEST_SH_IMM(src, srcw) \
1695 ((src) == SLJIT_IMM && !((srcw) & 0xffff))
1696 #define TEST_ADD_IMM(src, srcw) \
1697 ((src) == SLJIT_IMM)
1698 #define TEST_UI_IMM(src, srcw) \
1699 ((src) == SLJIT_IMM)
1700
1701 #define TEST_ADD_FORM1(op) \
1702 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1703 #define TEST_SUB_FORM2(op) \
1704 (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)
1705 #define TEST_SUB_FORM3(op) \
1706 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1707 #endif /* SLJIT_CONFIG_PPC_64 */
1708
sljit_emit_op2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1709 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1710 sljit_s32 dst, sljit_sw dstw,
1711 sljit_s32 src1, sljit_sw src1w,
1712 sljit_s32 src2, sljit_sw src2w)
1713 {
1714 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1715
1716 CHECK_ERROR();
1717 CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
1718 ADJUST_LOCAL_OFFSET(dst, dstw);
1719 ADJUST_LOCAL_OFFSET(src1, src1w);
1720 ADJUST_LOCAL_OFFSET(src2, src2w);
1721
1722 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1723 if (op & SLJIT_32) {
1724 /* Most operations expect sign extended arguments. */
1725 flags |= INT_DATA | SIGNED_DATA;
1726 if (src1 == SLJIT_IMM)
1727 src1w = (sljit_s32)(src1w);
1728 if (src2 == SLJIT_IMM)
1729 src2w = (sljit_s32)(src2w);
1730 if (HAS_FLAGS(op))
1731 flags |= ALT_SIGN_EXT;
1732 }
1733 #endif
1734 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1735 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1736
1737 switch (GET_OPCODE(op)) {
1738 case SLJIT_ADD:
1739 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1740
1741 if (TEST_ADD_FORM1(op))
1742 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1743
1744 if (!HAS_FLAGS(op) && (src1 == SLJIT_IMM || src2 == SLJIT_IMM)) {
1745 if (TEST_SL_IMM(src2, src2w)) {
1746 compiler->imm = (sljit_ins)src2w & 0xffff;
1747 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1748 }
1749 if (TEST_SL_IMM(src1, src1w)) {
1750 compiler->imm = (sljit_ins)src1w & 0xffff;
1751 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1752 }
1753 if (TEST_SH_IMM(src2, src2w)) {
1754 compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
1755 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1756 }
1757 if (TEST_SH_IMM(src1, src1w)) {
1758 compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
1759 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1760 }
1761 /* Range between -1 and -32768 is covered above. */
1762 if (TEST_ADD_IMM(src2, src2w)) {
1763 compiler->imm = (sljit_ins)src2w & 0xffffffff;
1764 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1765 }
1766 if (TEST_ADD_IMM(src1, src1w)) {
1767 compiler->imm = (sljit_ins)src1w & 0xffffffff;
1768 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1769 }
1770 }
1771
1772 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1773 if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {
1774 if (TEST_SL_IMM(src2, src2w)) {
1775 compiler->imm = (sljit_ins)src2w & 0xffff;
1776 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
1777 }
1778 if (TEST_SL_IMM(src1, src1w)) {
1779 compiler->imm = (sljit_ins)src1w & 0xffff;
1780 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
1781 }
1782 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1783 }
1784 #endif
1785 if (HAS_FLAGS(op)) {
1786 if (TEST_SL_IMM(src2, src2w)) {
1787 compiler->imm = (sljit_ins)src2w & 0xffff;
1788 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1789 }
1790 if (TEST_SL_IMM(src1, src1w)) {
1791 compiler->imm = (sljit_ins)src1w & 0xffff;
1792 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1793 }
1794 }
1795 return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
1796
1797 case SLJIT_ADDC:
1798 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1799 return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
1800
1801 case SLJIT_SUB:
1802 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1803
1804 if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
1805 if (dst == TMP_REG1) {
1806 if (TEST_UL_IMM(src2, src2w)) {
1807 compiler->imm = (sljit_ins)src2w & 0xffff;
1808 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1809 }
1810 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1811 }
1812
1813 if (src2 == SLJIT_IMM && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
1814 compiler->imm = (sljit_ins)src2w;
1815 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1816 }
1817 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1818 }
1819
1820 if (dst == TMP_REG1 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1821 if (TEST_SL_IMM(src2, src2w)) {
1822 compiler->imm = (sljit_ins)src2w & 0xffff;
1823 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1824 }
1825 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
1826 }
1827
1828 if (TEST_SUB_FORM2(op)) {
1829 if (src2 == SLJIT_IMM && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
1830 compiler->imm = (sljit_ins)src2w & 0xffff;
1831 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1832 }
1833 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1834 }
1835
1836 if (TEST_SUB_FORM3(op))
1837 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1838
1839 if (TEST_SL_IMM(src2, -src2w)) {
1840 compiler->imm = (sljit_ins)(-src2w) & 0xffff;
1841 return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
1842 }
1843
1844 if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
1845 compiler->imm = (sljit_ins)src1w & 0xffff;
1846 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1847 }
1848
1849 if (!HAS_FLAGS(op)) {
1850 if (TEST_SH_IMM(src2, -src2w)) {
1851 compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;
1852 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1853 }
1854 /* Range between -1 and -32768 is covered above. */
1855 if (TEST_ADD_IMM(src2, -src2w)) {
1856 compiler->imm = (sljit_ins)-src2w;
1857 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1858 }
1859 }
1860
1861 /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */
1862 return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
1863
1864 case SLJIT_SUBC:
1865 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1866 return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
1867
1868 case SLJIT_MUL:
1869 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1870 if (op & SLJIT_32)
1871 flags |= ALT_FORM2;
1872 #endif
1873 if (!HAS_FLAGS(op)) {
1874 if (TEST_SL_IMM(src2, src2w)) {
1875 compiler->imm = (sljit_ins)src2w & 0xffff;
1876 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1877 }
1878 if (TEST_SL_IMM(src1, src1w)) {
1879 compiler->imm = (sljit_ins)src1w & 0xffff;
1880 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1881 }
1882 }
1883 else
1884 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1885 return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
1886
1887 case SLJIT_XOR:
1888 if (src2 == SLJIT_IMM && src2w == -1) {
1889 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src1, src1w);
1890 }
1891 if (src1 == SLJIT_IMM && src1w == -1) {
1892 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w);
1893 }
1894 /* fallthrough */
1895 case SLJIT_AND:
1896 case SLJIT_OR:
1897 /* Commutative unsigned operations. */
1898 if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
1899 if (TEST_UL_IMM(src2, src2w)) {
1900 compiler->imm = (sljit_ins)src2w;
1901 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1902 }
1903 if (TEST_UL_IMM(src1, src1w)) {
1904 compiler->imm = (sljit_ins)src1w;
1905 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1906 }
1907 if (TEST_UH_IMM(src2, src2w)) {
1908 compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
1909 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1910 }
1911 if (TEST_UH_IMM(src1, src1w)) {
1912 compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
1913 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1914 }
1915 }
1916 if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
1917 /* Unlike or and xor, the and resets unwanted bits as well. */
1918 if (TEST_UI_IMM(src2, src2w)) {
1919 compiler->imm = (sljit_ins)src2w;
1920 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1921 }
1922 if (TEST_UI_IMM(src1, src1w)) {
1923 compiler->imm = (sljit_ins)src1w;
1924 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1925 }
1926 }
1927 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1928
1929 case SLJIT_SHL:
1930 case SLJIT_MSHL:
1931 case SLJIT_LSHR:
1932 case SLJIT_MLSHR:
1933 case SLJIT_ASHR:
1934 case SLJIT_MASHR:
1935 case SLJIT_ROTL:
1936 case SLJIT_ROTR:
1937 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1938 if (op & SLJIT_32)
1939 flags |= ALT_FORM2;
1940 #endif
1941 if (src2 == SLJIT_IMM) {
1942 compiler->imm = (sljit_ins)src2w;
1943 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1944 }
1945 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1946 }
1947
1948 return SLJIT_SUCCESS;
1949 }
1950
sljit_emit_op2u(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1951 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
1952 sljit_s32 src1, sljit_sw src1w,
1953 sljit_s32 src2, sljit_sw src2w)
1954 {
1955 CHECK_ERROR();
1956 CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
1957
1958 SLJIT_SKIP_CHECKS(compiler);
1959 return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
1960 }
1961
1962 #undef TEST_ADD_FORM1
1963 #undef TEST_SUB_FORM2
1964 #undef TEST_SUB_FORM3
1965
sljit_emit_op2r(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1966 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
1967 sljit_s32 dst_reg,
1968 sljit_s32 src1, sljit_sw src1w,
1969 sljit_s32 src2, sljit_sw src2w)
1970 {
1971 CHECK_ERROR();
1972 CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
1973
1974 switch (GET_OPCODE(op)) {
1975 case SLJIT_MULADD:
1976 SLJIT_SKIP_CHECKS(compiler);
1977 FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
1978 return push_inst(compiler, ADD | D(dst_reg) | A(dst_reg) | B(TMP_REG2));
1979 }
1980
1981 return SLJIT_SUCCESS;
1982 }
1983
sljit_emit_shift_into(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1_reg,sljit_s32 src2_reg,sljit_s32 src3,sljit_sw src3w)1984 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
1985 sljit_s32 dst_reg,
1986 sljit_s32 src1_reg,
1987 sljit_s32 src2_reg,
1988 sljit_s32 src3, sljit_sw src3w)
1989 {
1990 sljit_s32 is_right;
1991 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1992 sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
1993 sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
1994 #else /* !SLJIT_CONFIG_PPC_64 */
1995 sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
1996 sljit_sw bit_length = 32;
1997 #endif /* SLJIT_CONFIG_PPC_64 */
1998
1999 CHECK_ERROR();
2000 CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
2001
2002 is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR);
2003
2004 if (src1_reg == src2_reg) {
2005 SLJIT_SKIP_CHECKS(compiler);
2006 return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
2007 }
2008
2009 ADJUST_LOCAL_OFFSET(src3, src3w);
2010
2011 if (src3 == SLJIT_IMM) {
2012 src3w &= bit_length - 1;
2013
2014 if (src3w == 0)
2015 return SLJIT_SUCCESS;
2016
2017 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2018 if (!(op & SLJIT_32)) {
2019 if (is_right) {
2020 FAIL_IF(push_inst(compiler, SRDI(src3w) | S(src1_reg) | A(dst_reg)));
2021 return push_inst(compiler, RLDIMI | S(src2_reg) | A(dst_reg) | RLDI_SH(64 - src3w) | RLDI_MB(0));
2022 }
2023
2024 FAIL_IF(push_inst(compiler, SLDI(src3w) | S(src1_reg) | A(dst_reg)));
2025 /* Computes SRDI(64 - src2w). */
2026 FAIL_IF(push_inst(compiler, RLDICL | S(src2_reg) | A(TMP_REG1) | RLDI_SH(src3w) | RLDI_MB(64 - src3w)));
2027 return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
2028 }
2029 #endif /* SLJIT_CONFIG_PPC_64 */
2030
2031 if (is_right) {
2032 FAIL_IF(push_inst(compiler, SRWI(src3w) | S(src1_reg) | A(dst_reg)));
2033 return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(32 - src3w) | RLWI_MBE(0, src3w - 1));
2034 }
2035
2036 FAIL_IF(push_inst(compiler, SLWI(src3w) | S(src1_reg) | A(dst_reg)));
2037 return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(src3w) | RLWI_MBE(32 - src3w, 31));
2038 }
2039
2040 if (src3 & SLJIT_MEM) {
2041 FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w, TMP_REG2));
2042 src3 = TMP_REG2;
2043 }
2044
2045 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2046 if (!(op & SLJIT_32)) {
2047 if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {
2048 FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x3f));
2049 src3 = TMP_REG2;
2050 }
2051
2052 FAIL_IF(push_inst(compiler, (is_right ? SRD : SLD) | S(src1_reg) | A(dst_reg) | B(src3)));
2053 FAIL_IF(push_inst(compiler, (is_right ? SLDI(1) : SRDI(1)) | S(src2_reg) | A(TMP_REG1)));
2054 FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x3f));
2055 FAIL_IF(push_inst(compiler, (is_right ? SLD : SRD) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
2056 return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
2057 }
2058 #endif /* SLJIT_CONFIG_PPC_64 */
2059
2060 if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {
2061 FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x1f));
2062 src3 = TMP_REG2;
2063 }
2064
2065 FAIL_IF(push_inst(compiler, (is_right ? SRW : SLW) | S(src1_reg) | A(dst_reg) | B(src3)));
2066 FAIL_IF(push_inst(compiler, (is_right ? SLWI(1) : SRWI(1)) | S(src2_reg) | A(TMP_REG1)));
2067 FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x1f));
2068 FAIL_IF(push_inst(compiler, (is_right ? SLW : SRW) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
2069 return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
2070 }
2071
emit_prefetch(struct sljit_compiler * compiler,sljit_s32 src,sljit_sw srcw)2072 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
2073 sljit_s32 src, sljit_sw srcw)
2074 {
2075 if (!(src & OFFS_REG_MASK)) {
2076 if (srcw == 0 && (src & REG_MASK))
2077 return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
2078
2079 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
2080 /* Works with SLJIT_MEM0() case as well. */
2081 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
2082 }
2083
2084 srcw &= 0x3;
2085
2086 if (srcw == 0)
2087 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
2088
2089 FAIL_IF(push_inst(compiler, SLWI_W(srcw) | S(OFFS_REG(src)) | A(TMP_REG1)));
2090 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
2091 }
2092
sljit_emit_op_src(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src,sljit_sw srcw)2093 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
2094 sljit_s32 src, sljit_sw srcw)
2095 {
2096 CHECK_ERROR();
2097 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
2098 ADJUST_LOCAL_OFFSET(src, srcw);
2099
2100 switch (op) {
2101 case SLJIT_FAST_RETURN:
2102 if (FAST_IS_REG(src))
2103 FAIL_IF(push_inst(compiler, MTLR | S(src)));
2104 else {
2105 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2));
2106 FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
2107 }
2108
2109 return push_inst(compiler, BLR);
2110 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
2111 return SLJIT_SUCCESS;
2112 case SLJIT_PREFETCH_L1:
2113 case SLJIT_PREFETCH_L2:
2114 case SLJIT_PREFETCH_L3:
2115 case SLJIT_PREFETCH_ONCE:
2116 return emit_prefetch(compiler, src, srcw);
2117 }
2118
2119 return SLJIT_SUCCESS;
2120 }
2121
sljit_emit_op_dst(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw)2122 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
2123 sljit_s32 dst, sljit_sw dstw)
2124 {
2125 sljit_s32 dst_r;
2126
2127 CHECK_ERROR();
2128 CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
2129 ADJUST_LOCAL_OFFSET(dst, dstw);
2130
2131 switch (op) {
2132 case SLJIT_FAST_ENTER:
2133 if (FAST_IS_REG(dst))
2134 return push_inst(compiler, MFLR | D(dst));
2135
2136 FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG1)));
2137 break;
2138 case SLJIT_GET_RETURN_ADDRESS:
2139 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
2140 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + LR_SAVE_OFFSET, TMP_REG2));
2141 break;
2142 }
2143
2144 if (dst & SLJIT_MEM)
2145 return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
2146
2147 return SLJIT_SUCCESS;
2148 }
2149
sljit_get_register_index(sljit_s32 type,sljit_s32 reg)2150 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
2151 {
2152 CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
2153
2154 if (type == SLJIT_GP_REGISTER)
2155 return reg_map[reg];
2156
2157 if (type != SLJIT_FLOAT_REGISTER)
2158 return -1;
2159
2160 return freg_map[reg];
2161 }
2162
sljit_emit_op_custom(struct sljit_compiler * compiler,void * instruction,sljit_u32 size)2163 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
2164 void *instruction, sljit_u32 size)
2165 {
2166 SLJIT_UNUSED_ARG(size);
2167
2168 CHECK_ERROR();
2169 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
2170
2171 return push_inst(compiler, *(sljit_ins*)instruction);
2172 }
2173
2174 /* --------------------------------------------------------------------- */
2175 /* Floating point operators */
2176 /* --------------------------------------------------------------------- */
2177
2178 #define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))
2179
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2180 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
2181 sljit_s32 dst, sljit_sw dstw,
2182 sljit_s32 src, sljit_sw srcw)
2183 {
2184 if (src & SLJIT_MEM) {
2185 /* We can ignore the temporary data store on the stack from caching point of view. */
2186 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
2187 src = TMP_FREG1;
2188 }
2189
2190 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2191 op = GET_OPCODE(op);
2192 FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
2193
2194 if (op == SLJIT_CONV_SW_FROM_F64) {
2195 if (FAST_IS_REG(dst)) {
2196 FAIL_IF(push_inst(compiler, STFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
2197 return push_inst(compiler, LD | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
2198 }
2199 return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
2200 }
2201 #else /* !SLJIT_CONFIG_PPC_64 */
2202 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
2203 #endif /* SLJIT_CONFIG_PPC_64 */
2204
2205 if (FAST_IS_REG(dst)) {
2206 FAIL_IF(load_immediate(compiler, TMP_REG1, TMP_MEM_OFFSET));
2207 FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
2208 return push_inst(compiler, LWZ | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
2209 }
2210
2211 SLJIT_ASSERT(dst & SLJIT_MEM);
2212
2213 if (dst & OFFS_REG_MASK) {
2214 dstw &= 0x3;
2215 if (dstw) {
2216 FAIL_IF(push_inst(compiler, SLWI_W(dstw) | S(OFFS_REG(dst)) | A(TMP_REG1)));
2217 dstw = TMP_REG1;
2218 } else
2219 dstw = OFFS_REG(dst);
2220 }
2221 else {
2222 if ((dst & REG_MASK) && !dstw) {
2223 dstw = dst & REG_MASK;
2224 dst = 0;
2225 } else {
2226 /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
2227 FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
2228 dstw = TMP_REG1;
2229 }
2230 }
2231
2232 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
2233 }
2234
sljit_emit_fop1_cmp(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2235 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
2236 sljit_s32 src1, sljit_sw src1w,
2237 sljit_s32 src2, sljit_sw src2w)
2238 {
2239 if (src1 & SLJIT_MEM) {
2240 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
2241 src1 = TMP_FREG1;
2242 }
2243
2244 if (src2 & SLJIT_MEM) {
2245 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
2246 src2 = TMP_FREG2;
2247 }
2248
2249 FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)));
2250
2251 switch (GET_FLAG_TYPE(op)) {
2252 case SLJIT_UNORDERED_OR_EQUAL:
2253 return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));
2254 case SLJIT_UNORDERED_OR_LESS:
2255 return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));
2256 case SLJIT_UNORDERED_OR_GREATER:
2257 return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));
2258 }
2259
2260 return SLJIT_SUCCESS;
2261 }
2262
sljit_emit_fop1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2263 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
2264 sljit_s32 dst, sljit_sw dstw,
2265 sljit_s32 src, sljit_sw srcw)
2266 {
2267 sljit_s32 dst_r;
2268
2269 CHECK_ERROR();
2270
2271 SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
2272 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
2273
2274 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
2275 op ^= SLJIT_32;
2276
2277 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2278
2279 if (src & SLJIT_MEM) {
2280 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));
2281 src = dst_r;
2282 }
2283
2284 switch (GET_OPCODE(op)) {
2285 case SLJIT_CONV_F64_FROM_F32:
2286 op ^= SLJIT_32;
2287 if (op & SLJIT_32) {
2288 FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
2289 break;
2290 }
2291 /* Fall through. */
2292 case SLJIT_MOV_F64:
2293 if (src != dst_r) {
2294 if (!(dst & SLJIT_MEM))
2295 FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
2296 else
2297 dst_r = src;
2298 }
2299 break;
2300 case SLJIT_NEG_F64:
2301 FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
2302 break;
2303 case SLJIT_ABS_F64:
2304 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
2305 break;
2306 }
2307
2308 if (dst & SLJIT_MEM)
2309 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));
2310 return SLJIT_SUCCESS;
2311 }
2312
sljit_emit_fop2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2313 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
2314 sljit_s32 dst, sljit_sw dstw,
2315 sljit_s32 src1, sljit_sw src1w,
2316 sljit_s32 src2, sljit_sw src2w)
2317 {
2318 sljit_s32 dst_r;
2319
2320 CHECK_ERROR();
2321 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
2322 ADJUST_LOCAL_OFFSET(dst, dstw);
2323 ADJUST_LOCAL_OFFSET(src1, src1w);
2324 ADJUST_LOCAL_OFFSET(src2, src2w);
2325
2326 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
2327
2328 if (src1 & SLJIT_MEM) {
2329 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
2330 src1 = TMP_FREG1;
2331 }
2332
2333 if (src2 & SLJIT_MEM) {
2334 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG1));
2335 src2 = TMP_FREG2;
2336 }
2337
2338 switch (GET_OPCODE(op)) {
2339 case SLJIT_ADD_F64:
2340 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
2341 break;
2342 case SLJIT_SUB_F64:
2343 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
2344 break;
2345 case SLJIT_MUL_F64:
2346 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
2347 break;
2348 case SLJIT_DIV_F64:
2349 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
2350 break;
2351 case SLJIT_COPYSIGN_F64:
2352 FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(src2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
2353 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2354 FAIL_IF(push_inst(compiler, LWZ | S(TMP_REG1) | A(SLJIT_SP) | ((op & SLJIT_32) ? TMP_MEM_OFFSET : TMP_MEM_OFFSET_HI)));
2355 #else /* !SLJIT_CONFIG_PPC_32 */
2356 FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
2357 #endif /* SLJIT_CONFIG_PPC_32 */
2358 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src1)));
2359 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2360 FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(TMP_REG1) | 0));
2361 #else /* !SLJIT_CONFIG_PPC_32 */
2362 FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((op & SLJIT_32) ? 0 : 1)) | A(TMP_REG1) | 0));
2363 #endif /* SLJIT_CONFIG_PPC_32 */
2364 FAIL_IF(push_inst(compiler, BCx | (4 << 21) | (0 << 16) | 8));
2365 return push_inst(compiler, FNEG | FD(dst_r) | FB(dst_r));
2366 }
2367
2368 if (dst & SLJIT_MEM)
2369 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
2370
2371 return SLJIT_SUCCESS;
2372 }
2373
2374 #undef SELECT_FOP
2375
sljit_emit_fset32(struct sljit_compiler * compiler,sljit_s32 freg,sljit_f32 value)2376 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
2377 sljit_s32 freg, sljit_f32 value)
2378 {
2379 union {
2380 sljit_s32 imm;
2381 sljit_f32 value;
2382 } u;
2383
2384 CHECK_ERROR();
2385 CHECK(check_sljit_emit_fset32(compiler, freg, value));
2386
2387 u.value = value;
2388
2389 if (u.imm != 0)
2390 FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
2391
2392 FAIL_IF(push_inst(compiler, STW | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
2393 return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
2394 }
2395
2396 /* --------------------------------------------------------------------- */
2397 /* Conditional instructions */
2398 /* --------------------------------------------------------------------- */
2399
sljit_emit_label(struct sljit_compiler * compiler)2400 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2401 {
2402 struct sljit_label *label;
2403
2404 CHECK_ERROR_PTR();
2405 CHECK_PTR(check_sljit_emit_label(compiler));
2406
2407 if (compiler->last_label && compiler->last_label->size == compiler->size)
2408 return compiler->last_label;
2409
2410 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2411 PTR_FAIL_IF(!label);
2412 set_label(label, compiler);
2413 return label;
2414 }
2415
get_bo_bi_flags(struct sljit_compiler * compiler,sljit_s32 type)2416 static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)
2417 {
2418 switch (type) {
2419 case SLJIT_NOT_CARRY:
2420 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
2421 return (4 << 21) | (2 << 16);
2422 /* fallthrough */
2423
2424 case SLJIT_EQUAL:
2425 return (12 << 21) | (2 << 16);
2426
2427 case SLJIT_CARRY:
2428 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
2429 return (12 << 21) | (2 << 16);
2430 /* fallthrough */
2431
2432 case SLJIT_NOT_EQUAL:
2433 return (4 << 21) | (2 << 16);
2434
2435 case SLJIT_LESS:
2436 case SLJIT_SIG_LESS:
2437 return (12 << 21) | (0 << 16);
2438
2439 case SLJIT_GREATER_EQUAL:
2440 case SLJIT_SIG_GREATER_EQUAL:
2441 return (4 << 21) | (0 << 16);
2442
2443 case SLJIT_GREATER:
2444 case SLJIT_SIG_GREATER:
2445 return (12 << 21) | (1 << 16);
2446
2447 case SLJIT_LESS_EQUAL:
2448 case SLJIT_SIG_LESS_EQUAL:
2449 return (4 << 21) | (1 << 16);
2450
2451 case SLJIT_OVERFLOW:
2452 return (12 << 21) | (3 << 16);
2453
2454 case SLJIT_NOT_OVERFLOW:
2455 return (4 << 21) | (3 << 16);
2456
2457 case SLJIT_F_LESS:
2458 case SLJIT_ORDERED_LESS:
2459 case SLJIT_UNORDERED_OR_LESS:
2460 return (12 << 21) | ((4 + 0) << 16);
2461
2462 case SLJIT_F_GREATER_EQUAL:
2463 case SLJIT_ORDERED_GREATER_EQUAL:
2464 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2465 return (4 << 21) | ((4 + 0) << 16);
2466
2467 case SLJIT_F_GREATER:
2468 case SLJIT_ORDERED_GREATER:
2469 case SLJIT_UNORDERED_OR_GREATER:
2470 return (12 << 21) | ((4 + 1) << 16);
2471
2472 case SLJIT_F_LESS_EQUAL:
2473 case SLJIT_ORDERED_LESS_EQUAL:
2474 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2475 return (4 << 21) | ((4 + 1) << 16);
2476
2477 case SLJIT_F_EQUAL:
2478 case SLJIT_ORDERED_EQUAL:
2479 case SLJIT_UNORDERED_OR_EQUAL:
2480 return (12 << 21) | ((4 + 2) << 16);
2481
2482 case SLJIT_F_NOT_EQUAL:
2483 case SLJIT_ORDERED_NOT_EQUAL:
2484 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2485 return (4 << 21) | ((4 + 2) << 16);
2486
2487 case SLJIT_UNORDERED:
2488 return (12 << 21) | ((4 + 3) << 16);
2489
2490 case SLJIT_ORDERED:
2491 return (4 << 21) | ((4 + 3) << 16);
2492
2493 default:
2494 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
2495 return (20 << 21);
2496 }
2497 }
2498
sljit_emit_jump(struct sljit_compiler * compiler,sljit_s32 type)2499 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2500 {
2501 struct sljit_jump *jump;
2502 sljit_ins bo_bi_flags;
2503
2504 CHECK_ERROR_PTR();
2505 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2506
2507 bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
2508 if (!bo_bi_flags)
2509 return NULL;
2510
2511 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2512 PTR_FAIL_IF(!jump);
2513 set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);
2514 type &= 0xff;
2515
2516 if ((type | 0x1) == SLJIT_NOT_CARRY)
2517 PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG2) | A(TMP_ZERO) | B(TMP_ZERO)));
2518
2519 /* In PPC, we don't need to touch the arguments. */
2520 if (type < SLJIT_JUMP)
2521 jump->flags |= IS_COND;
2522 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2523 if (type >= SLJIT_CALL)
2524 jump->flags |= IS_CALL;
2525 #endif
2526
2527 jump->addr = compiler->size;
2528 PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
2529
2530 /* Maximum number of instructions required for generating a constant. */
2531 compiler->size += JUMP_MAX_SIZE - 1;
2532 return jump;
2533 }
2534
sljit_emit_call(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types)2535 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2536 sljit_s32 arg_types)
2537 {
2538 SLJIT_UNUSED_ARG(arg_types);
2539
2540 CHECK_ERROR_PTR();
2541 CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2542
2543 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2544 if ((type & 0xff) != SLJIT_CALL_REG_ARG)
2545 PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
2546 #endif
2547
2548 if (type & SLJIT_CALL_RETURN) {
2549 PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
2550 type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
2551 }
2552
2553 SLJIT_SKIP_CHECKS(compiler);
2554 return sljit_emit_jump(compiler, type);
2555 }
2556
sljit_emit_ijump(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src,sljit_sw srcw)2557 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2558 {
2559 struct sljit_jump *jump = NULL;
2560 sljit_s32 src_r;
2561
2562 CHECK_ERROR();
2563 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2564
2565 if (src == SLJIT_IMM) {
2566 /* These jumps are converted to jump/call instructions when possible. */
2567 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2568 FAIL_IF(!jump);
2569 set_jump(jump, compiler, JUMP_ADDR);
2570 jump->u.target = (sljit_uw)srcw;
2571
2572 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2573 if (type >= SLJIT_CALL)
2574 jump->flags |= IS_CALL;
2575 #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2576
2577 jump->addr = compiler->size;
2578 FAIL_IF(push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)));
2579
2580 /* Maximum number of instructions required for generating a constant. */
2581 compiler->size += JUMP_MAX_SIZE - 1;
2582 return SLJIT_SUCCESS;
2583 }
2584
2585 if (FAST_IS_REG(src)) {
2586 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2587 if (type >= SLJIT_CALL && src != TMP_CALL_REG) {
2588 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2589 src_r = TMP_CALL_REG;
2590 } else
2591 src_r = src;
2592 #else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2593 src_r = src;
2594 #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2595 } else {
2596 ADJUST_LOCAL_OFFSET(src, srcw);
2597 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
2598 src_r = TMP_CALL_REG;
2599 }
2600
2601 FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
2602 return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
2603 }
2604
sljit_emit_icall(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types,sljit_s32 src,sljit_sw srcw)2605 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
2606 sljit_s32 arg_types,
2607 sljit_s32 src, sljit_sw srcw)
2608 {
2609 SLJIT_UNUSED_ARG(arg_types);
2610
2611 CHECK_ERROR();
2612 CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
2613
2614 if (src & SLJIT_MEM) {
2615 ADJUST_LOCAL_OFFSET(src, srcw);
2616 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
2617 src = TMP_CALL_REG;
2618 }
2619
2620 if (type & SLJIT_CALL_RETURN) {
2621 if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
2622 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2623 src = TMP_CALL_REG;
2624 }
2625
2626 FAIL_IF(emit_stack_frame_release(compiler, 0));
2627 type = SLJIT_JUMP;
2628 }
2629
2630 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2631 if ((type & 0xff) != SLJIT_CALL_REG_ARG)
2632 FAIL_IF(call_with_args(compiler, arg_types, &src));
2633 #endif
2634
2635 SLJIT_SKIP_CHECKS(compiler);
2636 return sljit_emit_ijump(compiler, type, src, srcw);
2637 }
2638
sljit_emit_op_flags(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 type)2639 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2640 sljit_s32 dst, sljit_sw dstw,
2641 sljit_s32 type)
2642 {
2643 sljit_s32 reg, invert;
2644 sljit_u32 bit, from_xer;
2645 sljit_s32 saved_op = op;
2646 sljit_sw saved_dstw = dstw;
2647 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2648 sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;
2649 #else
2650 sljit_s32 input_flags = WORD_DATA;
2651 #endif
2652
2653 CHECK_ERROR();
2654 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2655 ADJUST_LOCAL_OFFSET(dst, dstw);
2656
2657 op = GET_OPCODE(op);
2658 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2659
2660 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2661 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
2662
2663 invert = 0;
2664 bit = 0;
2665 from_xer = 0;
2666
2667 switch (type) {
2668 case SLJIT_LESS:
2669 case SLJIT_SIG_LESS:
2670 break;
2671
2672 case SLJIT_GREATER_EQUAL:
2673 case SLJIT_SIG_GREATER_EQUAL:
2674 invert = 1;
2675 break;
2676
2677 case SLJIT_GREATER:
2678 case SLJIT_SIG_GREATER:
2679 bit = 1;
2680 break;
2681
2682 case SLJIT_LESS_EQUAL:
2683 case SLJIT_SIG_LESS_EQUAL:
2684 bit = 1;
2685 invert = 1;
2686 break;
2687
2688 case SLJIT_EQUAL:
2689 bit = 2;
2690 break;
2691
2692 case SLJIT_NOT_EQUAL:
2693 bit = 2;
2694 invert = 1;
2695 break;
2696
2697 case SLJIT_OVERFLOW:
2698 from_xer = 1;
2699 bit = 1;
2700 break;
2701
2702 case SLJIT_NOT_OVERFLOW:
2703 from_xer = 1;
2704 bit = 1;
2705 invert = 1;
2706 break;
2707
2708 case SLJIT_CARRY:
2709 from_xer = 1;
2710 bit = 2;
2711 invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;
2712 break;
2713
2714 case SLJIT_NOT_CARRY:
2715 from_xer = 1;
2716 bit = 2;
2717 invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;
2718 break;
2719
2720 case SLJIT_F_LESS:
2721 case SLJIT_ORDERED_LESS:
2722 case SLJIT_UNORDERED_OR_LESS:
2723 bit = 4 + 0;
2724 break;
2725
2726 case SLJIT_F_GREATER_EQUAL:
2727 case SLJIT_ORDERED_GREATER_EQUAL:
2728 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2729 bit = 4 + 0;
2730 invert = 1;
2731 break;
2732
2733 case SLJIT_F_GREATER:
2734 case SLJIT_ORDERED_GREATER:
2735 case SLJIT_UNORDERED_OR_GREATER:
2736 bit = 4 + 1;
2737 break;
2738
2739 case SLJIT_F_LESS_EQUAL:
2740 case SLJIT_ORDERED_LESS_EQUAL:
2741 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2742 bit = 4 + 1;
2743 invert = 1;
2744 break;
2745
2746 case SLJIT_F_EQUAL:
2747 case SLJIT_ORDERED_EQUAL:
2748 case SLJIT_UNORDERED_OR_EQUAL:
2749 bit = 4 + 2;
2750 break;
2751
2752 case SLJIT_F_NOT_EQUAL:
2753 case SLJIT_ORDERED_NOT_EQUAL:
2754 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2755 bit = 4 + 2;
2756 invert = 1;
2757 break;
2758
2759 case SLJIT_UNORDERED:
2760 bit = 4 + 3;
2761 break;
2762
2763 case SLJIT_ORDERED:
2764 bit = 4 + 3;
2765 invert = 1;
2766 break;
2767
2768 default:
2769 SLJIT_UNREACHABLE();
2770 break;
2771 }
2772
2773 FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));
2774 /* Simplified mnemonics: extrwi. */
2775 FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | RLWI_SH(1 + bit) | RLWI_MBE(31, 31)));
2776
2777 if (invert)
2778 FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
2779
2780 if (op < SLJIT_ADD) {
2781 if (!(dst & SLJIT_MEM))
2782 return SLJIT_SUCCESS;
2783 return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
2784 }
2785
2786 SLJIT_SKIP_CHECKS(compiler);
2787
2788 if (dst & SLJIT_MEM)
2789 return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
2790 return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
2791 }
2792
sljit_emit_select(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_reg)2793 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
2794 sljit_s32 dst_reg,
2795 sljit_s32 src1, sljit_sw src1w,
2796 sljit_s32 src2_reg)
2797 {
2798 sljit_ins *ptr;
2799 sljit_uw size;
2800 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2801 sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2802 #else /* !SLJIT_CONFIG_PPC_64 */
2803 sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
2804 #endif /* SLJIT_CONFIG_PPC_64 */
2805
2806 CHECK_ERROR();
2807 CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
2808
2809 ADJUST_LOCAL_OFFSET(src1, src1w);
2810
2811 if (dst_reg != src2_reg) {
2812 if (dst_reg == src1) {
2813 src1 = src2_reg;
2814 src1w = 0;
2815 type ^= 0x1;
2816 } else {
2817 if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
2818 FAIL_IF(push_inst(compiler, OR | S(dst_reg) | A(TMP_REG1) | B(dst_reg)));
2819
2820 if ((src1 & REG_MASK) == dst_reg)
2821 src1 = (src1 & ~REG_MASK) | TMP_REG1;
2822
2823 if (OFFS_REG(src1) == dst_reg)
2824 src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
2825 }
2826
2827 FAIL_IF(push_inst(compiler, OR | S(src2_reg) | A(dst_reg) | B(src2_reg)));
2828 }
2829 }
2830
2831 if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)
2832 FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
2833
2834 size = compiler->size;
2835
2836 ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
2837 FAIL_IF(!ptr);
2838 compiler->size++;
2839
2840 if (src1 & SLJIT_MEM) {
2841 FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w, TMP_REG1));
2842 } else if (src1 == SLJIT_IMM) {
2843 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
2844 if (type & SLJIT_32)
2845 src1w = (sljit_s32)src1w;
2846 #endif /* SLJIT_CONFIG_RISCV_64 */
2847 FAIL_IF(load_immediate(compiler, dst_reg, src1w));
2848 } else
2849 FAIL_IF(push_inst(compiler, OR | S(src1) | A(dst_reg) | B(src1)));
2850
2851 *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);
2852 return SLJIT_SUCCESS;
2853 }
2854
sljit_emit_fselect(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_freg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_freg)2855 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
2856 sljit_s32 dst_freg,
2857 sljit_s32 src1, sljit_sw src1w,
2858 sljit_s32 src2_freg)
2859 {
2860 sljit_ins *ptr;
2861 sljit_uw size;
2862
2863 CHECK_ERROR();
2864 CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
2865
2866 ADJUST_LOCAL_OFFSET(src1, src1w);
2867
2868 if (dst_freg != src2_freg) {
2869 if (dst_freg == src1) {
2870 src1 = src2_freg;
2871 src1w = 0;
2872 type ^= 0x1;
2873 } else
2874 FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src2_freg)));
2875 }
2876
2877 if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)
2878 FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
2879
2880 size = compiler->size;
2881
2882 ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
2883 FAIL_IF(!ptr);
2884 compiler->size++;
2885
2886 if (src1 & SLJIT_MEM)
2887 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w, TMP_REG1));
2888 else
2889 FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src1)));
2890
2891 *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);
2892 return SLJIT_SUCCESS;
2893 }
2894
2895 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2896
2897 #define EMIT_MEM_LOAD_IMM(inst, mem, memw) \
2898 ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw))
2899
2900 #else /* !SLJIT_CONFIG_PPC_32 */
2901
2902 #define EMIT_MEM_LOAD_IMM(inst, mem, memw) \
2903 ((((inst) & INT_ALIGNED) && ((memw) & 0x3) != 0) \
2904 || ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) \
2905 || ((memw) > 0x7fff7fffl || (memw) < -0x80000000l)) \
2906
2907 #endif /* SLJIT_CONFIG_PPC_32 */
2908
sljit_emit_mem(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 reg,sljit_s32 mem,sljit_sw memw)2909 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
2910 sljit_s32 reg,
2911 sljit_s32 mem, sljit_sw memw)
2912 {
2913 sljit_ins inst;
2914
2915 CHECK_ERROR();
2916 CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
2917
2918 if (!(reg & REG_PAIR_MASK))
2919 return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
2920
2921 ADJUST_LOCAL_OFFSET(mem, memw);
2922
2923 inst = data_transfer_insts[WORD_DATA | ((type & SLJIT_MEM_STORE) ? 0 : LOAD_DATA)];
2924
2925 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2926 memw &= 0x3;
2927
2928 if (memw != 0) {
2929 FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(OFFS_REG(mem)) | A(TMP_REG1)));
2930 FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(TMP_REG1) | B(mem & REG_MASK)));
2931 } else
2932 FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
2933
2934 mem = TMP_REG1;
2935 memw = 0;
2936 } else {
2937 if (EMIT_MEM_LOAD_IMM(inst, mem, memw)) {
2938 if ((mem & REG_MASK) != 0) {
2939 SLJIT_SKIP_CHECKS(compiler);
2940 FAIL_IF(sljit_emit_op2(compiler, SLJIT_ADD, TMP_REG1, 0, mem & REG_MASK, 0, SLJIT_IMM, memw));
2941 } else
2942 FAIL_IF(load_immediate(compiler, TMP_REG1, memw));
2943
2944 memw = 0;
2945 mem = TMP_REG1;
2946 } else if (memw > SIMM_MAX || memw < SIMM_MIN) {
2947 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(mem & REG_MASK) | IMM((memw + 0x8000) >> 16)));
2948
2949 memw &= 0xffff;
2950 mem = TMP_REG1;
2951 } else {
2952 memw &= 0xffff;
2953 mem &= REG_MASK;
2954 }
2955 }
2956
2957 SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw >= 0x8000 && memw <= 0xffff));
2958
2959 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2960 inst &= (sljit_ins)~INT_ALIGNED;
2961 #endif /* SLJIT_CONFIG_PPC_64 */
2962
2963 if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
2964 FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw))));
2965 return push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw));
2966 }
2967
2968 FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw)));
2969 return push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw)));
2970 }
2971
2972 #undef EMIT_MEM_LOAD_IMM
2973
sljit_emit_mem_update(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 reg,sljit_s32 mem,sljit_sw memw)2974 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
2975 sljit_s32 reg,
2976 sljit_s32 mem, sljit_sw memw)
2977 {
2978 sljit_s32 mem_flags;
2979 sljit_ins inst;
2980
2981 CHECK_ERROR();
2982 CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
2983
2984 if (type & SLJIT_MEM_POST)
2985 return SLJIT_ERR_UNSUPPORTED;
2986
2987 switch (type & 0xff) {
2988 case SLJIT_MOV:
2989 case SLJIT_MOV_P:
2990 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2991 case SLJIT_MOV_U32:
2992 case SLJIT_MOV_S32:
2993 case SLJIT_MOV32:
2994 #endif
2995 mem_flags = WORD_DATA;
2996 break;
2997
2998 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2999 case SLJIT_MOV_U32:
3000 case SLJIT_MOV32:
3001 mem_flags = INT_DATA;
3002 break;
3003
3004 case SLJIT_MOV_S32:
3005 mem_flags = INT_DATA;
3006
3007 if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {
3008 if (mem & OFFS_REG_MASK)
3009 mem_flags |= SIGNED_DATA;
3010 else
3011 return SLJIT_ERR_UNSUPPORTED;
3012 }
3013 break;
3014 #endif
3015
3016 case SLJIT_MOV_U8:
3017 case SLJIT_MOV_S8:
3018 mem_flags = BYTE_DATA;
3019 break;
3020
3021 case SLJIT_MOV_U16:
3022 mem_flags = HALF_DATA;
3023 break;
3024
3025 case SLJIT_MOV_S16:
3026 mem_flags = HALF_DATA | SIGNED_DATA;
3027 break;
3028
3029 default:
3030 SLJIT_UNREACHABLE();
3031 mem_flags = WORD_DATA;
3032 break;
3033 }
3034
3035 if (!(type & SLJIT_MEM_STORE))
3036 mem_flags |= LOAD_DATA;
3037
3038 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3039 if (memw != 0)
3040 return SLJIT_ERR_UNSUPPORTED;
3041
3042 if (type & SLJIT_MEM_SUPP)
3043 return SLJIT_SUCCESS;
3044
3045 inst = updated_data_transfer_insts[mem_flags | INDEXED];
3046 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
3047 }
3048 else {
3049 if (memw > SIMM_MAX || memw < SIMM_MIN)
3050 return SLJIT_ERR_UNSUPPORTED;
3051
3052 inst = updated_data_transfer_insts[mem_flags];
3053
3054 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
3055 if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)
3056 return SLJIT_ERR_UNSUPPORTED;
3057 #endif
3058
3059 if (type & SLJIT_MEM_SUPP)
3060 return SLJIT_SUCCESS;
3061
3062 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
3063 }
3064
3065 if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)
3066 return push_inst(compiler, EXTSB | S(reg) | A(reg));
3067 return SLJIT_SUCCESS;
3068 }
3069
sljit_emit_fmem_update(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 mem,sljit_sw memw)3070 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
3071 sljit_s32 freg,
3072 sljit_s32 mem, sljit_sw memw)
3073 {
3074 sljit_s32 mem_flags;
3075 sljit_ins inst;
3076
3077 CHECK_ERROR();
3078 CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));
3079
3080 if (type & SLJIT_MEM_POST)
3081 return SLJIT_ERR_UNSUPPORTED;
3082
3083 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3084 if (memw != 0)
3085 return SLJIT_ERR_UNSUPPORTED;
3086 }
3087 else {
3088 if (memw > SIMM_MAX || memw < SIMM_MIN)
3089 return SLJIT_ERR_UNSUPPORTED;
3090 }
3091
3092 if (type & SLJIT_MEM_SUPP)
3093 return SLJIT_SUCCESS;
3094
3095 mem_flags = FLOAT_DATA(type);
3096
3097 if (!(type & SLJIT_MEM_STORE))
3098 mem_flags |= LOAD_DATA;
3099
3100 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3101 inst = updated_data_transfer_insts[mem_flags | INDEXED];
3102 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));
3103 }
3104
3105 inst = updated_data_transfer_insts[mem_flags];
3106 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));
3107 }
3108
sljit_emit_const(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw,sljit_sw init_value)3109 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
3110 {
3111 struct sljit_const *const_;
3112 sljit_s32 dst_r;
3113
3114 CHECK_ERROR_PTR();
3115 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
3116 ADJUST_LOCAL_OFFSET(dst, dstw);
3117
3118 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
3119 PTR_FAIL_IF(!const_);
3120 set_const(const_, compiler);
3121
3122 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3123 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
3124
3125 if (dst & SLJIT_MEM)
3126 PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));
3127
3128 return const_;
3129 }
3130
sljit_emit_mov_addr(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)3131 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
3132 {
3133 struct sljit_jump *jump;
3134 sljit_s32 dst_r;
3135
3136 CHECK_ERROR_PTR();
3137 CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
3138 ADJUST_LOCAL_OFFSET(dst, dstw);
3139
3140 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3141 PTR_FAIL_IF(!jump);
3142 set_mov_addr(jump, compiler, 0);
3143
3144 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3145 PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
3146 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
3147 compiler->size++;
3148 #else
3149 compiler->size += 4;
3150 #endif
3151
3152 if (dst & SLJIT_MEM)
3153 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
3154
3155 return jump;
3156 }
3157
sljit_set_const(sljit_uw addr,sljit_sw new_constant,sljit_sw executable_offset)3158 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
3159 {
3160 sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
3161 }
3162