Support unsaved registers
[sljit.git] / sljit_src / sljitNativePPC_common.c
blob7dcf32d7833db3d0dfcda32dc24b1e2864c02495
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, 1)
739 + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
740 local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
741 compiler->local_size = local_size;
743 FAIL_IF(push_inst(compiler, MFLR | D(0)));
745 base = SLJIT_SP;
746 offset = local_size;
748 if (local_size <= STACK_MAX_DISTANCE) {
749 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
750 FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
751 #else
752 FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
753 #endif
754 } else {
755 base = TMP_REG1;
756 FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));
757 FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));
758 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
759 FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
760 #else
761 FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
762 #endif
763 local_size = 0;
764 offset = 0;
767 tmp = SLJIT_FS0 - fsaveds;
768 for (i = SLJIT_FS0; i > tmp; i--) {
769 offset -= SSIZE_OF(f64);
770 FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
773 for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
774 offset -= SSIZE_OF(f64);
775 FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
778 offset -= SSIZE_OF(sw);
779 FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
781 tmp = SLJIT_S0 - saveds;
782 for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
783 offset -= SSIZE_OF(sw);
784 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
787 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
788 offset -= SSIZE_OF(sw);
789 FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
792 FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
793 FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
795 arg_types >>= SLJIT_ARG_SHIFT;
797 while (arg_types > 0) {
798 if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
799 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
800 do {
801 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
802 tmp = SLJIT_S0 - saved_arg_count;
803 saved_arg_count++;
804 } else if (arg_count != word_arg_count)
805 tmp = SLJIT_R0 + word_arg_count;
806 else
807 break;
809 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));
810 } while (0);
811 #else
812 if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
813 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));
814 saved_arg_count++;
816 #endif
817 word_arg_count++;
820 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
821 arg_count++;
822 #endif
823 arg_types >>= SLJIT_ARG_SHIFT;
826 return SLJIT_SUCCESS;
829 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
830 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
831 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
833 CHECK_ERROR();
834 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
835 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
837 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1)
838 + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
839 compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
840 return SLJIT_SUCCESS;
844 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
846 sljit_s32 i, tmp, base, offset;
847 sljit_s32 local_size = compiler->local_size;
849 base = SLJIT_SP;
850 if (local_size > STACK_MAX_DISTANCE) {
851 base = TMP_REG1;
852 if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {
853 FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));
854 local_size = 0;
855 } else {
856 FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));
857 local_size = STACK_MAX_DISTANCE;
861 offset = local_size;
862 FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));
864 tmp = SLJIT_FS0 - compiler->fsaveds;
865 for (i = SLJIT_FS0; i > tmp; i--) {
866 offset -= SSIZE_OF(f64);
867 FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
870 for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
871 offset -= SSIZE_OF(f64);
872 FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
875 offset -= SSIZE_OF(sw);
876 FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
878 tmp = SLJIT_S0 - compiler->saveds;
879 for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
880 offset -= SSIZE_OF(sw);
881 FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
884 for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
885 offset -= SSIZE_OF(sw);
886 FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
889 push_inst(compiler, MTLR | S(0));
891 if (local_size > 0)
892 return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));
894 SLJIT_ASSERT(base == TMP_REG1);
895 return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));
898 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
900 CHECK_ERROR();
901 CHECK(check_sljit_emit_return_void(compiler));
903 FAIL_IF(emit_stack_frame_release(compiler));
904 return push_inst(compiler, BLR);
907 #undef STACK_STORE
908 #undef STACK_LOAD
910 /* --------------------------------------------------------------------- */
911 /* Operators */
912 /* --------------------------------------------------------------------- */
914 /* s/l - store/load (1 bit)
915 i/x - immediate/indexed form
916 u/s - signed/unsigned (1 bit)
917 w/b/h/i - word/byte/half/int allowed (2 bit)
919 Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
921 /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
922 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
923 #define INT_ALIGNED 0x10000
924 #endif
926 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
927 #define ARCH_32_64(a, b) a
928 #define INST_CODE_AND_DST(inst, flags, reg) \
929 ((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
930 #else
931 #define ARCH_32_64(a, b) b
932 #define INST_CODE_AND_DST(inst, flags, reg) \
933 (((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
934 #endif
936 static const sljit_ins data_transfer_insts[64 + 16] = {
938 /* -------- Integer -------- */
940 /* Word. */
942 /* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
943 /* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
944 /* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
945 /* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
947 /* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
948 /* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
949 /* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
950 /* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
952 /* Byte. */
954 /* b u i s */ HI(38) /* stb */,
955 /* b u i l */ HI(34) /* lbz */,
956 /* b u x s */ HI(31) | LO(215) /* stbx */,
957 /* b u x l */ HI(31) | LO(87) /* lbzx */,
959 /* b s i s */ HI(38) /* stb */,
960 /* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,
961 /* b s x s */ HI(31) | LO(215) /* stbx */,
962 /* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
964 /* Half. */
966 /* h u i s */ HI(44) /* sth */,
967 /* h u i l */ HI(40) /* lhz */,
968 /* h u x s */ HI(31) | LO(407) /* sthx */,
969 /* h u x l */ HI(31) | LO(279) /* lhzx */,
971 /* h s i s */ HI(44) /* sth */,
972 /* h s i l */ HI(42) /* lha */,
973 /* h s x s */ HI(31) | LO(407) /* sthx */,
974 /* h s x l */ HI(31) | LO(343) /* lhax */,
976 /* Int. */
978 /* i u i s */ HI(36) /* stw */,
979 /* i u i l */ HI(32) /* lwz */,
980 /* i u x s */ HI(31) | LO(151) /* stwx */,
981 /* i u x l */ HI(31) | LO(23) /* lwzx */,
983 /* i s i s */ HI(36) /* stw */,
984 /* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
985 /* i s x s */ HI(31) | LO(151) /* stwx */,
986 /* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
988 /* -------- Floating point -------- */
990 /* d i s */ HI(54) /* stfd */,
991 /* d i l */ HI(50) /* lfd */,
992 /* d x s */ HI(31) | LO(727) /* stfdx */,
993 /* d x l */ HI(31) | LO(599) /* lfdx */,
995 /* s i s */ HI(52) /* stfs */,
996 /* s i l */ HI(48) /* lfs */,
997 /* s x s */ HI(31) | LO(663) /* stfsx */,
998 /* s x l */ HI(31) | LO(535) /* lfsx */,
1001 static const sljit_ins updated_data_transfer_insts[64] = {
1003 /* -------- Integer -------- */
1005 /* Word. */
1007 /* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
1008 /* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
1009 /* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
1010 /* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
1012 /* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
1013 /* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
1014 /* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
1015 /* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
1017 /* Byte. */
1019 /* b u i s */ HI(39) /* stbu */,
1020 /* b u i l */ HI(35) /* lbzu */,
1021 /* b u x s */ HI(31) | LO(247) /* stbux */,
1022 /* b u x l */ HI(31) | LO(119) /* lbzux */,
1024 /* b s i s */ HI(39) /* stbu */,
1025 /* b s i l */ 0 /* no such instruction */,
1026 /* b s x s */ HI(31) | LO(247) /* stbux */,
1027 /* b s x l */ 0 /* no such instruction */,
1029 /* Half. */
1031 /* h u i s */ HI(45) /* sthu */,
1032 /* h u i l */ HI(41) /* lhzu */,
1033 /* h u x s */ HI(31) | LO(439) /* sthux */,
1034 /* h u x l */ HI(31) | LO(311) /* lhzux */,
1036 /* h s i s */ HI(45) /* sthu */,
1037 /* h s i l */ HI(43) /* lhau */,
1038 /* h s x s */ HI(31) | LO(439) /* sthux */,
1039 /* h s x l */ HI(31) | LO(375) /* lhaux */,
1041 /* Int. */
1043 /* i u i s */ HI(37) /* stwu */,
1044 /* i u i l */ HI(33) /* lwzu */,
1045 /* i u x s */ HI(31) | LO(183) /* stwux */,
1046 /* i u x l */ HI(31) | LO(55) /* lwzux */,
1048 /* i s i s */ HI(37) /* stwu */,
1049 /* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),
1050 /* i s x s */ HI(31) | LO(183) /* stwux */,
1051 /* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
1053 /* -------- Floating point -------- */
1055 /* d i s */ HI(55) /* stfdu */,
1056 /* d i l */ HI(51) /* lfdu */,
1057 /* d x s */ HI(31) | LO(759) /* stfdux */,
1058 /* d x l */ HI(31) | LO(631) /* lfdux */,
1060 /* s i s */ HI(53) /* stfsu */,
1061 /* s i l */ HI(49) /* lfsu */,
1062 /* s x s */ HI(31) | LO(695) /* stfsux */,
1063 /* s x l */ HI(31) | LO(567) /* lfsux */,
1066 #undef ARCH_32_64
1068 /* Simple cases, (no caching is required). */
1069 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
1070 sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
1072 sljit_ins inst;
1073 sljit_s32 offs_reg;
1074 sljit_sw high_short;
1076 /* Should work when (arg & REG_MASK) == 0. */
1077 SLJIT_ASSERT(A(0) == 0);
1078 SLJIT_ASSERT(arg & SLJIT_MEM);
1080 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1081 argw &= 0x3;
1082 offs_reg = OFFS_REG(arg);
1084 if (argw != 0) {
1085 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1086 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | ((sljit_ins)argw << 11) | ((31 - (sljit_ins)argw) << 1)));
1087 #else
1088 FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1)));
1089 #endif
1090 offs_reg = tmp_reg;
1093 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1095 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1096 SLJIT_ASSERT(!(inst & INT_ALIGNED));
1097 #endif
1099 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
1102 inst = data_transfer_insts[inp_flags & MEM_MASK];
1103 arg &= REG_MASK;
1105 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1106 if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {
1107 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1109 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1110 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1112 #endif
1114 if (argw <= SIMM_MAX && argw >= SIMM_MIN)
1115 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));
1117 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1118 if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
1119 #endif
1121 high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff;
1123 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1124 SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l);
1125 #else
1126 SLJIT_ASSERT(high_short);
1127 #endif
1129 FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16)));
1130 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));
1132 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1135 /* The rest is PPC-64 only. */
1137 FAIL_IF(load_immediate(compiler, tmp_reg, argw));
1139 inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
1140 return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
1141 #endif
1144 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
1145 sljit_s32 dst, sljit_sw dstw,
1146 sljit_s32 src1, sljit_sw src1w,
1147 sljit_s32 src2, sljit_sw src2w)
1149 /* arg1 goes to TMP_REG1 or src reg
1150 arg2 goes to TMP_REG2, imm or src reg
1151 result goes to TMP_REG2, so put result can use TMP_REG1. */
1152 sljit_s32 dst_r = TMP_REG2;
1153 sljit_s32 src1_r;
1154 sljit_s32 src2_r;
1155 sljit_s32 sugg_src2_r = TMP_REG2;
1156 sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
1158 /* Destination check. */
1159 if (FAST_IS_REG(dst)) {
1160 dst_r = dst;
1161 /* The REG_DEST is only used by SLJIT_MOV operations, although
1162 * it is set for op2 operations with unset destination. */
1163 flags |= REG_DEST;
1165 if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1166 sugg_src2_r = dst_r;
1169 /* Source 1. */
1170 if (FAST_IS_REG(src1)) {
1171 src1_r = src1;
1172 flags |= REG1_SOURCE;
1174 else if (src1 & SLJIT_IMM) {
1175 src1_r = TMP_ZERO;
1176 if (src1w != 0) {
1177 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
1178 src1_r = TMP_REG1;
1181 else {
1182 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
1183 src1_r = TMP_REG1;
1186 /* Source 2. */
1187 if (FAST_IS_REG(src2)) {
1188 src2_r = src2;
1189 flags |= REG2_SOURCE;
1191 if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
1192 dst_r = src2_r;
1194 else if (src2 & SLJIT_IMM) {
1195 src2_r = TMP_ZERO;
1196 if (src2w != 0) {
1197 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
1198 src2_r = sugg_src2_r;
1201 else {
1202 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2));
1203 src2_r = sugg_src2_r;
1206 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1208 if (!(dst & SLJIT_MEM))
1209 return SLJIT_SUCCESS;
1211 return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
1214 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1216 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1217 sljit_s32 int_op = op & SLJIT_32;
1218 #endif
1220 CHECK_ERROR();
1221 CHECK(check_sljit_emit_op0(compiler, op));
1223 op = GET_OPCODE(op);
1224 switch (op) {
1225 case SLJIT_BREAKPOINT:
1226 case SLJIT_NOP:
1227 return push_inst(compiler, NOP);
1228 case SLJIT_LMUL_UW:
1229 case SLJIT_LMUL_SW:
1230 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1231 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1232 FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1233 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1234 #else
1235 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
1236 return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
1237 #endif
1238 case SLJIT_DIVMOD_UW:
1239 case SLJIT_DIVMOD_SW:
1240 FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
1241 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1242 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)));
1243 FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1244 #else
1245 FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
1246 FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
1247 #endif
1248 return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
1249 case SLJIT_DIV_UW:
1250 case SLJIT_DIV_SW:
1251 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1252 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));
1253 #else
1254 return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
1255 #endif
1256 case SLJIT_ENDBR:
1257 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1258 return SLJIT_SUCCESS;
1261 return SLJIT_SUCCESS;
1264 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1265 sljit_s32 src, sljit_sw srcw)
1267 if (!(src & OFFS_REG_MASK)) {
1268 if (srcw == 0 && (src & REG_MASK))
1269 return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
1271 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1272 /* Works with SLJIT_MEM0() case as well. */
1273 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1276 srcw &= 0x3;
1278 if (srcw == 0)
1279 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
1281 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1282 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | ((sljit_ins)srcw << 11) | ((31 - (sljit_ins)srcw) << 1)));
1283 #else
1284 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
1285 #endif
1286 return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
1289 #define EMIT_MOV(type, type_flags, type_cast) \
1290 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)
1292 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1293 sljit_s32 dst, sljit_sw dstw,
1294 sljit_s32 src, sljit_sw srcw)
1296 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1297 sljit_s32 op_flags = GET_ALL_FLAGS(op);
1299 CHECK_ERROR();
1300 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1301 ADJUST_LOCAL_OFFSET(dst, dstw);
1302 ADJUST_LOCAL_OFFSET(src, srcw);
1304 op = GET_OPCODE(op);
1306 if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
1307 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1309 if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) {
1310 if (!TYPE_CAST_NEEDED(op))
1311 return SLJIT_SUCCESS;
1314 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1315 if (op_flags & SLJIT_32) {
1316 if (op < SLJIT_NOT) {
1317 if (src & SLJIT_MEM) {
1318 if (op == SLJIT_MOV_S32)
1319 op = SLJIT_MOV_U32;
1321 else if (src & SLJIT_IMM) {
1322 if (op == SLJIT_MOV_U32)
1323 op = SLJIT_MOV_S32;
1326 else {
1327 /* Most operations expect sign extended arguments. */
1328 flags |= INT_DATA | SIGNED_DATA;
1329 if (HAS_FLAGS(op_flags))
1330 flags |= ALT_SIGN_EXT;
1333 #endif
1335 switch (op) {
1336 case SLJIT_MOV:
1337 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1338 case SLJIT_MOV_U32:
1339 case SLJIT_MOV_S32:
1340 case SLJIT_MOV32:
1341 #endif
1342 case SLJIT_MOV_P:
1343 return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
1345 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1346 case SLJIT_MOV_U32:
1347 return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
1349 case SLJIT_MOV_S32:
1350 case SLJIT_MOV32:
1351 return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
1352 #endif
1354 case SLJIT_MOV_U8:
1355 return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
1357 case SLJIT_MOV_S8:
1358 return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
1360 case SLJIT_MOV_U16:
1361 return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
1363 case SLJIT_MOV_S16:
1364 return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
1366 case SLJIT_NOT:
1367 return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1369 case SLJIT_CLZ:
1370 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1371 return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
1372 #else
1373 return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1374 #endif
1377 return SLJIT_SUCCESS;
1380 #undef EMIT_MOV
1382 #define TEST_SL_IMM(src, srcw) \
1383 (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
1385 #define TEST_UL_IMM(src, srcw) \
1386 (((src) & SLJIT_IMM) && !((srcw) & ~0xffff))
1388 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1389 #define TEST_SH_IMM(src, srcw) \
1390 (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
1391 #else
1392 #define TEST_SH_IMM(src, srcw) \
1393 (((src) & SLJIT_IMM) && !((srcw) & 0xffff))
1394 #endif
1396 #define TEST_UH_IMM(src, srcw) \
1397 (((src) & SLJIT_IMM) && !((srcw) & ~(sljit_sw)0xffff0000))
1399 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1400 #define TEST_ADD_IMM(src, srcw) \
1401 (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
1402 #else
1403 #define TEST_ADD_IMM(src, srcw) \
1404 ((src) & SLJIT_IMM)
1405 #endif
1407 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1408 #define TEST_UI_IMM(src, srcw) \
1409 (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff))
1410 #else
1411 #define TEST_UI_IMM(src, srcw) \
1412 ((src) & SLJIT_IMM)
1413 #endif
1415 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1416 #define TEST_ADD_FORM1(op) \
1417 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1418 || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))
1419 #define TEST_SUB_FORM2(op) \
1420 ((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
1421 || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))
1422 #define TEST_SUB_FORM3(op) \
1423 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
1424 || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))
1425 #else
1426 #define TEST_ADD_FORM1(op) \
1427 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1428 #define TEST_SUB_FORM2(op) \
1429 (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)
1430 #define TEST_SUB_FORM3(op) \
1431 (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1432 #endif
1434 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1435 sljit_s32 dst, sljit_sw dstw,
1436 sljit_s32 src1, sljit_sw src1w,
1437 sljit_s32 src2, sljit_sw src2w)
1439 sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
1441 CHECK_ERROR();
1442 CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
1443 ADJUST_LOCAL_OFFSET(dst, dstw);
1444 ADJUST_LOCAL_OFFSET(src1, src1w);
1445 ADJUST_LOCAL_OFFSET(src2, src2w);
1447 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1448 if (op & SLJIT_32) {
1449 /* Most operations expect sign extended arguments. */
1450 flags |= INT_DATA | SIGNED_DATA;
1451 if (src1 & SLJIT_IMM)
1452 src1w = (sljit_s32)(src1w);
1453 if (src2 & SLJIT_IMM)
1454 src2w = (sljit_s32)(src2w);
1455 if (HAS_FLAGS(op))
1456 flags |= ALT_SIGN_EXT;
1458 #endif
1459 if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
1460 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1462 switch (GET_OPCODE(op)) {
1463 case SLJIT_ADD:
1464 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1466 if (TEST_ADD_FORM1(op))
1467 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1469 if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
1470 if (TEST_SL_IMM(src2, src2w)) {
1471 compiler->imm = (sljit_ins)src2w & 0xffff;
1472 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1474 if (TEST_SL_IMM(src1, src1w)) {
1475 compiler->imm = (sljit_ins)src1w & 0xffff;
1476 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1478 if (TEST_SH_IMM(src2, src2w)) {
1479 compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
1480 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1482 if (TEST_SH_IMM(src1, src1w)) {
1483 compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
1484 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1486 /* Range between -1 and -32768 is covered above. */
1487 if (TEST_ADD_IMM(src2, src2w)) {
1488 compiler->imm = (sljit_ins)src2w & 0xffffffff;
1489 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1491 if (TEST_ADD_IMM(src1, src1w)) {
1492 compiler->imm = (sljit_ins)src1w & 0xffffffff;
1493 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1497 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1498 if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {
1499 if (TEST_SL_IMM(src2, src2w)) {
1500 compiler->imm = (sljit_ins)src2w & 0xffff;
1501 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
1503 if (TEST_SL_IMM(src1, src1w)) {
1504 compiler->imm = (sljit_ins)src1w & 0xffff;
1505 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
1507 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1509 #endif
1510 if (HAS_FLAGS(op)) {
1511 if (TEST_SL_IMM(src2, src2w)) {
1512 compiler->imm = (sljit_ins)src2w & 0xffff;
1513 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1515 if (TEST_SL_IMM(src1, src1w)) {
1516 compiler->imm = (sljit_ins)src1w & 0xffff;
1517 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1520 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);
1522 case SLJIT_ADDC:
1523 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1524 return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
1526 case SLJIT_SUB:
1527 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1529 if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
1530 if (dst == TMP_REG2) {
1531 if (TEST_UL_IMM(src2, src2w)) {
1532 compiler->imm = (sljit_ins)src2w & 0xffff;
1533 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1535 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
1538 if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
1539 compiler->imm = (sljit_ins)src2w;
1540 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1542 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1545 if (dst == TMP_REG2 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1546 if (TEST_SL_IMM(src2, src2w)) {
1547 compiler->imm = (sljit_ins)src2w & 0xffff;
1548 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1550 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
1553 if (TEST_SUB_FORM2(op)) {
1554 if ((src2 & SLJIT_IMM) && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
1555 compiler->imm = (sljit_ins)src2w & 0xffff;
1556 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1558 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
1561 if (TEST_SUB_FORM3(op))
1562 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
1564 if (TEST_SL_IMM(src2, -src2w)) {
1565 compiler->imm = (sljit_ins)(-src2w) & 0xffff;
1566 return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
1569 if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
1570 compiler->imm = (sljit_ins)src1w & 0xffff;
1571 return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
1574 if (!HAS_FLAGS(op)) {
1575 if (TEST_SH_IMM(src2, -src2w)) {
1576 compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;
1577 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1579 /* Range between -1 and -32768 is covered above. */
1580 if (TEST_ADD_IMM(src2, -src2w)) {
1581 compiler->imm = (sljit_ins)-src2w;
1582 return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
1586 /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */
1587 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);
1589 case SLJIT_SUBC:
1590 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1591 return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
1593 case SLJIT_MUL:
1594 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1595 if (op & SLJIT_32)
1596 flags |= ALT_FORM2;
1597 #endif
1598 if (!HAS_FLAGS(op)) {
1599 if (TEST_SL_IMM(src2, src2w)) {
1600 compiler->imm = (sljit_ins)src2w & 0xffff;
1601 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1603 if (TEST_SL_IMM(src1, src1w)) {
1604 compiler->imm = (sljit_ins)src1w & 0xffff;
1605 return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1608 else
1609 FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
1610 return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
1612 case SLJIT_AND:
1613 case SLJIT_OR:
1614 case SLJIT_XOR:
1615 /* Commutative unsigned operations. */
1616 if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
1617 if (TEST_UL_IMM(src2, src2w)) {
1618 compiler->imm = (sljit_ins)src2w;
1619 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1621 if (TEST_UL_IMM(src1, src1w)) {
1622 compiler->imm = (sljit_ins)src1w;
1623 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
1625 if (TEST_UH_IMM(src2, src2w)) {
1626 compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
1627 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
1629 if (TEST_UH_IMM(src1, src1w)) {
1630 compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
1631 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
1634 if (GET_OPCODE(op) != SLJIT_AND) {
1635 /* Unlike or and xor, the and resets unwanted bits as well. */
1636 if (TEST_UI_IMM(src2, src2w)) {
1637 compiler->imm = (sljit_ins)src2w;
1638 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
1640 if (TEST_UI_IMM(src1, src1w)) {
1641 compiler->imm = (sljit_ins)src1w;
1642 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
1645 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1647 case SLJIT_SHL:
1648 case SLJIT_LSHR:
1649 case SLJIT_ASHR:
1650 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1651 if (op & SLJIT_32)
1652 flags |= ALT_FORM2;
1653 #endif
1654 if (src2 & SLJIT_IMM) {
1655 compiler->imm = (sljit_ins)src2w;
1656 return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
1658 return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
1661 return SLJIT_SUCCESS;
1664 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
1665 sljit_s32 src1, sljit_sw src1w,
1666 sljit_s32 src2, sljit_sw src2w)
1668 CHECK_ERROR();
1669 CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
1671 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1672 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1673 compiler->skip_checks = 1;
1674 #endif
1675 return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
1678 #undef TEST_ADD_FORM1
1679 #undef TEST_SUB_FORM2
1680 #undef TEST_SUB_FORM3
1682 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
1683 sljit_s32 src, sljit_sw srcw)
1685 CHECK_ERROR();
1686 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1687 ADJUST_LOCAL_OFFSET(src, srcw);
1689 switch (op) {
1690 case SLJIT_FAST_RETURN:
1691 if (FAST_IS_REG(src))
1692 FAIL_IF(push_inst(compiler, MTLR | S(src)));
1693 else {
1694 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
1695 FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
1698 return push_inst(compiler, BLR);
1699 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
1700 return SLJIT_SUCCESS;
1701 case SLJIT_PREFETCH_L1:
1702 case SLJIT_PREFETCH_L2:
1703 case SLJIT_PREFETCH_L3:
1704 case SLJIT_PREFETCH_ONCE:
1705 return emit_prefetch(compiler, src, srcw);
1708 return SLJIT_SUCCESS;
1711 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1713 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1714 return reg_map[reg];
1717 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1719 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1720 return freg_map[reg];
1723 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1724 void *instruction, sljit_u32 size)
1726 CHECK_ERROR();
1727 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1729 return push_inst(compiler, *(sljit_ins*)instruction);
1732 /* --------------------------------------------------------------------- */
1733 /* Floating point operators */
1734 /* --------------------------------------------------------------------- */
1736 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))
1737 #define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))
1739 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1740 #define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
1741 #else
1742 #define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
1744 #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
1745 #define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw))
1746 #define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw))
1747 #else
1748 #define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw))
1749 #define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw))
1750 #endif
1752 #endif /* SLJIT_CONFIG_PPC_64 */
1754 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1755 sljit_s32 dst, sljit_sw dstw,
1756 sljit_s32 src, sljit_sw srcw)
1758 if (src & SLJIT_MEM) {
1759 /* We can ignore the temporary data store on the stack from caching point of view. */
1760 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1761 src = TMP_FREG1;
1764 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1765 op = GET_OPCODE(op);
1766 FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
1768 if (op == SLJIT_CONV_SW_FROM_F64) {
1769 if (FAST_IS_REG(dst)) {
1770 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1771 return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1773 return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
1775 #else
1776 FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
1777 #endif
1779 if (FAST_IS_REG(dst)) {
1780 FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET));
1781 FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
1782 return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1);
1785 SLJIT_ASSERT(dst & SLJIT_MEM);
1787 if (dst & OFFS_REG_MASK) {
1788 dstw &= 0x3;
1789 if (dstw) {
1790 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
1791 FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | ((sljit_ins)dstw << 11) | ((31 - (sljit_ins)dstw) << 1)));
1792 #else
1793 FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
1794 #endif
1795 dstw = TMP_REG1;
1797 else
1798 dstw = OFFS_REG(dst);
1800 else {
1801 if ((dst & REG_MASK) && !dstw) {
1802 dstw = dst & REG_MASK;
1803 dst = 0;
1805 else {
1806 /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
1807 FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
1808 dstw = TMP_REG1;
1812 return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
1815 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1816 sljit_s32 dst, sljit_sw dstw,
1817 sljit_s32 src, sljit_sw srcw)
1819 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
1821 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1823 if (src & SLJIT_IMM) {
1824 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1825 srcw = (sljit_s32)srcw;
1826 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
1827 src = TMP_REG1;
1829 else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
1830 if (FAST_IS_REG(src))
1831 FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
1832 else
1833 FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1834 src = TMP_REG1;
1837 if (FAST_IS_REG(src)) {
1838 FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1839 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1841 else
1842 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
1844 FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
1846 if (dst & SLJIT_MEM)
1847 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1848 if (op & SLJIT_32)
1849 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1850 return SLJIT_SUCCESS;
1852 #else
1854 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1855 sljit_s32 invert_sign = 1;
1857 if (src & SLJIT_IMM) {
1858 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
1859 src = TMP_REG1;
1860 invert_sign = 0;
1862 else if (!FAST_IS_REG(src)) {
1863 FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1864 src = TMP_REG1;
1867 /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31)))
1868 The double precision format has exactly 53 bit precision, so the lower 32 bit represents
1869 the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000
1870 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating
1871 point value, we need to substract 2^53 + 2^31 from the constructed value. */
1872 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
1873 if (invert_sign)
1874 FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
1875 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1));
1876 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1877 FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
1878 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1879 FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2));
1880 FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1));
1882 FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
1884 if (dst & SLJIT_MEM)
1885 return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
1886 if (op & SLJIT_32)
1887 return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
1888 return SLJIT_SUCCESS;
1890 #endif
1893 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1894 sljit_s32 src1, sljit_sw src1w,
1895 sljit_s32 src2, sljit_sw src2w)
1897 if (src1 & SLJIT_MEM) {
1898 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
1899 src1 = TMP_FREG1;
1902 if (src2 & SLJIT_MEM) {
1903 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
1904 src2 = TMP_FREG2;
1907 FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)));
1909 switch (GET_FLAG_TYPE(op)) {
1910 case SLJIT_UNORDERED_OR_EQUAL:
1911 case SLJIT_ORDERED_NOT_EQUAL:
1912 return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));
1913 case SLJIT_UNORDERED_OR_LESS:
1914 case SLJIT_ORDERED_GREATER_EQUAL:
1915 return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));
1916 case SLJIT_UNORDERED_OR_GREATER:
1917 case SLJIT_ORDERED_LESS_EQUAL:
1918 return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));
1921 return SLJIT_SUCCESS;
1924 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1925 sljit_s32 dst, sljit_sw dstw,
1926 sljit_s32 src, sljit_sw srcw)
1928 sljit_s32 dst_r;
1930 CHECK_ERROR();
1932 SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
1933 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1935 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1936 op ^= SLJIT_32;
1938 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1940 if (src & SLJIT_MEM) {
1941 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));
1942 src = dst_r;
1945 switch (GET_OPCODE(op)) {
1946 case SLJIT_CONV_F64_FROM_F32:
1947 op ^= SLJIT_32;
1948 if (op & SLJIT_32) {
1949 FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
1950 break;
1952 /* Fall through. */
1953 case SLJIT_MOV_F64:
1954 if (src != dst_r) {
1955 if (dst_r != TMP_FREG1)
1956 FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
1957 else
1958 dst_r = src;
1960 break;
1961 case SLJIT_NEG_F64:
1962 FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
1963 break;
1964 case SLJIT_ABS_F64:
1965 FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
1966 break;
1969 if (dst & SLJIT_MEM)
1970 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));
1971 return SLJIT_SUCCESS;
1974 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1975 sljit_s32 dst, sljit_sw dstw,
1976 sljit_s32 src1, sljit_sw src1w,
1977 sljit_s32 src2, sljit_sw src2w)
1979 sljit_s32 dst_r;
1981 CHECK_ERROR();
1982 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1983 ADJUST_LOCAL_OFFSET(dst, dstw);
1984 ADJUST_LOCAL_OFFSET(src1, src1w);
1985 ADJUST_LOCAL_OFFSET(src2, src2w);
1987 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
1989 if (src1 & SLJIT_MEM) {
1990 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
1991 src1 = TMP_FREG1;
1994 if (src2 & SLJIT_MEM) {
1995 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
1996 src2 = TMP_FREG2;
1999 switch (GET_OPCODE(op)) {
2000 case SLJIT_ADD_F64:
2001 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
2002 break;
2004 case SLJIT_SUB_F64:
2005 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
2006 break;
2008 case SLJIT_MUL_F64:
2009 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
2010 break;
2012 case SLJIT_DIV_F64:
2013 FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
2014 break;
2017 if (dst & SLJIT_MEM)
2018 FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
2020 return SLJIT_SUCCESS;
2023 #undef SELECT_FOP
2025 /* --------------------------------------------------------------------- */
2026 /* Other instructions */
2027 /* --------------------------------------------------------------------- */
2029 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2031 CHECK_ERROR();
2032 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
2033 ADJUST_LOCAL_OFFSET(dst, dstw);
2035 if (FAST_IS_REG(dst))
2036 return push_inst(compiler, MFLR | D(dst));
2038 /* Memory. */
2039 FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2)));
2040 return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2043 /* --------------------------------------------------------------------- */
2044 /* Conditional instructions */
2045 /* --------------------------------------------------------------------- */
2047 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2049 struct sljit_label *label;
2051 CHECK_ERROR_PTR();
2052 CHECK_PTR(check_sljit_emit_label(compiler));
2054 if (compiler->last_label && compiler->last_label->size == compiler->size)
2055 return compiler->last_label;
2057 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2058 PTR_FAIL_IF(!label);
2059 set_label(label, compiler);
2060 return label;
2063 static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)
2065 switch (type) {
2066 case SLJIT_NOT_CARRY:
2067 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
2068 return (4 << 21) | (2 << 16);
2069 /* fallthrough */
2071 case SLJIT_EQUAL:
2072 return (12 << 21) | (2 << 16);
2074 case SLJIT_CARRY:
2075 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
2076 return (12 << 21) | (2 << 16);
2077 /* fallthrough */
2079 case SLJIT_NOT_EQUAL:
2080 return (4 << 21) | (2 << 16);
2082 case SLJIT_LESS:
2083 case SLJIT_SIG_LESS:
2084 return (12 << 21) | (0 << 16);
2086 case SLJIT_GREATER_EQUAL:
2087 case SLJIT_SIG_GREATER_EQUAL:
2088 return (4 << 21) | (0 << 16);
2090 case SLJIT_GREATER:
2091 case SLJIT_SIG_GREATER:
2092 return (12 << 21) | (1 << 16);
2094 case SLJIT_LESS_EQUAL:
2095 case SLJIT_SIG_LESS_EQUAL:
2096 return (4 << 21) | (1 << 16);
2098 case SLJIT_OVERFLOW:
2099 return (12 << 21) | (3 << 16);
2101 case SLJIT_NOT_OVERFLOW:
2102 return (4 << 21) | (3 << 16);
2104 case SLJIT_F_LESS:
2105 case SLJIT_ORDERED_LESS:
2106 case SLJIT_UNORDERED_OR_LESS:
2107 return (12 << 21) | ((4 + 0) << 16);
2109 case SLJIT_F_GREATER_EQUAL:
2110 case SLJIT_ORDERED_GREATER_EQUAL:
2111 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2112 return (4 << 21) | ((4 + 0) << 16);
2114 case SLJIT_F_GREATER:
2115 case SLJIT_ORDERED_GREATER:
2116 case SLJIT_UNORDERED_OR_GREATER:
2117 return (12 << 21) | ((4 + 1) << 16);
2119 case SLJIT_F_LESS_EQUAL:
2120 case SLJIT_ORDERED_LESS_EQUAL:
2121 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2122 return (4 << 21) | ((4 + 1) << 16);
2124 case SLJIT_F_EQUAL:
2125 case SLJIT_ORDERED_EQUAL:
2126 case SLJIT_UNORDERED_OR_EQUAL:
2127 return (12 << 21) | ((4 + 2) << 16);
2129 case SLJIT_F_NOT_EQUAL:
2130 case SLJIT_ORDERED_NOT_EQUAL:
2131 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2132 return (4 << 21) | ((4 + 2) << 16);
2134 case SLJIT_UNORDERED:
2135 return (12 << 21) | ((4 + 3) << 16);
2137 case SLJIT_ORDERED:
2138 return (4 << 21) | ((4 + 3) << 16);
2140 default:
2141 SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
2142 return (20 << 21);
2146 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2148 struct sljit_jump *jump;
2149 sljit_ins bo_bi_flags;
2151 CHECK_ERROR_PTR();
2152 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2154 bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
2155 if (!bo_bi_flags)
2156 return NULL;
2158 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2159 PTR_FAIL_IF(!jump);
2160 set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);
2161 type &= 0xff;
2163 if (type == SLJIT_CARRY || type == SLJIT_NOT_CARRY)
2164 PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
2166 /* In PPC, we don't need to touch the arguments. */
2167 if (type < SLJIT_JUMP)
2168 jump->flags |= IS_COND;
2169 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2170 if (type >= SLJIT_CALL)
2171 jump->flags |= IS_CALL;
2172 #endif
2174 PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2175 PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG)));
2176 jump->addr = compiler->size;
2177 PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
2178 return jump;
2181 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2182 sljit_s32 arg_types)
2184 CHECK_ERROR_PTR();
2185 CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2187 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2188 PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
2189 #endif
2191 if (type & SLJIT_CALL_RETURN) {
2192 PTR_FAIL_IF(emit_stack_frame_release(compiler));
2193 type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
2196 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2197 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2198 compiler->skip_checks = 1;
2199 #endif
2201 return sljit_emit_jump(compiler, type);
2204 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2206 struct sljit_jump *jump = NULL;
2207 sljit_s32 src_r;
2209 CHECK_ERROR();
2210 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2211 ADJUST_LOCAL_OFFSET(src, srcw);
2213 if (FAST_IS_REG(src)) {
2214 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2215 if (type >= SLJIT_CALL && src != TMP_CALL_REG) {
2216 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2217 src_r = TMP_CALL_REG;
2219 else
2220 src_r = src;
2221 #else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2222 src_r = src;
2223 #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2224 } else if (src & SLJIT_IMM) {
2225 /* These jumps are converted to jump/call instructions when possible. */
2226 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2227 FAIL_IF(!jump);
2228 set_jump(jump, compiler, JUMP_ADDR);
2229 jump->u.target = (sljit_uw)srcw;
2231 #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
2232 if (type >= SLJIT_CALL)
2233 jump->flags |= IS_CALL;
2234 #endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
2236 FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
2237 src_r = TMP_CALL_REG;
2239 else {
2240 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2241 src_r = TMP_CALL_REG;
2244 FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
2245 if (jump)
2246 jump->addr = compiler->size;
2247 return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
2250 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
2251 sljit_s32 arg_types,
2252 sljit_s32 src, sljit_sw srcw)
2254 CHECK_ERROR();
2255 CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
2257 if (src & SLJIT_MEM) {
2258 ADJUST_LOCAL_OFFSET(src, srcw);
2259 FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
2260 src = TMP_CALL_REG;
2263 if (type & SLJIT_CALL_RETURN) {
2264 if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
2265 FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
2266 src = TMP_CALL_REG;
2269 FAIL_IF(emit_stack_frame_release(compiler));
2270 type = SLJIT_JUMP;
2273 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2274 FAIL_IF(call_with_args(compiler, arg_types, &src));
2275 #endif
2277 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2278 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2279 compiler->skip_checks = 1;
2280 #endif
2282 return sljit_emit_ijump(compiler, type, src, srcw);
2285 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2286 sljit_s32 dst, sljit_sw dstw,
2287 sljit_s32 type)
2289 sljit_s32 reg, invert;
2290 sljit_u32 bit, from_xer;
2291 sljit_s32 saved_op = op;
2292 sljit_sw saved_dstw = dstw;
2293 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2294 sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;
2295 #else
2296 sljit_s32 input_flags = WORD_DATA;
2297 #endif
2299 CHECK_ERROR();
2300 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2301 ADJUST_LOCAL_OFFSET(dst, dstw);
2303 op = GET_OPCODE(op);
2304 reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2306 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2307 FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
2309 invert = 0;
2310 bit = 0;
2311 from_xer = 0;
2313 switch (type) {
2314 case SLJIT_LESS:
2315 case SLJIT_SIG_LESS:
2316 break;
2318 case SLJIT_GREATER_EQUAL:
2319 case SLJIT_SIG_GREATER_EQUAL:
2320 invert = 1;
2321 break;
2323 case SLJIT_GREATER:
2324 case SLJIT_SIG_GREATER:
2325 bit = 1;
2326 break;
2328 case SLJIT_LESS_EQUAL:
2329 case SLJIT_SIG_LESS_EQUAL:
2330 bit = 1;
2331 invert = 1;
2332 break;
2334 case SLJIT_EQUAL:
2335 bit = 2;
2336 break;
2338 case SLJIT_NOT_EQUAL:
2339 bit = 2;
2340 invert = 1;
2341 break;
2343 case SLJIT_OVERFLOW:
2344 from_xer = 1;
2345 bit = 1;
2346 break;
2348 case SLJIT_NOT_OVERFLOW:
2349 from_xer = 1;
2350 bit = 1;
2351 invert = 1;
2352 break;
2354 case SLJIT_CARRY:
2355 from_xer = 1;
2356 bit = 2;
2357 invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;
2358 break;
2360 case SLJIT_NOT_CARRY:
2361 from_xer = 1;
2362 bit = 2;
2363 invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;
2364 break;
2366 case SLJIT_F_LESS:
2367 case SLJIT_ORDERED_LESS:
2368 case SLJIT_UNORDERED_OR_LESS:
2369 bit = 4 + 0;
2370 break;
2372 case SLJIT_F_GREATER_EQUAL:
2373 case SLJIT_ORDERED_GREATER_EQUAL:
2374 case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2375 bit = 4 + 0;
2376 invert = 1;
2377 break;
2379 case SLJIT_F_GREATER:
2380 case SLJIT_ORDERED_GREATER:
2381 case SLJIT_UNORDERED_OR_GREATER:
2382 bit = 4 + 1;
2383 break;
2385 case SLJIT_F_LESS_EQUAL:
2386 case SLJIT_ORDERED_LESS_EQUAL:
2387 case SLJIT_UNORDERED_OR_LESS_EQUAL:
2388 bit = 4 + 1;
2389 invert = 1;
2390 break;
2392 case SLJIT_F_EQUAL:
2393 case SLJIT_ORDERED_EQUAL:
2394 case SLJIT_UNORDERED_OR_EQUAL:
2395 bit = 4 + 2;
2396 break;
2398 case SLJIT_F_NOT_EQUAL:
2399 case SLJIT_ORDERED_NOT_EQUAL:
2400 case SLJIT_UNORDERED_OR_NOT_EQUAL:
2401 bit = 4 + 2;
2402 invert = 1;
2403 break;
2405 case SLJIT_UNORDERED:
2406 bit = 4 + 3;
2407 break;
2409 case SLJIT_ORDERED:
2410 bit = 4 + 3;
2411 invert = 1;
2412 break;
2414 default:
2415 SLJIT_UNREACHABLE();
2416 break;
2419 FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));
2420 FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + bit) << 11) | (31 << 6) | (31 << 1)));
2422 if (invert)
2423 FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
2425 if (op < SLJIT_ADD) {
2426 if (!(dst & SLJIT_MEM))
2427 return SLJIT_SUCCESS;
2428 return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
2431 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2432 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2433 compiler->skip_checks = 1;
2434 #endif
2435 if (dst & SLJIT_MEM)
2436 return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
2437 return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
2440 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2441 sljit_s32 dst_reg,
2442 sljit_s32 src, sljit_sw srcw)
2444 CHECK_ERROR();
2445 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2447 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
2450 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
2451 sljit_s32 reg,
2452 sljit_s32 mem, sljit_sw memw)
2454 sljit_s32 mem_flags;
2455 sljit_ins inst;
2457 CHECK_ERROR();
2458 CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
2460 if (type & SLJIT_MEM_POST)
2461 return SLJIT_ERR_UNSUPPORTED;
2463 switch (type & 0xff) {
2464 case SLJIT_MOV:
2465 case SLJIT_MOV_P:
2466 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2467 case SLJIT_MOV_U32:
2468 case SLJIT_MOV_S32:
2469 case SLJIT_MOV32:
2470 #endif
2471 mem_flags = WORD_DATA;
2472 break;
2474 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2475 case SLJIT_MOV_U32:
2476 case SLJIT_MOV32:
2477 mem_flags = INT_DATA;
2478 break;
2480 case SLJIT_MOV_S32:
2481 mem_flags = INT_DATA;
2483 if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {
2484 if (mem & OFFS_REG_MASK)
2485 mem_flags |= SIGNED_DATA;
2486 else
2487 return SLJIT_ERR_UNSUPPORTED;
2489 break;
2490 #endif
2492 case SLJIT_MOV_U8:
2493 case SLJIT_MOV_S8:
2494 mem_flags = BYTE_DATA;
2495 break;
2497 case SLJIT_MOV_U16:
2498 mem_flags = HALF_DATA;
2499 break;
2501 case SLJIT_MOV_S16:
2502 mem_flags = HALF_DATA | SIGNED_DATA;
2503 break;
2505 default:
2506 SLJIT_UNREACHABLE();
2507 mem_flags = WORD_DATA;
2508 break;
2511 if (!(type & SLJIT_MEM_STORE))
2512 mem_flags |= LOAD_DATA;
2514 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2515 if (memw != 0)
2516 return SLJIT_ERR_UNSUPPORTED;
2518 if (type & SLJIT_MEM_SUPP)
2519 return SLJIT_SUCCESS;
2521 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2522 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
2524 else {
2525 if (memw > SIMM_MAX || memw < SIMM_MIN)
2526 return SLJIT_ERR_UNSUPPORTED;
2528 inst = updated_data_transfer_insts[mem_flags];
2530 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
2531 if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)
2532 return SLJIT_ERR_UNSUPPORTED;
2533 #endif
2535 if (type & SLJIT_MEM_SUPP)
2536 return SLJIT_SUCCESS;
2538 FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
2541 if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)
2542 return push_inst(compiler, EXTSB | S(reg) | A(reg));
2543 return SLJIT_SUCCESS;
2546 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
2547 sljit_s32 freg,
2548 sljit_s32 mem, sljit_sw memw)
2550 sljit_s32 mem_flags;
2551 sljit_ins inst;
2553 CHECK_ERROR();
2554 CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
2556 if (type & SLJIT_MEM_POST)
2557 return SLJIT_ERR_UNSUPPORTED;
2559 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2560 if (memw != 0)
2561 return SLJIT_ERR_UNSUPPORTED;
2563 else {
2564 if (memw > SIMM_MAX || memw < SIMM_MIN)
2565 return SLJIT_ERR_UNSUPPORTED;
2568 if (type & SLJIT_MEM_SUPP)
2569 return SLJIT_SUCCESS;
2571 mem_flags = FLOAT_DATA(type);
2573 if (!(type & SLJIT_MEM_STORE))
2574 mem_flags |= LOAD_DATA;
2576 if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
2577 inst = updated_data_transfer_insts[mem_flags | INDEXED];
2578 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));
2581 inst = updated_data_transfer_insts[mem_flags];
2582 return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));
2585 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2587 struct sljit_const *const_;
2588 sljit_s32 dst_r;
2590 CHECK_ERROR_PTR();
2591 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2592 ADJUST_LOCAL_OFFSET(dst, dstw);
2594 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2595 PTR_FAIL_IF(!const_);
2596 set_const(const_, compiler);
2598 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2599 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
2601 if (dst & SLJIT_MEM)
2602 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2604 return const_;
2607 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2609 struct sljit_put_label *put_label;
2610 sljit_s32 dst_r;
2612 CHECK_ERROR_PTR();
2613 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
2614 ADJUST_LOCAL_OFFSET(dst, dstw);
2616 put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
2617 PTR_FAIL_IF(!put_label);
2618 set_put_label(put_label, compiler, 0);
2620 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2621 #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
2622 PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
2623 #else
2624 PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
2625 compiler->size += 4;
2626 #endif
2628 if (dst & SLJIT_MEM)
2629 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2631 return put_label;