Fix incorrect flag settings on PPC.
[sljit.git] / sljit_src / sljitNativePPC_common.c
blob2174dbb07b2f34b9abb176b695986ad72215729b
1 /*
2 * Stack-less Just-In-Time compiler
4 * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
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.
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.
27 SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
29 return "PowerPC" SLJIT_CPUINFO;
32 /* Length of an instruction word.
33 Both for ppc-32 and ppc-64. */
34 typedef sljit_u32 sljit_ins;
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
41 #ifdef _AIX
42 #include <sys/cache.h>
43 #endif
45 #if (defined _CALL_ELF && _CALL_ELF == 2)
46 #define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
47 #endif
49 #if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
51 static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
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)
64 from++;
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)
78 from++;
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 */
92 #endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
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)
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
104 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
105 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
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
111 static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
112 0, 1, 2, 3, 4, 5, 6, 0, 7
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)
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)
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))
230 #define SIMM_MAX (0x7fff)
231 #define SIMM_MIN (-0x8000)
232 #define UIMM_MAX (0xffff)
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))
237 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
238 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
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];
248 #endif
250 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
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;
259 static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
261 sljit_sw diff;
262 sljit_uw target_addr;
263 sljit_sw extra_jump_flags;
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
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;
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
285 diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
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;
293 if (target_addr <= 0xffff) {
294 jump->flags |= PATCH_B | PATCH_ABS_B;
295 return 1;
297 extra_jump_flags = REMOVE_COND;
299 diff -= sizeof(sljit_ins);
302 if (diff <= 0x01ffffff && diff >= -0x02000000) {
303 jump->flags |= PATCH_B | extra_jump_flags;
304 return 1;
307 if (target_addr <= 0x03ffffff) {
308 jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
309 return 1;
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)
314 keep_address:
315 #endif
316 if (target_addr <= 0x7fffffff) {
317 jump->flags |= PATCH_ABS32;
318 return 1;
321 if (target_addr <= 0x7fffffffffffl) {
322 jump->flags |= PATCH_ABS48;
323 return 1;
325 #endif
327 return 0;
330 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
332 static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
334 if (max_label < 0x100000000l) {
335 put_label->flags = 0;
336 return 1;
339 if (max_label < 0x1000000000000l) {
340 put_label->flags = 1;
341 return 3;
344 put_label->flags = 2;
345 return 4;
348 static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
350 sljit_uw addr = put_label->label->addr;
351 sljit_ins *inst = (sljit_ins *)put_label->addr;
352 sljit_s32 reg = *inst;
354 if (put_label->flags == 0) {
355 SLJIT_ASSERT(addr < 0x100000000l);
356 inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);
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);
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 ++;
369 inst[1] = RLDI(reg, reg, 32, 31, 1);
370 inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);
371 inst += 2;
374 inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);
377 #endif
379 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
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;
391 struct sljit_label *label;
392 struct sljit_jump *jump;
393 struct sljit_const *const_;
394 struct sljit_put_label *put_label;
396 CHECK_ERROR_PTR();
397 CHECK_PTR(check_sljit_generate_code(compiler));
398 reverse_buf(compiler);
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;
411 code_ptr = code;
412 word_count = 0;
413 next_addr = 0;
414 executable_offset = SLJIT_EXEC_OFFSET(code);
416 label = compiler->labels;
417 jump = compiler->jumps;
418 const_ = compiler->consts;
419 put_label = compiler->put_labels;
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);
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;
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];
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;
465 else {
466 code_ptr[-6] = code_ptr[0];
467 code_ptr -= 6;
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;
478 jump = jump->next;
480 if (const_ && const_->addr == word_count) {
481 const_->addr = (sljit_uw)code_ptr;
482 const_ = const_->next;
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;
493 next_addr = compute_next_addr(label, jump, const_, put_label);
495 code_ptr ++;
496 word_count ++;
497 } while (buf_ptr < buf_end);
499 buf = buf->next;
500 } while (buf);
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;
508 SLJIT_ASSERT(!label);
509 SLJIT_ASSERT(!jump);
510 SLJIT_ASSERT(!const_);
511 SLJIT_ASSERT(!put_label);
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
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;
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);
532 else {
533 SLJIT_ASSERT(addr <= 0xffff);
534 *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
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);
543 else {
544 SLJIT_ASSERT(addr <= 0x03ffffff);
545 *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
548 break;
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;
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;
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;
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;
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;
593 compiler->error = SLJIT_ERR_COMPILED;
594 compiler->executable_offset = executable_offset;
595 compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
597 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
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
607 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
609 SLJIT_CACHE_FLUSH(code, code_ptr);
610 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
612 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
613 return code_ptr;
614 #else
615 return code;
616 #endif
619 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
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
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;
636 default:
637 return 0;
641 /* --------------------------------------------------------------------- */
642 /* Entry, exit */
643 /* --------------------------------------------------------------------- */
645 /* inp_flags: */
647 /* Creates an index in data_transfer_insts array. */
648 #define LOAD_DATA 0x01
649 #define INDEXED 0x02
650 #define SIGNED_DATA 0x04
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
660 #define MEM_MASK 0x7f
662 /* Other inp_flags. */
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
674 /* Source and destination is register. */
675 #define REG_DEST 0x000001
676 #define REG1_SOURCE 0x000002
677 #define REG2_SOURCE 0x000004
679 ALT_SIGN_EXT 0x000100
680 ALT_SET_FLAGS 0x000200
681 ALT_FORM1 0x001000
683 ALT_FORM5 0x010000 */
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
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
699 SLJIT_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)
703 sljit_s32 args, i, tmp, offs;
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);
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)));
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)));
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)));
724 SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
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
732 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
734 args = get_arg_count(arg_types);
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)));
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;
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)));
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)));
761 #endif
763 return SLJIT_SUCCESS;
766 SLJIT_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)
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);
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;
779 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
781 sljit_s32 i, tmp, offs;
783 CHECK_ERROR();
784 CHECK(check_sljit_emit_return(compiler, op, src, srcw));
786 FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
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)));
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
801 offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
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));
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));
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)));
818 FAIL_IF(push_inst(compiler, MTLR | S(0)));
819 FAIL_IF(push_inst(compiler, BLR));
821 return SLJIT_SUCCESS;
824 #undef STACK_STORE
825 #undef STACK_LOAD
827 /* --------------------------------------------------------------------- */
828 /* Operators */
829 /* --------------------------------------------------------------------- */
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)
836 Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
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
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
853 static const sljit_ins data_transfer_insts[64 + 16] = {
855 /* -------- Integer -------- */
857 /* Word. */
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 */),
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 */),
869 /* Byte. */
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 */,
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 */,
881 /* Half. */
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 */,
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 */,
893 /* Int. */
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 */,
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 */),
905 /* -------- Floating point -------- */
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 */,
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 */,
918 static const sljit_ins updated_data_transfer_insts[64] = {
920 /* -------- Integer -------- */
922 /* Word. */
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 */),
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 */),
934 /* Byte. */
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 */,
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 */,
946 /* Half. */
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 */,
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 */,
958 /* Int. */
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 */,
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 */),
970 /* -------- Floating point -------- */
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 */,
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 */,
983 #undef ARCH_32_64
985 /* Simple cases, (no caching is required). */
986 static 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)
989 sljit_ins inst;
990 sljit_s32 offs_reg;
991 sljit_sw high_short;
993 /* Should work when (arg & REG_MASK) == 0. */
994 SLJIT_ASSERT(A(0) == 0);
995 SLJIT_ASSERT(arg & SLJIT_MEM);
997 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
998 argw &= 0x3;
999 offs_reg = OFFS_REG(arg);
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;
1010 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1012 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1013 SLJIT_ASSERT(!(inst & INT_ALIGNED));
1014 #endif
1016 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
1019 inst = data_transfer_insts[inp_flags & MEM_MASK];
1020 arg &= REG_MASK;
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));
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));
1029 #endif
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));
1034 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1035 if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
1036 #endif
1038 high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
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
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));
1049 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1052 /* The rest is PPC-64 only. */
1054 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
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
1061 static 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)
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);
1075 /* Destination check. */
1076 if (SLOW_IS_REG(dst)) {
1077 dst_r = dst;
1078 flags |= REG_DEST;
1080 if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1081 sugg_src2_r = dst_r;
1084 /* Source 1. */
1085 if (FAST_IS_REG(src1)) {
1086 src1_r = src1;
1087 flags |= REG1_SOURCE;
1089 else if (src1 & SLJIT_IMM) {
1090 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1091 src1_r = TMP_REG1;
1093 else {
1094 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
1095 src1_r = TMP_REG1;
1098 /* Source 2. */
1099 if (FAST_IS_REG(src2)) {
1100 src2_r = src2;
1101 flags |= REG2_SOURCE;
1103 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1104 dst_r = src2_r;
1106 else if (src2 & SLJIT_IMM) {
1107 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
1108 src2_r = sugg_src2_r;
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;
1115 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1117 if (!(dst & SLJIT_MEM))
1118 return SLJIT_SUCCESS;
1120 return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
1123 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1125 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1126 sljit_s32 int_op = op & SLJIT_I32_OP;
1127 #endif
1129 CHECK_ERROR();
1130 CHECK(check_sljit_emit_op0(compiler, op));
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;
1170 return SLJIT_SUCCESS;
1173 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1174 sljit_s32 src, sljit_sw srcw)
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));
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));
1185 srcw &= 0x3;
1187 if (srcw == 0)
1188 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
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));
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)
1201 SLJIT_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)
1205 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1206 sljit_s32 op_flags = GET_ALL_FLAGS(op);
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);
1213 op = GET_OPCODE(op);
1214 if ((src & SLJIT_IMM) && srcw == 0)
1215 src = TMP_ZERO;
1217 if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
1218 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1220 if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) {
1221 if (!TYPE_CAST_NEEDED(op))
1222 return SLJIT_SUCCESS;
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;
1232 else if (src & SLJIT_IMM) {
1233 if (op == SLJIT_MOV_U32)
1234 op = SLJIT_MOV_S32;
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;
1244 #endif
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);
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));
1259 case SLJIT_MOV_S32:
1260 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1261 #endif
1263 case SLJIT_MOV_U8:
1264 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1266 case SLJIT_MOV_S8:
1267 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1269 case SLJIT_MOV_U16:
1270 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1272 case SLJIT_MOV_S16:
1273 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1275 case SLJIT_NOT:
1276 return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
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);
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
1289 return SLJIT_SUCCESS;
1292 #undef EMIT_MOV
1294 #define TEST_SL_IMM(src, srcw) \
1295 (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1297 #define TEST_UL_IMM(src, srcw) \
1298 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
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
1308 #define TEST_UH_IMM(src, srcw) \
1309 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
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
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
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
1346 SLJIT_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)
1351 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
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);
1359 if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
1360 return SLJIT_SUCCESS;
1362 if ((src1 & SLJIT_IMM) && src1w == 0)
1363 src1 = TMP_ZERO;
1364 if ((src2 & SLJIT_IMM) && src2w == 0)
1365 src2 = TMP_ZERO;
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;
1378 #endif
1379 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1380 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
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);
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);
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);
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);
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);
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);
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);
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);
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);
1425 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
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);
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);
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);
1440 case SLJIT_ADDC:
1441 return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
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);
1450 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
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);
1457 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
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);
1465 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
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);
1473 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1476 if (TEST_SUB_FORM3(op))
1477 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
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);
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);
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);
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);
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);
1504 case SLJIT_SUBC:
1505 return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1559 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
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);
1572 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1575 return SLJIT_SUCCESS;
1578 #undef TEST_ADD_FORM1
1579 #undef TEST_SUB_FORM2
1580 #undef TEST_SUB_FORM3
1582 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
1583 sljit_s32 src, sljit_sw srcw)
1585 CHECK_ERROR();
1586 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1587 ADJUST_LOCAL_OFFSET(src, srcw);
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)));
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);
1608 return SLJIT_SUCCESS;
1611 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1613 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1614 return reg_map[reg];
1617 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1619 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1620 return freg_map[reg];
1623 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1624 void *instruction, sljit_s32 size)
1626 CHECK_ERROR();
1627 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1629 return push_inst(compiler, *(sljit_ins*)instruction);
1632 /* --------------------------------------------------------------------- */
1633 /* Floating point operators */
1634 /* --------------------------------------------------------------------- */
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)
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))
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
1652 #endif /* SLJIT_CONFIG_PPC_64 */
1654 static 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)
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;
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)));
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);
1673 return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
1675 #else
1676 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
1677 #endif
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);
1685 SLJIT_ASSERT(dst & SLJIT_MEM);
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;
1697 else
1698 dstw = OFFS_REG(dst);
1700 else {
1701 if ((dst & REG_MASK) && !dstw) {
1702 dstw = dst & REG_MASK;
1703 dst = 0;
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;
1712 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
1715 static 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)
1719 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1721 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
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;
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;
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));
1741 else
1742 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1744 FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
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;
1752 #else
1754 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1755 sljit_s32 invert_sign = 1;
1757 if (src & SLJIT_IMM) {
1758 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
1759 src = TMP_REG1;
1760 invert_sign = 0;
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;
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));
1782 FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
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;
1790 #endif
1793 static 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)
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;
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;
1807 return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));
1810 SLJIT_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)
1814 sljit_s32 dst_r;
1816 CHECK_ERROR();
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);
1821 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1822 op ^= SLJIT_F32_OP;
1824 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
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;
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;
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;
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;
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;
1860 SLJIT_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)
1865 sljit_s32 dst_r;
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);
1873 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
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;
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;
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;
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;
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;
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;
1903 if (dst & SLJIT_MEM)
1904 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
1906 return SLJIT_SUCCESS;
1909 #undef SELECT_FOP
1911 /* --------------------------------------------------------------------- */
1912 /* Other instructions */
1913 /* --------------------------------------------------------------------- */
1915 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
1917 CHECK_ERROR();
1918 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
1919 ADJUST_LOCAL_OFFSET(dst, dstw);
1921 if (FAST_IS_REG(dst))
1922 return push_inst(compiler, MFLR | D(dst));
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);
1929 /* --------------------------------------------------------------------- */
1930 /* Conditional instructions */
1931 /* --------------------------------------------------------------------- */
1933 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
1935 struct sljit_label *label;
1937 CHECK_ERROR_PTR();
1938 CHECK_PTR(check_sljit_emit_label(compiler));
1940 if (compiler->last_label && compiler->last_label->size == compiler->size)
1941 return compiler->last_label;
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;
1949 static sljit_ins get_bo_bi_flags(sljit_s32 type)
1951 switch (type) {
1952 case SLJIT_EQUAL:
1953 return (12 << 21) | (2 << 16);
1955 case SLJIT_NOT_EQUAL:
1956 return (4 << 21) | (2 << 16);
1958 case SLJIT_LESS:
1959 case SLJIT_SIG_LESS:
1960 return (12 << 21) | (0 << 16);
1962 case SLJIT_GREATER_EQUAL:
1963 case SLJIT_SIG_GREATER_EQUAL:
1964 return (4 << 21) | (0 << 16);
1966 case SLJIT_GREATER:
1967 case SLJIT_SIG_GREATER:
1968 return (12 << 21) | (1 << 16);
1970 case SLJIT_LESS_EQUAL:
1971 case SLJIT_SIG_LESS_EQUAL:
1972 return (4 << 21) | (1 << 16);
1974 case SLJIT_LESS_F64:
1975 return (12 << 21) | ((4 + 0) << 16);
1977 case SLJIT_GREATER_EQUAL_F64:
1978 return (4 << 21) | ((4 + 0) << 16);
1980 case SLJIT_GREATER_F64:
1981 return (12 << 21) | ((4 + 1) << 16);
1983 case SLJIT_LESS_EQUAL_F64:
1984 return (4 << 21) | ((4 + 1) << 16);
1986 case SLJIT_OVERFLOW:
1987 return (12 << 21) | (3 << 16);
1989 case SLJIT_NOT_OVERFLOW:
1990 return (4 << 21) | (3 << 16);
1992 case SLJIT_EQUAL_F64:
1993 return (12 << 21) | ((4 + 2) << 16);
1995 case SLJIT_NOT_EQUAL_F64:
1996 return (4 << 21) | ((4 + 2) << 16);
1998 case SLJIT_UNORDERED_F64:
1999 return (12 << 21) | ((4 + 3) << 16);
2001 case SLJIT_ORDERED_F64:
2002 return (4 << 21) | ((4 + 3) << 16);
2004 default:
2005 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
2006 return (20 << 21);
2010 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2012 struct sljit_jump *jump;
2013 sljit_ins bo_bi_flags;
2015 CHECK_ERROR_PTR();
2016 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2018 bo_bi_flags = get_bo_bi_flags(type & 0xff);
2019 if (!bo_bi_flags)
2020 return NULL;
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;
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
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;
2042 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2043 sljit_s32 arg_types)
2045 CHECK_ERROR_PTR();
2046 CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2048 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2049 PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
2050 #endif
2052 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2053 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2054 compiler->skip_checks = 1;
2055 #endif
2057 return sljit_emit_jump(compiler, type);
2060 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2062 struct sljit_jump *jump = NULL;
2063 sljit_s32 src_r;
2065 CHECK_ERROR();
2066 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2067 ADJUST_LOCAL_OFFSET(src, srcw);
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;
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;
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;
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));
2104 SLJIT_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)
2108 CHECK_ERROR();
2109 CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
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;
2118 FAIL_IF(call_with_args(compiler, arg_types, &src));
2119 #endif
2121 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2122 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2123 compiler->skip_checks = 1;
2124 #endif
2126 return sljit_emit_ijump(compiler, type, src, srcw);
2129 SLJIT_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)
2133 sljit_s32 reg, input_flags, cr_bit, invert;
2134 sljit_s32 saved_op = op;
2135 sljit_sw saved_dstw = dstw;
2137 CHECK_ERROR();
2138 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2139 ADJUST_LOCAL_OFFSET(dst, dstw);
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
2147 op = GET_OPCODE(op);
2148 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
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));
2153 invert = 0;
2154 cr_bit = 0;
2156 switch (type & 0xff) {
2157 case SLJIT_LESS:
2158 case SLJIT_SIG_LESS:
2159 break;
2161 case SLJIT_GREATER_EQUAL:
2162 case SLJIT_SIG_GREATER_EQUAL:
2163 invert = 1;
2164 break;
2166 case SLJIT_GREATER:
2167 case SLJIT_SIG_GREATER:
2168 cr_bit = 1;
2169 break;
2171 case SLJIT_LESS_EQUAL:
2172 case SLJIT_SIG_LESS_EQUAL:
2173 cr_bit = 1;
2174 invert = 1;
2175 break;
2177 case SLJIT_EQUAL:
2178 cr_bit = 2;
2179 break;
2181 case SLJIT_NOT_EQUAL:
2182 cr_bit = 2;
2183 invert = 1;
2184 break;
2186 case SLJIT_OVERFLOW:
2187 cr_bit = 3;
2188 break;
2190 case SLJIT_NOT_OVERFLOW:
2191 cr_bit = 3;
2192 invert = 1;
2193 break;
2195 case SLJIT_LESS_F64:
2196 cr_bit = 4 + 0;
2197 break;
2199 case SLJIT_GREATER_EQUAL_F64:
2200 cr_bit = 4 + 0;
2201 invert = 1;
2202 break;
2204 case SLJIT_GREATER_F64:
2205 cr_bit = 4 + 1;
2206 break;
2208 case SLJIT_LESS_EQUAL_F64:
2209 cr_bit = 4 + 1;
2210 invert = 1;
2211 break;
2213 case SLJIT_EQUAL_F64:
2214 cr_bit = 4 + 2;
2215 break;
2217 case SLJIT_NOT_EQUAL_F64:
2218 cr_bit = 4 + 2;
2219 invert = 1;
2220 break;
2222 case SLJIT_UNORDERED_F64:
2223 cr_bit = 4 + 3;
2224 break;
2226 case SLJIT_ORDERED_F64:
2227 cr_bit = 4 + 3;
2228 invert = 1;
2229 break;
2231 default:
2232 SLJIT_UNREACHABLE();
2233 break;
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)));
2239 if (invert)
2240 FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
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);
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);
2257 SLJIT_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)
2261 CHECK_ERROR();
2262 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2264 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
2267 SLJIT_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)
2271 sljit_s32 mem_flags;
2272 sljit_ins inst;
2274 CHECK_ERROR();
2275 CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
2277 if (type & SLJIT_MEM_POST)
2278 return SLJIT_ERR_UNSUPPORTED;
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;
2290 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2291 case SLJIT_MOV_U32:
2292 mem_flags = INT_DATA;
2293 break;
2295 case SLJIT_MOV_S32:
2296 mem_flags = INT_DATA;
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;
2304 break;
2305 #endif
2307 case SLJIT_MOV_U8:
2308 case SLJIT_MOV_S8:
2309 mem_flags = BYTE_DATA;
2310 break;
2312 case SLJIT_MOV_U16:
2313 mem_flags = HALF_DATA;
2314 break;
2316 case SLJIT_MOV_S16:
2317 mem_flags = HALF_DATA | SIGNED_DATA;
2318 break;
2320 default:
2321 SLJIT_UNREACHABLE();
2322 mem_flags = WORD_DATA;
2323 break;
2326 if (!(type & SLJIT_MEM_STORE))
2327 mem_flags |= LOAD_DATA;
2329 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2330 if (memw != 0)
2331 return SLJIT_ERR_UNSUPPORTED;
2333 if (type & SLJIT_MEM_SUPP)
2334 return SLJIT_SUCCESS;
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))));
2339 else {
2340 if (memw > SIMM_MAX || memw < SIMM_MIN)
2341 return SLJIT_ERR_UNSUPPORTED;
2343 inst = updated_data_transfer_insts[mem_flags];
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
2350 if (type & SLJIT_MEM_SUPP)
2351 return SLJIT_SUCCESS;
2353 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
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;
2361 SLJIT_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)
2365 sljit_s32 mem_flags;
2366 sljit_ins inst;
2368 CHECK_ERROR();
2369 CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
2371 if (type & SLJIT_MEM_POST)
2372 return SLJIT_ERR_UNSUPPORTED;
2374 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2375 if (memw != 0)
2376 return SLJIT_ERR_UNSUPPORTED;
2378 else {
2379 if (memw > SIMM_MAX || memw < SIMM_MIN)
2380 return SLJIT_ERR_UNSUPPORTED;
2383 if (type & SLJIT_MEM_SUPP)
2384 return SLJIT_SUCCESS;
2386 mem_flags = FLOAT_DATA(type);
2388 if (!(type & SLJIT_MEM_STORE))
2389 mem_flags |= LOAD_DATA;
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)));
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));
2400 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2402 struct sljit_const *const_;
2403 sljit_s32 dst_r;
2405 CHECK_ERROR_PTR();
2406 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2407 ADJUST_LOCAL_OFFSET(dst, dstw);
2409 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2410 PTR_FAIL_IF(!const_);
2411 set_const(const_, compiler);
2413 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2414 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
2416 if (dst & SLJIT_MEM)
2417 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2419 return const_;
2422 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2424 struct sljit_put_label *put_label;
2425 sljit_s32 dst_r;
2427 CHECK_ERROR_PTR();
2428 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
2429 ADJUST_LOCAL_OFFSET(dst, dstw);
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);
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
2443 if (dst & SLJIT_MEM)
2444 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2446 return put_label;