php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
sljitNativePPC_common.c
Go to the documentation of this file.
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
28{
29 return "PowerPC" SLJIT_CPUINFO;
30}
31
32/* Length of an instruction word.
33 Both for ppc-32 and ppc-64. */
34typedef 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
51static 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
107static 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
111static 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)
290SLJIT_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
304static 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
313static 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)
372keep_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
389exit:
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
402static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
403{
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
431static 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
495static 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
587SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
588{
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
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);
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
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. */
748 case SLJIT_HAS_CLZ:
749 case SLJIT_HAS_ROT:
751 return 1;
752
753 case SLJIT_HAS_CTZ:
754 return 2;
755
756 default:
757 return 0;
758 }
759}
760
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/*
816ALT_SIGN_EXT 0x000100
817ALT_SET_FLAGS 0x000200
818ALT_FORM1 0x001000
819...
820ALT_FORM5 0x010000 */
821
822static 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
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
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
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
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
976 local_size += SSIZE_OF(sw);
977
978 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
979 return SLJIT_SUCCESS;
980}
981
982static 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
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
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
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
1103static 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
1168static 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). */
1236static 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);
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
1294static 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;
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
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:
1404 return SLJIT_SUCCESS;
1405 }
1406
1407 return SLJIT_SUCCESS;
1408}
1409
1410static 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
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. */
1603 if (HAS_FLAGS(op_flags))
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:
1622
1623 case SLJIT_MOV_S32:
1624 case SLJIT_MOV32:
1626#endif
1627
1628 case SLJIT_MOV_U8:
1630
1631 case SLJIT_MOV_S8:
1633
1634 case SLJIT_MOV_U16:
1636
1637 case SLJIT_MOV_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
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. */
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))
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
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
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
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
2072static 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
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);
2111 return SLJIT_SUCCESS;
2112 case SLJIT_PREFETCH_L1:
2113 case SLJIT_PREFETCH_L2:
2114 case SLJIT_PREFETCH_L3:
2116 return emit_prefetch(compiler, src, srcw);
2117 }
2118
2119 return SLJIT_SUCCESS;
2120}
2121
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;
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
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
2158 return -1;
2159
2160 return freg_map[reg];
2161}
2162
2164 void *instruction, sljit_u32 size)
2165{
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
2180static 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
2235static 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)) {
2253 return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));
2255 return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));
2257 return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));
2258 }
2259
2260 return SLJIT_SUCCESS;
2261}
2262
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
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)) {
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
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
2378{
2379 union {
2380 sljit_s32 imm;
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
2401{
2402 struct sljit_label *label;
2403
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
2416static 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
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:
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:
2460 return (12 << 21) | ((4 + 0) << 16);
2461
2465 return (4 << 21) | ((4 + 0) << 16);
2466
2467 case SLJIT_F_GREATER:
2470 return (12 << 21) | ((4 + 1) << 16);
2471
2472 case SLJIT_F_LESS_EQUAL:
2475 return (4 << 21) | ((4 + 1) << 16);
2476
2477 case SLJIT_F_EQUAL:
2480 return (12 << 21) | ((4 + 2) << 16);
2481
2482 case SLJIT_F_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:
2495 return (20 << 21);
2496 }
2497}
2498
2500{
2501 struct sljit_jump *jump;
2502 sljit_ins bo_bi_flags;
2503
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
2536 sljit_s32 arg_types)
2537{
2538 SLJIT_UNUSED_ARG(arg_types);
2539
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));
2551 }
2552
2553 SLJIT_SKIP_CHECKS(compiler);
2554 return sljit_emit_jump(compiler, type);
2555}
2556
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
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
2640 sljit_s32 dst, sljit_sw dstw,
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
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:
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:
2723 bit = 4 + 0;
2724 break;
2725
2729 bit = 4 + 0;
2730 invert = 1;
2731 break;
2732
2733 case SLJIT_F_GREATER:
2736 bit = 4 + 1;
2737 break;
2738
2739 case SLJIT_F_LESS_EQUAL:
2742 bit = 4 + 1;
2743 invert = 1;
2744 break;
2745
2746 case SLJIT_F_EQUAL:
2749 bit = 4 + 2;
2750 break;
2751
2752 case SLJIT_F_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:
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
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
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
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
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:
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
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
3110{
3111 struct sljit_const *const_;
3112 sljit_s32 dst_r;
3113
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
3132{
3133 struct sljit_jump *jump;
3134 sljit_s32 dst_r;
3135
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
3159{
3160 sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
3161}
sizeof(Countable|array $value, int $mode=COUNT_NORMAL)
uint32_t u
Definition cdf.c:78
zend_ffi_type * type
Definition ffi.c:3812
new_type size
Definition ffi.c:4365
void * ptr
Definition ffi.c:3814
zval * arg
Definition ffi.c:3975
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
zend_long offset
#define NULL
Definition gdcache.h:45
#define A(x, l, r)
Definition hash_gost.c:85
#define GET_OPCODE(i)
Definition minilua.c:929
PHP_JSON_API size_t int options
Definition php_json.h:102
#define SLJIT_UNREACHABLE()
unsigned short int sljit_u16
signed short int sljit_s16
#define SLJIT_UNLIKELY(x)
#define SLJIT_LOCALS_OFFSET
#define SLJIT_API_FUNC_ATTRIBUTE
unsigned int sljit_uw
unsigned char sljit_u8
#define SLJIT_COMPILE_ASSERT(x, description)
signed int sljit_s32
unsigned int sljit_u32
signed char sljit_s8
#define SLJIT_ASSERT(x)
#define SLJIT_UNUSED_ARG(arg)
#define SLJIT_INLINE
float sljit_f32
#define SLJIT_CACHE_FLUSH(from, to)
int sljit_sw
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
#define CHECK_ERROR()
Definition sljitLir.c:43
#define PTR_FAIL_IF(expr)
Definition sljitLir.c:61
#define FAIL_IF(expr)
Definition sljitLir.c:55
#define PTR_FAIL_WITH_EXEC_IF(ptr)
Definition sljitLir.c:83
#define CHECK_ERROR_PTR()
Definition sljitLir.c:49
#define SLJIT_UNORDERED_OR_LESS_EQUAL
Definition sljitLir.h:1626
#define SLJIT_SUB_F64
Definition sljitLir.h:1451
#define SLJIT_NOT_CARRY
Definition sljitLir.h:1581
#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN
Definition sljitLir.h:1357
#define SLJIT_CALL_REG_ARG
Definition sljitLir.h:1650
#define SLJIT_ARG_TYPE_SCRATCH_REG
Definition sljitLir.h:348
#define SLJIT_ORDERED
Definition sljitLir.h:1608
#define SLJIT_DIVMOD_SW
Definition sljitLir.h:1079
#define SLJIT_MEM_SUPP
Definition sljitLir.h:1806
#define SLJIT_ORDERED_LESS_EQUAL
Definition sljitLir.h:1639
#define SLJIT_FAST_CALL
Definition sljitLir.h:1645
#define SLJIT_OVERFLOW
Definition sljitLir.h:1574
#define SLJIT_REV_S16
Definition sljitLir.h:1176
#define SLJIT_CONV_S32_FROM_F64
Definition sljitLir.h:1415
#define SLJIT_FAST_RETURN
Definition sljitLir.h:1353
#define SLJIT_HAS_ZERO_REGISTER
Definition sljitLir.h:690
#define SLJIT_R1
Definition sljitLir.h:169
#define SLJIT_XOR
Definition sljitLir.h:1227
#define SLJIT_FIRST_SAVED_REG
Definition sljitLir.h:208
#define SLJIT_DIV_F64
Definition sljitLir.h:1457
#define SLJIT_SP
Definition sljitLir.h:214
#define SLJIT_ROTL
Definition sljitLir.h:1268
SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
#define SLJIT_UNORDERED_OR_GREATER
Definition sljitLir.h:1637
#define SLJIT_MUL_F64
Definition sljitLir.h:1454
#define SLJIT_LMUL_UW
Definition sljitLir.h:1062
#define SLJIT_UNORDERED
Definition sljitLir.h:1605
#define SLJIT_ADD
Definition sljitLir.h:1203
#define SLJIT_ORDERED_GREATER_EQUAL
Definition sljitLir.h:1635
#define SLJIT_PREFETCH_L3
Definition sljitLir.h:1375
#define SLJIT_SIG_GREATER_EQUAL
Definition sljitLir.h:1567
#define SLJIT_MOV_U16
Definition sljitLir.h:1133
#define SLJIT_UNORDERED_OR_NOT_EQUAL
Definition sljitLir.h:1618
#define SLJIT_ARG_TYPE_F64
Definition sljitLir.h:362
#define SLJIT_LMUL_SW
Definition sljitLir.h:1066
#define SLJIT_NOT_EQUAL
Definition sljitLir.h:1554
#define SLJIT_PREFETCH_L1
Definition sljitLir.h:1363
#define SLJIT_ABS_F64
Definition sljitLir.h:1437
#define SLJIT_32
Definition sljitLir.h:978
#define SLJIT_COPYSIGN_F64
Definition sljitLir.h:1469
#define SLJIT_MSHL
Definition sljitLir.h:1239
#define SLJIT_F_EQUAL
Definition sljitLir.h:1591
#define SLJIT_ORDERED_EQUAL
Definition sljitLir.h:1616
#define SLJIT_MOV_S8
Definition sljitLir.h:1130
#define SLJIT_ERR_UNSUPPORTED
Definition sljitLir.h:112
#define SLJIT_MULADD
Definition sljitLir.h:1292
#define SLJIT_HAS_FPU
Definition sljitLir.h:686
#define SLJIT_UNORDERED_OR_LESS
Definition sljitLir.h:1633
#define SLJIT_MEM_POST
Definition sljitLir.h:1800
#define SLJIT_SUB
Definition sljitLir.h:1211
#define SLJIT_ASHR
Definition sljitLir.h:1258
#define SLJIT_SUCCESS
Definition sljitLir.h:101
#define SLJIT_ORDERED_GREATER
Definition sljitLir.h:1624
#define SLJIT_SIG_LESS_EQUAL
Definition sljitLir.h:1571
#define SLJIT_IMM
Definition sljitLir.h:931
#define SLJIT_DIVMOD_UW
Definition sljitLir.h:1071
#define SLJIT_UNORDERED_OR_EQUAL
Definition sljitLir.h:1629
#define SLJIT_CALL
Definition sljitLir.h:1647
#define SLJIT_HAS_ROT
Definition sljitLir.h:698
#define SLJIT_ROTR
Definition sljitLir.h:1273
#define SLJIT_LESS_EQUAL
Definition sljitLir.h:1563
#define SLJIT_CALL_RETURN
Definition sljitLir.h:1659
#define SLJIT_CTZ
Definition sljitLir.h:1158
#define SLJIT_MUL
Definition sljitLir.h:1218
#define SLJIT_REWRITABLE_JUMP
Definition sljitLir.h:1653
#define SLJIT_OR
Definition sljitLir.h:1224
#define SLJIT_CARRY
Definition sljitLir.h:1579
#define SLJIT_MOV_F64
Definition sljitLir.h:1403
#define SLJIT_SIG_LESS
Definition sljitLir.h:1565
#define SLJIT_SET_Z
Definition sljitLir.h:1043
#define SLJIT_NOT_OVERFLOW
Definition sljitLir.h:1576
#define SLJIT_F_NOT_EQUAL
Definition sljitLir.h:1593
#define SLJIT_MEM1(r1)
Definition sljitLir.h:929
#define SLJIT_F_GREATER_EQUAL
Definition sljitLir.h:1597
#define SLJIT_HAS_CLZ
Definition sljitLir.h:692
#define SLJIT_EQUAL
Definition sljitLir.h:1552
#define SLJIT_CONV_SW_FROM_F64
Definition sljitLir.h:1412
#define SLJIT_JUMP
Definition sljitLir.h:1643
#define SLJIT_CURRENT_FLAGS_ADD
Definition sljitLir.h:2251
#define SLJIT_GREATER
Definition sljitLir.h:1561
#define SLJIT_FS0
Definition sljitLir.h:244
#define SLJIT_AND
Definition sljitLir.h:1221
#define SLJIT_HAS_PREFETCH
Definition sljitLir.h:702
#define SLJIT_ENTER_REG_ARG
Definition sljitLir.h:809
#define SLJIT_BREAKPOINT
Definition sljitLir.h:1054
#define SLJIT_SIG_GREATER
Definition sljitLir.h:1569
#define SLJIT_ARG_SHIFT
Definition sljitLir.h:366
#define SLJIT_FLOAT_REGISTER
Definition sljitLir.h:2214
#define SLJIT_GET_RETURN_ADDRESS
Definition sljitLir.h:1394
#define SLJIT_MOV_U32
Definition sljitLir.h:1140
#define SLJIT_FIRST_SAVED_FLOAT_REG
Definition sljitLir.h:259
#define SLJIT_DIV_SW
Definition sljitLir.h:1093
#define SLJIT_DIV_UW
Definition sljitLir.h:1085
#define SLJIT_MOV_S16
Definition sljitLir.h:1136
#define SLJIT_GREATER_EQUAL
Definition sljitLir.h:1559
#define SLJIT_GP_REGISTER
Definition sljitLir.h:2212
#define SLJIT_MEM
Definition sljitLir.h:927
#define SLJIT_MOV_U8
Definition sljitLir.h:1127
#define SLJIT_SKIP_FRAMES_BEFORE_RETURN
Definition sljitLir.h:1104
#define SLJIT_MEM_STORE
Definition sljitLir.h:1783
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
#define SLJIT_ADDC
Definition sljitLir.h:1206
#define SLJIT_FAST_ENTER
Definition sljitLir.h:1388
#define SLJIT_ERR_COMPILED
Definition sljitLir.h:105
#define SLJIT_ENDBR
Definition sljitLir.h:1099
#define SLJIT_CLZ
Definition sljitLir.h:1153
#define SLJIT_F_LESS_EQUAL
Definition sljitLir.h:1601
#define SLJIT_HAS_CTZ
Definition sljitLir.h:694
#define SLJIT_REV_U16
Definition sljitLir.h:1170
#define SLJIT_SUBC
Definition sljitLir.h:1214
#define SLJIT_MLSHR
Definition sljitLir.h:1251
#define SLJIT_ORDERED_LESS
Definition sljitLir.h:1620
#define SLJIT_OP2_BASE
Definition sljitLir.h:1200
#define SLJIT_LSHR
Definition sljitLir.h:1246
#define SLJIT_MOV_S32
Definition sljitLir.h:1143
#define SLJIT_CONV_F64_FROM_F32
Definition sljitLir.h:1409
#define SLJIT_PREFETCH_L2
Definition sljitLir.h:1369
#define SLJIT_CURRENT_FLAGS_SUB
Definition sljitLir.h:2253
#define SLJIT_SHL
Definition sljitLir.h:1234
#define SLJIT_PREFETCH_ONCE
Definition sljitLir.h:1381
#define SLJIT_MASHR
Definition sljitLir.h:1263
#define SLJIT_F_GREATER
Definition sljitLir.h:1599
#define SLJIT_R0
Definition sljitLir.h:168
#define SLJIT_ORDERED_NOT_EQUAL
Definition sljitLir.h:1631
#define SLJIT_HAS_REV
Definition sljitLir.h:696
#define SLJIT_MOV_P
Definition sljitLir.h:1149
#define SLJIT_NEG_F64
Definition sljitLir.h:1434
#define SLJIT_REV
Definition sljitLir.h:1164
#define SLJIT_F_LESS
Definition sljitLir.h:1595
#define SLJIT_S0
Definition sljitLir.h:188
#define SLJIT_LESS
Definition sljitLir.h:1557
#define SLJIT_MOV32
Definition sljitLir.h:1145
#define SLJIT_MOV
Definition sljitLir.h:1125
#define SLJIT_REV_S32
Definition sljitLir.h:1187
#define SLJIT_UNORDERED_OR_GREATER_EQUAL
Definition sljitLir.h:1622
#define SLJIT_REV_U32
Definition sljitLir.h:1182
#define SLJIT_ADD_F64
Definition sljitLir.h:1448
#define SLJIT_NOP
Definition sljitLir.h:1058
#define TMP_REG2
#define TMP_FREG2
#define TMP_REG1
#define NOP
#define ADD
#define LOAD_DATA
sljit_u32 sljit_ins
#define TMP_FREG1
#define FADD
#define FMUL
#define ADDI
#define ADDE
#define FSUB
#define ANDI
#define FNEG
#define FDIV
#define BLR
#define TMP_ZERO
#define FABS
#define CMPI
#define HALF_DATA
#define XORI
#define REG_DEST
#define OR
#define SIGNED_DATA
#define INT_DATA
#define DOUBLE_DATA
#define WORD_DATA
#define REG2_SOURCE
#define REG1_SOURCE
#define STACK_LOAD
#define BYTE_DATA
#define STACK_STORE
#define MEM_MASK
#define STACK_MAX_DISTANCE
#define ORI
#define SLJIT_IS_FPU_AVAILABLE
#define SIMM_MIN
#define SIMM_MAX
#define LD
#define MULHDU
#define STFD
#define MFLR
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type)
#define FA(fa)
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
#define LR_SAVE_OFFSET
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types)
#define MFCR
#define TMP_MEM_OFFSET_HI
#define RLDI_SH(sh)
#define MTXER
#define FADDS
#define SLW
#define DIVW
#define TEST_SUB_FORM2(op)
#define LWBRX_FIRST_REG
#define RLDI_MB(mb)
#define STW
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 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)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2_reg)
#define ALT_FORM2
#define FLOAT_DATA(op)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw)
#define RLWIMI
#define INST_CODE_AND_DST(inst, flags, reg)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
SLJIT_API_FUNC_ATTRIBUTE const char * sljit_get_platform_name(void)
#define STWUX
#define TEST_SH_IMM(src, srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w)
#define ORIS
#define STHBRX
#define CRD(d)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
#define STDU
#define EXTSB
#define LFD
#define TEST_ADD_IMM(src, srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
#define TMP_CALL_REG
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
#define ARCH_32_64(a, b)
#define ALT_FORM3
#define BCCTR
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
#define RLWINM
#define SRWI(shift)
#define DIVDU
#define STWU
#define SLD
#define MTCTR
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_compiler *compiler)
#define FD(fd)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
#define FRSP
#define MULHD
#define LWBRX_SECOND_REG
#define MULHWU
#define DIVWU
#define SELECT_FOP(op, single, double)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler, sljit_s32 freg, sljit_f32 value)
#define SRW
#define RLWI_MBE(mb, me)
#define A(a)
#define DIVD
#define LO(opcode)
#define TEST_UI_IMM(src, srcw)
#define SLWI_W(shift)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw)
#define ALT_SET_FLAGS
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 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)
#define D(d)
#define MULHW
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
#define LFS
#define EMIT_MEM_LOAD_IMM(inst, mem, memw)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
#define STDUX
#define SRDI(shift)
#define TEST_UH_IMM(src, srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 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)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
#define BCx
#define FSUBS
#define FMULS
#define S(s)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 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)
#define RLWI_SH(sh)
#define FDIVS
#define SUBF
#define SLDI(shift)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 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)
#define MULLD
#define STFIWX
#define RLDICL
#define EXTSW
#define SRD
#define Bx
#define MTLR
#define B(b)
#define STFS
#define FB(fb)
#define CROR
#define TMP_MEM_OFFSET
#define LWZ
#define FCTIDZ
#define EXTSH
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw)
#define FC(fc)
#define IMM(imm)
#define EMIT_MOV(type, type_flags, type_cast)
#define HI(opcode)
#define SLWI(shift)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_freg, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2_freg)
#define STWBRX
#define MFXER
#define LHBRX
#define ALT_SIGN_EXT
#define TEST_UL_IMM(src, srcw)
#define ALT_FORM1
#define INDEXED
#define RLDIMI
#define FCTIWZ
#define FCMPU
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
#define TEST_SL_IMM(src, srcw)
#define TMP_MEM_OFFSET_LO
#define ADDIS
#define FS(fs)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 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)
#define RC(flags)
#define TEST_SUB_FORM3(op)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_u32 size)
#define DCBT
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw)
#define TEST_ADD_FORM1(op)
#define ALT_FORM4
#define LWBRX
#define MULLW
#define FMR
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
#define ALT_FORM5
Definition dce.c:49
sljit_s32 saveds
Definition sljitLir.h:481
sljit_uw executable_size
Definition sljitLir.h:493
struct sljit_const * consts
Definition sljitLir.h:466
sljit_uw size
Definition sljitLir.h:489
sljit_sw executable_offset
Definition sljitLir.h:491
sljit_s32 local_size
Definition sljitLir.h:487
struct sljit_jump * jumps
Definition sljitLir.h:465
sljit_s32 error
Definition sljitLir.h:461
sljit_s32 fscratches
Definition sljitLir.h:483
struct sljit_label * last_label
Definition sljitLir.h:467
struct sljit_memory_fragment * buf
Definition sljitLir.h:473
sljit_s32 scratches
Definition sljitLir.h:479
struct sljit_label * labels
Definition sljitLir.h:464
sljit_s32 fsaveds
Definition sljitLir.h:485
sljit_s32 options
Definition sljitLir.h:462
struct sljit_const * next
Definition sljitLir.h:450
sljit_uw addr
Definition sljitLir.h:451
struct sljit_label * next
Definition sljitLir.h:429
union sljit_label::@034003116150245300057154161307153110213245130244 u
sljit_uw size
Definition sljitLir.h:435
sljit_uw addr
Definition sljitLir.h:432
exit(string|int $status=0)
execute_data func
value