Support argument passing on PPC64 and SPARC32.
[sljit.git] / sljit_src / sljitNativePPC_common.c
blob55837cc9b909acce30488b2b98294109b6897937
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 SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
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_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
97 #define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 5)
99 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
100 #define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 6)
101 #else
102 #define TMP_CALL_REG TMP_REG2
103 #endif
105 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
106 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
108 static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
109 0, 3, 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 8, 9, 10, 31, 12
112 static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
113 0, 1, 2, 3, 4, 5, 6, 0, 7
116 /* --------------------------------------------------------------------- */
117 /* Instrucion forms */
118 /* --------------------------------------------------------------------- */
119 #define D(d) (reg_map[d] << 21)
120 #define S(s) (reg_map[s] << 21)
121 #define A(a) (reg_map[a] << 16)
122 #define B(b) (reg_map[b] << 11)
123 #define C(c) (reg_map[c] << 6)
124 #define FD(fd) (freg_map[fd] << 21)
125 #define FS(fs) (freg_map[fs] << 21)
126 #define FA(fa) (freg_map[fa] << 16)
127 #define FB(fb) (freg_map[fb] << 11)
128 #define FC(fc) (freg_map[fc] << 6)
129 #define IMM(imm) ((imm) & 0xffff)
130 #define CRD(d) ((d) << 21)
132 /* Instruction bit sections.
133 OE and Rc flag (see ALT_SET_FLAGS). */
134 #define OE(flags) ((flags) & ALT_SET_FLAGS)
135 /* Rc flag (see ALT_SET_FLAGS). */
136 #define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10)
137 #define HI(opcode) ((opcode) << 26)
138 #define LO(opcode) ((opcode) << 1)
140 #define ADD (HI(31) | LO(266))
141 #define ADDC (HI(31) | LO(10))
142 #define ADDE (HI(31) | LO(138))
143 #define ADDI (HI(14))
144 #define ADDIC (HI(13))
145 #define ADDIS (HI(15))
146 #define ADDME (HI(31) | LO(234))
147 #define AND (HI(31) | LO(28))
148 #define ANDI (HI(28))
149 #define ANDIS (HI(29))
150 #define Bx (HI(18))
151 #define BCx (HI(16))
152 #define BCCTR (HI(19) | LO(528) | (3 << 11))
153 #define BLR (HI(19) | LO(16) | (0x14 << 21))
154 #define CNTLZD (HI(31) | LO(58))
155 #define CNTLZW (HI(31) | LO(26))
156 #define CMP (HI(31) | LO(0))
157 #define CMPI (HI(11))
158 #define CMPL (HI(31) | LO(32))
159 #define CMPLI (HI(10))
160 #define CROR (HI(19) | LO(449))
161 #define DCBT (HI(31) | LO(278))
162 #define DIVD (HI(31) | LO(489))
163 #define DIVDU (HI(31) | LO(457))
164 #define DIVW (HI(31) | LO(491))
165 #define DIVWU (HI(31) | LO(459))
166 #define EXTSB (HI(31) | LO(954))
167 #define EXTSH (HI(31) | LO(922))
168 #define EXTSW (HI(31) | LO(986))
169 #define FABS (HI(63) | LO(264))
170 #define FADD (HI(63) | LO(21))
171 #define FADDS (HI(59) | LO(21))
172 #define FCFID (HI(63) | LO(846))
173 #define FCMPU (HI(63) | LO(0))
174 #define FCTIDZ (HI(63) | LO(815))
175 #define FCTIWZ (HI(63) | LO(15))
176 #define FDIV (HI(63) | LO(18))
177 #define FDIVS (HI(59) | LO(18))
178 #define FMR (HI(63) | LO(72))
179 #define FMUL (HI(63) | LO(25))
180 #define FMULS (HI(59) | LO(25))
181 #define FNEG (HI(63) | LO(40))
182 #define FRSP (HI(63) | LO(12))
183 #define FSUB (HI(63) | LO(20))
184 #define FSUBS (HI(59) | LO(20))
185 #define LD (HI(58) | 0)
186 #define LWZ (HI(32))
187 #define MFCR (HI(31) | LO(19))
188 #define MFLR (HI(31) | LO(339) | 0x80000)
189 #define MFXER (HI(31) | LO(339) | 0x10000)
190 #define MTCTR (HI(31) | LO(467) | 0x90000)
191 #define MTLR (HI(31) | LO(467) | 0x80000)
192 #define MTXER (HI(31) | LO(467) | 0x10000)
193 #define MULHD (HI(31) | LO(73))
194 #define MULHDU (HI(31) | LO(9))
195 #define MULHW (HI(31) | LO(75))
196 #define MULHWU (HI(31) | LO(11))
197 #define MULLD (HI(31) | LO(233))
198 #define MULLI (HI(7))
199 #define MULLW (HI(31) | LO(235))
200 #define NEG (HI(31) | LO(104))
201 #define NOP (HI(24))
202 #define NOR (HI(31) | LO(124))
203 #define OR (HI(31) | LO(444))
204 #define ORI (HI(24))
205 #define ORIS (HI(25))
206 #define RLDICL (HI(30))
207 #define RLWINM (HI(21))
208 #define SLD (HI(31) | LO(27))
209 #define SLW (HI(31) | LO(24))
210 #define SRAD (HI(31) | LO(794))
211 #define SRADI (HI(31) | LO(413 << 1))
212 #define SRAW (HI(31) | LO(792))
213 #define SRAWI (HI(31) | LO(824))
214 #define SRD (HI(31) | LO(539))
215 #define SRW (HI(31) | LO(536))
216 #define STD (HI(62) | 0)
217 #define STDU (HI(62) | 1)
218 #define STDUX (HI(31) | LO(181))
219 #define STFIWX (HI(31) | LO(983))
220 #define STW (HI(36))
221 #define STWU (HI(37))
222 #define STWUX (HI(31) | LO(183))
223 #define SUBF (HI(31) | LO(40))
224 #define SUBFC (HI(31) | LO(8))
225 #define SUBFE (HI(31) | LO(136))
226 #define SUBFIC (HI(8))
227 #define XOR (HI(31) | LO(316))
228 #define XORI (HI(26))
229 #define XORIS (HI(27))
231 #define SIMM_MAX (0x7fff)
232 #define SIMM_MIN (-0x8000)
233 #define UIMM_MAX (0xffff)
235 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
236 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
238 sljit_sw* ptrs;
239 if (func_ptr)
240 *func_ptr = (void*)context;
241 ptrs = (sljit_sw*)func;
242 context->addr = addr ? addr : ptrs[0];
243 context->r2 = ptrs[1];
244 context->r11 = ptrs[2];
246 #endif
248 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
250 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
251 FAIL_IF(!ptr);
252 *ptr = ins;
253 compiler->size++;
254 return SLJIT_SUCCESS;
257 static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
259 sljit_sw diff;
260 sljit_uw target_addr;
261 sljit_sw extra_jump_flags;
263 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
264 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
265 return 0;
266 #else
267 if (jump->flags & SLJIT_REWRITABLE_JUMP)
268 return 0;
269 #endif
271 if (jump->flags & JUMP_ADDR)
272 target_addr = jump->u.target;
273 else {
274 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
275 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
278 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
279 if (jump->flags & IS_CALL)
280 goto keep_address;
281 #endif
283 diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
285 extra_jump_flags = 0;
286 if (jump->flags & IS_COND) {
287 if (diff <= 0x7fff && diff >= -0x8000) {
288 jump->flags |= PATCH_B;
289 return 1;
291 if (target_addr <= 0xffff) {
292 jump->flags |= PATCH_B | PATCH_ABS_B;
293 return 1;
295 extra_jump_flags = REMOVE_COND;
297 diff -= sizeof(sljit_ins);
300 if (diff <= 0x01ffffff && diff >= -0x02000000) {
301 jump->flags |= PATCH_B | extra_jump_flags;
302 return 1;
305 if (target_addr <= 0x03ffffff) {
306 jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
307 return 1;
310 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
311 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
312 keep_address:
313 #endif
314 if (target_addr <= 0x7fffffff) {
315 jump->flags |= PATCH_ABS32;
316 return 1;
319 if (target_addr <= 0x7fffffffffffl) {
320 jump->flags |= PATCH_ABS48;
321 return 1;
323 #endif
325 return 0;
328 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
330 struct sljit_memory_fragment *buf;
331 sljit_ins *code;
332 sljit_ins *code_ptr;
333 sljit_ins *buf_ptr;
334 sljit_ins *buf_end;
335 sljit_uw word_count;
336 sljit_sw executable_offset;
337 sljit_uw addr;
339 struct sljit_label *label;
340 struct sljit_jump *jump;
341 struct sljit_const *const_;
343 CHECK_ERROR_PTR();
344 CHECK_PTR(check_sljit_generate_code(compiler));
345 reverse_buf(compiler);
347 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
348 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
349 compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
350 #else
351 compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
352 #endif
353 #endif
354 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins));
355 PTR_FAIL_WITH_EXEC_IF(code);
356 buf = compiler->buf;
358 code_ptr = code;
359 word_count = 0;
360 executable_offset = SLJIT_EXEC_OFFSET(code);
362 label = compiler->labels;
363 jump = compiler->jumps;
364 const_ = compiler->consts;
366 do {
367 buf_ptr = (sljit_ins*)buf->memory;
368 buf_end = buf_ptr + (buf->used_size >> 2);
369 do {
370 *code_ptr = *buf_ptr++;
371 SLJIT_ASSERT(!label || label->size >= word_count);
372 SLJIT_ASSERT(!jump || jump->addr >= word_count);
373 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
374 /* These structures are ordered by their address. */
375 if (label && label->size == word_count) {
376 /* Just recording the address. */
377 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
378 label->size = code_ptr - code;
379 label = label->next;
381 if (jump && jump->addr == word_count) {
382 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
383 jump->addr = (sljit_uw)(code_ptr - 3);
384 #else
385 jump->addr = (sljit_uw)(code_ptr - 6);
386 #endif
387 if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
388 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
389 code_ptr[-3] = code_ptr[0];
390 code_ptr -= 3;
391 #else
392 if (jump->flags & PATCH_ABS32) {
393 code_ptr -= 3;
394 code_ptr[-1] = code_ptr[2];
395 code_ptr[0] = code_ptr[3];
397 else if (jump->flags & PATCH_ABS48) {
398 code_ptr--;
399 code_ptr[-1] = code_ptr[0];
400 code_ptr[0] = code_ptr[1];
401 /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
402 SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
403 code_ptr[-3] ^= 0x8422;
404 /* oris -> ori */
405 code_ptr[-2] ^= 0x4000000;
407 else {
408 code_ptr[-6] = code_ptr[0];
409 code_ptr -= 6;
411 #endif
412 if (jump->flags & REMOVE_COND) {
413 code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
414 code_ptr++;
415 jump->addr += sizeof(sljit_ins);
416 code_ptr[0] = Bx;
417 jump->flags -= IS_COND;
420 jump = jump->next;
422 if (const_ && const_->addr == word_count) {
423 const_->addr = (sljit_uw)code_ptr;
424 const_ = const_->next;
426 code_ptr ++;
427 word_count ++;
428 } while (buf_ptr < buf_end);
430 buf = buf->next;
431 } while (buf);
433 if (label && label->size == word_count) {
434 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
435 label->size = code_ptr - code;
436 label = label->next;
439 SLJIT_ASSERT(!label);
440 SLJIT_ASSERT(!jump);
441 SLJIT_ASSERT(!const_);
442 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
443 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
444 #else
445 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
446 #endif
448 jump = compiler->jumps;
449 while (jump) {
450 do {
451 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
452 buf_ptr = (sljit_ins *)jump->addr;
454 if (jump->flags & PATCH_B) {
455 if (jump->flags & IS_COND) {
456 if (!(jump->flags & PATCH_ABS_B)) {
457 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
458 SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
459 *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
461 else {
462 SLJIT_ASSERT(addr <= 0xffff);
463 *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
466 else {
467 if (!(jump->flags & PATCH_ABS_B)) {
468 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
469 SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
470 *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
472 else {
473 SLJIT_ASSERT(addr <= 0x03ffffff);
474 *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
477 break;
480 /* Set the fields of immediate loads. */
481 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
482 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
483 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
484 #else
485 if (jump->flags & PATCH_ABS32) {
486 SLJIT_ASSERT(addr <= 0x7fffffff);
487 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
488 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
489 break;
491 if (jump->flags & PATCH_ABS48) {
492 SLJIT_ASSERT(addr <= 0x7fffffffffff);
493 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
494 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
495 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
496 break;
498 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
499 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
500 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
501 buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
502 #endif
503 } while (0);
504 jump = jump->next;
507 compiler->error = SLJIT_ERR_COMPILED;
508 compiler->executable_offset = executable_offset;
509 compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
511 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
513 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
514 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
515 if (((sljit_sw)code_ptr) & 0x4)
516 code_ptr++;
517 #endif
518 sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
519 #endif
521 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
523 SLJIT_CACHE_FLUSH(code, code_ptr);
525 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
526 return code_ptr;
527 #else
528 return code;
529 #endif
532 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
534 switch (feature_type) {
535 case SLJIT_HAS_FPU:
536 #ifdef SLJIT_IS_FPU_AVAILABLE
537 return SLJIT_IS_FPU_AVAILABLE;
538 #else
539 /* Available by default. */
540 return 1;
541 #endif
543 case SLJIT_HAS_PRE_UPDATE:
544 case SLJIT_HAS_CLZ:
545 return 1;
547 default:
548 return 0;
552 /* --------------------------------------------------------------------- */
553 /* Entry, exit */
554 /* --------------------------------------------------------------------- */
556 /* inp_flags: */
558 /* Creates an index in data_transfer_insts array. */
559 #define LOAD_DATA 0x01
560 #define INDEXED 0x02
561 #define WRITE_BACK 0x04
562 #define WORD_DATA 0x00
563 #define BYTE_DATA 0x08
564 #define HALF_DATA 0x10
565 #define INT_DATA 0x18
566 #define SIGNED_DATA 0x20
567 /* Separates integer and floating point registers */
568 #define GPR_REG 0x3f
569 #define DOUBLE_DATA 0x40
571 #define MEM_MASK 0x7f
573 /* Other inp_flags. */
575 #define ARG_TEST 0x000100
576 /* Integer opertion and set flags -> requires exts on 64 bit systems. */
577 #define ALT_SIGN_EXT 0x000200
578 /* This flag affects the RC() and OERC() macros. */
579 #define ALT_SET_FLAGS 0x000400
580 #define ALT_KEEP_CACHE 0x000800
581 #define ALT_FORM1 0x010000
582 #define ALT_FORM2 0x020000
583 #define ALT_FORM3 0x040000
584 #define ALT_FORM4 0x080000
585 #define ALT_FORM5 0x100000
587 /* Source and destination is register. */
588 #define REG_DEST 0x000001
589 #define REG1_SOURCE 0x000002
590 #define REG2_SOURCE 0x000004
591 /* getput_arg_fast returned true. */
592 #define FAST_DEST 0x000008
593 /* Multiple instructions are required. */
594 #define SLOW_DEST 0x000010
596 ALT_SIGN_EXT 0x000200
597 ALT_SET_FLAGS 0x000400
598 ALT_FORM1 0x010000
600 ALT_FORM5 0x100000 */
602 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
603 #include "sljitNativePPC_32.c"
604 #else
605 #include "sljitNativePPC_64.c"
606 #endif
608 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
609 #define STACK_STORE STW
610 #define STACK_LOAD LWZ
611 #else
612 #define STACK_STORE STD
613 #define STACK_LOAD LD
614 #endif
616 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
617 sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
618 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
620 sljit_s32 i, tmp, offs;
622 CHECK_ERROR();
623 CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
624 set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
626 FAIL_IF(push_inst(compiler, MFLR | D(0)));
627 offs = -(sljit_s32)(sizeof(sljit_sw));
628 FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
630 tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
631 for (i = SLJIT_S0; i >= tmp; i--) {
632 offs -= (sljit_s32)(sizeof(sljit_sw));
633 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
636 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
637 offs -= (sljit_s32)(sizeof(sljit_sw));
638 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
641 SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
643 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
644 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
645 #else
646 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
647 #endif
649 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
650 if (args >= 1)
651 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0)));
652 if (args >= 2)
653 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1)));
654 if (args >= 3)
655 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2)));
657 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
658 local_size = (local_size + 15) & ~0xf;
659 compiler->local_size = local_size;
661 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
662 if (local_size <= SIMM_MAX)
663 FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
664 else {
665 FAIL_IF(load_immediate(compiler, 0, -local_size));
666 FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
668 #else
669 if (local_size <= SIMM_MAX)
670 FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
671 else {
672 FAIL_IF(load_immediate(compiler, 0, -local_size));
673 FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
675 #endif
677 return SLJIT_SUCCESS;
680 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
681 sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds,
682 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
684 CHECK_ERROR();
685 CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
686 set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);
688 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
689 compiler->local_size = (local_size + 15) & ~0xf;
690 return SLJIT_SUCCESS;
693 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
695 sljit_s32 i, tmp, offs;
697 CHECK_ERROR();
698 CHECK(check_sljit_emit_return(compiler, op, src, srcw));
700 FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
702 if (compiler->local_size <= SIMM_MAX)
703 FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size)));
704 else {
705 FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
706 FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0)));
709 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
710 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
711 #else
712 FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
713 #endif
715 offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
717 tmp = compiler->scratches;
718 for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
719 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
720 offs += (sljit_s32)(sizeof(sljit_sw));
723 tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
724 for (i = tmp; i <= SLJIT_S0; i++) {
725 FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
726 offs += (sljit_s32)(sizeof(sljit_sw));
729 FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
730 SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw)));
732 FAIL_IF(push_inst(compiler, MTLR | S(0)));
733 FAIL_IF(push_inst(compiler, BLR));
735 return SLJIT_SUCCESS;
738 #undef STACK_STORE
739 #undef STACK_LOAD
741 /* --------------------------------------------------------------------- */
742 /* Operators */
743 /* --------------------------------------------------------------------- */
745 /* i/x - immediate/indexed form
746 n/w - no write-back / write-back (1 bit)
747 s/l - store/load (1 bit)
748 u/s - signed/unsigned (1 bit)
749 w/b/h/i - word/byte/half/int allowed (2 bit)
750 It contans 32 items, but not all are different. */
752 /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
753 #define INT_ALIGNED 0x10000
754 /* 64-bit only: there is no lwau instruction. */
755 #define UPDATE_REQ 0x20000
757 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
758 #define ARCH_32_64(a, b) a
759 #define INST_CODE_AND_DST(inst, flags, reg) \
760 ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
761 #else
762 #define ARCH_32_64(a, b) b
763 #define INST_CODE_AND_DST(inst, flags, reg) \
764 (((inst) & ~(INT_ALIGNED | UPDATE_REQ)) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
765 #endif
767 static const sljit_ins data_transfer_insts[64 + 16] = {
769 /* -------- Unsigned -------- */
771 /* Word. */
773 /* u w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
774 /* u w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
775 /* u w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
776 /* u w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
778 /* u w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
779 /* u w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
780 /* u w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
781 /* u w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
783 /* Byte. */
785 /* u b n i s */ HI(38) /* stb */,
786 /* u b n i l */ HI(34) /* lbz */,
787 /* u b n x s */ HI(31) | LO(215) /* stbx */,
788 /* u b n x l */ HI(31) | LO(87) /* lbzx */,
790 /* u b w i s */ HI(39) /* stbu */,
791 /* u b w i l */ HI(35) /* lbzu */,
792 /* u b w x s */ HI(31) | LO(247) /* stbux */,
793 /* u b w x l */ HI(31) | LO(119) /* lbzux */,
795 /* Half. */
797 /* u h n i s */ HI(44) /* sth */,
798 /* u h n i l */ HI(40) /* lhz */,
799 /* u h n x s */ HI(31) | LO(407) /* sthx */,
800 /* u h n x l */ HI(31) | LO(279) /* lhzx */,
802 /* u h w i s */ HI(45) /* sthu */,
803 /* u h w i l */ HI(41) /* lhzu */,
804 /* u h w x s */ HI(31) | LO(439) /* sthux */,
805 /* u h w x l */ HI(31) | LO(311) /* lhzux */,
807 /* Int. */
809 /* u i n i s */ HI(36) /* stw */,
810 /* u i n i l */ HI(32) /* lwz */,
811 /* u i n x s */ HI(31) | LO(151) /* stwx */,
812 /* u i n x l */ HI(31) | LO(23) /* lwzx */,
814 /* u i w i s */ HI(37) /* stwu */,
815 /* u i w i l */ HI(33) /* lwzu */,
816 /* u i w x s */ HI(31) | LO(183) /* stwux */,
817 /* u i w x l */ HI(31) | LO(55) /* lwzux */,
819 /* -------- Signed -------- */
821 /* Word. */
823 /* s w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
824 /* s w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
825 /* s w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
826 /* s w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
828 /* s w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
829 /* s w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
830 /* s w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
831 /* s w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
833 /* Byte. */
835 /* s b n i s */ HI(38) /* stb */,
836 /* s b n i l */ HI(34) /* lbz */ /* EXTS_REQ */,
837 /* s b n x s */ HI(31) | LO(215) /* stbx */,
838 /* s b n x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
840 /* s b w i s */ HI(39) /* stbu */,
841 /* s b w i l */ HI(35) /* lbzu */ /* EXTS_REQ */,
842 /* s b w x s */ HI(31) | LO(247) /* stbux */,
843 /* s b w x l */ HI(31) | LO(119) /* lbzux */ /* EXTS_REQ */,
845 /* Half. */
847 /* s h n i s */ HI(44) /* sth */,
848 /* s h n i l */ HI(42) /* lha */,
849 /* s h n x s */ HI(31) | LO(407) /* sthx */,
850 /* s h n x l */ HI(31) | LO(343) /* lhax */,
852 /* s h w i s */ HI(45) /* sthu */,
853 /* s h w i l */ HI(43) /* lhau */,
854 /* s h w x s */ HI(31) | LO(439) /* sthux */,
855 /* s h w x l */ HI(31) | LO(375) /* lhaux */,
857 /* Int. */
859 /* s i n i s */ HI(36) /* stw */,
860 /* s i n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
861 /* s i n x s */ HI(31) | LO(151) /* stwx */,
862 /* s i n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
864 /* s i w i s */ HI(37) /* stwu */,
865 /* s i w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | UPDATE_REQ | 0x2 /* lwa */),
866 /* s i w x s */ HI(31) | LO(183) /* stwux */,
867 /* s i w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
869 /* -------- Double -------- */
871 /* d n i s */ HI(54) /* stfd */,
872 /* d n i l */ HI(50) /* lfd */,
873 /* d n x s */ HI(31) | LO(727) /* stfdx */,
874 /* d n x l */ HI(31) | LO(599) /* lfdx */,
876 /* d w i s */ HI(55) /* stfdu */,
877 /* d w i l */ HI(51) /* lfdu */,
878 /* d w x s */ HI(31) | LO(759) /* stfdux */,
879 /* d w x l */ HI(31) | LO(631) /* lfdux */,
881 /* s n i s */ HI(52) /* stfs */,
882 /* s n i l */ HI(48) /* lfs */,
883 /* s n x s */ HI(31) | LO(663) /* stfsx */,
884 /* s n x l */ HI(31) | LO(535) /* lfsx */,
886 /* s w i s */ HI(53) /* stfsu */,
887 /* s w i l */ HI(49) /* lfsu */,
888 /* s w x s */ HI(31) | LO(695) /* stfsux */,
889 /* s w x l */ HI(31) | LO(567) /* lfsux */,
892 #undef ARCH_32_64
894 /* Simple cases, (no caching is required). */
895 static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
897 sljit_ins inst;
899 /* Should work when (arg & REG_MASK) == 0. */
900 SLJIT_ASSERT(A(0) == 0);
901 SLJIT_ASSERT(arg & SLJIT_MEM);
903 if (arg & OFFS_REG_MASK) {
904 if (argw & 0x3)
905 return 0;
906 if (inp_flags & ARG_TEST)
907 return 1;
909 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
910 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
911 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(OFFS_REG(arg))));
912 return -1;
915 if (SLJIT_UNLIKELY(!(arg & REG_MASK)))
916 inp_flags &= ~WRITE_BACK;
918 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
919 inst = data_transfer_insts[inp_flags & MEM_MASK];
920 SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ));
922 if (argw > SIMM_MAX || argw < SIMM_MIN || ((inst & INT_ALIGNED) && (argw & 0x3)) || (inst & UPDATE_REQ))
923 return 0;
924 if (inp_flags & ARG_TEST)
925 return 1;
926 #endif
928 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
929 if (argw > SIMM_MAX || argw < SIMM_MIN)
930 return 0;
931 if (inp_flags & ARG_TEST)
932 return 1;
934 inst = data_transfer_insts[inp_flags & MEM_MASK];
935 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
936 #endif
938 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | IMM(argw)));
939 return -1;
942 /* See getput_arg below.
943 Note: can_cache is called only for binary operators. Those operator always
944 uses word arguments without write back. */
945 static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
947 sljit_sw high_short, next_high_short;
948 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
949 sljit_sw diff;
950 #endif
952 SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
954 if (arg & OFFS_REG_MASK)
955 return ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && (argw & 0x3) == (next_argw & 0x3));
957 if (next_arg & OFFS_REG_MASK)
958 return 0;
960 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
961 high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff;
962 next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
963 return high_short == next_high_short;
964 #else
965 if (argw <= 0x7fffffffl && argw >= -0x80000000l) {
966 high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff;
967 next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
968 if (high_short == next_high_short)
969 return 1;
972 diff = argw - next_argw;
973 if (!(arg & REG_MASK))
974 return diff <= SIMM_MAX && diff >= SIMM_MIN;
976 if (arg == next_arg && diff <= SIMM_MAX && diff >= SIMM_MIN)
977 return 1;
979 return 0;
980 #endif
983 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
984 #define ADJUST_CACHED_IMM(imm) \
985 if ((inst & INT_ALIGNED) && (imm & 0x3)) { \
986 /* Adjust cached value. Fortunately this is really a rare case */ \
987 compiler->cache_argw += imm & 0x3; \
988 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | (imm & 0x3))); \
989 imm &= ~0x3; \
991 #endif
993 /* Emit the necessary instructions. See can_cache above. */
994 static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
996 sljit_s32 tmp_r;
997 sljit_ins inst;
998 sljit_sw high_short, next_high_short;
999 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1000 sljit_sw diff;
1001 #endif
1003 SLJIT_ASSERT(arg & SLJIT_MEM);
1005 tmp_r = ((inp_flags & LOAD_DATA) && ((inp_flags) & MEM_MASK) <= GPR_REG) ? reg : TMP_REG1;
1006 /* Special case for "mov reg, [reg, ... ]". */
1007 if ((arg & REG_MASK) == tmp_r)
1008 tmp_r = TMP_REG1;
1010 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1011 argw &= 0x3;
1012 /* Otherwise getput_arg_fast would capture it. */
1013 SLJIT_ASSERT(argw);
1015 if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg && argw == compiler->cache_argw)
1016 tmp_r = TMP_REG3;
1017 else {
1018 if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) {
1019 compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1020 compiler->cache_argw = argw;
1021 tmp_r = TMP_REG3;
1023 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1024 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1)));
1025 #else
1026 FAIL_IF(push_inst(compiler, RLDI(tmp_r, OFFS_REG(arg), argw, 63 - argw, 1)));
1027 #endif
1029 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1030 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
1031 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r));
1034 if (SLJIT_UNLIKELY(!(arg & REG_MASK)))
1035 inp_flags &= ~WRITE_BACK;
1037 inst = data_transfer_insts[inp_flags & MEM_MASK];
1038 SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ));
1040 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1041 if (argw <= 0x7fff7fffl && argw >= -0x80000000l
1042 && (!(inst & INT_ALIGNED) || !(argw & 0x3)) && !(inst & UPDATE_REQ)) {
1043 #endif
1045 arg &= REG_MASK;
1046 high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
1047 /* The getput_arg_fast should handle this otherwise. */
1048 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1049 SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
1050 #else
1051 SLJIT_ASSERT(high_short && !(inst & (INT_ALIGNED | UPDATE_REQ)));
1052 #endif
1054 if (inp_flags & WRITE_BACK) {
1055 tmp_r = arg;
1056 FAIL_IF(push_inst(compiler, ADDIS | D(arg) | A(arg) | IMM(high_short >> 16)));
1058 else if (compiler->cache_arg != (SLJIT_MEM | arg) || high_short != compiler->cache_argw) {
1059 if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK)) {
1060 next_high_short = (sljit_s32)(next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff;
1061 if (high_short == next_high_short) {
1062 compiler->cache_arg = SLJIT_MEM | arg;
1063 compiler->cache_argw = high_short;
1064 tmp_r = TMP_REG3;
1067 FAIL_IF(push_inst(compiler, ADDIS | D(tmp_r) | A(arg & REG_MASK) | IMM(high_short >> 16)));
1069 else
1070 tmp_r = TMP_REG3;
1072 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r) | IMM(argw));
1074 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1077 /* Everything else is PPC-64 only. */
1078 if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
1079 diff = argw - compiler->cache_argw;
1080 if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1081 ADJUST_CACHED_IMM(diff);
1082 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff));
1085 diff = argw - next_argw;
1086 if ((next_arg & SLJIT_MEM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1087 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1089 compiler->cache_arg = SLJIT_IMM;
1090 compiler->cache_argw = argw;
1091 tmp_r = TMP_REG3;
1094 FAIL_IF(load_immediate(compiler, tmp_r, argw));
1095 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r));
1098 diff = argw - compiler->cache_argw;
1099 if (compiler->cache_arg == arg && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1100 SLJIT_ASSERT(!(inp_flags & WRITE_BACK) && !(inst & UPDATE_REQ));
1101 ADJUST_CACHED_IMM(diff);
1102 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff));
1105 if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1106 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1107 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
1108 if (compiler->cache_argw != argw) {
1109 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | IMM(diff)));
1110 compiler->cache_argw = argw;
1112 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3));
1115 if (argw == next_argw && (next_arg & SLJIT_MEM)) {
1116 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1117 FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
1119 compiler->cache_arg = SLJIT_IMM;
1120 compiler->cache_argw = argw;
1122 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1123 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
1124 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3));
1127 diff = argw - next_argw;
1128 if (arg == next_arg && !(inp_flags & WRITE_BACK) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1129 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1130 FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
1131 FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | A(TMP_REG3) | B(arg & REG_MASK)));
1133 compiler->cache_arg = arg;
1134 compiler->cache_argw = argw;
1136 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3));
1139 if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK) && diff <= SIMM_MAX && diff >= SIMM_MIN) {
1140 SLJIT_ASSERT(inp_flags & LOAD_DATA);
1141 FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
1143 compiler->cache_arg = SLJIT_IMM;
1144 compiler->cache_argw = argw;
1145 tmp_r = TMP_REG3;
1147 else
1148 FAIL_IF(load_immediate(compiler, tmp_r, argw));
1150 /* Get the indexed version instead of the normal one. */
1151 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1152 SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ)));
1153 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r));
1154 #endif
1157 static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
1159 if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1160 return compiler->error;
1161 return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1164 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
1165 sljit_s32 dst, sljit_sw dstw,
1166 sljit_s32 src1, sljit_sw src1w,
1167 sljit_s32 src2, sljit_sw src2w)
1169 /* arg1 goes to TMP_REG1 or src reg
1170 arg2 goes to TMP_REG2, imm or src reg
1171 TMP_REG3 can be used for caching
1172 result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1173 sljit_s32 dst_r;
1174 sljit_s32 src1_r;
1175 sljit_s32 src2_r;
1176 sljit_s32 sugg_src2_r = TMP_REG2;
1177 sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
1179 if (!(input_flags & ALT_KEEP_CACHE)) {
1180 compiler->cache_arg = 0;
1181 compiler->cache_argw = 0;
1184 /* Destination check. */
1185 if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
1186 dst_r = TMP_REG2;
1188 else if (FAST_IS_REG(dst)) {
1189 dst_r = dst;
1190 flags |= REG_DEST;
1191 if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
1192 sugg_src2_r = dst_r;
1194 else {
1195 SLJIT_ASSERT(dst & SLJIT_MEM);
1196 if (getput_arg_fast(compiler, input_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
1197 flags |= FAST_DEST;
1198 dst_r = TMP_REG2;
1200 else {
1201 flags |= SLOW_DEST;
1202 dst_r = 0;
1206 /* Source 1. */
1207 if (FAST_IS_REG(src1)) {
1208 src1_r = src1;
1209 flags |= REG1_SOURCE;
1211 else if (src1 & SLJIT_IMM) {
1212 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1213 src1_r = TMP_REG1;
1215 else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
1216 FAIL_IF(compiler->error);
1217 src1_r = TMP_REG1;
1219 else
1220 src1_r = 0;
1222 /* Source 2. */
1223 if (FAST_IS_REG(src2)) {
1224 src2_r = src2;
1225 flags |= REG2_SOURCE;
1226 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
1227 dst_r = src2_r;
1229 else if (src2 & SLJIT_IMM) {
1230 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
1231 src2_r = sugg_src2_r;
1233 else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
1234 FAIL_IF(compiler->error);
1235 src2_r = sugg_src2_r;
1237 else
1238 src2_r = 0;
1240 /* src1_r, src2_r and dst_r can be zero (=unprocessed).
1241 All arguments are complex addressing modes, and it is a binary operator. */
1242 if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
1243 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1244 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
1245 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
1247 else {
1248 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
1249 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
1251 src1_r = TMP_REG1;
1252 src2_r = TMP_REG2;
1254 else if (src1_r == 0 && src2_r == 0) {
1255 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
1256 src1_r = TMP_REG1;
1258 else if (src1_r == 0 && dst_r == 0) {
1259 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
1260 src1_r = TMP_REG1;
1262 else if (src2_r == 0 && dst_r == 0) {
1263 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
1264 src2_r = sugg_src2_r;
1267 if (dst_r == 0)
1268 dst_r = TMP_REG2;
1270 if (src1_r == 0) {
1271 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
1272 src1_r = TMP_REG1;
1275 if (src2_r == 0) {
1276 FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
1277 src2_r = sugg_src2_r;
1280 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1282 if (flags & (FAST_DEST | SLOW_DEST)) {
1283 if (flags & FAST_DEST)
1284 FAIL_IF(getput_arg_fast(compiler, input_flags, dst_r, dst, dstw));
1285 else
1286 FAIL_IF(getput_arg(compiler, input_flags, dst_r, dst, dstw, 0, 0));
1288 return SLJIT_SUCCESS;
1291 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1293 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1294 sljit_s32 int_op = op & SLJIT_I32_OP;
1295 #endif
1297 CHECK_ERROR();
1298 CHECK(check_sljit_emit_op0(compiler, op));
1300 op = GET_OPCODE(op);
1301 switch (op) {
1302 case SLJIT_BREAKPOINT:
1303 case SLJIT_NOP:
1304 return push_inst(compiler, NOP);
1305 case SLJIT_LMUL_UW:
1306 case SLJIT_LMUL_SW:
1307 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1308 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1309 FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1310 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1311 #else
1312 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1313 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1314 #endif
1315 case SLJIT_DIVMOD_UW:
1316 case SLJIT_DIVMOD_SW:
1317 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1318 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1319 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)));
1320 FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1321 #else
1322 FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1323 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1324 #endif
1325 return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
1326 case SLJIT_DIV_UW:
1327 case SLJIT_DIV_SW:
1328 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1329 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));
1330 #else
1331 return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1332 #endif
1335 return SLJIT_SUCCESS;
1338 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1339 sljit_s32 src, sljit_sw srcw)
1341 if (!(src & OFFS_REG_MASK)) {
1342 if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED)
1343 return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
1345 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1346 /* Works with SLJIT_MEM0() case as well. */
1347 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1350 srcw &= 0x3;
1352 if (srcw == 0)
1353 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
1355 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1356 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1)));
1357 #else
1358 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
1359 #endif
1360 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1363 #define EMIT_MOV(type, type_flags, type_cast) \
1364 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)
1366 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1367 sljit_s32 dst, sljit_sw dstw,
1368 sljit_s32 src, sljit_sw srcw)
1370 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1371 sljit_s32 op_flags = GET_ALL_FLAGS(op);
1373 CHECK_ERROR();
1374 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1375 ADJUST_LOCAL_OFFSET(dst, dstw);
1376 ADJUST_LOCAL_OFFSET(src, srcw);
1378 if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
1379 if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
1380 return emit_prefetch(compiler, src, srcw);
1382 return SLJIT_SUCCESS;
1385 op = GET_OPCODE(op);
1386 if ((src & SLJIT_IMM) && srcw == 0)
1387 src = TMP_ZERO;
1389 if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
1390 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1392 if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) {
1393 if (!TYPE_CAST_NEEDED(op))
1394 return SLJIT_SUCCESS;
1397 if (op_flags & SLJIT_I32_OP) {
1398 if (op < SLJIT_NOT) {
1399 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1400 if (src & SLJIT_MEM) {
1401 if (op == SLJIT_MOV_S32)
1402 op = SLJIT_MOV_U32;
1403 if (op == SLJIT_MOVU_S32)
1404 op = SLJIT_MOVU_U32;
1406 else if (src & SLJIT_IMM) {
1407 if (op == SLJIT_MOV_U32)
1408 op = SLJIT_MOV_S32;
1409 if (op == SLJIT_MOVU_U32)
1410 op = SLJIT_MOVU_S32;
1412 #endif
1414 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1415 else {
1416 /* Most operations expect sign extended arguments. */
1417 flags |= INT_DATA | SIGNED_DATA;
1418 if (src & SLJIT_IMM)
1419 srcw = (sljit_s32)srcw;
1420 if (HAS_FLAGS(op_flags))
1421 flags |= ALT_SIGN_EXT;
1423 #endif
1426 switch (op) {
1427 case SLJIT_MOV:
1428 case SLJIT_MOV_P:
1429 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1430 case SLJIT_MOV_U32:
1431 case SLJIT_MOV_S32:
1432 #endif
1433 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
1435 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1436 case SLJIT_MOV_U32:
1437 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
1439 case SLJIT_MOV_S32:
1440 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1441 #endif
1443 case SLJIT_MOV_U8:
1444 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1446 case SLJIT_MOV_S8:
1447 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1449 case SLJIT_MOV_U16:
1450 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1452 case SLJIT_MOV_S16:
1453 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1455 case SLJIT_MOVU:
1456 case SLJIT_MOVU_P:
1457 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1458 case SLJIT_MOVU_U32:
1459 case SLJIT_MOVU_S32:
1460 #endif
1461 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
1463 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1464 case SLJIT_MOVU_U32:
1465 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA | WRITE_BACK, (sljit_u32));
1467 case SLJIT_MOVU_S32:
1468 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s32));
1469 #endif
1471 case SLJIT_MOVU_U8:
1472 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, (sljit_u8));
1474 case SLJIT_MOVU_S8:
1475 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s8));
1477 case SLJIT_MOVU_U16:
1478 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, (sljit_u16));
1480 case SLJIT_MOVU_S16:
1481 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s16));
1483 case SLJIT_NOT:
1484 return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1486 case SLJIT_NEG:
1487 return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);
1489 case SLJIT_CLZ:
1490 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1491 return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
1492 #else
1493 return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1494 #endif
1497 return SLJIT_SUCCESS;
1500 #undef EMIT_MOV
1502 #define TEST_SL_IMM(src, srcw) \
1503 (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1505 #define TEST_UL_IMM(src, srcw) \
1506 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
1508 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1509 #define TEST_SH_IMM(src, srcw) \
1510 (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
1511 #else
1512 #define TEST_SH_IMM(src, srcw) \
1513 (((src) & SLJIT_IMM) && !((srcw) & 0xffff))
1514 #endif
1516 #define TEST_UH_IMM(src, srcw) \
1517 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
1519 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1520 #define TEST_ADD_IMM(src, srcw) \
1521 (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
1522 #else
1523 #define TEST_ADD_IMM(src, srcw) \
1524 ((src) & SLJIT_IMM)
1525 #endif
1527 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1528 #define TEST_UI_IMM(src, srcw) \
1529 (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
1530 #else
1531 #define TEST_UI_IMM(src, srcw) \
1532 ((src) & SLJIT_IMM)
1533 #endif
1535 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1536 sljit_s32 dst, sljit_sw dstw,
1537 sljit_s32 src1, sljit_sw src1w,
1538 sljit_s32 src2, sljit_sw src2w)
1540 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1542 CHECK_ERROR();
1543 CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1544 ADJUST_LOCAL_OFFSET(dst, dstw);
1545 ADJUST_LOCAL_OFFSET(src1, src1w);
1546 ADJUST_LOCAL_OFFSET(src2, src2w);
1548 if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
1549 return SLJIT_SUCCESS;
1551 if ((src1 & SLJIT_IMM) && src1w == 0)
1552 src1 = TMP_ZERO;
1553 if ((src2 & SLJIT_IMM) && src2w == 0)
1554 src2 = TMP_ZERO;
1556 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1557 if (op & SLJIT_I32_OP) {
1558 /* Most operations expect sign extended arguments. */
1559 flags |= INT_DATA | SIGNED_DATA;
1560 if (src1 & SLJIT_IMM)
1561 src1w = (sljit_s32)(src1w);
1562 if (src2 & SLJIT_IMM)
1563 src2w = (sljit_s32)(src2w);
1564 if (HAS_FLAGS(op))
1565 flags |= ALT_SIGN_EXT;
1567 #endif
1568 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1569 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1570 if (src2 == TMP_REG2)
1571 flags |= ALT_KEEP_CACHE;
1573 switch (GET_OPCODE(op)) {
1574 case SLJIT_ADD:
1575 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1576 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1578 if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1579 if (TEST_SL_IMM(src2, src2w)) {
1580 compiler->imm = src2w & 0xffff;
1581 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1583 if (TEST_SL_IMM(src1, src1w)) {
1584 compiler->imm = src1w & 0xffff;
1585 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1587 if (TEST_SH_IMM(src2, src2w)) {
1588 compiler->imm = (src2w >> 16) & 0xffff;
1589 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1591 if (TEST_SH_IMM(src1, src1w)) {
1592 compiler->imm = (src1w >> 16) & 0xffff;
1593 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1595 /* Range between -1 and -32768 is covered above. */
1596 if (TEST_ADD_IMM(src2, src2w)) {
1597 compiler->imm = src2w & 0xffffffff;
1598 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1600 if (TEST_ADD_IMM(src1, src1w)) {
1601 compiler->imm = src1w & 0xffffffff;
1602 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1605 if (HAS_FLAGS(op)) {
1606 if (TEST_SL_IMM(src2, src2w)) {
1607 compiler->imm = src2w & 0xffff;
1608 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1610 if (TEST_SL_IMM(src1, src1w)) {
1611 compiler->imm = src1w & 0xffff;
1612 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1615 return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w);
1617 case SLJIT_ADDC:
1618 return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
1620 case SLJIT_SUB:
1621 if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
1622 if (dst == SLJIT_UNUSED) {
1623 if (TEST_UL_IMM(src2, src2w)) {
1624 compiler->imm = src2w & 0xffff;
1625 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1627 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1630 if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
1631 compiler->imm = src2w;
1632 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1634 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1637 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1638 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
1640 if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1641 if (TEST_SL_IMM(src2, -src2w)) {
1642 compiler->imm = (-src2w) & 0xffff;
1643 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1645 if (TEST_SL_IMM(src1, src1w)) {
1646 compiler->imm = src1w & 0xffff;
1647 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1649 if (TEST_SH_IMM(src2, -src2w)) {
1650 compiler->imm = ((-src2w) >> 16) & 0xffff;
1651 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1653 /* Range between -1 and -32768 is covered above. */
1654 if (TEST_ADD_IMM(src2, -src2w)) {
1655 compiler->imm = -src2w & 0xffffffff;
1656 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1660 if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) {
1661 if (TEST_SL_IMM(src2, src2w)) {
1662 compiler->imm = src2w & 0xffff;
1663 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
1665 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1668 if (TEST_SL_IMM(src2, -src2w)) {
1669 compiler->imm = (-src2w) & 0xffff;
1670 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1672 /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
1673 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);
1675 case SLJIT_SUBC:
1676 return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
1678 case SLJIT_MUL:
1679 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1680 if (op & SLJIT_I32_OP)
1681 flags |= ALT_FORM2;
1682 #endif
1683 if (!HAS_FLAGS(op)) {
1684 if (TEST_SL_IMM(src2, src2w)) {
1685 compiler->imm = src2w & 0xffff;
1686 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1688 if (TEST_SL_IMM(src1, src1w)) {
1689 compiler->imm = src1w & 0xffff;
1690 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1693 else
1694 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1695 return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
1697 case SLJIT_AND:
1698 case SLJIT_OR:
1699 case SLJIT_XOR:
1700 /* Commutative unsigned operations. */
1701 if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
1702 if (TEST_UL_IMM(src2, src2w)) {
1703 compiler->imm = src2w;
1704 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1706 if (TEST_UL_IMM(src1, src1w)) {
1707 compiler->imm = src1w;
1708 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1710 if (TEST_UH_IMM(src2, src2w)) {
1711 compiler->imm = (src2w >> 16) & 0xffff;
1712 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1714 if (TEST_UH_IMM(src1, src1w)) {
1715 compiler->imm = (src1w >> 16) & 0xffff;
1716 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1719 if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) {
1720 /* Unlike or and xor, and resets unwanted bits as well. */
1721 if (TEST_UI_IMM(src2, src2w)) {
1722 compiler->imm = src2w;
1723 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1725 if (TEST_UI_IMM(src1, src1w)) {
1726 compiler->imm = src1w;
1727 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1730 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1732 case SLJIT_SHL:
1733 case SLJIT_LSHR:
1734 case SLJIT_ASHR:
1735 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1736 if (op & SLJIT_I32_OP)
1737 flags |= ALT_FORM2;
1738 #endif
1739 if (src2 & SLJIT_IMM) {
1740 compiler->imm = src2w;
1741 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1743 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1746 return SLJIT_SUCCESS;
1749 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1751 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1752 return reg_map[reg];
1755 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1757 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1758 return freg_map[reg];
1761 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1762 void *instruction, sljit_s32 size)
1764 CHECK_ERROR();
1765 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1767 return push_inst(compiler, *(sljit_ins*)instruction);
1770 /* --------------------------------------------------------------------- */
1771 /* Floating point operators */
1772 /* --------------------------------------------------------------------- */
1774 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 5))
1775 #define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
1777 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1778 #define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
1779 #else
1780 #define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
1782 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
1783 #define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))
1784 #define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))
1785 #else
1786 #define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))
1787 #define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))
1788 #endif
1790 #endif /* SLJIT_CONFIG_PPC_64 */
1792 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1793 sljit_s32 dst, sljit_sw dstw,
1794 sljit_s32 src, sljit_sw srcw)
1796 if (src & SLJIT_MEM) {
1797 /* We can ignore the temporary data store on the stack from caching point of view. */
1798 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
1799 src = TMP_FREG1;
1802 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1803 op = GET_OPCODE(op);
1804 FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
1806 if (op == SLJIT_CONV_SW_FROM_F64) {
1807 if (FAST_IS_REG(dst)) {
1808 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0));
1809 return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0);
1811 return emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, 0, 0);
1813 #else
1814 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
1815 #endif
1817 if (FAST_IS_REG(dst)) {
1818 FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));
1819 FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
1820 return emit_op_mem2(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0);
1823 SLJIT_ASSERT(dst & SLJIT_MEM);
1825 if (dst & OFFS_REG_MASK) {
1826 dstw &= 0x3;
1827 if (dstw) {
1828 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1829 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1)));
1830 #else
1831 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
1832 #endif
1833 dstw = TMP_REG1;
1835 else
1836 dstw = OFFS_REG(dst);
1838 else {
1839 if ((dst & REG_MASK) && !dstw) {
1840 dstw = dst & REG_MASK;
1841 dst = 0;
1843 else {
1844 /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
1845 FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
1846 dstw = TMP_REG1;
1850 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
1853 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1854 sljit_s32 dst, sljit_sw dstw,
1855 sljit_s32 src, sljit_sw srcw)
1857 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1859 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1861 if (src & SLJIT_IMM) {
1862 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1863 srcw = (sljit_s32)srcw;
1864 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1865 src = TMP_REG1;
1867 else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
1868 if (FAST_IS_REG(src))
1869 FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
1870 else
1871 FAIL_IF(emit_op_mem2(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1872 src = TMP_REG1;
1875 if (FAST_IS_REG(src)) {
1876 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1877 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, dst, dstw));
1879 else
1880 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
1882 FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
1884 if (dst & SLJIT_MEM)
1885 return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
1886 if (op & SLJIT_F32_OP)
1887 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1888 return SLJIT_SUCCESS;
1890 #else
1892 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1893 sljit_s32 invert_sign = 1;
1895 if (src & SLJIT_IMM) {
1896 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
1897 src = TMP_REG1;
1898 invert_sign = 0;
1900 else if (!FAST_IS_REG(src)) {
1901 FAIL_IF(emit_op_mem2(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
1902 src = TMP_REG1;
1905 /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))
1906 The double precision format has exactly 53 bit precision, so the lower 32 bit represents
1907 the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000
1908 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating
1909 point value, we need to substract 2^53 + 2^31 from the constructed value. */
1910 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
1911 if (invert_sign)
1912 FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
1913 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1914 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI));
1915 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
1916 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
1917 FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET));
1918 FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW));
1920 FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
1922 if (dst & SLJIT_MEM)
1923 return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
1924 if (op & SLJIT_F32_OP)
1925 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1926 return SLJIT_SUCCESS;
1928 #endif
1931 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1932 sljit_s32 src1, sljit_sw src1w,
1933 sljit_s32 src2, sljit_sw src2w)
1935 if (src1 & SLJIT_MEM) {
1936 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
1937 src1 = TMP_FREG1;
1940 if (src2 & SLJIT_MEM) {
1941 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
1942 src2 = TMP_FREG2;
1945 return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2));
1948 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1949 sljit_s32 dst, sljit_sw dstw,
1950 sljit_s32 src, sljit_sw srcw)
1952 sljit_s32 dst_r;
1954 CHECK_ERROR();
1955 compiler->cache_arg = 0;
1956 compiler->cache_argw = 0;
1958 SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
1959 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1961 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1962 op ^= SLJIT_F32_OP;
1964 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1966 if (src & SLJIT_MEM) {
1967 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
1968 src = dst_r;
1971 switch (GET_OPCODE(op)) {
1972 case SLJIT_CONV_F64_FROM_F32:
1973 op ^= SLJIT_F32_OP;
1974 if (op & SLJIT_F32_OP) {
1975 FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
1976 break;
1978 /* Fall through. */
1979 case SLJIT_MOV_F64:
1980 if (src != dst_r) {
1981 if (dst_r != TMP_FREG1)
1982 FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
1983 else
1984 dst_r = src;
1986 break;
1987 case SLJIT_NEG_F64:
1988 FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
1989 break;
1990 case SLJIT_ABS_F64:
1991 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
1992 break;
1995 if (dst & SLJIT_MEM)
1996 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0));
1997 return SLJIT_SUCCESS;
2000 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
2001 sljit_s32 dst, sljit_sw dstw,
2002 sljit_s32 src1, sljit_sw src1w,
2003 sljit_s32 src2, sljit_sw src2w)
2005 sljit_s32 dst_r, flags = 0;
2007 CHECK_ERROR();
2008 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
2009 ADJUST_LOCAL_OFFSET(dst, dstw);
2010 ADJUST_LOCAL_OFFSET(src1, src1w);
2011 ADJUST_LOCAL_OFFSET(src2, src2w);
2013 compiler->cache_arg = 0;
2014 compiler->cache_argw = 0;
2016 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
2018 if (src1 & SLJIT_MEM) {
2019 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
2020 FAIL_IF(compiler->error);
2021 src1 = TMP_FREG1;
2022 } else
2023 flags |= ALT_FORM1;
2026 if (src2 & SLJIT_MEM) {
2027 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
2028 FAIL_IF(compiler->error);
2029 src2 = TMP_FREG2;
2030 } else
2031 flags |= ALT_FORM2;
2034 if ((flags & (ALT_FORM1 | ALT_FORM2)) == (ALT_FORM1 | ALT_FORM2)) {
2035 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
2036 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
2037 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
2039 else {
2040 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
2041 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
2044 else if (flags & ALT_FORM1)
2045 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
2046 else if (flags & ALT_FORM2)
2047 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
2049 if (flags & ALT_FORM1)
2050 src1 = TMP_FREG1;
2051 if (flags & ALT_FORM2)
2052 src2 = TMP_FREG2;
2054 switch (GET_OPCODE(op)) {
2055 case SLJIT_ADD_F64:
2056 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
2057 break;
2059 case SLJIT_SUB_F64:
2060 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
2061 break;
2063 case SLJIT_MUL_F64:
2064 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
2065 break;
2067 case SLJIT_DIV_F64:
2068 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
2069 break;
2072 if (dst_r == TMP_FREG2)
2073 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
2075 return SLJIT_SUCCESS;
2078 #undef FLOAT_DATA
2079 #undef SELECT_FOP
2081 /* --------------------------------------------------------------------- */
2082 /* Other instructions */
2083 /* --------------------------------------------------------------------- */
2085 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2087 CHECK_ERROR();
2088 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
2089 ADJUST_LOCAL_OFFSET(dst, dstw);
2091 if (FAST_IS_REG(dst))
2092 return push_inst(compiler, MFLR | D(dst));
2094 /* Memory. */
2095 FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
2096 return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2099 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
2101 CHECK_ERROR();
2102 CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
2103 ADJUST_LOCAL_OFFSET(src, srcw);
2105 if (FAST_IS_REG(src))
2106 FAIL_IF(push_inst(compiler, MTLR | S(src)));
2107 else {
2108 if (src & SLJIT_MEM)
2109 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
2110 else if (src & SLJIT_IMM)
2111 FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
2112 FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
2114 return push_inst(compiler, BLR);
2117 /* --------------------------------------------------------------------- */
2118 /* Conditional instructions */
2119 /* --------------------------------------------------------------------- */
2121 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2123 struct sljit_label *label;
2125 CHECK_ERROR_PTR();
2126 CHECK_PTR(check_sljit_emit_label(compiler));
2128 if (compiler->last_label && compiler->last_label->size == compiler->size)
2129 return compiler->last_label;
2131 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2132 PTR_FAIL_IF(!label);
2133 set_label(label, compiler);
2134 return label;
2137 static sljit_ins get_bo_bi_flags(sljit_s32 type)
2139 switch (type) {
2140 case SLJIT_EQUAL:
2141 return (12 << 21) | (2 << 16);
2143 case SLJIT_NOT_EQUAL:
2144 return (4 << 21) | (2 << 16);
2146 case SLJIT_LESS:
2147 case SLJIT_SIG_LESS:
2148 return (12 << 21) | (0 << 16);
2150 case SLJIT_GREATER_EQUAL:
2151 case SLJIT_SIG_GREATER_EQUAL:
2152 return (4 << 21) | (0 << 16);
2154 case SLJIT_GREATER:
2155 case SLJIT_SIG_GREATER:
2156 return (12 << 21) | (1 << 16);
2158 case SLJIT_LESS_EQUAL:
2159 case SLJIT_SIG_LESS_EQUAL:
2160 return (4 << 21) | (1 << 16);
2162 case SLJIT_LESS_F64:
2163 return (12 << 21) | ((4 + 0) << 16);
2165 case SLJIT_GREATER_EQUAL_F64:
2166 return (4 << 21) | ((4 + 0) << 16);
2168 case SLJIT_GREATER_F64:
2169 return (12 << 21) | ((4 + 1) << 16);
2171 case SLJIT_LESS_EQUAL_F64:
2172 return (4 << 21) | ((4 + 1) << 16);
2174 case SLJIT_OVERFLOW:
2175 case SLJIT_MUL_OVERFLOW:
2176 return (12 << 21) | (3 << 16);
2178 case SLJIT_NOT_OVERFLOW:
2179 case SLJIT_MUL_NOT_OVERFLOW:
2180 return (4 << 21) | (3 << 16);
2182 case SLJIT_EQUAL_F64:
2183 return (12 << 21) | ((4 + 2) << 16);
2185 case SLJIT_NOT_EQUAL_F64:
2186 return (4 << 21) | ((4 + 2) << 16);
2188 case SLJIT_UNORDERED_F64:
2189 return (12 << 21) | ((4 + 3) << 16);
2191 case SLJIT_ORDERED_F64:
2192 return (4 << 21) | ((4 + 3) << 16);
2194 default:
2195 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
2196 return (20 << 21);
2200 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2202 struct sljit_jump *jump;
2203 sljit_ins bo_bi_flags;
2205 CHECK_ERROR_PTR();
2206 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2208 bo_bi_flags = get_bo_bi_flags(type & 0xff);
2209 if (!bo_bi_flags)
2210 return NULL;
2212 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2213 PTR_FAIL_IF(!jump);
2214 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2215 type &= 0xff;
2217 /* In PPC, we don't need to touch the arguments. */
2218 if (type < SLJIT_JUMP)
2219 jump->flags |= IS_COND;
2220 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2221 if (type >= SLJIT_CALL)
2222 jump->flags |= IS_CALL;
2223 #endif
2225 PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2226 PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));
2227 jump->addr = compiler->size;
2228 PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
2229 return jump;
2232 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2233 sljit_s32 arg_types)
2235 CHECK_ERROR_PTR();
2236 CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2238 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2239 PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
2240 #endif
2242 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2243 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2244 compiler->skip_checks = 1;
2245 #endif
2247 return sljit_emit_jump(compiler, type);
2250 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2252 struct sljit_jump *jump = NULL;
2253 sljit_s32 src_r;
2255 CHECK_ERROR();
2256 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2257 ADJUST_LOCAL_OFFSET(src, srcw);
2259 if (FAST_IS_REG(src)) {
2260 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2261 if (type >= SLJIT_CALL) {
2262 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2263 src_r = TMP_CALL_REG;
2265 else
2266 src_r = src;
2267 #else
2268 src_r = src;
2269 #endif
2270 } else if (src & SLJIT_IMM) {
2271 /* These jumps are converted to jump/call instructions when possible. */
2272 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2273 FAIL_IF(!jump);
2274 set_jump(jump, compiler, JUMP_ADDR);
2275 jump->u.target = srcw;
2276 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2277 if (type >= SLJIT_CALL)
2278 jump->flags |= IS_CALL;
2279 #endif
2280 FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2281 src_r = TMP_CALL_REG;
2283 else {
2284 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2285 src_r = TMP_CALL_REG;
2288 FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
2289 if (jump)
2290 jump->addr = compiler->size;
2291 return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
2294 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
2295 sljit_s32 arg_types,
2296 sljit_s32 src, sljit_sw srcw)
2298 CHECK_ERROR();
2299 CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
2301 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2302 if (src & SLJIT_MEM) {
2303 ADJUST_LOCAL_OFFSET(src, srcw);
2304 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2305 src = TMP_CALL_REG;
2308 FAIL_IF(call_with_args(compiler, arg_types, &src));
2309 #endif
2311 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2312 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2313 compiler->skip_checks = 1;
2314 #endif
2316 return sljit_emit_ijump(compiler, type, src, srcw);
2319 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2320 sljit_s32 dst, sljit_sw dstw,
2321 sljit_s32 type)
2323 sljit_s32 reg, input_flags, cr_bit, invert;
2324 sljit_s32 saved_op = op;
2325 sljit_sw saved_dstw = dstw;
2327 CHECK_ERROR();
2328 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2329 ADJUST_LOCAL_OFFSET(dst, dstw);
2331 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2332 input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
2333 #else
2334 input_flags = WORD_DATA;
2335 #endif
2337 op = GET_OPCODE(op);
2338 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2340 compiler->cache_arg = 0;
2341 compiler->cache_argw = 0;
2343 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2344 FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
2346 invert = 0;
2347 cr_bit = 0;
2349 switch (type & 0xff) {
2350 case SLJIT_LESS:
2351 case SLJIT_SIG_LESS:
2352 break;
2354 case SLJIT_GREATER_EQUAL:
2355 case SLJIT_SIG_GREATER_EQUAL:
2356 invert = 1;
2357 break;
2359 case SLJIT_GREATER:
2360 case SLJIT_SIG_GREATER:
2361 cr_bit = 1;
2362 break;
2364 case SLJIT_LESS_EQUAL:
2365 case SLJIT_SIG_LESS_EQUAL:
2366 cr_bit = 1;
2367 invert = 1;
2368 break;
2370 case SLJIT_EQUAL:
2371 cr_bit = 2;
2372 break;
2374 case SLJIT_NOT_EQUAL:
2375 cr_bit = 2;
2376 invert = 1;
2377 break;
2379 case SLJIT_OVERFLOW:
2380 case SLJIT_MUL_OVERFLOW:
2381 cr_bit = 3;
2382 break;
2384 case SLJIT_NOT_OVERFLOW:
2385 case SLJIT_MUL_NOT_OVERFLOW:
2386 cr_bit = 3;
2387 invert = 1;
2388 break;
2390 case SLJIT_LESS_F64:
2391 cr_bit = 4 + 0;
2392 break;
2394 case SLJIT_GREATER_EQUAL_F64:
2395 cr_bit = 4 + 0;
2396 invert = 1;
2397 break;
2399 case SLJIT_GREATER_F64:
2400 cr_bit = 4 + 1;
2401 break;
2403 case SLJIT_LESS_EQUAL_F64:
2404 cr_bit = 4 + 1;
2405 invert = 1;
2406 break;
2408 case SLJIT_EQUAL_F64:
2409 cr_bit = 4 + 2;
2410 break;
2412 case SLJIT_NOT_EQUAL_F64:
2413 cr_bit = 4 + 2;
2414 invert = 1;
2415 break;
2417 case SLJIT_UNORDERED_F64:
2418 cr_bit = 4 + 3;
2419 break;
2421 case SLJIT_ORDERED_F64:
2422 cr_bit = 4 + 3;
2423 invert = 1;
2424 break;
2426 default:
2427 SLJIT_UNREACHABLE();
2428 break;
2431 FAIL_IF(push_inst(compiler, MFCR | D(reg)));
2432 FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1)));
2434 if (invert)
2435 FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
2437 if (op < SLJIT_ADD) {
2438 if (!(dst & SLJIT_MEM))
2439 return SLJIT_SUCCESS;
2440 return emit_op_mem2(compiler, input_flags, reg, dst, dstw, reg, 0);
2443 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2444 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2445 compiler->skip_checks = 1;
2446 #endif
2447 if (dst & SLJIT_MEM)
2448 return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
2449 return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
2452 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2453 sljit_s32 dst_reg,
2454 sljit_s32 src, sljit_sw srcw)
2456 CHECK_ERROR();
2457 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2459 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
2462 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2464 struct sljit_const *const_;
2465 sljit_s32 reg;
2467 CHECK_ERROR_PTR();
2468 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2469 ADJUST_LOCAL_OFFSET(dst, dstw);
2471 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2472 PTR_FAIL_IF(!const_);
2473 set_const(const_, compiler);
2475 reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
2477 PTR_FAIL_IF(emit_const(compiler, reg, init_value));
2479 if (dst & SLJIT_MEM)
2480 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2481 return const_;