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