blob: 2174dbb07b2f34b9abb176b695986ad72215729b [file] [log] [blame]
Elliott Hughes5b808042021-10-01 10:56:10 -07001/*
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
27SLJIT_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. */
34typedef sljit_u32 sljit_ins;
35
36#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \
37 || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
38#define SLJIT_PPC_STACK_FRAME_V2 1
39#endif
40
41#ifdef _AIX
42#include <sys/cache.h>
43#endif
44
45#if (defined _CALL_ELF && _CALL_ELF == 2)
46#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
47#endif
48
49#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
50
51static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
52{
53#ifdef _AIX
54 _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));
55#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
56# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)
57 /* Cache flush for POWER architecture. */
58 while (from < to) {
59 __asm__ volatile (
60 "clf 0, %0\n"
61 "dcs\n"
62 : : "r"(from)
63 );
64 from++;
65 }
66 __asm__ volatile ( "ics" );
67# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)
68# error "Cache flush is not implemented for PowerPC/POWER common mode."
69# else
70 /* Cache flush for PowerPC architecture. */
71 while (from < to) {
72 __asm__ volatile (
73 "dcbf 0, %0\n"
74 "sync\n"
75 "icbi 0, %0\n"
76 : : "r"(from)
77 );
78 from++;
79 }
80 __asm__ volatile ( "isync" );
81# endif
82# ifdef __xlc__
83# warning "This file may fail to compile if -qfuncsect is used"
84# endif
85#elif defined(__xlc__)
86#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"
87#else
88#error "This platform requires a cache flush implementation."
89#endif /* _AIX */
90}
91
92#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
93
94#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
95#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
96#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)
97
98#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
99#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5)
100#else
101#define TMP_CALL_REG TMP_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
107static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
108 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12
109};
110
111static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
112 0, 1, 2, 3, 4, 5, 6, 0, 7
113};
114
115/* --------------------------------------------------------------------- */
116/* Instrucion forms */
117/* --------------------------------------------------------------------- */
118#define D(d) (reg_map[d] << 21)
119#define S(s) (reg_map[s] << 21)
120#define A(a) (reg_map[a] << 16)
121#define B(b) (reg_map[b] << 11)
122#define C(c) (reg_map[c] << 6)
123#define FD(fd) (freg_map[fd] << 21)
124#define FS(fs) (freg_map[fs] << 21)
125#define FA(fa) (freg_map[fa] << 16)
126#define FB(fb) (freg_map[fb] << 11)
127#define FC(fc) (freg_map[fc] << 6)
128#define IMM(imm) ((imm) & 0xffff)
129#define CRD(d) ((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) (((flags) & ALT_SET_FLAGS) >> 10)
136#define HI(opcode) ((opcode) << 26)
137#define LO(opcode) ((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#define CNTLZD (HI(31) | LO(58))
154#define CNTLZW (HI(31) | LO(26))
155#define CMP (HI(31) | LO(0))
156#define CMPI (HI(11))
157#define CMPL (HI(31) | LO(32))
158#define CMPLI (HI(10))
159#define CROR (HI(19) | LO(449))
160#define DCBT (HI(31) | LO(278))
161#define DIVD (HI(31) | LO(489))
162#define DIVDU (HI(31) | LO(457))
163#define DIVW (HI(31) | LO(491))
164#define DIVWU (HI(31) | LO(459))
165#define EXTSB (HI(31) | LO(954))
166#define EXTSH (HI(31) | LO(922))
167#define EXTSW (HI(31) | LO(986))
168#define FABS (HI(63) | LO(264))
169#define FADD (HI(63) | LO(21))
170#define FADDS (HI(59) | LO(21))
171#define FCFID (HI(63) | LO(846))
172#define FCMPU (HI(63) | LO(0))
173#define FCTIDZ (HI(63) | LO(815))
174#define FCTIWZ (HI(63) | LO(15))
175#define FDIV (HI(63) | LO(18))
176#define FDIVS (HI(59) | LO(18))
177#define FMR (HI(63) | LO(72))
178#define FMUL (HI(63) | LO(25))
179#define FMULS (HI(59) | LO(25))
180#define FNEG (HI(63) | LO(40))
181#define FRSP (HI(63) | LO(12))
182#define FSUB (HI(63) | LO(20))
183#define FSUBS (HI(59) | LO(20))
184#define LD (HI(58) | 0)
185#define LWZ (HI(32))
186#define MFCR (HI(31) | LO(19))
187#define MFLR (HI(31) | LO(339) | 0x80000)
188#define MFXER (HI(31) | LO(339) | 0x10000)
189#define MTCTR (HI(31) | LO(467) | 0x90000)
190#define MTLR (HI(31) | LO(467) | 0x80000)
191#define MTXER (HI(31) | LO(467) | 0x10000)
192#define MULHD (HI(31) | LO(73))
193#define MULHDU (HI(31) | LO(9))
194#define MULHW (HI(31) | LO(75))
195#define MULHWU (HI(31) | LO(11))
196#define MULLD (HI(31) | LO(233))
197#define MULLI (HI(7))
198#define MULLW (HI(31) | LO(235))
199#define NEG (HI(31) | LO(104))
200#define NOP (HI(24))
201#define NOR (HI(31) | LO(124))
202#define OR (HI(31) | LO(444))
203#define ORI (HI(24))
204#define ORIS (HI(25))
205#define RLDICL (HI(30))
206#define RLWINM (HI(21))
207#define SLD (HI(31) | LO(27))
208#define SLW (HI(31) | LO(24))
209#define SRAD (HI(31) | LO(794))
210#define SRADI (HI(31) | LO(413 << 1))
211#define SRAW (HI(31) | LO(792))
212#define SRAWI (HI(31) | LO(824))
213#define SRD (HI(31) | LO(539))
214#define SRW (HI(31) | LO(536))
215#define STD (HI(62) | 0)
216#define STDU (HI(62) | 1)
217#define STDUX (HI(31) | LO(181))
218#define STFIWX (HI(31) | LO(983))
219#define STW (HI(36))
220#define STWU (HI(37))
221#define STWUX (HI(31) | LO(183))
222#define SUBF (HI(31) | LO(40))
223#define SUBFC (HI(31) | LO(8))
224#define SUBFE (HI(31) | LO(136))
225#define SUBFIC (HI(8))
226#define XOR (HI(31) | LO(316))
227#define XORI (HI(26))
228#define XORIS (HI(27))
229
230#define SIMM_MAX (0x7fff)
231#define SIMM_MIN (-0x8000)
232#define UIMM_MAX (0xffff)
233
234#define RLDI(dst, src, sh, mb, type) \
235 (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
236
237#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
238SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
239{
240 sljit_sw* ptrs;
241 if (func_ptr)
242 *func_ptr = (void*)context;
243 ptrs = (sljit_sw*)func;
244 context->addr = addr ? addr : ptrs[0];
245 context->r2 = ptrs[1];
246 context->r11 = ptrs[2];
247}
248#endif
249
250static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
251{
252 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
253 FAIL_IF(!ptr);
254 *ptr = ins;
255 compiler->size++;
256 return SLJIT_SUCCESS;
257}
258
259static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
260{
261 sljit_sw diff;
262 sljit_uw target_addr;
263 sljit_sw extra_jump_flags;
264
265#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
266 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
267 return 0;
268#else
269 if (jump->flags & SLJIT_REWRITABLE_JUMP)
270 return 0;
271#endif
272
273 if (jump->flags & JUMP_ADDR)
274 target_addr = jump->u.target;
275 else {
276 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
277 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
278 }
279
280#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
281 if (jump->flags & IS_CALL)
282 goto keep_address;
283#endif
284
285 diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
286
287 extra_jump_flags = 0;
288 if (jump->flags & IS_COND) {
289 if (diff <= 0x7fff && diff >= -0x8000) {
290 jump->flags |= PATCH_B;
291 return 1;
292 }
293 if (target_addr <= 0xffff) {
294 jump->flags |= PATCH_B | PATCH_ABS_B;
295 return 1;
296 }
297 extra_jump_flags = REMOVE_COND;
298
299 diff -= sizeof(sljit_ins);
300 }
301
302 if (diff <= 0x01ffffff && diff >= -0x02000000) {
303 jump->flags |= PATCH_B | extra_jump_flags;
304 return 1;
305 }
306
307 if (target_addr <= 0x03ffffff) {
308 jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
309 return 1;
310 }
311
312#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
313#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
314keep_address:
315#endif
316 if (target_addr <= 0x7fffffff) {
317 jump->flags |= PATCH_ABS32;
318 return 1;
319 }
320
321 if (target_addr <= 0x7fffffffffffl) {
322 jump->flags |= PATCH_ABS48;
323 return 1;
324 }
325#endif
326
327 return 0;
328}
329
330#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
331
332static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
333{
334 if (max_label < 0x100000000l) {
335 put_label->flags = 0;
336 return 1;
337 }
338
339 if (max_label < 0x1000000000000l) {
340 put_label->flags = 1;
341 return 3;
342 }
343
344 put_label->flags = 2;
345 return 4;
346}
347
348static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
349{
350 sljit_uw addr = put_label->label->addr;
351 sljit_ins *inst = (sljit_ins *)put_label->addr;
352 sljit_s32 reg = *inst;
353
354 if (put_label->flags == 0) {
355 SLJIT_ASSERT(addr < 0x100000000l);
356 inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);
357 }
358 else {
359 if (put_label->flags == 1) {
360 SLJIT_ASSERT(addr < 0x1000000000000l);
361 inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32);
362 }
363 else {
364 inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48);
365 inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff);
366 inst ++;
367 }
368
369 inst[1] = RLDI(reg, reg, 32, 31, 1);
370 inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);
371 inst += 2;
372 }
373
374 inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);
375}
376
377#endif
378
379SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
380{
381 struct sljit_memory_fragment *buf;
382 sljit_ins *code;
383 sljit_ins *code_ptr;
384 sljit_ins *buf_ptr;
385 sljit_ins *buf_end;
386 sljit_uw word_count;
387 sljit_uw next_addr;
388 sljit_sw executable_offset;
389 sljit_uw addr;
390
391 struct sljit_label *label;
392 struct sljit_jump *jump;
393 struct sljit_const *const_;
394 struct sljit_put_label *put_label;
395
396 CHECK_ERROR_PTR();
397 CHECK_PTR(check_sljit_generate_code(compiler));
398 reverse_buf(compiler);
399
400#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
401#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
402 compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
403#else
404 compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
405#endif
406#endif
407 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);
408 PTR_FAIL_WITH_EXEC_IF(code);
409 buf = compiler->buf;
410
411 code_ptr = code;
412 word_count = 0;
413 next_addr = 0;
414 executable_offset = SLJIT_EXEC_OFFSET(code);
415
416 label = compiler->labels;
417 jump = compiler->jumps;
418 const_ = compiler->consts;
419 put_label = compiler->put_labels;
420
421 do {
422 buf_ptr = (sljit_ins*)buf->memory;
423 buf_end = buf_ptr + (buf->used_size >> 2);
424 do {
425 *code_ptr = *buf_ptr++;
426 if (next_addr == word_count) {
427 SLJIT_ASSERT(!label || label->size >= word_count);
428 SLJIT_ASSERT(!jump || jump->addr >= word_count);
429 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
430 SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
431
432 /* These structures are ordered by their address. */
433 if (label && label->size == word_count) {
434 /* Just recording the address. */
435 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
436 label->size = code_ptr - code;
437 label = label->next;
438 }
439 if (jump && jump->addr == word_count) {
440#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
441 jump->addr = (sljit_uw)(code_ptr - 3);
442#else
443 jump->addr = (sljit_uw)(code_ptr - 6);
444#endif
445 if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
446#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
447 code_ptr[-3] = code_ptr[0];
448 code_ptr -= 3;
449#else
450 if (jump->flags & PATCH_ABS32) {
451 code_ptr -= 3;
452 code_ptr[-1] = code_ptr[2];
453 code_ptr[0] = code_ptr[3];
454 }
455 else if (jump->flags & PATCH_ABS48) {
456 code_ptr--;
457 code_ptr[-1] = code_ptr[0];
458 code_ptr[0] = code_ptr[1];
459 /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
460 SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
461 code_ptr[-3] ^= 0x8422;
462 /* oris -> ori */
463 code_ptr[-2] ^= 0x4000000;
464 }
465 else {
466 code_ptr[-6] = code_ptr[0];
467 code_ptr -= 6;
468 }
469#endif
470 if (jump->flags & REMOVE_COND) {
471 code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
472 code_ptr++;
473 jump->addr += sizeof(sljit_ins);
474 code_ptr[0] = Bx;
475 jump->flags -= IS_COND;
476 }
477 }
478 jump = jump->next;
479 }
480 if (const_ && const_->addr == word_count) {
481 const_->addr = (sljit_uw)code_ptr;
482 const_ = const_->next;
483 }
484 if (put_label && put_label->addr == word_count) {
485 SLJIT_ASSERT(put_label->label);
486 put_label->addr = (sljit_uw)code_ptr;
487#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
488 code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
489 word_count += 4;
490#endif
491 put_label = put_label->next;
492 }
493 next_addr = compute_next_addr(label, jump, const_, put_label);
494 }
495 code_ptr ++;
496 word_count ++;
497 } while (buf_ptr < buf_end);
498
499 buf = buf->next;
500 } while (buf);
501
502 if (label && label->size == word_count) {
503 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
504 label->size = code_ptr - code;
505 label = label->next;
506 }
507
508 SLJIT_ASSERT(!label);
509 SLJIT_ASSERT(!jump);
510 SLJIT_ASSERT(!const_);
511 SLJIT_ASSERT(!put_label);
512
513#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
514 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
515#else
516 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
517#endif
518
519 jump = compiler->jumps;
520 while (jump) {
521 do {
522 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
523 buf_ptr = (sljit_ins *)jump->addr;
524
525 if (jump->flags & PATCH_B) {
526 if (jump->flags & IS_COND) {
527 if (!(jump->flags & PATCH_ABS_B)) {
528 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
529 SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
530 *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
531 }
532 else {
533 SLJIT_ASSERT(addr <= 0xffff);
534 *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
535 }
536 }
537 else {
538 if (!(jump->flags & PATCH_ABS_B)) {
539 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
540 SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
541 *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
542 }
543 else {
544 SLJIT_ASSERT(addr <= 0x03ffffff);
545 *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
546 }
547 }
548 break;
549 }
550
551 /* Set the fields of immediate loads. */
552#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
553 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
554 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
555#else
556 if (jump->flags & PATCH_ABS32) {
557 SLJIT_ASSERT(addr <= 0x7fffffff);
558 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
559 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
560 break;
561 }
562 if (jump->flags & PATCH_ABS48) {
563 SLJIT_ASSERT(addr <= 0x7fffffffffff);
564 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
565 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
566 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
567 break;
568 }
569 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
570 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
571 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
572 buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
573#endif
574 } while (0);
575 jump = jump->next;
576 }
577
578 put_label = compiler->put_labels;
579 while (put_label) {
580#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
581 addr = put_label->label->addr;
582 buf_ptr = (sljit_ins *)put_label->addr;
583
584 SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI);
585 buf_ptr[0] |= (addr >> 16) & 0xffff;
586 buf_ptr[1] |= addr & 0xffff;
587#else
588 put_label_set(put_label);
589#endif
590 put_label = put_label->next;
591 }
592
593 compiler->error = SLJIT_ERR_COMPILED;
594 compiler->executable_offset = executable_offset;
595 compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
596
597 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
598
599#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
600#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
601 if (((sljit_sw)code_ptr) & 0x4)
602 code_ptr++;
603#endif
604 sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
605#endif
606
607 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
608
609 SLJIT_CACHE_FLUSH(code, code_ptr);
610 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
611
612#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
613 return code_ptr;
614#else
615 return code;
616#endif
617}
618
619SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
620{
621 switch (feature_type) {
622 case SLJIT_HAS_FPU:
623#ifdef SLJIT_IS_FPU_AVAILABLE
624 return SLJIT_IS_FPU_AVAILABLE;
625#else
626 /* Available by default. */
627 return 1;
628#endif
629
630 /* A saved register is set to a zero value. */
631 case SLJIT_HAS_ZERO_REGISTER:
632 case SLJIT_HAS_CLZ:
633 case SLJIT_HAS_PREFETCH:
634 return 1;
635
636 default:
637 return 0;
638 }
639}
640
641/* --------------------------------------------------------------------- */
642/* Entry, exit */
643/* --------------------------------------------------------------------- */
644
645/* inp_flags: */
646
647/* Creates an index in data_transfer_insts array. */
648#define LOAD_DATA 0x01
649#define INDEXED 0x02
650#define SIGNED_DATA 0x04
651
652#define WORD_DATA 0x00
653#define BYTE_DATA 0x08
654#define HALF_DATA 0x10
655#define INT_DATA 0x18
656/* Separates integer and floating point registers */
657#define GPR_REG 0x1f
658#define DOUBLE_DATA 0x20
659
660#define MEM_MASK 0x7f
661
662/* Other inp_flags. */
663
664/* Integer opertion and set flags -> requires exts on 64 bit systems. */
665#define ALT_SIGN_EXT 0x000100
666/* This flag affects the RC() and OERC() macros. */
667#define ALT_SET_FLAGS 0x000400
668#define ALT_FORM1 0x001000
669#define ALT_FORM2 0x002000
670#define ALT_FORM3 0x004000
671#define ALT_FORM4 0x008000
672#define ALT_FORM5 0x010000
673
674/* Source and destination is register. */
675#define REG_DEST 0x000001
676#define REG1_SOURCE 0x000002
677#define REG2_SOURCE 0x000004
678/*
679ALT_SIGN_EXT 0x000100
680ALT_SET_FLAGS 0x000200
681ALT_FORM1 0x001000
682...
683ALT_FORM5 0x010000 */
684
685#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
686#include "sljitNativePPC_32.c"
687#else
688#include "sljitNativePPC_64.c"
689#endif
690
691#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
692#define STACK_STORE STW
693#define STACK_LOAD LWZ
694#else
695#define STACK_STORE STD
696#define STACK_LOAD LD
697#endif
698
699SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
700 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
701 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
702{
703 sljit_s32 args, i, tmp, offs;
704
705 CHECK_ERROR();
706 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
707 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
708
709 FAIL_IF(push_inst(compiler, MFLR | D(0)));
710 offs = -(sljit_s32)(sizeof(sljit_sw));
711 FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
712
713 tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
714 for (i = SLJIT_S0; i >= tmp; i--) {
715 offs -= (sljit_s32)(sizeof(sljit_sw));
716 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
717 }
718
719 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
720 offs -= (sljit_s32)(sizeof(sljit_sw));
721 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
722 }
723
724 SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
725
726#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
727 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
728#else
729 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
730#endif
731
732 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
733
734 args = get_arg_count(arg_types);
735
736 if (args >= 1)
737 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0)));
738 if (args >= 2)
739 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1)));
740 if (args >= 3)
741 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2)));
742
743 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
744 local_size = (local_size + 15) & ~0xf;
745 compiler->local_size = local_size;
746
747#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
748 if (local_size <= SIMM_MAX)
749 FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
750 else {
751 FAIL_IF(load_immediate(compiler, 0, -local_size));
752 FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
753 }
754#else
755 if (local_size <= SIMM_MAX)
756 FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
757 else {
758 FAIL_IF(load_immediate(compiler, 0, -local_size));
759 FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
760 }
761#endif
762
763 return SLJIT_SUCCESS;
764}
765
766SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
767 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
768 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
769{
770 CHECK_ERROR();
771 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
772 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
773
774 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
775 compiler->local_size = (local_size + 15) & ~0xf;
776 return SLJIT_SUCCESS;
777}
778
779SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
780{
781 sljit_s32 i, tmp, offs;
782
783 CHECK_ERROR();
784 CHECK(check_sljit_emit_return(compiler, op, src, srcw));
785
786 FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
787
788 if (compiler->local_size <= SIMM_MAX)
789 FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size)));
790 else {
791 FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
792 FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0)));
793 }
794
795#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
796 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
797#else
798 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
799#endif
800
801 offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
802
803 tmp = compiler->scratches;
804 for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
805 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
806 offs += (sljit_s32)(sizeof(sljit_sw));
807 }
808
809 tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
810 for (i = tmp; i <= SLJIT_S0; i++) {
811 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
812 offs += (sljit_s32)(sizeof(sljit_sw));
813 }
814
815 FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
816 SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw)));
817
818 FAIL_IF(push_inst(compiler, MTLR | S(0)));
819 FAIL_IF(push_inst(compiler, BLR));
820
821 return SLJIT_SUCCESS;
822}
823
824#undef STACK_STORE
825#undef STACK_LOAD
826
827/* --------------------------------------------------------------------- */
828/* Operators */
829/* --------------------------------------------------------------------- */
830
831/* s/l - store/load (1 bit)
832 i/x - immediate/indexed form
833 u/s - signed/unsigned (1 bit)
834 w/b/h/i - word/byte/half/int allowed (2 bit)
835
836 Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
837
838/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
839#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
840#define INT_ALIGNED 0x10000
841#endif
842
843#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
844#define ARCH_32_64(a, b) a
845#define INST_CODE_AND_DST(inst, flags, reg) \
846 ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
847#else
848#define ARCH_32_64(a, b) b
849#define INST_CODE_AND_DST(inst, flags, reg) \
850 (((inst) & ~INT_ALIGNED) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
851#endif
852
853static const sljit_ins data_transfer_insts[64 + 16] = {
854
855/* -------- Integer -------- */
856
857/* Word. */
858
859/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
860/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
861/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
862/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
863
864/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
865/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
866/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
867/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
868
869/* Byte. */
870
871/* b u i s */ HI(38) /* stb */,
872/* b u i l */ HI(34) /* lbz */,
873/* b u x s */ HI(31) | LO(215) /* stbx */,
874/* b u x l */ HI(31) | LO(87) /* lbzx */,
875
876/* b s i s */ HI(38) /* stb */,
877/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,
878/* b s x s */ HI(31) | LO(215) /* stbx */,
879/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
880
881/* Half. */
882
883/* h u i s */ HI(44) /* sth */,
884/* h u i l */ HI(40) /* lhz */,
885/* h u x s */ HI(31) | LO(407) /* sthx */,
886/* h u x l */ HI(31) | LO(279) /* lhzx */,
887
888/* h s i s */ HI(44) /* sth */,
889/* h s i l */ HI(42) /* lha */,
890/* h s x s */ HI(31) | LO(407) /* sthx */,
891/* h s x l */ HI(31) | LO(343) /* lhax */,
892
893/* Int. */
894
895/* i u i s */ HI(36) /* stw */,
896/* i u i l */ HI(32) /* lwz */,
897/* i u x s */ HI(31) | LO(151) /* stwx */,
898/* i u x l */ HI(31) | LO(23) /* lwzx */,
899
900/* i s i s */ HI(36) /* stw */,
901/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
902/* i s x s */ HI(31) | LO(151) /* stwx */,
903/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
904
905/* -------- Floating point -------- */
906
907/* d i s */ HI(54) /* stfd */,
908/* d i l */ HI(50) /* lfd */,
909/* d x s */ HI(31) | LO(727) /* stfdx */,
910/* d x l */ HI(31) | LO(599) /* lfdx */,
911
912/* s i s */ HI(52) /* stfs */,
913/* s i l */ HI(48) /* lfs */,
914/* s x s */ HI(31) | LO(663) /* stfsx */,
915/* s x l */ HI(31) | LO(535) /* lfsx */,
916};
917
918static const sljit_ins updated_data_transfer_insts[64] = {
919
920/* -------- Integer -------- */
921
922/* Word. */
923
924/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
925/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
926/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
927/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
928
929/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
930/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
931/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
932/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
933
934/* Byte. */
935
936/* b u i s */ HI(39) /* stbu */,
937/* b u i l */ HI(35) /* lbzu */,
938/* b u x s */ HI(31) | LO(247) /* stbux */,
939/* b u x l */ HI(31) | LO(119) /* lbzux */,
940
941/* b s i s */ HI(39) /* stbu */,
942/* b s i l */ 0 /* no such instruction */,
943/* b s x s */ HI(31) | LO(247) /* stbux */,
944/* b s x l */ 0 /* no such instruction */,
945
946/* Half. */
947
948/* h u i s */ HI(45) /* sthu */,
949/* h u i l */ HI(41) /* lhzu */,
950/* h u x s */ HI(31) | LO(439) /* sthux */,
951/* h u x l */ HI(31) | LO(311) /* lhzux */,
952
953/* h s i s */ HI(45) /* sthu */,
954/* h s i l */ HI(43) /* lhau */,
955/* h s x s */ HI(31) | LO(439) /* sthux */,
956/* h s x l */ HI(31) | LO(375) /* lhaux */,
957
958/* Int. */
959
960/* i u i s */ HI(37) /* stwu */,
961/* i u i l */ HI(33) /* lwzu */,
962/* i u x s */ HI(31) | LO(183) /* stwux */,
963/* i u x l */ HI(31) | LO(55) /* lwzux */,
964
965/* i s i s */ HI(37) /* stwu */,
966/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),
967/* i s x s */ HI(31) | LO(183) /* stwux */,
968/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
969
970/* -------- Floating point -------- */
971
972/* d i s */ HI(55) /* stfdu */,
973/* d i l */ HI(51) /* lfdu */,
974/* d x s */ HI(31) | LO(759) /* stfdux */,
975/* d x l */ HI(31) | LO(631) /* lfdux */,
976
977/* s i s */ HI(53) /* stfsu */,
978/* s i l */ HI(49) /* lfsu */,
979/* s x s */ HI(31) | LO(695) /* stfsux */,
980/* s x l */ HI(31) | LO(567) /* lfsux */,
981};
982
983#undef ARCH_32_64
984
985/* Simple cases, (no caching is required). */
986static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
987 sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
988{
989 sljit_ins inst;
990 sljit_s32 offs_reg;
991 sljit_sw high_short;
992
993 /* Should work when (arg & REG_MASK) == 0. */
994 SLJIT_ASSERT(A(0) == 0);
995 SLJIT_ASSERT(arg & SLJIT_MEM);
996
997 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
998 argw &= 0x3;
999 offs_reg = OFFS_REG(arg);
1000
1001 if (argw != 0) {
1002#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1003 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | (argw << 11) | ((31 - argw) << 1)));
1004#else
1005 FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1)));
1006#endif
1007 offs_reg = tmp_reg;
1008 }
1009
1010 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1011
1012#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1013 SLJIT_ASSERT(!(inst & INT_ALIGNED));
1014#endif
1015
1016 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
1017 }
1018
1019 inst = data_transfer_insts[inp_flags & MEM_MASK];
1020 arg &= REG_MASK;
1021
1022#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1023 if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {
1024 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1025
1026 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1027 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1028 }
1029#endif
1030
1031 if (argw <= SIMM_MAX && argw >= SIMM_MIN)
1032 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));
1033
1034#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1035 if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
1036#endif
1037
1038 high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
1039
1040#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1041 SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
1042#else
1043 SLJIT_ASSERT(high_short);
1044#endif
1045
1046 FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16)));
1047 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));
1048
1049#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1050 }
1051
1052 /* The rest is PPC-64 only. */
1053
1054 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1055
1056 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1057 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1058#endif
1059}
1060
1061static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
1062 sljit_s32 dst, sljit_sw dstw,
1063 sljit_s32 src1, sljit_sw src1w,
1064 sljit_s32 src2, sljit_sw src2w)
1065{
1066 /* arg1 goes to TMP_REG1 or src reg
1067 arg2 goes to TMP_REG2, imm or src reg
1068 result goes to TMP_REG2, so put result can use TMP_REG1. */
1069 sljit_s32 dst_r = TMP_REG2;
1070 sljit_s32 src1_r;
1071 sljit_s32 src2_r;
1072 sljit_s32 sugg_src2_r = TMP_REG2;
1073 sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
1074
1075 /* Destination check. */
1076 if (SLOW_IS_REG(dst)) {
1077 dst_r = dst;
1078 flags |= REG_DEST;
1079
1080 if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1081 sugg_src2_r = dst_r;
1082 }
1083
1084 /* Source 1. */
1085 if (FAST_IS_REG(src1)) {
1086 src1_r = src1;
1087 flags |= REG1_SOURCE;
1088 }
1089 else if (src1 & SLJIT_IMM) {
1090 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1091 src1_r = TMP_REG1;
1092 }
1093 else {
1094 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
1095 src1_r = TMP_REG1;
1096 }
1097
1098 /* Source 2. */
1099 if (FAST_IS_REG(src2)) {
1100 src2_r = src2;
1101 flags |= REG2_SOURCE;
1102
1103 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1104 dst_r = src2_r;
1105 }
1106 else if (src2 & SLJIT_IMM) {
1107 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
1108 src2_r = sugg_src2_r;
1109 }
1110 else {
1111 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2));
1112 src2_r = sugg_src2_r;
1113 }
1114
1115 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1116
1117 if (!(dst & SLJIT_MEM))
1118 return SLJIT_SUCCESS;
1119
1120 return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
1121}
1122
1123SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1124{
1125#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1126 sljit_s32 int_op = op & SLJIT_I32_OP;
1127#endif
1128
1129 CHECK_ERROR();
1130 CHECK(check_sljit_emit_op0(compiler, op));
1131
1132 op = GET_OPCODE(op);
1133 switch (op) {
1134 case SLJIT_BREAKPOINT:
1135 case SLJIT_NOP:
1136 return push_inst(compiler, NOP);
1137 case SLJIT_LMUL_UW:
1138 case SLJIT_LMUL_SW:
1139 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1140#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1141 FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1142 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1143#else
1144 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1145 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1146#endif
1147 case SLJIT_DIVMOD_UW:
1148 case SLJIT_DIVMOD_SW:
1149 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1150#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1151 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)));
1152 FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1153#else
1154 FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1155 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1156#endif
1157 return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
1158 case SLJIT_DIV_UW:
1159 case SLJIT_DIV_SW:
1160#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1161 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));
1162#else
1163 return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1164#endif
1165 case SLJIT_ENDBR:
1166 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1167 return SLJIT_SUCCESS;
1168 }
1169
1170 return SLJIT_SUCCESS;
1171}
1172
1173static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1174 sljit_s32 src, sljit_sw srcw)
1175{
1176 if (!(src & OFFS_REG_MASK)) {
1177 if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED)
1178 return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
1179
1180 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1181 /* Works with SLJIT_MEM0() case as well. */
1182 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1183 }
1184
1185 srcw &= 0x3;
1186
1187 if (srcw == 0)
1188 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
1189
1190#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1191 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1)));
1192#else
1193 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
1194#endif
1195 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1196}
1197
1198#define EMIT_MOV(type, type_flags, type_cast) \
1199 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)
1200
1201SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1202 sljit_s32 dst, sljit_sw dstw,
1203 sljit_s32 src, sljit_sw srcw)
1204{
1205 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1206 sljit_s32 op_flags = GET_ALL_FLAGS(op);
1207
1208 CHECK_ERROR();
1209 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1210 ADJUST_LOCAL_OFFSET(dst, dstw);
1211 ADJUST_LOCAL_OFFSET(src, srcw);
1212
1213 op = GET_OPCODE(op);
1214 if ((src & SLJIT_IMM) && srcw == 0)
1215 src = TMP_ZERO;
1216
1217 if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
1218 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1219
1220 if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) {
1221 if (!TYPE_CAST_NEEDED(op))
1222 return SLJIT_SUCCESS;
1223 }
1224
1225#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1226 if (op_flags & SLJIT_I32_OP) {
1227 if (op < SLJIT_NOT) {
1228 if (src & SLJIT_MEM) {
1229 if (op == SLJIT_MOV_S32)
1230 op = SLJIT_MOV_U32;
1231 }
1232 else if (src & SLJIT_IMM) {
1233 if (op == SLJIT_MOV_U32)
1234 op = SLJIT_MOV_S32;
1235 }
1236 }
1237 else {
1238 /* Most operations expect sign extended arguments. */
1239 flags |= INT_DATA | SIGNED_DATA;
1240 if (HAS_FLAGS(op_flags))
1241 flags |= ALT_SIGN_EXT;
1242 }
1243 }
1244#endif
1245
1246 switch (op) {
1247 case SLJIT_MOV:
1248 case SLJIT_MOV_P:
1249#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1250 case SLJIT_MOV_U32:
1251 case SLJIT_MOV_S32:
1252#endif
1253 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
1254
1255#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1256 case SLJIT_MOV_U32:
1257 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
1258
1259 case SLJIT_MOV_S32:
1260 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1261#endif
1262
1263 case SLJIT_MOV_U8:
1264 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1265
1266 case SLJIT_MOV_S8:
1267 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1268
1269 case SLJIT_MOV_U16:
1270 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1271
1272 case SLJIT_MOV_S16:
1273 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1274
1275 case SLJIT_NOT:
1276 return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1277
1278 case SLJIT_NEG:
1279 return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);
1280
1281 case SLJIT_CLZ:
1282#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1283 return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
1284#else
1285 return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1286#endif
1287 }
1288
1289 return SLJIT_SUCCESS;
1290}
1291
1292#undef EMIT_MOV
1293
1294#define TEST_SL_IMM(src, srcw) \
1295 (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1296
1297#define TEST_UL_IMM(src, srcw) \
1298 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
1299
1300#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1301#define TEST_SH_IMM(src, srcw) \
1302 (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
1303#else
1304#define TEST_SH_IMM(src, srcw) \
1305 (((src) & SLJIT_IMM) && !((srcw) & 0xffff))
1306#endif
1307
1308#define TEST_UH_IMM(src, srcw) \
1309 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
1310
1311#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1312#define TEST_ADD_IMM(src, srcw) \
1313 (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
1314#else
1315#define TEST_ADD_IMM(src, srcw) \
1316 ((src) & SLJIT_IMM)
1317#endif
1318
1319#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1320#define TEST_UI_IMM(src, srcw) \
1321 (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
1322#else
1323#define TEST_UI_IMM(src, srcw) \
1324 ((src) & SLJIT_IMM)
1325#endif
1326
1327#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1328#define TEST_ADD_FORM1(op) \
1329 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1330 || (op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_I32_OP | SLJIT_SET_Z | SLJIT_SET_CARRY))
1331#define TEST_SUB_FORM2(op) \
1332 ((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
1333 || (op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_I32_OP | SLJIT_SET_Z))
1334#define TEST_SUB_FORM3(op) \
1335 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1336 || (op & (SLJIT_I32_OP | SLJIT_SET_Z)) == (SLJIT_I32_OP | SLJIT_SET_Z))
1337#else
1338#define TEST_ADD_FORM1(op) \
1339 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1340#define TEST_SUB_FORM2(op) \
1341 (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)
1342#define TEST_SUB_FORM3(op) \
1343 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1344#endif
1345
1346SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1347 sljit_s32 dst, sljit_sw dstw,
1348 sljit_s32 src1, sljit_sw src1w,
1349 sljit_s32 src2, sljit_sw src2w)
1350{
1351 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1352
1353 CHECK_ERROR();
1354 CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1355 ADJUST_LOCAL_OFFSET(dst, dstw);
1356 ADJUST_LOCAL_OFFSET(src1, src1w);
1357 ADJUST_LOCAL_OFFSET(src2, src2w);
1358
1359 if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
1360 return SLJIT_SUCCESS;
1361
1362 if ((src1 & SLJIT_IMM) && src1w == 0)
1363 src1 = TMP_ZERO;
1364 if ((src2 & SLJIT_IMM) && src2w == 0)
1365 src2 = TMP_ZERO;
1366
1367#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1368 if (op & SLJIT_I32_OP) {
1369 /* Most operations expect sign extended arguments. */
1370 flags |= INT_DATA | SIGNED_DATA;
1371 if (src1 & SLJIT_IMM)
1372 src1w = (sljit_s32)(src1w);
1373 if (src2 & SLJIT_IMM)
1374 src2w = (sljit_s32)(src2w);
1375 if (HAS_FLAGS(op))
1376 flags |= ALT_SIGN_EXT;
1377 }
1378#endif
1379 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1380 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1381
1382 switch (GET_OPCODE(op)) {
1383 case SLJIT_ADD:
1384 if (TEST_ADD_FORM1(op))
1385 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1386
1387 if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1388 if (TEST_SL_IMM(src2, src2w)) {
1389 compiler->imm = src2w & 0xffff;
1390 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1391 }
1392 if (TEST_SL_IMM(src1, src1w)) {
1393 compiler->imm = src1w & 0xffff;
1394 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1395 }
1396 if (TEST_SH_IMM(src2, src2w)) {
1397 compiler->imm = (src2w >> 16) & 0xffff;
1398 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1399 }
1400 if (TEST_SH_IMM(src1, src1w)) {
1401 compiler->imm = (src1w >> 16) & 0xffff;
1402 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1403 }
1404 /* Range between -1 and -32768 is covered above. */
1405 if (TEST_ADD_IMM(src2, src2w)) {
1406 compiler->imm = src2w & 0xffffffff;
1407 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1408 }
1409 if (TEST_ADD_IMM(src1, src1w)) {
1410 compiler->imm = src1w & 0xffffffff;
1411 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1412 }
1413 }
1414
1415#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1416 if ((op & (SLJIT_I32_OP | SLJIT_SET_Z)) == (SLJIT_I32_OP | SLJIT_SET_Z)) {
1417 if (TEST_SL_IMM(src2, src2w)) {
1418 compiler->imm = src2w & 0xffff;
1419 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
1420 }
1421 if (TEST_SL_IMM(src1, src1w)) {
1422 compiler->imm = src1w & 0xffff;
1423 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
1424 }
1425 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1426 }
1427#endif
1428 if (HAS_FLAGS(op)) {
1429 if (TEST_SL_IMM(src2, src2w)) {
1430 compiler->imm = src2w & 0xffff;
1431 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1432 }
1433 if (TEST_SL_IMM(src1, src1w)) {
1434 compiler->imm = src1w & 0xffff;
1435 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1436 }
1437 }
1438 return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
1439
1440 case SLJIT_ADDC:
1441 return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
1442
1443 case SLJIT_SUB:
1444 if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
1445 if (dst == SLJIT_UNUSED) {
1446 if (TEST_UL_IMM(src2, src2w)) {
1447 compiler->imm = src2w & 0xffff;
1448 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1449 }
1450 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1451 }
1452
1453 if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
1454 compiler->imm = src2w;
1455 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1456 }
1457 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1458 }
1459
1460 if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1461 if (TEST_SL_IMM(src2, src2w)) {
1462 compiler->imm = src2w & 0xffff;
1463 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1464 }
1465 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
1466 }
1467
1468 if (TEST_SUB_FORM2(op)) {
1469 if ((src2 & SLJIT_IMM) && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
1470 compiler->imm = src2w & 0xffff;
1471 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1472 }
1473 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1474 }
1475
1476 if (TEST_SUB_FORM3(op))
1477 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1478
1479 if (TEST_SL_IMM(src2, -src2w)) {
1480 compiler->imm = (-src2w) & 0xffff;
1481 return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
1482 }
1483
1484 if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
1485 compiler->imm = src1w & 0xffff;
1486 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1487 }
1488
1489 if (!HAS_FLAGS(op)) {
1490 if (TEST_SH_IMM(src2, -src2w)) {
1491 compiler->imm = ((-src2w) >> 16) & 0xffff;
1492 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1493 }
1494 /* Range between -1 and -32768 is covered above. */
1495 if (TEST_ADD_IMM(src2, -src2w)) {
1496 compiler->imm = -src2w & 0xffffffff;
1497 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1498 }
1499 }
1500
1501 /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
1502 return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
1503
1504 case SLJIT_SUBC:
1505 return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
1506
1507 case SLJIT_MUL:
1508#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1509 if (op & SLJIT_I32_OP)
1510 flags |= ALT_FORM2;
1511#endif
1512 if (!HAS_FLAGS(op)) {
1513 if (TEST_SL_IMM(src2, src2w)) {
1514 compiler->imm = src2w & 0xffff;
1515 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1516 }
1517 if (TEST_SL_IMM(src1, src1w)) {
1518 compiler->imm = src1w & 0xffff;
1519 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1520 }
1521 }
1522 else
1523 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1524 return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
1525
1526 case SLJIT_AND:
1527 case SLJIT_OR:
1528 case SLJIT_XOR:
1529 /* Commutative unsigned operations. */
1530 if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
1531 if (TEST_UL_IMM(src2, src2w)) {
1532 compiler->imm = src2w;
1533 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1534 }
1535 if (TEST_UL_IMM(src1, src1w)) {
1536 compiler->imm = src1w;
1537 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1538 }
1539 if (TEST_UH_IMM(src2, src2w)) {
1540 compiler->imm = (src2w >> 16) & 0xffff;
1541 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1542 }
1543 if (TEST_UH_IMM(src1, src1w)) {
1544 compiler->imm = (src1w >> 16) & 0xffff;
1545 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1546 }
1547 }
1548 if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) {
1549 /* Unlike or and xor, and resets unwanted bits as well. */
1550 if (TEST_UI_IMM(src2, src2w)) {
1551 compiler->imm = src2w;
1552 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1553 }
1554 if (TEST_UI_IMM(src1, src1w)) {
1555 compiler->imm = src1w;
1556 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1557 }
1558 }
1559 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1560
1561 case SLJIT_SHL:
1562 case SLJIT_LSHR:
1563 case SLJIT_ASHR:
1564#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1565 if (op & SLJIT_I32_OP)
1566 flags |= ALT_FORM2;
1567#endif
1568 if (src2 & SLJIT_IMM) {
1569 compiler->imm = src2w;
1570 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1571 }
1572 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1573 }
1574
1575 return SLJIT_SUCCESS;
1576}
1577
1578#undef TEST_ADD_FORM1
1579#undef TEST_SUB_FORM2
1580#undef TEST_SUB_FORM3
1581
1582SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
1583 sljit_s32 src, sljit_sw srcw)
1584{
1585 CHECK_ERROR();
1586 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1587 ADJUST_LOCAL_OFFSET(src, srcw);
1588
1589 switch (op) {
1590 case SLJIT_FAST_RETURN:
1591 if (FAST_IS_REG(src))
1592 FAIL_IF(push_inst(compiler, MTLR | S(src)));
1593 else {
1594 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
1595 FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
1596 }
1597
1598 return push_inst(compiler, BLR);
1599 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
1600 return SLJIT_SUCCESS;
1601 case SLJIT_PREFETCH_L1:
1602 case SLJIT_PREFETCH_L2:
1603 case SLJIT_PREFETCH_L3:
1604 case SLJIT_PREFETCH_ONCE:
1605 return emit_prefetch(compiler, src, srcw);
1606 }
1607
1608 return SLJIT_SUCCESS;
1609}
1610
1611SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1612{
1613 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1614 return reg_map[reg];
1615}
1616
1617SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1618{
1619 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1620 return freg_map[reg];
1621}
1622
1623SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1624 void *instruction, sljit_s32 size)
1625{
1626 CHECK_ERROR();
1627 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1628
1629 return push_inst(compiler, *(sljit_ins*)instruction);
1630}
1631
1632/* --------------------------------------------------------------------- */
1633/* Floating point operators */
1634/* --------------------------------------------------------------------- */
1635
1636#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
1637#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
1638
1639#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1640#define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
1641#else
1642#define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
1643
1644#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
1645#define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))
1646#define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))
1647#else
1648#define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))
1649#define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))
1650#endif
1651
1652#endif /* SLJIT_CONFIG_PPC_64 */
1653
1654static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1655 sljit_s32 dst, sljit_sw dstw,
1656 sljit_s32 src, sljit_sw srcw)
1657{
1658 if (src & SLJIT_MEM) {
1659 /* We can ignore the temporary data store on the stack from caching point of view. */
1660 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1661 src = TMP_FREG1;
1662 }
1663
1664#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1665 op = GET_OPCODE(op);
1666 FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
1667
1668 if (op == SLJIT_CONV_SW_FROM_F64) {
1669 if (FAST_IS_REG(dst)) {
1670 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1671 return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1672 }
1673 return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
1674 }
1675#else
1676 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
1677#endif
1678
1679 if (FAST_IS_REG(dst)) {
1680 FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));
1681 FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
1682 return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1683 }
1684
1685 SLJIT_ASSERT(dst & SLJIT_MEM);
1686
1687 if (dst & OFFS_REG_MASK) {
1688 dstw &= 0x3;
1689 if (dstw) {
1690#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1691 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1)));
1692#else
1693 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
1694#endif
1695 dstw = TMP_REG1;
1696 }
1697 else
1698 dstw = OFFS_REG(dst);
1699 }
1700 else {
1701 if ((dst & REG_MASK) && !dstw) {
1702 dstw = dst & REG_MASK;
1703 dst = 0;
1704 }
1705 else {
1706 /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
1707 FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
1708 dstw = TMP_REG1;
1709 }
1710 }
1711
1712 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
1713}
1714
1715static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1716 sljit_s32 dst, sljit_sw dstw,
1717 sljit_s32 src, sljit_sw srcw)
1718{
1719#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1720
1721 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1722
1723 if (src & SLJIT_IMM) {
1724 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1725 srcw = (sljit_s32)srcw;
1726 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1727 src = TMP_REG1;
1728 }
1729 else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
1730 if (FAST_IS_REG(src))
1731 FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
1732 else
1733 FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1734 src = TMP_REG1;
1735 }
1736
1737 if (FAST_IS_REG(src)) {
1738 FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1739 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1740 }
1741 else
1742 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1743
1744 FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
1745
1746 if (dst & SLJIT_MEM)
1747 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1748 if (op & SLJIT_F32_OP)
1749 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1750 return SLJIT_SUCCESS;
1751
1752#else
1753
1754 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1755 sljit_s32 invert_sign = 1;
1756
1757 if (src & SLJIT_IMM) {
1758 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
1759 src = TMP_REG1;
1760 invert_sign = 0;
1761 }
1762 else if (!FAST_IS_REG(src)) {
1763 FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1764 src = TMP_REG1;
1765 }
1766
1767 /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))
1768 The double precision format has exactly 53 bit precision, so the lower 32 bit represents
1769 the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000
1770 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating
1771 point value, we need to substract 2^53 + 2^31 from the constructed value. */
1772 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
1773 if (invert_sign)
1774 FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
1775 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1));
1776 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1777 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
1778 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1779 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1780 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1781
1782 FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
1783
1784 if (dst & SLJIT_MEM)
1785 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1786 if (op & SLJIT_F32_OP)
1787 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1788 return SLJIT_SUCCESS;
1789
1790#endif
1791}
1792
1793static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1794 sljit_s32 src1, sljit_sw src1w,
1795 sljit_s32 src2, sljit_sw src2w)
1796{
1797 if (src1 & SLJIT_MEM) {
1798 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
1799 src1 = TMP_FREG1;
1800 }
1801
1802 if (src2 & SLJIT_MEM) {
1803 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
1804 src2 = TMP_FREG2;
1805 }
1806
1807 return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));
1808}
1809
1810SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1811 sljit_s32 dst, sljit_sw dstw,
1812 sljit_s32 src, sljit_sw srcw)
1813{
1814 sljit_s32 dst_r;
1815
1816 CHECK_ERROR();
1817
1818 SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
1819 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1820
1821 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1822 op ^= SLJIT_F32_OP;
1823
1824 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1825
1826 if (src & SLJIT_MEM) {
1827 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));
1828 src = dst_r;
1829 }
1830
1831 switch (GET_OPCODE(op)) {
1832 case SLJIT_CONV_F64_FROM_F32:
1833 op ^= SLJIT_F32_OP;
1834 if (op & SLJIT_F32_OP) {
1835 FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
1836 break;
1837 }
1838 /* Fall through. */
1839 case SLJIT_MOV_F64:
1840 if (src != dst_r) {
1841 if (dst_r != TMP_FREG1)
1842 FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
1843 else
1844 dst_r = src;
1845 }
1846 break;
1847 case SLJIT_NEG_F64:
1848 FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
1849 break;
1850 case SLJIT_ABS_F64:
1851 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
1852 break;
1853 }
1854
1855 if (dst & SLJIT_MEM)
1856 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));
1857 return SLJIT_SUCCESS;
1858}
1859
1860SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1861 sljit_s32 dst, sljit_sw dstw,
1862 sljit_s32 src1, sljit_sw src1w,
1863 sljit_s32 src2, sljit_sw src2w)
1864{
1865 sljit_s32 dst_r;
1866
1867 CHECK_ERROR();
1868 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1869 ADJUST_LOCAL_OFFSET(dst, dstw);
1870 ADJUST_LOCAL_OFFSET(src1, src1w);
1871 ADJUST_LOCAL_OFFSET(src2, src2w);
1872
1873 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
1874
1875 if (src1 & SLJIT_MEM) {
1876 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
1877 src1 = TMP_FREG1;
1878 }
1879
1880 if (src2 & SLJIT_MEM) {
1881 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
1882 src2 = TMP_FREG2;
1883 }
1884
1885 switch (GET_OPCODE(op)) {
1886 case SLJIT_ADD_F64:
1887 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
1888 break;
1889
1890 case SLJIT_SUB_F64:
1891 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
1892 break;
1893
1894 case SLJIT_MUL_F64:
1895 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
1896 break;
1897
1898 case SLJIT_DIV_F64:
1899 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
1900 break;
1901 }
1902
1903 if (dst & SLJIT_MEM)
1904 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
1905
1906 return SLJIT_SUCCESS;
1907}
1908
1909#undef SELECT_FOP
1910
1911/* --------------------------------------------------------------------- */
1912/* Other instructions */
1913/* --------------------------------------------------------------------- */
1914
1915SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
1916{
1917 CHECK_ERROR();
1918 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
1919 ADJUST_LOCAL_OFFSET(dst, dstw);
1920
1921 if (FAST_IS_REG(dst))
1922 return push_inst(compiler, MFLR | D(dst));
1923
1924 /* Memory. */
1925 FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
1926 return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
1927}
1928
1929/* --------------------------------------------------------------------- */
1930/* Conditional instructions */
1931/* --------------------------------------------------------------------- */
1932
1933SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
1934{
1935 struct sljit_label *label;
1936
1937 CHECK_ERROR_PTR();
1938 CHECK_PTR(check_sljit_emit_label(compiler));
1939
1940 if (compiler->last_label && compiler->last_label->size == compiler->size)
1941 return compiler->last_label;
1942
1943 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
1944 PTR_FAIL_IF(!label);
1945 set_label(label, compiler);
1946 return label;
1947}
1948
1949static sljit_ins get_bo_bi_flags(sljit_s32 type)
1950{
1951 switch (type) {
1952 case SLJIT_EQUAL:
1953 return (12 << 21) | (2 << 16);
1954
1955 case SLJIT_NOT_EQUAL:
1956 return (4 << 21) | (2 << 16);
1957
1958 case SLJIT_LESS:
1959 case SLJIT_SIG_LESS:
1960 return (12 << 21) | (0 << 16);
1961
1962 case SLJIT_GREATER_EQUAL:
1963 case SLJIT_SIG_GREATER_EQUAL:
1964 return (4 << 21) | (0 << 16);
1965
1966 case SLJIT_GREATER:
1967 case SLJIT_SIG_GREATER:
1968 return (12 << 21) | (1 << 16);
1969
1970 case SLJIT_LESS_EQUAL:
1971 case SLJIT_SIG_LESS_EQUAL:
1972 return (4 << 21) | (1 << 16);
1973
1974 case SLJIT_LESS_F64:
1975 return (12 << 21) | ((4 + 0) << 16);
1976
1977 case SLJIT_GREATER_EQUAL_F64:
1978 return (4 << 21) | ((4 + 0) << 16);
1979
1980 case SLJIT_GREATER_F64:
1981 return (12 << 21) | ((4 + 1) << 16);
1982
1983 case SLJIT_LESS_EQUAL_F64:
1984 return (4 << 21) | ((4 + 1) << 16);
1985
1986 case SLJIT_OVERFLOW:
1987 return (12 << 21) | (3 << 16);
1988
1989 case SLJIT_NOT_OVERFLOW:
1990 return (4 << 21) | (3 << 16);
1991
1992 case SLJIT_EQUAL_F64:
1993 return (12 << 21) | ((4 + 2) << 16);
1994
1995 case SLJIT_NOT_EQUAL_F64:
1996 return (4 << 21) | ((4 + 2) << 16);
1997
1998 case SLJIT_UNORDERED_F64:
1999 return (12 << 21) | ((4 + 3) << 16);
2000
2001 case SLJIT_ORDERED_F64:
2002 return (4 << 21) | ((4 + 3) << 16);
2003
2004 default:
2005 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
2006 return (20 << 21);
2007 }
2008}
2009
2010SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2011{
2012 struct sljit_jump *jump;
2013 sljit_ins bo_bi_flags;
2014
2015 CHECK_ERROR_PTR();
2016 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2017
2018 bo_bi_flags = get_bo_bi_flags(type & 0xff);
2019 if (!bo_bi_flags)
2020 return NULL;
2021
2022 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2023 PTR_FAIL_IF(!jump);
2024 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2025 type &= 0xff;
2026
2027 /* In PPC, we don't need to touch the arguments. */
2028 if (type < SLJIT_JUMP)
2029 jump->flags |= IS_COND;
2030#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2031 if (type >= SLJIT_CALL)
2032 jump->flags |= IS_CALL;
2033#endif
2034
2035 PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2036 PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));
2037 jump->addr = compiler->size;
2038 PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
2039 return jump;
2040}
2041
2042SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2043 sljit_s32 arg_types)
2044{
2045 CHECK_ERROR_PTR();
2046 CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2047
2048#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2049 PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
2050#endif
2051
2052#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2053 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2054 compiler->skip_checks = 1;
2055#endif
2056
2057 return sljit_emit_jump(compiler, type);
2058}
2059
2060SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2061{
2062 struct sljit_jump *jump = NULL;
2063 sljit_s32 src_r;
2064
2065 CHECK_ERROR();
2066 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2067 ADJUST_LOCAL_OFFSET(src, srcw);
2068
2069 if (FAST_IS_REG(src)) {
2070#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2071 if (type >= SLJIT_CALL) {
2072 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2073 src_r = TMP_CALL_REG;
2074 }
2075 else
2076 src_r = src;
2077#else
2078 src_r = src;
2079#endif
2080 } else if (src & SLJIT_IMM) {
2081 /* These jumps are converted to jump/call instructions when possible. */
2082 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2083 FAIL_IF(!jump);
2084 set_jump(jump, compiler, JUMP_ADDR);
2085 jump->u.target = srcw;
2086#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2087 if (type >= SLJIT_CALL)
2088 jump->flags |= IS_CALL;
2089#endif
2090 FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2091 src_r = TMP_CALL_REG;
2092 }
2093 else {
2094 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2095 src_r = TMP_CALL_REG;
2096 }
2097
2098 FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
2099 if (jump)
2100 jump->addr = compiler->size;
2101 return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
2102}
2103
2104SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
2105 sljit_s32 arg_types,
2106 sljit_s32 src, sljit_sw srcw)
2107{
2108 CHECK_ERROR();
2109 CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
2110
2111#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2112 if (src & SLJIT_MEM) {
2113 ADJUST_LOCAL_OFFSET(src, srcw);
2114 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2115 src = TMP_CALL_REG;
2116 }
2117
2118 FAIL_IF(call_with_args(compiler, arg_types, &src));
2119#endif
2120
2121#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2122 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2123 compiler->skip_checks = 1;
2124#endif
2125
2126 return sljit_emit_ijump(compiler, type, src, srcw);
2127}
2128
2129SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2130 sljit_s32 dst, sljit_sw dstw,
2131 sljit_s32 type)
2132{
2133 sljit_s32 reg, input_flags, cr_bit, invert;
2134 sljit_s32 saved_op = op;
2135 sljit_sw saved_dstw = dstw;
2136
2137 CHECK_ERROR();
2138 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2139 ADJUST_LOCAL_OFFSET(dst, dstw);
2140
2141#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2142 input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
2143#else
2144 input_flags = WORD_DATA;
2145#endif
2146
2147 op = GET_OPCODE(op);
2148 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2149
2150 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2151 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
2152
2153 invert = 0;
2154 cr_bit = 0;
2155
2156 switch (type & 0xff) {
2157 case SLJIT_LESS:
2158 case SLJIT_SIG_LESS:
2159 break;
2160
2161 case SLJIT_GREATER_EQUAL:
2162 case SLJIT_SIG_GREATER_EQUAL:
2163 invert = 1;
2164 break;
2165
2166 case SLJIT_GREATER:
2167 case SLJIT_SIG_GREATER:
2168 cr_bit = 1;
2169 break;
2170
2171 case SLJIT_LESS_EQUAL:
2172 case SLJIT_SIG_LESS_EQUAL:
2173 cr_bit = 1;
2174 invert = 1;
2175 break;
2176
2177 case SLJIT_EQUAL:
2178 cr_bit = 2;
2179 break;
2180
2181 case SLJIT_NOT_EQUAL:
2182 cr_bit = 2;
2183 invert = 1;
2184 break;
2185
2186 case SLJIT_OVERFLOW:
2187 cr_bit = 3;
2188 break;
2189
2190 case SLJIT_NOT_OVERFLOW:
2191 cr_bit = 3;
2192 invert = 1;
2193 break;
2194
2195 case SLJIT_LESS_F64:
2196 cr_bit = 4 + 0;
2197 break;
2198
2199 case SLJIT_GREATER_EQUAL_F64:
2200 cr_bit = 4 + 0;
2201 invert = 1;
2202 break;
2203
2204 case SLJIT_GREATER_F64:
2205 cr_bit = 4 + 1;
2206 break;
2207
2208 case SLJIT_LESS_EQUAL_F64:
2209 cr_bit = 4 + 1;
2210 invert = 1;
2211 break;
2212
2213 case SLJIT_EQUAL_F64:
2214 cr_bit = 4 + 2;
2215 break;
2216
2217 case SLJIT_NOT_EQUAL_F64:
2218 cr_bit = 4 + 2;
2219 invert = 1;
2220 break;
2221
2222 case SLJIT_UNORDERED_F64:
2223 cr_bit = 4 + 3;
2224 break;
2225
2226 case SLJIT_ORDERED_F64:
2227 cr_bit = 4 + 3;
2228 invert = 1;
2229 break;
2230
2231 default:
2232 SLJIT_UNREACHABLE();
2233 break;
2234 }
2235
2236 FAIL_IF(push_inst(compiler, MFCR | D(reg)));
2237 FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1)));
2238
2239 if (invert)
2240 FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
2241
2242 if (op < SLJIT_ADD) {
2243 if (!(dst & SLJIT_MEM))
2244 return SLJIT_SUCCESS;
2245 return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
2246 }
2247
2248#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2249 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2250 compiler->skip_checks = 1;
2251#endif
2252 if (dst & SLJIT_MEM)
2253 return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
2254 return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
2255}
2256
2257SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2258 sljit_s32 dst_reg,
2259 sljit_s32 src, sljit_sw srcw)
2260{
2261 CHECK_ERROR();
2262 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2263
2264 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
2265}
2266
2267SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
2268 sljit_s32 reg,
2269 sljit_s32 mem, sljit_sw memw)
2270{
2271 sljit_s32 mem_flags;
2272 sljit_ins inst;
2273
2274 CHECK_ERROR();
2275 CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
2276
2277 if (type & SLJIT_MEM_POST)
2278 return SLJIT_ERR_UNSUPPORTED;
2279
2280 switch (type & 0xff) {
2281 case SLJIT_MOV:
2282 case SLJIT_MOV_P:
2283#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2284 case SLJIT_MOV_U32:
2285 case SLJIT_MOV_S32:
2286#endif
2287 mem_flags = WORD_DATA;
2288 break;
2289
2290#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2291 case SLJIT_MOV_U32:
2292 mem_flags = INT_DATA;
2293 break;
2294
2295 case SLJIT_MOV_S32:
2296 mem_flags = INT_DATA;
2297
2298 if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_I32_OP)) {
2299 if (mem & OFFS_REG_MASK)
2300 mem_flags |= SIGNED_DATA;
2301 else
2302 return SLJIT_ERR_UNSUPPORTED;
2303 }
2304 break;
2305#endif
2306
2307 case SLJIT_MOV_U8:
2308 case SLJIT_MOV_S8:
2309 mem_flags = BYTE_DATA;
2310 break;
2311
2312 case SLJIT_MOV_U16:
2313 mem_flags = HALF_DATA;
2314 break;
2315
2316 case SLJIT_MOV_S16:
2317 mem_flags = HALF_DATA | SIGNED_DATA;
2318 break;
2319
2320 default:
2321 SLJIT_UNREACHABLE();
2322 mem_flags = WORD_DATA;
2323 break;
2324 }
2325
2326 if (!(type & SLJIT_MEM_STORE))
2327 mem_flags |= LOAD_DATA;
2328
2329 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2330 if (memw != 0)
2331 return SLJIT_ERR_UNSUPPORTED;
2332
2333 if (type & SLJIT_MEM_SUPP)
2334 return SLJIT_SUCCESS;
2335
2336 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2337 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
2338 }
2339 else {
2340 if (memw > SIMM_MAX || memw < SIMM_MIN)
2341 return SLJIT_ERR_UNSUPPORTED;
2342
2343 inst = updated_data_transfer_insts[mem_flags];
2344
2345#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2346 if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)
2347 return SLJIT_ERR_UNSUPPORTED;
2348#endif
2349
2350 if (type & SLJIT_MEM_SUPP)
2351 return SLJIT_SUCCESS;
2352
2353 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
2354 }
2355
2356 if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)
2357 return push_inst(compiler, EXTSB | S(reg) | A(reg));
2358 return SLJIT_SUCCESS;
2359}
2360
2361SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
2362 sljit_s32 freg,
2363 sljit_s32 mem, sljit_sw memw)
2364{
2365 sljit_s32 mem_flags;
2366 sljit_ins inst;
2367
2368 CHECK_ERROR();
2369 CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
2370
2371 if (type & SLJIT_MEM_POST)
2372 return SLJIT_ERR_UNSUPPORTED;
2373
2374 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2375 if (memw != 0)
2376 return SLJIT_ERR_UNSUPPORTED;
2377 }
2378 else {
2379 if (memw > SIMM_MAX || memw < SIMM_MIN)
2380 return SLJIT_ERR_UNSUPPORTED;
2381 }
2382
2383 if (type & SLJIT_MEM_SUPP)
2384 return SLJIT_SUCCESS;
2385
2386 mem_flags = FLOAT_DATA(type);
2387
2388 if (!(type & SLJIT_MEM_STORE))
2389 mem_flags |= LOAD_DATA;
2390
2391 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2392 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2393 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));
2394 }
2395
2396 inst = updated_data_transfer_insts[mem_flags];
2397 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));
2398}
2399
2400SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2401{
2402 struct sljit_const *const_;
2403 sljit_s32 dst_r;
2404
2405 CHECK_ERROR_PTR();
2406 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2407 ADJUST_LOCAL_OFFSET(dst, dstw);
2408
2409 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2410 PTR_FAIL_IF(!const_);
2411 set_const(const_, compiler);
2412
2413 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2414 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
2415
2416 if (dst & SLJIT_MEM)
2417 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2418
2419 return const_;
2420}
2421
2422SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2423{
2424 struct sljit_put_label *put_label;
2425 sljit_s32 dst_r;
2426
2427 CHECK_ERROR_PTR();
2428 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
2429 ADJUST_LOCAL_OFFSET(dst, dstw);
2430
2431 put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
2432 PTR_FAIL_IF(!put_label);
2433 set_put_label(put_label, compiler, 0);
2434
2435 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2436#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2437 PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
2438#else
2439 PTR_FAIL_IF(push_inst(compiler, dst_r));
2440 compiler->size += 4;
2441#endif
2442
2443 if (dst & SLJIT_MEM)
2444 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2445
2446 return put_label;
2447}