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