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