Rework x86-32 stack layout
[sljit.git] / sljit_src / sljitNativePPC_common.c
blob719e772bc49ce3f9c231fae066fae19b418e6936
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, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13
115 /* --------------------------------------------------------------------- */
116 /* Instrucion forms */
117 /* --------------------------------------------------------------------- */
118 #define D(d) ((sljit_ins)reg_map[d] << 21)
119 #define S(s) ((sljit_ins)reg_map[s] << 21)
120 #define A(a) ((sljit_ins)reg_map[a] << 16)
121 #define B(b) ((sljit_ins)reg_map[b] << 11)
122 #define C(c) ((sljit_ins)reg_map[c] << 6)
123 #define FD(fd) ((sljit_ins)freg_map[fd] << 21)
124 #define FS(fs) ((sljit_ins)freg_map[fs] << 21)
125 #define FA(fa) ((sljit_ins)freg_map[fa] << 16)
126 #define FB(fb) ((sljit_ins)freg_map[fb] << 11)
127 #define FC(fc) ((sljit_ins)freg_map[fc] << 6)
128 #define IMM(imm) ((sljit_ins)(imm) & 0xffff)
129 #define CRD(d) ((sljit_ins)(d) << 21)
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) ((sljit_ins)(opcode) << 26)
137 #define LO(opcode) ((sljit_ins)(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 LFD (HI(50))
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 STFD (HI(54))
220 #define STFIWX (HI(31) | LO(983))
221 #define STW (HI(36))
222 #define STWU (HI(37))
223 #define STWUX (HI(31) | LO(183))
224 #define SUBF (HI(31) | LO(40))
225 #define SUBFC (HI(31) | LO(8))
226 #define SUBFE (HI(31) | LO(136))
227 #define SUBFIC (HI(8))
228 #define XOR (HI(31) | LO(316))
229 #define XORI (HI(26))
230 #define XORIS (HI(27))
232 #define SIMM_MAX (0x7fff)
233 #define SIMM_MIN (-0x8000)
234 #define UIMM_MAX (0xffff)
236 #define RLDI(dst, src, sh, mb, type) \
237 (HI(30) | S(src) | A(dst) | ((sljit_ins)(type) << 2) | (((sljit_ins)(sh) & 0x1f) << 11) \
238 | (((sljit_ins)(sh) & 0x20) >> 4) | (((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))
240 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
241 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func)
243 sljit_uw* ptrs;
245 if (func_ptr)
246 *func_ptr = (void*)context;
248 ptrs = (sljit_uw*)func;
249 context->addr = addr ? addr : ptrs[0];
250 context->r2 = ptrs[1];
251 context->r11 = ptrs[2];
253 #endif
255 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
257 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
258 FAIL_IF(!ptr);
259 *ptr = ins;
260 compiler->size++;
261 return SLJIT_SUCCESS;
264 static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
266 sljit_sw diff;
267 sljit_uw target_addr;
268 sljit_uw extra_jump_flags;
270 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
271 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
272 return 0;
273 #else
274 if (jump->flags & SLJIT_REWRITABLE_JUMP)
275 return 0;
276 #endif
278 if (jump->flags & JUMP_ADDR)
279 target_addr = jump->u.target;
280 else {
281 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
282 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
285 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
286 if (jump->flags & IS_CALL)
287 goto keep_address;
288 #endif
290 diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l;
292 extra_jump_flags = 0;
293 if (jump->flags & IS_COND) {
294 if (diff <= 0x7fff && diff >= -0x8000) {
295 jump->flags |= PATCH_B;
296 return 1;
298 if (target_addr <= 0xffff) {
299 jump->flags |= PATCH_B | PATCH_ABS_B;
300 return 1;
302 extra_jump_flags = REMOVE_COND;
304 diff -= SSIZE_OF(ins);
307 if (diff <= 0x01ffffff && diff >= -0x02000000) {
308 jump->flags |= PATCH_B | extra_jump_flags;
309 return 1;
312 if (target_addr <= 0x03ffffff) {
313 jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags;
314 return 1;
317 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
318 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
319 keep_address:
320 #endif
321 if (target_addr <= 0x7fffffff) {
322 jump->flags |= PATCH_ABS32;
323 return 1;
326 if (target_addr <= 0x7fffffffffffl) {
327 jump->flags |= PATCH_ABS48;
328 return 1;
330 #endif
332 return 0;
335 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
337 static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
339 if (max_label < 0x100000000l) {
340 put_label->flags = 0;
341 return 1;
344 if (max_label < 0x1000000000000l) {
345 put_label->flags = 1;
346 return 3;
349 put_label->flags = 2;
350 return 4;
353 static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
355 sljit_uw addr = put_label->label->addr;
356 sljit_ins *inst = (sljit_ins *)put_label->addr;
357 sljit_u32 reg = *inst;
359 if (put_label->flags == 0) {
360 SLJIT_ASSERT(addr < 0x100000000l);
361 inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 16);
363 else {
364 if (put_label->flags == 1) {
365 SLJIT_ASSERT(addr < 0x1000000000000l);
366 inst[0] = ORI | S(TMP_ZERO) | A(reg) | IMM(addr >> 32);
368 else {
369 inst[0] = ORIS | S(TMP_ZERO) | A(reg) | IMM(addr >> 48);
370 inst[1] = ORI | S(reg) | A(reg) | IMM((addr >> 32) & 0xffff);
371 inst++;
374 inst[1] = RLDI(reg, reg, 32, 31, 1);
375 inst[2] = ORIS | S(reg) | A(reg) | IMM((addr >> 16) & 0xffff);
376 inst += 2;
379 inst[1] = ORI | S(reg) | A(reg) | IMM(addr & 0xffff);
382 #endif
384 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
386 struct sljit_memory_fragment *buf;
387 sljit_ins *code;
388 sljit_ins *code_ptr;
389 sljit_ins *buf_ptr;
390 sljit_ins *buf_end;
391 sljit_uw word_count;
392 sljit_uw next_addr;
393 sljit_sw executable_offset;
394 sljit_uw addr;
396 struct sljit_label *label;
397 struct sljit_jump *jump;
398 struct sljit_const *const_;
399 struct sljit_put_label *put_label;
401 CHECK_ERROR_PTR();
402 CHECK_PTR(check_sljit_generate_code(compiler));
403 reverse_buf(compiler);
405 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
406 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
407 compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
408 #else
409 compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
410 #endif
411 #endif
412 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);
413 PTR_FAIL_WITH_EXEC_IF(code);
414 buf = compiler->buf;
416 code_ptr = code;
417 word_count = 0;
418 next_addr = 0;
419 executable_offset = SLJIT_EXEC_OFFSET(code);
421 label = compiler->labels;
422 jump = compiler->jumps;
423 const_ = compiler->consts;
424 put_label = compiler->put_labels;
426 do {
427 buf_ptr = (sljit_ins*)buf->memory;
428 buf_end = buf_ptr + (buf->used_size >> 2);
429 do {
430 *code_ptr = *buf_ptr++;
431 if (next_addr == word_count) {
432 SLJIT_ASSERT(!label || label->size >= word_count);
433 SLJIT_ASSERT(!jump || jump->addr >= word_count);
434 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
435 SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
437 /* These structures are ordered by their address. */
438 if (label && label->size == word_count) {
439 /* Just recording the address. */
440 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
441 label->size = (sljit_uw)(code_ptr - code);
442 label = label->next;
444 if (jump && jump->addr == word_count) {
445 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
446 jump->addr = (sljit_uw)(code_ptr - 3);
447 #else
448 jump->addr = (sljit_uw)(code_ptr - 6);
449 #endif
450 if (detect_jump_type(jump, code_ptr, code, executable_offset)) {
451 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
452 code_ptr[-3] = code_ptr[0];
453 code_ptr -= 3;
454 #else
455 if (jump->flags & PATCH_ABS32) {
456 code_ptr -= 3;
457 code_ptr[-1] = code_ptr[2];
458 code_ptr[0] = code_ptr[3];
460 else if (jump->flags & PATCH_ABS48) {
461 code_ptr--;
462 code_ptr[-1] = code_ptr[0];
463 code_ptr[0] = code_ptr[1];
464 /* rldicr rX,rX,32,31 -> rX,rX,16,47 */
465 SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6);
466 code_ptr[-3] ^= 0x8422;
467 /* oris -> ori */
468 code_ptr[-2] ^= 0x4000000;
470 else {
471 code_ptr[-6] = code_ptr[0];
472 code_ptr -= 6;
474 #endif
475 if (jump->flags & REMOVE_COND) {
476 code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
477 code_ptr++;
478 jump->addr += sizeof(sljit_ins);
479 code_ptr[0] = Bx;
480 jump->flags -= IS_COND;
483 jump = jump->next;
485 if (const_ && const_->addr == word_count) {
486 const_->addr = (sljit_uw)code_ptr;
487 const_ = const_->next;
489 if (put_label && put_label->addr == word_count) {
490 SLJIT_ASSERT(put_label->label);
491 put_label->addr = (sljit_uw)code_ptr;
492 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
493 code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
494 word_count += 4;
495 #endif
496 put_label = put_label->next;
498 next_addr = compute_next_addr(label, jump, const_, put_label);
500 code_ptr++;
501 word_count++;
502 } while (buf_ptr < buf_end);
504 buf = buf->next;
505 } while (buf);
507 if (label && label->size == word_count) {
508 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
509 label->size = (sljit_uw)(code_ptr - code);
510 label = label->next;
513 SLJIT_ASSERT(!label);
514 SLJIT_ASSERT(!jump);
515 SLJIT_ASSERT(!const_);
516 SLJIT_ASSERT(!put_label);
518 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
519 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));
520 #else
521 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
522 #endif
524 jump = compiler->jumps;
525 while (jump) {
526 do {
527 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
528 buf_ptr = (sljit_ins *)jump->addr;
530 if (jump->flags & PATCH_B) {
531 if (jump->flags & IS_COND) {
532 if (!(jump->flags & PATCH_ABS_B)) {
533 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
534 SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
535 *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
537 else {
538 SLJIT_ASSERT(addr <= 0xffff);
539 *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
542 else {
543 if (!(jump->flags & PATCH_ABS_B)) {
544 addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
545 SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
546 *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
548 else {
549 SLJIT_ASSERT(addr <= 0x03ffffff);
550 *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
553 break;
556 /* Set the fields of immediate loads. */
557 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
558 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
559 buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
560 buf_ptr[1] |= (sljit_ins)addr & 0xffff;
561 #else
562 if (jump->flags & PATCH_ABS32) {
563 SLJIT_ASSERT(addr <= 0x7fffffff);
564 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
565 buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
566 buf_ptr[1] |= (sljit_ins)addr & 0xffff;
567 break;
570 if (jump->flags & PATCH_ABS48) {
571 SLJIT_ASSERT(addr <= 0x7fffffffffff);
572 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0);
573 buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff;
574 buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff;
575 buf_ptr[3] |= (sljit_ins)addr & 0xffff;
576 break;
579 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[4]) & 0xffff) == 0);
580 buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff;
581 buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff;
582 buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff;
583 buf_ptr[4] |= (sljit_ins)addr & 0xffff;
584 #endif
585 } while (0);
586 jump = jump->next;
589 put_label = compiler->put_labels;
590 while (put_label) {
591 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
592 addr = put_label->label->addr;
593 buf_ptr = (sljit_ins *)put_label->addr;
595 SLJIT_ASSERT((buf_ptr[0] & 0xfc1f0000) == ADDIS && (buf_ptr[1] & 0xfc000000) == ORI);
596 buf_ptr[0] |= (addr >> 16) & 0xffff;
597 buf_ptr[1] |= addr & 0xffff;
598 #else
599 put_label_set(put_label);
600 #endif
601 put_label = put_label->next;
604 compiler->error = SLJIT_ERR_COMPILED;
605 compiler->executable_offset = executable_offset;
606 compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
608 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
610 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
611 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
612 if (((sljit_sw)code_ptr) & 0x4)
613 code_ptr++;
614 #endif
615 sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);
616 #endif
618 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
620 SLJIT_CACHE_FLUSH(code, code_ptr);
621 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
623 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
624 return code_ptr;
625 #else
626 return code;
627 #endif
630 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
632 switch (feature_type) {
633 case SLJIT_HAS_FPU:
634 #ifdef SLJIT_IS_FPU_AVAILABLE
635 return SLJIT_IS_FPU_AVAILABLE;
636 #else
637 /* Available by default. */
638 return 1;
639 #endif
641 /* A saved register is set to a zero value. */
642 case SLJIT_HAS_ZERO_REGISTER:
643 case SLJIT_HAS_CLZ:
644 case SLJIT_HAS_PREFETCH:
645 return 1;
647 default:
648 return 0;
652 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
654 return (type >= SLJIT_UNORDERED && type <= SLJIT_ORDERED_LESS_EQUAL);
657 /* --------------------------------------------------------------------- */
658 /* Entry, exit */
659 /* --------------------------------------------------------------------- */
661 /* inp_flags: */
663 /* Creates an index in data_transfer_insts array. */
664 #define LOAD_DATA 0x01
665 #define INDEXED 0x02
666 #define SIGNED_DATA 0x04
668 #define WORD_DATA 0x00
669 #define BYTE_DATA 0x08
670 #define HALF_DATA 0x10
671 #define INT_DATA 0x18
672 /* Separates integer and floating point registers */
673 #define GPR_REG 0x1f
674 #define DOUBLE_DATA 0x20
676 #define MEM_MASK 0x7f
678 /* Other inp_flags. */
680 /* Integer opertion and set flags -> requires exts on 64 bit systems. */
681 #define ALT_SIGN_EXT 0x000100
682 /* This flag affects the RC() and OERC() macros. */
683 #define ALT_SET_FLAGS 0x000400
684 #define ALT_FORM1 0x001000
685 #define ALT_FORM2 0x002000
686 #define ALT_FORM3 0x004000
687 #define ALT_FORM4 0x008000
688 #define ALT_FORM5 0x010000
690 /* Source and destination is register. */
691 #define REG_DEST 0x000001
692 #define REG1_SOURCE 0x000002
693 #define REG2_SOURCE 0x000004
695 ALT_SIGN_EXT 0x000100
696 ALT_SET_FLAGS 0x000200
697 ALT_FORM1 0x001000
699 ALT_FORM5 0x010000 */
701 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
702 #include "sljitNativePPC_32.c"
703 #else
704 #include "sljitNativePPC_64.c"
705 #endif
707 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
708 #define STACK_STORE STW
709 #define STACK_LOAD LWZ
710 #else
711 #define STACK_STORE STD
712 #define STACK_LOAD LD
713 #endif
715 #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
716 #define LR_SAVE_OFFSET 2 * SSIZE_OF(sw)
717 #else
718 #define LR_SAVE_OFFSET SSIZE_OF(sw)
719 #endif
721 #define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)
723 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
724 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
725 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
727 sljit_s32 i, tmp, base, offset;
728 sljit_s32 word_arg_count = 0;
729 sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
730 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
731 sljit_s32 arg_count = 0;
732 #endif
734 CHECK_ERROR();
735 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
736 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
738 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)
739 + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
741 if (!(options & SLJIT_ENTER_REG_ARG))
742 local_size += SSIZE_OF(sw);
744 local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
745 compiler->local_size = local_size;
747 FAIL_IF(push_inst(compiler, MFLR | D(0)));
749 base = SLJIT_SP;
750 offset = local_size;
752 if (local_size <= STACK_MAX_DISTANCE) {
753 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
754 FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
755 #else
756 FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
757 #endif
758 } else {
759 base = TMP_REG1;
760 FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));
761 FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));
762 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
763 FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
764 #else
765 FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
766 #endif
767 local_size = 0;
768 offset = 0;
771 tmp = SLJIT_FS0 - fsaveds;
772 for (i = SLJIT_FS0; i > tmp; i--) {
773 offset -= SSIZE_OF(f64);
774 FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
777 for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
778 offset -= SSIZE_OF(f64);
779 FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
782 if (!(options & SLJIT_ENTER_REG_ARG)) {
783 offset -= SSIZE_OF(sw);
784 FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
787 tmp = SLJIT_S0 - saveds;
788 for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
789 offset -= SSIZE_OF(sw);
790 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
793 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
794 offset -= SSIZE_OF(sw);
795 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
798 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
800 if (options & SLJIT_ENTER_REG_ARG)
801 return SLJIT_SUCCESS;
803 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
805 arg_types >>= SLJIT_ARG_SHIFT;
806 saved_arg_count = 0;
808 while (arg_types > 0) {
809 if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
810 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
811 do {
812 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
813 tmp = SLJIT_S0 - saved_arg_count;
814 saved_arg_count++;
815 } else if (arg_count != word_arg_count)
816 tmp = SLJIT_R0 + word_arg_count;
817 else
818 break;
820 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));
821 } while (0);
822 #else
823 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
824 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));
825 saved_arg_count++;
827 #endif
828 word_arg_count++;
831 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
832 arg_count++;
833 #endif
834 arg_types >>= SLJIT_ARG_SHIFT;
837 return SLJIT_SUCCESS;
840 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
841 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
842 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
844 CHECK_ERROR();
845 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
846 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
848 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)
849 + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
851 if (!(options & SLJIT_ENTER_REG_ARG))
852 local_size += SSIZE_OF(sw);
854 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
855 return SLJIT_SUCCESS;
858 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
860 sljit_s32 i, tmp, base, offset;
861 sljit_s32 local_size = compiler->local_size;
863 base = SLJIT_SP;
864 if (local_size > STACK_MAX_DISTANCE) {
865 base = TMP_REG1;
866 if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {
867 FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));
868 local_size = 0;
869 } else {
870 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));
871 local_size = STACK_MAX_DISTANCE;
875 offset = local_size;
876 FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));
878 tmp = SLJIT_FS0 - compiler->fsaveds;
879 for (i = SLJIT_FS0; i > tmp; i--) {
880 offset -= SSIZE_OF(f64);
881 FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
884 for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
885 offset -= SSIZE_OF(f64);
886 FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
889 if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {
890 offset -= SSIZE_OF(sw);
891 FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
894 tmp = SLJIT_S0 - compiler->saveds;
895 for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
896 offset -= SSIZE_OF(sw);
897 FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
900 for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
901 offset -= SSIZE_OF(sw);
902 FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
905 push_inst(compiler, MTLR | S(0));
907 if (local_size > 0)
908 return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));
910 SLJIT_ASSERT(base == TMP_REG1);
911 return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));
914 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
916 CHECK_ERROR();
917 CHECK(check_sljit_emit_return_void(compiler));
919 FAIL_IF(emit_stack_frame_release(compiler));
920 return push_inst(compiler, BLR);
923 #undef STACK_STORE
924 #undef STACK_LOAD
926 /* --------------------------------------------------------------------- */
927 /* Operators */
928 /* --------------------------------------------------------------------- */
930 /* s/l - store/load (1 bit)
931 i/x - immediate/indexed form
932 u/s - signed/unsigned (1 bit)
933 w/b/h/i - word/byte/half/int allowed (2 bit)
935 Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
937 /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
938 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
939 #define INT_ALIGNED 0x10000
940 #endif
942 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
943 #define ARCH_32_64(a, b) a
944 #define INST_CODE_AND_DST(inst, flags, reg) \
945 ((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
946 #else
947 #define ARCH_32_64(a, b) b
948 #define INST_CODE_AND_DST(inst, flags, reg) \
949 (((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
950 #endif
952 static const sljit_ins data_transfer_insts[64 + 16] = {
954 /* -------- Integer -------- */
956 /* Word. */
958 /* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
959 /* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
960 /* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
961 /* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
963 /* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
964 /* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
965 /* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
966 /* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
968 /* Byte. */
970 /* b u i s */ HI(38) /* stb */,
971 /* b u i l */ HI(34) /* lbz */,
972 /* b u x s */ HI(31) | LO(215) /* stbx */,
973 /* b u x l */ HI(31) | LO(87) /* lbzx */,
975 /* b s i s */ HI(38) /* stb */,
976 /* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,
977 /* b s x s */ HI(31) | LO(215) /* stbx */,
978 /* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
980 /* Half. */
982 /* h u i s */ HI(44) /* sth */,
983 /* h u i l */ HI(40) /* lhz */,
984 /* h u x s */ HI(31) | LO(407) /* sthx */,
985 /* h u x l */ HI(31) | LO(279) /* lhzx */,
987 /* h s i s */ HI(44) /* sth */,
988 /* h s i l */ HI(42) /* lha */,
989 /* h s x s */ HI(31) | LO(407) /* sthx */,
990 /* h s x l */ HI(31) | LO(343) /* lhax */,
992 /* Int. */
994 /* i u i s */ HI(36) /* stw */,
995 /* i u i l */ HI(32) /* lwz */,
996 /* i u x s */ HI(31) | LO(151) /* stwx */,
997 /* i u x l */ HI(31) | LO(23) /* lwzx */,
999 /* i s i s */ HI(36) /* stw */,
1000 /* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
1001 /* i s x s */ HI(31) | LO(151) /* stwx */,
1002 /* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
1004 /* -------- Floating point -------- */
1006 /* d i s */ HI(54) /* stfd */,
1007 /* d i l */ HI(50) /* lfd */,
1008 /* d x s */ HI(31) | LO(727) /* stfdx */,
1009 /* d x l */ HI(31) | LO(599) /* lfdx */,
1011 /* s i s */ HI(52) /* stfs */,
1012 /* s i l */ HI(48) /* lfs */,
1013 /* s x s */ HI(31) | LO(663) /* stfsx */,
1014 /* s x l */ HI(31) | LO(535) /* lfsx */,
1017 static const sljit_ins updated_data_transfer_insts[64] = {
1019 /* -------- Integer -------- */
1021 /* Word. */
1023 /* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
1024 /* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
1025 /* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
1026 /* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
1028 /* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
1029 /* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
1030 /* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
1031 /* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
1033 /* Byte. */
1035 /* b u i s */ HI(39) /* stbu */,
1036 /* b u i l */ HI(35) /* lbzu */,
1037 /* b u x s */ HI(31) | LO(247) /* stbux */,
1038 /* b u x l */ HI(31) | LO(119) /* lbzux */,
1040 /* b s i s */ HI(39) /* stbu */,
1041 /* b s i l */ 0 /* no such instruction */,
1042 /* b s x s */ HI(31) | LO(247) /* stbux */,
1043 /* b s x l */ 0 /* no such instruction */,
1045 /* Half. */
1047 /* h u i s */ HI(45) /* sthu */,
1048 /* h u i l */ HI(41) /* lhzu */,
1049 /* h u x s */ HI(31) | LO(439) /* sthux */,
1050 /* h u x l */ HI(31) | LO(311) /* lhzux */,
1052 /* h s i s */ HI(45) /* sthu */,
1053 /* h s i l */ HI(43) /* lhau */,
1054 /* h s x s */ HI(31) | LO(439) /* sthux */,
1055 /* h s x l */ HI(31) | LO(375) /* lhaux */,
1057 /* Int. */
1059 /* i u i s */ HI(37) /* stwu */,
1060 /* i u i l */ HI(33) /* lwzu */,
1061 /* i u x s */ HI(31) | LO(183) /* stwux */,
1062 /* i u x l */ HI(31) | LO(55) /* lwzux */,
1064 /* i s i s */ HI(37) /* stwu */,
1065 /* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),
1066 /* i s x s */ HI(31) | LO(183) /* stwux */,
1067 /* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
1069 /* -------- Floating point -------- */
1071 /* d i s */ HI(55) /* stfdu */,
1072 /* d i l */ HI(51) /* lfdu */,
1073 /* d x s */ HI(31) | LO(759) /* stfdux */,
1074 /* d x l */ HI(31) | LO(631) /* lfdux */,
1076 /* s i s */ HI(53) /* stfsu */,
1077 /* s i l */ HI(49) /* lfsu */,
1078 /* s x s */ HI(31) | LO(695) /* stfsux */,
1079 /* s x l */ HI(31) | LO(567) /* lfsux */,
1082 #undef ARCH_32_64
1084 /* Simple cases, (no caching is required). */
1085 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
1086 sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
1088 sljit_ins inst;
1089 sljit_s32 offs_reg;
1090 sljit_sw high_short;
1092 /* Should work when (arg & REG_MASK) == 0. */
1093 SLJIT_ASSERT(A(0) == 0);
1094 SLJIT_ASSERT(arg & SLJIT_MEM);
1096 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1097 argw &= 0x3;
1098 offs_reg = OFFS_REG(arg);
1100 if (argw != 0) {
1101 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1102 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | ((sljit_ins)argw << 11) | ((31 - (sljit_ins)argw) << 1)));
1103 #else
1104 FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1)));
1105 #endif
1106 offs_reg = tmp_reg;
1109 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1111 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1112 SLJIT_ASSERT(!(inst & INT_ALIGNED));
1113 #endif
1115 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
1118 inst = data_transfer_insts[inp_flags & MEM_MASK];
1119 arg &= REG_MASK;
1121 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1122 if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {
1123 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1125 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1126 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1128 #endif
1130 if (argw <= SIMM_MAX && argw >= SIMM_MIN)
1131 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));
1133 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1134 if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
1135 #endif
1137 high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
1139 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1140 SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
1141 #else
1142 SLJIT_ASSERT(high_short);
1143 #endif
1145 FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16)));
1146 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));
1148 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1151 /* The rest is PPC-64 only. */
1153 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1155 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1156 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1157 #endif
1160 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
1161 sljit_s32 dst, sljit_sw dstw,
1162 sljit_s32 src1, sljit_sw src1w,
1163 sljit_s32 src2, sljit_sw src2w)
1165 /* arg1 goes to TMP_REG1 or src reg
1166 arg2 goes to TMP_REG2, imm or src reg
1167 result goes to TMP_REG2, so put result can use TMP_REG1. */
1168 sljit_s32 dst_r = TMP_REG2;
1169 sljit_s32 src1_r;
1170 sljit_s32 src2_r;
1171 sljit_s32 sugg_src2_r = TMP_REG2;
1172 sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
1174 /* Destination check. */
1175 if (FAST_IS_REG(dst)) {
1176 dst_r = dst;
1177 /* The REG_DEST is only used by SLJIT_MOV operations, although
1178 * it is set for op2 operations with unset destination. */
1179 flags |= REG_DEST;
1181 if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1182 sugg_src2_r = dst_r;
1185 /* Source 1. */
1186 if (FAST_IS_REG(src1)) {
1187 src1_r = src1;
1188 flags |= REG1_SOURCE;
1190 else if (src1 & SLJIT_IMM) {
1191 src1_r = TMP_ZERO;
1192 if (src1w != 0) {
1193 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1194 src1_r = TMP_REG1;
1197 else {
1198 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
1199 src1_r = TMP_REG1;
1202 /* Source 2. */
1203 if (FAST_IS_REG(src2)) {
1204 src2_r = src2;
1205 flags |= REG2_SOURCE;
1207 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1208 dst_r = src2_r;
1210 else if (src2 & SLJIT_IMM) {
1211 src2_r = TMP_ZERO;
1212 if (src2w != 0) {
1213 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
1214 src2_r = sugg_src2_r;
1217 else {
1218 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2));
1219 src2_r = sugg_src2_r;
1222 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1224 if (!(dst & SLJIT_MEM))
1225 return SLJIT_SUCCESS;
1227 return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
1230 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1232 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1233 sljit_s32 int_op = op & SLJIT_32;
1234 #endif
1236 CHECK_ERROR();
1237 CHECK(check_sljit_emit_op0(compiler, op));
1239 op = GET_OPCODE(op);
1240 switch (op) {
1241 case SLJIT_BREAKPOINT:
1242 case SLJIT_NOP:
1243 return push_inst(compiler, NOP);
1244 case SLJIT_LMUL_UW:
1245 case SLJIT_LMUL_SW:
1246 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1247 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1248 FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1249 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1250 #else
1251 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1252 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1253 #endif
1254 case SLJIT_DIVMOD_UW:
1255 case SLJIT_DIVMOD_SW:
1256 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1257 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1258 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)));
1259 FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1260 #else
1261 FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1262 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1263 #endif
1264 return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
1265 case SLJIT_DIV_UW:
1266 case SLJIT_DIV_SW:
1267 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1268 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));
1269 #else
1270 return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1271 #endif
1272 case SLJIT_ENDBR:
1273 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1274 return SLJIT_SUCCESS;
1277 return SLJIT_SUCCESS;
1280 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1281 sljit_s32 src, sljit_sw srcw)
1283 if (!(src & OFFS_REG_MASK)) {
1284 if (srcw == 0 && (src & REG_MASK))
1285 return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
1287 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1288 /* Works with SLJIT_MEM0() case as well. */
1289 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1292 srcw &= 0x3;
1294 if (srcw == 0)
1295 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
1297 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1298 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | ((sljit_ins)srcw << 11) | ((31 - (sljit_ins)srcw) << 1)));
1299 #else
1300 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
1301 #endif
1302 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1305 #define EMIT_MOV(type, type_flags, type_cast) \
1306 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)
1308 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1309 sljit_s32 dst, sljit_sw dstw,
1310 sljit_s32 src, sljit_sw srcw)
1312 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1313 sljit_s32 op_flags = GET_ALL_FLAGS(op);
1315 CHECK_ERROR();
1316 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1317 ADJUST_LOCAL_OFFSET(dst, dstw);
1318 ADJUST_LOCAL_OFFSET(src, srcw);
1320 op = GET_OPCODE(op);
1322 if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
1323 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1325 if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) {
1326 if (!TYPE_CAST_NEEDED(op))
1327 return SLJIT_SUCCESS;
1330 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1331 if (op_flags & SLJIT_32) {
1332 if (op < SLJIT_NOT) {
1333 if (src & SLJIT_MEM) {
1334 if (op == SLJIT_MOV_S32)
1335 op = SLJIT_MOV_U32;
1337 else if (src & SLJIT_IMM) {
1338 if (op == SLJIT_MOV_U32)
1339 op = SLJIT_MOV_S32;
1342 else {
1343 /* Most operations expect sign extended arguments. */
1344 flags |= INT_DATA | SIGNED_DATA;
1345 if (HAS_FLAGS(op_flags))
1346 flags |= ALT_SIGN_EXT;
1349 #endif
1351 switch (op) {
1352 case SLJIT_MOV:
1353 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1354 case SLJIT_MOV_U32:
1355 case SLJIT_MOV_S32:
1356 case SLJIT_MOV32:
1357 #endif
1358 case SLJIT_MOV_P:
1359 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
1361 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1362 case SLJIT_MOV_U32:
1363 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
1365 case SLJIT_MOV_S32:
1366 case SLJIT_MOV32:
1367 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1368 #endif
1370 case SLJIT_MOV_U8:
1371 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1373 case SLJIT_MOV_S8:
1374 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1376 case SLJIT_MOV_U16:
1377 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1379 case SLJIT_MOV_S16:
1380 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1382 case SLJIT_NOT:
1383 return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1385 case SLJIT_CLZ:
1386 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1387 return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
1388 #else
1389 return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1390 #endif
1393 return SLJIT_SUCCESS;
1396 #undef EMIT_MOV
1398 #define TEST_SL_IMM(src, srcw) \
1399 (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1401 #define TEST_UL_IMM(src, srcw) \
1402 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
1404 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1405 #define TEST_SH_IMM(src, srcw) \
1406 (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
1407 #else
1408 #define TEST_SH_IMM(src, srcw) \
1409 (((src) & SLJIT_IMM) && !((srcw) & 0xffff))
1410 #endif
1412 #define TEST_UH_IMM(src, srcw) \
1413 (((src) & SLJIT_IMM) && !((srcw) & ~(sljit_sw)0xffff0000))
1415 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1416 #define TEST_ADD_IMM(src, srcw) \
1417 (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
1418 #else
1419 #define TEST_ADD_IMM(src, srcw) \
1420 ((src) & SLJIT_IMM)
1421 #endif
1423 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1424 #define TEST_UI_IMM(src, srcw) \
1425 (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
1426 #else
1427 #define TEST_UI_IMM(src, srcw) \
1428 ((src) & SLJIT_IMM)
1429 #endif
1431 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1432 #define TEST_ADD_FORM1(op) \
1433 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1434 || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))
1435 #define TEST_SUB_FORM2(op) \
1436 ((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
1437 || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))
1438 #define TEST_SUB_FORM3(op) \
1439 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1440 || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))
1441 #else
1442 #define TEST_ADD_FORM1(op) \
1443 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1444 #define TEST_SUB_FORM2(op) \
1445 (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)
1446 #define TEST_SUB_FORM3(op) \
1447 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1448 #endif
1450 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1451 sljit_s32 dst, sljit_sw dstw,
1452 sljit_s32 src1, sljit_sw src1w,
1453 sljit_s32 src2, sljit_sw src2w)
1455 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1457 CHECK_ERROR();
1458 CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
1459 ADJUST_LOCAL_OFFSET(dst, dstw);
1460 ADJUST_LOCAL_OFFSET(src1, src1w);
1461 ADJUST_LOCAL_OFFSET(src2, src2w);
1463 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1464 if (op & SLJIT_32) {
1465 /* Most operations expect sign extended arguments. */
1466 flags |= INT_DATA | SIGNED_DATA;
1467 if (src1 & SLJIT_IMM)
1468 src1w = (sljit_s32)(src1w);
1469 if (src2 & SLJIT_IMM)
1470 src2w = (sljit_s32)(src2w);
1471 if (HAS_FLAGS(op))
1472 flags |= ALT_SIGN_EXT;
1474 #endif
1475 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1476 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1478 switch (GET_OPCODE(op)) {
1479 case SLJIT_ADD:
1480 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1482 if (TEST_ADD_FORM1(op))
1483 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1485 if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1486 if (TEST_SL_IMM(src2, src2w)) {
1487 compiler->imm = (sljit_ins)src2w & 0xffff;
1488 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1490 if (TEST_SL_IMM(src1, src1w)) {
1491 compiler->imm = (sljit_ins)src1w & 0xffff;
1492 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1494 if (TEST_SH_IMM(src2, src2w)) {
1495 compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
1496 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1498 if (TEST_SH_IMM(src1, src1w)) {
1499 compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
1500 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1502 /* Range between -1 and -32768 is covered above. */
1503 if (TEST_ADD_IMM(src2, src2w)) {
1504 compiler->imm = (sljit_ins)src2w & 0xffffffff;
1505 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1507 if (TEST_ADD_IMM(src1, src1w)) {
1508 compiler->imm = (sljit_ins)src1w & 0xffffffff;
1509 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1513 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1514 if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {
1515 if (TEST_SL_IMM(src2, src2w)) {
1516 compiler->imm = (sljit_ins)src2w & 0xffff;
1517 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
1519 if (TEST_SL_IMM(src1, src1w)) {
1520 compiler->imm = (sljit_ins)src1w & 0xffff;
1521 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
1523 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1525 #endif
1526 if (HAS_FLAGS(op)) {
1527 if (TEST_SL_IMM(src2, src2w)) {
1528 compiler->imm = (sljit_ins)src2w & 0xffff;
1529 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1531 if (TEST_SL_IMM(src1, src1w)) {
1532 compiler->imm = (sljit_ins)src1w & 0xffff;
1533 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1536 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);
1538 case SLJIT_ADDC:
1539 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1540 return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
1542 case SLJIT_SUB:
1543 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1545 if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
1546 if (dst == TMP_REG2) {
1547 if (TEST_UL_IMM(src2, src2w)) {
1548 compiler->imm = (sljit_ins)src2w & 0xffff;
1549 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1551 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1554 if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
1555 compiler->imm = (sljit_ins)src2w;
1556 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1558 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1561 if (dst == TMP_REG2 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1562 if (TEST_SL_IMM(src2, src2w)) {
1563 compiler->imm = (sljit_ins)src2w & 0xffff;
1564 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1566 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
1569 if (TEST_SUB_FORM2(op)) {
1570 if ((src2 & SLJIT_IMM) && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
1571 compiler->imm = (sljit_ins)src2w & 0xffff;
1572 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1574 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1577 if (TEST_SUB_FORM3(op))
1578 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1580 if (TEST_SL_IMM(src2, -src2w)) {
1581 compiler->imm = (sljit_ins)(-src2w) & 0xffff;
1582 return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
1585 if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
1586 compiler->imm = (sljit_ins)src1w & 0xffff;
1587 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1590 if (!HAS_FLAGS(op)) {
1591 if (TEST_SH_IMM(src2, -src2w)) {
1592 compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;
1593 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1595 /* Range between -1 and -32768 is covered above. */
1596 if (TEST_ADD_IMM(src2, -src2w)) {
1597 compiler->imm = (sljit_ins)-src2w;
1598 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1602 /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */
1603 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);
1605 case SLJIT_SUBC:
1606 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1607 return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
1609 case SLJIT_MUL:
1610 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1611 if (op & SLJIT_32)
1612 flags |= ALT_FORM2;
1613 #endif
1614 if (!HAS_FLAGS(op)) {
1615 if (TEST_SL_IMM(src2, src2w)) {
1616 compiler->imm = (sljit_ins)src2w & 0xffff;
1617 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1619 if (TEST_SL_IMM(src1, src1w)) {
1620 compiler->imm = (sljit_ins)src1w & 0xffff;
1621 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1624 else
1625 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1626 return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
1628 case SLJIT_AND:
1629 case SLJIT_OR:
1630 case SLJIT_XOR:
1631 /* Commutative unsigned operations. */
1632 if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
1633 if (TEST_UL_IMM(src2, src2w)) {
1634 compiler->imm = (sljit_ins)src2w;
1635 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1637 if (TEST_UL_IMM(src1, src1w)) {
1638 compiler->imm = (sljit_ins)src1w;
1639 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1641 if (TEST_UH_IMM(src2, src2w)) {
1642 compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
1643 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1645 if (TEST_UH_IMM(src1, src1w)) {
1646 compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
1647 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1650 if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
1651 /* Unlike or and xor, the and resets unwanted bits as well. */
1652 if (TEST_UI_IMM(src2, src2w)) {
1653 compiler->imm = (sljit_ins)src2w;
1654 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1656 if (TEST_UI_IMM(src1, src1w)) {
1657 compiler->imm = (sljit_ins)src1w;
1658 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1661 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1663 case SLJIT_SHL:
1664 case SLJIT_LSHR:
1665 case SLJIT_ASHR:
1666 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1667 if (op & SLJIT_32)
1668 flags |= ALT_FORM2;
1669 #endif
1670 if (src2 & SLJIT_IMM) {
1671 compiler->imm = (sljit_ins)src2w;
1672 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1674 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1677 return SLJIT_SUCCESS;
1680 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
1681 sljit_s32 src1, sljit_sw src1w,
1682 sljit_s32 src2, sljit_sw src2w)
1684 CHECK_ERROR();
1685 CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
1687 SLJIT_SKIP_CHECKS(compiler);
1688 return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
1691 #undef TEST_ADD_FORM1
1692 #undef TEST_SUB_FORM2
1693 #undef TEST_SUB_FORM3
1695 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
1696 sljit_s32 src, sljit_sw srcw)
1698 CHECK_ERROR();
1699 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1700 ADJUST_LOCAL_OFFSET(src, srcw);
1702 switch (op) {
1703 case SLJIT_FAST_RETURN:
1704 if (FAST_IS_REG(src))
1705 FAIL_IF(push_inst(compiler, MTLR | S(src)));
1706 else {
1707 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
1708 FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
1711 return push_inst(compiler, BLR);
1712 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
1713 return SLJIT_SUCCESS;
1714 case SLJIT_PREFETCH_L1:
1715 case SLJIT_PREFETCH_L2:
1716 case SLJIT_PREFETCH_L3:
1717 case SLJIT_PREFETCH_ONCE:
1718 return emit_prefetch(compiler, src, srcw);
1721 return SLJIT_SUCCESS;
1724 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1726 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1727 return reg_map[reg];
1730 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1732 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1733 return freg_map[reg];
1736 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1737 void *instruction, sljit_u32 size)
1739 CHECK_ERROR();
1740 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1742 return push_inst(compiler, *(sljit_ins*)instruction);
1745 /* --------------------------------------------------------------------- */
1746 /* Floating point operators */
1747 /* --------------------------------------------------------------------- */
1749 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))
1750 #define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))
1752 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1753 #define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
1754 #else
1755 #define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
1757 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
1758 #define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))
1759 #define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))
1760 #else
1761 #define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))
1762 #define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))
1763 #endif
1765 #endif /* SLJIT_CONFIG_PPC_64 */
1767 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1768 sljit_s32 dst, sljit_sw dstw,
1769 sljit_s32 src, sljit_sw srcw)
1771 if (src & SLJIT_MEM) {
1772 /* We can ignore the temporary data store on the stack from caching point of view. */
1773 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1774 src = TMP_FREG1;
1777 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1778 op = GET_OPCODE(op);
1779 FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
1781 if (op == SLJIT_CONV_SW_FROM_F64) {
1782 if (FAST_IS_REG(dst)) {
1783 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1784 return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1786 return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
1788 #else
1789 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
1790 #endif
1792 if (FAST_IS_REG(dst)) {
1793 FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));
1794 FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
1795 return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1798 SLJIT_ASSERT(dst & SLJIT_MEM);
1800 if (dst & OFFS_REG_MASK) {
1801 dstw &= 0x3;
1802 if (dstw) {
1803 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1804 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | ((sljit_ins)dstw << 11) | ((31 - (sljit_ins)dstw) << 1)));
1805 #else
1806 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
1807 #endif
1808 dstw = TMP_REG1;
1810 else
1811 dstw = OFFS_REG(dst);
1813 else {
1814 if ((dst & REG_MASK) && !dstw) {
1815 dstw = dst & REG_MASK;
1816 dst = 0;
1818 else {
1819 /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
1820 FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
1821 dstw = TMP_REG1;
1825 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
1828 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1829 sljit_s32 dst, sljit_sw dstw,
1830 sljit_s32 src, sljit_sw srcw)
1832 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1834 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1836 if (src & SLJIT_IMM) {
1837 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1838 srcw = (sljit_s32)srcw;
1840 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1841 src = TMP_REG1;
1843 else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
1844 if (FAST_IS_REG(src))
1845 FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
1846 else
1847 FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1848 src = TMP_REG1;
1851 if (FAST_IS_REG(src)) {
1852 FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1853 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1855 else
1856 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1858 FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
1860 if (dst & SLJIT_MEM)
1861 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1862 if (op & SLJIT_32)
1863 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1864 return SLJIT_SUCCESS;
1866 #else
1868 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1869 sljit_s32 invert_sign = 1;
1871 if (src & SLJIT_IMM) {
1872 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
1873 src = TMP_REG1;
1874 invert_sign = 0;
1876 else if (!FAST_IS_REG(src)) {
1877 FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1878 src = TMP_REG1;
1881 /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))
1882 The double precision format has exactly 53 bit precision, so the lower 32 bit represents
1883 the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000
1884 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating
1885 point value, we need to substract 2^53 + 2^31 from the constructed value. */
1886 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
1887 if (invert_sign)
1888 FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
1889 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1));
1890 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1891 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
1892 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1893 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1894 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1896 FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
1898 if (dst & SLJIT_MEM)
1899 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1900 if (op & SLJIT_32)
1901 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1902 return SLJIT_SUCCESS;
1904 #endif
1907 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1908 sljit_s32 src1, sljit_sw src1w,
1909 sljit_s32 src2, sljit_sw src2w)
1911 if (src1 & SLJIT_MEM) {
1912 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
1913 src1 = TMP_FREG1;
1916 if (src2 & SLJIT_MEM) {
1917 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
1918 src2 = TMP_FREG2;
1921 FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)));
1923 switch (GET_FLAG_TYPE(op)) {
1924 case SLJIT_UNORDERED_OR_EQUAL:
1925 case SLJIT_ORDERED_NOT_EQUAL:
1926 return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));
1927 case SLJIT_UNORDERED_OR_LESS:
1928 case SLJIT_ORDERED_GREATER_EQUAL:
1929 return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));
1930 case SLJIT_UNORDERED_OR_GREATER:
1931 case SLJIT_ORDERED_LESS_EQUAL:
1932 return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));
1935 return SLJIT_SUCCESS;
1938 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1939 sljit_s32 dst, sljit_sw dstw,
1940 sljit_s32 src, sljit_sw srcw)
1942 sljit_s32 dst_r;
1944 CHECK_ERROR();
1946 SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
1947 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1949 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1950 op ^= SLJIT_32;
1952 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1954 if (src & SLJIT_MEM) {
1955 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));
1956 src = dst_r;
1959 switch (GET_OPCODE(op)) {
1960 case SLJIT_CONV_F64_FROM_F32:
1961 op ^= SLJIT_32;
1962 if (op & SLJIT_32) {
1963 FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
1964 break;
1966 /* Fall through. */
1967 case SLJIT_MOV_F64:
1968 if (src != dst_r) {
1969 if (dst_r != TMP_FREG1)
1970 FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
1971 else
1972 dst_r = src;
1974 break;
1975 case SLJIT_NEG_F64:
1976 FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
1977 break;
1978 case SLJIT_ABS_F64:
1979 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
1980 break;
1983 if (dst & SLJIT_MEM)
1984 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));
1985 return SLJIT_SUCCESS;
1988 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1989 sljit_s32 dst, sljit_sw dstw,
1990 sljit_s32 src1, sljit_sw src1w,
1991 sljit_s32 src2, sljit_sw src2w)
1993 sljit_s32 dst_r;
1995 CHECK_ERROR();
1996 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1997 ADJUST_LOCAL_OFFSET(dst, dstw);
1998 ADJUST_LOCAL_OFFSET(src1, src1w);
1999 ADJUST_LOCAL_OFFSET(src2, src2w);
2001 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
2003 if (src1 & SLJIT_MEM) {
2004 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
2005 src1 = TMP_FREG1;
2008 if (src2 & SLJIT_MEM) {
2009 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
2010 src2 = TMP_FREG2;
2013 switch (GET_OPCODE(op)) {
2014 case SLJIT_ADD_F64:
2015 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
2016 break;
2018 case SLJIT_SUB_F64:
2019 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
2020 break;
2022 case SLJIT_MUL_F64:
2023 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
2024 break;
2026 case SLJIT_DIV_F64:
2027 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
2028 break;
2031 if (dst & SLJIT_MEM)
2032 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
2034 return SLJIT_SUCCESS;
2037 #undef SELECT_FOP
2039 /* --------------------------------------------------------------------- */
2040 /* Other instructions */
2041 /* --------------------------------------------------------------------- */
2043 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2045 CHECK_ERROR();
2046 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
2047 ADJUST_LOCAL_OFFSET(dst, dstw);
2049 if (FAST_IS_REG(dst))
2050 return push_inst(compiler, MFLR | D(dst));
2052 /* Memory. */
2053 FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
2054 return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2057 /* --------------------------------------------------------------------- */
2058 /* Conditional instructions */
2059 /* --------------------------------------------------------------------- */
2061 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2063 struct sljit_label *label;
2065 CHECK_ERROR_PTR();
2066 CHECK_PTR(check_sljit_emit_label(compiler));
2068 if (compiler->last_label && compiler->last_label->size == compiler->size)
2069 return compiler->last_label;
2071 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2072 PTR_FAIL_IF(!label);
2073 set_label(label, compiler);
2074 return label;
2077 static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)
2079 switch (type) {
2080 case SLJIT_NOT_CARRY:
2081 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
2082 return (4 << 21) | (2 << 16);
2083 /* fallthrough */
2085 case SLJIT_EQUAL:
2086 return (12 << 21) | (2 << 16);
2088 case SLJIT_CARRY:
2089 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
2090 return (12 << 21) | (2 << 16);
2091 /* fallthrough */
2093 case SLJIT_NOT_EQUAL:
2094 return (4 << 21) | (2 << 16);
2096 case SLJIT_LESS:
2097 case SLJIT_SIG_LESS:
2098 return (12 << 21) | (0 << 16);
2100 case SLJIT_GREATER_EQUAL:
2101 case SLJIT_SIG_GREATER_EQUAL:
2102 return (4 << 21) | (0 << 16);
2104 case SLJIT_GREATER:
2105 case SLJIT_SIG_GREATER:
2106 return (12 << 21) | (1 << 16);
2108 case SLJIT_LESS_EQUAL:
2109 case SLJIT_SIG_LESS_EQUAL:
2110 return (4 << 21) | (1 << 16);
2112 case SLJIT_OVERFLOW:
2113 return (12 << 21) | (3 << 16);
2115 case SLJIT_NOT_OVERFLOW:
2116 return (4 << 21) | (3 << 16);
2118 case SLJIT_F_LESS:
2119 case SLJIT_ORDERED_LESS:
2120 case SLJIT_UNORDERED_OR_LESS:
2121 return (12 << 21) | ((4 + 0) << 16);
2123 case SLJIT_F_GREATER_EQUAL:
2124 case SLJIT_ORDERED_GREATER_EQUAL:
2125 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2126 return (4 << 21) | ((4 + 0) << 16);
2128 case SLJIT_F_GREATER:
2129 case SLJIT_ORDERED_GREATER:
2130 case SLJIT_UNORDERED_OR_GREATER:
2131 return (12 << 21) | ((4 + 1) << 16);
2133 case SLJIT_F_LESS_EQUAL:
2134 case SLJIT_ORDERED_LESS_EQUAL:
2135 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2136 return (4 << 21) | ((4 + 1) << 16);
2138 case SLJIT_F_EQUAL:
2139 case SLJIT_ORDERED_EQUAL:
2140 case SLJIT_UNORDERED_OR_EQUAL:
2141 return (12 << 21) | ((4 + 2) << 16);
2143 case SLJIT_F_NOT_EQUAL:
2144 case SLJIT_ORDERED_NOT_EQUAL:
2145 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2146 return (4 << 21) | ((4 + 2) << 16);
2148 case SLJIT_UNORDERED:
2149 return (12 << 21) | ((4 + 3) << 16);
2151 case SLJIT_ORDERED:
2152 return (4 << 21) | ((4 + 3) << 16);
2154 default:
2155 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
2156 return (20 << 21);
2160 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2162 struct sljit_jump *jump;
2163 sljit_ins bo_bi_flags;
2165 CHECK_ERROR_PTR();
2166 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2168 bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
2169 if (!bo_bi_flags)
2170 return NULL;
2172 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2173 PTR_FAIL_IF(!jump);
2174 set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);
2175 type &= 0xff;
2177 if (type == SLJIT_CARRY || type == SLJIT_NOT_CARRY)
2178 PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
2180 /* In PPC, we don't need to touch the arguments. */
2181 if (type < SLJIT_JUMP)
2182 jump->flags |= IS_COND;
2183 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2184 if (type >= SLJIT_CALL)
2185 jump->flags |= IS_CALL;
2186 #endif
2188 PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2189 PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));
2190 jump->addr = compiler->size;
2191 PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
2192 return jump;
2195 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2196 sljit_s32 arg_types)
2198 CHECK_ERROR_PTR();
2199 CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2201 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2202 if ((type & 0xff) != SLJIT_CALL_REG_ARG)
2203 PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
2204 #endif
2206 if (type & SLJIT_CALL_RETURN) {
2207 PTR_FAIL_IF(emit_stack_frame_release(compiler));
2208 type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
2211 SLJIT_SKIP_CHECKS(compiler);
2212 return sljit_emit_jump(compiler, type);
2215 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2217 struct sljit_jump *jump = NULL;
2218 sljit_s32 src_r;
2220 CHECK_ERROR();
2221 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2222 ADJUST_LOCAL_OFFSET(src, srcw);
2224 if (FAST_IS_REG(src)) {
2225 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2226 if (type >= SLJIT_CALL && src != TMP_CALL_REG) {
2227 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2228 src_r = TMP_CALL_REG;
2230 else
2231 src_r = src;
2232 #else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2233 src_r = src;
2234 #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2235 } else if (src & SLJIT_IMM) {
2236 /* These jumps are converted to jump/call instructions when possible. */
2237 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2238 FAIL_IF(!jump);
2239 set_jump(jump, compiler, JUMP_ADDR);
2240 jump->u.target = (sljit_uw)srcw;
2242 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2243 if (type >= SLJIT_CALL)
2244 jump->flags |= IS_CALL;
2245 #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2247 FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2248 src_r = TMP_CALL_REG;
2250 else {
2251 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2252 src_r = TMP_CALL_REG;
2255 FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
2256 if (jump)
2257 jump->addr = compiler->size;
2258 return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
2261 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
2262 sljit_s32 arg_types,
2263 sljit_s32 src, sljit_sw srcw)
2265 CHECK_ERROR();
2266 CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
2268 if (src & SLJIT_MEM) {
2269 ADJUST_LOCAL_OFFSET(src, srcw);
2270 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2271 src = TMP_CALL_REG;
2274 if (type & SLJIT_CALL_RETURN) {
2275 if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
2276 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2277 src = TMP_CALL_REG;
2280 FAIL_IF(emit_stack_frame_release(compiler));
2281 type = SLJIT_JUMP;
2284 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2285 if ((type & 0xff) != SLJIT_CALL_REG_ARG)
2286 FAIL_IF(call_with_args(compiler, arg_types, &src));
2287 #endif
2289 SLJIT_SKIP_CHECKS(compiler);
2290 return sljit_emit_ijump(compiler, type, src, srcw);
2293 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2294 sljit_s32 dst, sljit_sw dstw,
2295 sljit_s32 type)
2297 sljit_s32 reg, invert;
2298 sljit_u32 bit, from_xer;
2299 sljit_s32 saved_op = op;
2300 sljit_sw saved_dstw = dstw;
2301 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2302 sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;
2303 #else
2304 sljit_s32 input_flags = WORD_DATA;
2305 #endif
2307 CHECK_ERROR();
2308 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2309 ADJUST_LOCAL_OFFSET(dst, dstw);
2311 op = GET_OPCODE(op);
2312 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2314 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2315 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
2317 invert = 0;
2318 bit = 0;
2319 from_xer = 0;
2321 switch (type) {
2322 case SLJIT_LESS:
2323 case SLJIT_SIG_LESS:
2324 break;
2326 case SLJIT_GREATER_EQUAL:
2327 case SLJIT_SIG_GREATER_EQUAL:
2328 invert = 1;
2329 break;
2331 case SLJIT_GREATER:
2332 case SLJIT_SIG_GREATER:
2333 bit = 1;
2334 break;
2336 case SLJIT_LESS_EQUAL:
2337 case SLJIT_SIG_LESS_EQUAL:
2338 bit = 1;
2339 invert = 1;
2340 break;
2342 case SLJIT_EQUAL:
2343 bit = 2;
2344 break;
2346 case SLJIT_NOT_EQUAL:
2347 bit = 2;
2348 invert = 1;
2349 break;
2351 case SLJIT_OVERFLOW:
2352 from_xer = 1;
2353 bit = 1;
2354 break;
2356 case SLJIT_NOT_OVERFLOW:
2357 from_xer = 1;
2358 bit = 1;
2359 invert = 1;
2360 break;
2362 case SLJIT_CARRY:
2363 from_xer = 1;
2364 bit = 2;
2365 invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;
2366 break;
2368 case SLJIT_NOT_CARRY:
2369 from_xer = 1;
2370 bit = 2;
2371 invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;
2372 break;
2374 case SLJIT_F_LESS:
2375 case SLJIT_ORDERED_LESS:
2376 case SLJIT_UNORDERED_OR_LESS:
2377 bit = 4 + 0;
2378 break;
2380 case SLJIT_F_GREATER_EQUAL:
2381 case SLJIT_ORDERED_GREATER_EQUAL:
2382 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2383 bit = 4 + 0;
2384 invert = 1;
2385 break;
2387 case SLJIT_F_GREATER:
2388 case SLJIT_ORDERED_GREATER:
2389 case SLJIT_UNORDERED_OR_GREATER:
2390 bit = 4 + 1;
2391 break;
2393 case SLJIT_F_LESS_EQUAL:
2394 case SLJIT_ORDERED_LESS_EQUAL:
2395 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2396 bit = 4 + 1;
2397 invert = 1;
2398 break;
2400 case SLJIT_F_EQUAL:
2401 case SLJIT_ORDERED_EQUAL:
2402 case SLJIT_UNORDERED_OR_EQUAL:
2403 bit = 4 + 2;
2404 break;
2406 case SLJIT_F_NOT_EQUAL:
2407 case SLJIT_ORDERED_NOT_EQUAL:
2408 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2409 bit = 4 + 2;
2410 invert = 1;
2411 break;
2413 case SLJIT_UNORDERED:
2414 bit = 4 + 3;
2415 break;
2417 case SLJIT_ORDERED:
2418 bit = 4 + 3;
2419 invert = 1;
2420 break;
2422 default:
2423 SLJIT_UNREACHABLE();
2424 break;
2427 FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));
2428 FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + bit) << 11) | (31 << 6) | (31 << 1)));
2430 if (invert)
2431 FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
2433 if (op < SLJIT_ADD) {
2434 if (!(dst & SLJIT_MEM))
2435 return SLJIT_SUCCESS;
2436 return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
2439 SLJIT_SKIP_CHECKS(compiler);
2441 if (dst & SLJIT_MEM)
2442 return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
2443 return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
2446 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2447 sljit_s32 dst_reg,
2448 sljit_s32 src, sljit_sw srcw)
2450 CHECK_ERROR();
2451 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2453 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
2456 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
2457 sljit_s32 reg,
2458 sljit_s32 mem, sljit_sw memw)
2460 sljit_s32 mem_flags;
2461 sljit_ins inst;
2463 CHECK_ERROR();
2464 CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
2466 if (type & SLJIT_MEM_UNALIGNED)
2467 return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
2469 if (type & SLJIT_MEM_POST)
2470 return SLJIT_ERR_UNSUPPORTED;
2472 switch (type & 0xff) {
2473 case SLJIT_MOV:
2474 case SLJIT_MOV_P:
2475 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2476 case SLJIT_MOV_U32:
2477 case SLJIT_MOV_S32:
2478 case SLJIT_MOV32:
2479 #endif
2480 mem_flags = WORD_DATA;
2481 break;
2483 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2484 case SLJIT_MOV_U32:
2485 case SLJIT_MOV32:
2486 mem_flags = INT_DATA;
2487 break;
2489 case SLJIT_MOV_S32:
2490 mem_flags = INT_DATA;
2492 if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {
2493 if (mem & OFFS_REG_MASK)
2494 mem_flags |= SIGNED_DATA;
2495 else
2496 return SLJIT_ERR_UNSUPPORTED;
2498 break;
2499 #endif
2501 case SLJIT_MOV_U8:
2502 case SLJIT_MOV_S8:
2503 mem_flags = BYTE_DATA;
2504 break;
2506 case SLJIT_MOV_U16:
2507 mem_flags = HALF_DATA;
2508 break;
2510 case SLJIT_MOV_S16:
2511 mem_flags = HALF_DATA | SIGNED_DATA;
2512 break;
2514 default:
2515 SLJIT_UNREACHABLE();
2516 mem_flags = WORD_DATA;
2517 break;
2520 if (!(type & SLJIT_MEM_STORE))
2521 mem_flags |= LOAD_DATA;
2523 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2524 if (memw != 0)
2525 return SLJIT_ERR_UNSUPPORTED;
2527 if (type & SLJIT_MEM_SUPP)
2528 return SLJIT_SUCCESS;
2530 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2531 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
2533 else {
2534 if (memw > SIMM_MAX || memw < SIMM_MIN)
2535 return SLJIT_ERR_UNSUPPORTED;
2537 inst = updated_data_transfer_insts[mem_flags];
2539 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2540 if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)
2541 return SLJIT_ERR_UNSUPPORTED;
2542 #endif
2544 if (type & SLJIT_MEM_SUPP)
2545 return SLJIT_SUCCESS;
2547 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
2550 if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)
2551 return push_inst(compiler, EXTSB | S(reg) | A(reg));
2552 return SLJIT_SUCCESS;
2555 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
2556 sljit_s32 freg,
2557 sljit_s32 mem, sljit_sw memw)
2559 sljit_s32 mem_flags;
2560 sljit_ins inst;
2562 CHECK_ERROR();
2563 CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
2565 if (type & SLJIT_MEM_UNALIGNED)
2566 return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
2568 if (type & SLJIT_MEM_POST)
2569 return SLJIT_ERR_UNSUPPORTED;
2571 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2572 if (memw != 0)
2573 return SLJIT_ERR_UNSUPPORTED;
2575 else {
2576 if (memw > SIMM_MAX || memw < SIMM_MIN)
2577 return SLJIT_ERR_UNSUPPORTED;
2580 if (type & SLJIT_MEM_SUPP)
2581 return SLJIT_SUCCESS;
2583 mem_flags = FLOAT_DATA(type);
2585 if (!(type & SLJIT_MEM_STORE))
2586 mem_flags |= LOAD_DATA;
2588 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2589 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2590 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));
2593 inst = updated_data_transfer_insts[mem_flags];
2594 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));
2597 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2599 struct sljit_const *const_;
2600 sljit_s32 dst_r;
2602 CHECK_ERROR_PTR();
2603 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2604 ADJUST_LOCAL_OFFSET(dst, dstw);
2606 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2607 PTR_FAIL_IF(!const_);
2608 set_const(const_, compiler);
2610 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2611 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
2613 if (dst & SLJIT_MEM)
2614 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2616 return const_;
2619 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2621 struct sljit_put_label *put_label;
2622 sljit_s32 dst_r;
2624 CHECK_ERROR_PTR();
2625 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
2626 ADJUST_LOCAL_OFFSET(dst, dstw);
2628 put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
2629 PTR_FAIL_IF(!put_label);
2630 set_put_label(put_label, compiler, 0);
2632 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2633 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2634 PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
2635 #else
2636 PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
2637 compiler->size += 4;
2638 #endif
2640 if (dst & SLJIT_MEM)
2641 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2643 return put_label;
2646 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
2648 sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);